I have a macro in excel 2013 that is trying to connect to an Oracle database through "Microsoft ODBC for Oracle", the 32bit version, as the 64bit has issues for some reason. And though the query works from Toad, it returns no results in my macro.
I have tried shorter queries and they do return results making me think that this monster query cannot be appended correctly, but I have no way to test this.
My current situation is a giant and very ugly append to get this query into one long string to be executed by my ADOConnection.
SQLString = "SELECT LEVEL, "
SQLString = SQLString & "MSIL.SEGMENT1 ITEM, "
SQLString = SQLString & "MSIL.DESCRIPTION DESC_COMPONENT, "
SQLString = SQLString & "BIC.ITEM_TYPE, "
SQLString = SQLString & "BIC.SUPPLY_TYPE, "
SQLString = SQLString & "MSIL.PRIMARY_UOM_CODE UOM, "
SQLString = SQLString & "BIC.COMPONENT_QUANTITY, "
SQLString = SQLString & "item_attribute.ITEM_LENGTH, "
SQLString = SQLString & "item_attribute.ANGLE_LEFT, "
SQLString = SQLString & "item_attribute.ANGLE_RIGHT, "
SQLString = SQLString & "item_attribute.WT_HT_FLAG, "
SQLString = SQLString & "item_attribute.FABRICATION_NUMBER, "
SQLString = SQLString & "item_attribute.PANEL_WIDTH, "
SQLString = SQLString & "item_attribute.PANEL_HEIGHT, item_attribute.GLASS_DIM1, item_attribute.GLASS_DIM2, item_attribute.DIMENSION1, item_attribute.DIMENSION2, "
SQLString = SQLString & "item_attribute.DIMENSION3, item_attribute.DIMENSION4, item_Attribute.DIMENSION5 "
SQLString = SQLString & "FROM APPS.MTL_SYSTEM_ITEMS MSI, APPS.BOM_BILL_OF_MATERIALS BOM, APPS.BOM_INVENTORY_COMPONENTS_V BIC, APPS.MTL_SYSTEM_ITEMS MSIL, APPS.mtl_parameters mp, "
SQLString = SQLString & "APPS.MTL_ITEM_CATALOG_GROUPS_VL micg, (SELECT * FROM (SELECT msi.inventory_item_id, mde.element_name, "
SQLString = SQLString & "mdev.element_value "
SQLString = SQLString & "FROM APPS.mtl_parameters mp, APPS.mtl_system_items_b msi, APPS.MTL_ITEM_CATALOG_GROUPS_VL micg, APPS.MTL_DESCRIPTIVE_ELEMENTS mde, APPS.MTL_DESCR_ELEMENT_VALUES mdev "
SQLString = SQLString & "WHERE mp.organization_id = MSI.organization_id AND mp.organization_code = 'POR' "
SQLString = SQLString & "AND micg.ITEM_CATALOG_GROUP_ID = MSI.ITEM_CATALOG_GROUP_ID AND mde.ITEM_CATALOG_GROUP_ID = micg.ITEM_CATALOG_GROUP_ID "
SQLString = SQLString & "AND mdev.element_name = mde.element_name AND mdev.inventory_item_id = msi.inventory_item_id AND mde.element_name IN ('Length', "
SQLString = SQLString & "'Angle Left', 'Angle Right', 'Wt Ht Flag', 'Fabrication Number', 'Panel Width', 'Panel Height', 'Glass Dim 1', 'Glass Dim 2', "
SQLString = SQLString & "'Dimension 1', 'Dimension 2', 'Dimension 3', 'Dimension 4', 'Dimension 5')) PIVOT (MAX (Element_value) FOR (element_name) "
SQLString = SQLString & "IN ('Length' AS ITEM_LENGTH, 'Angle Left' AS ANGLE_LEFT, 'Angle Right' AS ANGLE_RIGHT, 'Wt Ht Flag' AS WT_HT_FLAG, "
SQLString = SQLString & "'Fabrication Number' AS FABRICATION_NUMBER, 'Panel Width' AS PANEL_WIDTH, 'Panel Height' AS PANEL_HEIGHT, 'Glass Dim 1' AS GLASS_DIM1, "
SQLString = SQLString & "'Glass Dim 2' AS GLASS_DIM2, 'Dimension 1' AS DIMENSION1, 'Dimension 2' AS DIMENSION2, 'Dimension 3' AS DIMENSION3, "
SQLString = SQLString & "'Dimension 4' AS DIMENSION4, 'Dimension 5' AS DIMENSION5)) ORDER BY inventory_item_id) Item_attribute WHERE 1 = 1 "
SQLString = SQLString & "AND item_Attribute.inventory_item_id(+) = msil.INVENTORY_ITEM_ID AND BOM.ASSEMBLY_ITEM_ID = MSI.INVENTORY_ITEM_ID "
SQLString = SQLString & "AND BOM.ORGANIZATION_ID = MSI.ORGANIZATION_id AND bom.bill_sequence_id = bic.bill_sequence_id AND NVL (bic.disable_date, SYSDATE) >= SYSDATE "
SQLString = SQLString & "AND BIC.component_ITEM_ID = MSIL.INVENTORY_ITEM_ID AND Bom.ORGANIZATION_ID = MSIL.ORGANIZATION_ID AND mp.organization_id = msi.organization_id "
SQLString = SQLString & "AND mp.organization_code = 'POR' "
SQLString = SQLString & "AND micg.ITEM_CATALOG_GROUP_ID = msi.ITEM_CATALOG_GROUP_ID AND MSI.ORGANIZATION_ID = (SELECT DISTINCT OOL.SHIP_FROM_ORG_ID "
'These two lines are the ones that have our variables
SQLString = SQLString & "FROM APPS.OE_ORDER_HEADERS_ALL OOH, APPS.OE_ORDER_LINES_ALL OOL, APPS.MTL_SYSTEM_ITEMS MSI1 WHERE OOH.ORDER_NUMBER = '" & OracleOrderNumber & "' "
SQLString = SQLString & "AND OOL.LINE_NUMBER = '" & OracleLineNumber & "' "
'----------------------------------------------------
SQLString = SQLString & "AND OOL.HEADER_ID = OOH.HEADER_ID AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID) "
SQLString = SQLString & "CONNECT BY PRIOR BIC.COMPONENT_ITEM_ID = BOM.ASSEMBLY_ITEM_ID START WITH MSI.INVENTORY_ITEM_ID IN (SELECT MSI1.INVENTORY_ITEM_ID "
SQLString = SQLString & "FROM APPS.OE_ORDER_HEADERS_ALL OOH, APPS.OE_ORDER_LINES_ALL OOL, APPS.MTL_SYSTEM_ITEMS MSI1 "
'These two lines are the ones that have our variables...again
SQLString = SQLString & "WHERE OOH.ORDER_NUMBER = '" & OracleOrderNumber & "' "
SQLString = SQLString & "AND OOL.LINE_NUMBER = '" & OracleLineNumber & "' "
'----------------------------------------------------
SQLString = SQLString & "AND OOL.HEADER_ID = OOH.HEADER_ID AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID)"
There original query in it's cleaned up form is here.
SELECT LEVEL,
MSIL.SEGMENT1 ITEM,
MSIL.DESCRIPTION DESC_COMPONENT,
BIC.ITEM_TYPE,
BIC.SUPPLY_TYPE,
MSIL.PRIMARY_UOM_CODE UOM,
BIC.COMPONENT_QUANTITY,
item_attribute.ITEM_LENGTH,
item_attribute.ANGLE_LEFT,
item_attribute.ANGLE_RIGHT,
item_attribute.WT_HT_FLAG,
item_attribute.FABRICATION_NUMBER,
item_attribute.PANEL_WIDTH,
item_attribute.PANEL_HEIGHT,
item_attribute.GLASS_DIM1,
item_attribute.GLASS_DIM2,
item_attribute.DIMENSION1,
item_attribute.DIMENSION2,
item_attribute.DIMENSION3,
item_attribute.DIMENSION4,
item_attribute.DIMENSION5
FROM APPS.MTL_SYSTEM_ITEMS MSI,
APPS.BOM_BILL_OF_MATERIALS BOM,
APPS.BOM_INVENTORY_COMPONENTS_V BIC,
APPS.MTL_SYSTEM_ITEMS MSIL,
APPS.mtl_parameters mp,
APPS.MTL_ITEM_CATALOG_GROUPS_VL micg,
( SELECT *
FROM (SELECT msi.inventory_item_id,
mde.element_name,
mdev.element_value
FROM APPS.mtl_parameters mp,
APPS.mtl_system_items_b msi,
APPS.MTL_ITEM_CATALOG_GROUPS_VL micg,
APPS.MTL_DESCRIPTIVE_ELEMENTS mde,
APPS.MTL_DESCR_ELEMENT_VALUES mdev
WHERE mp.organization_id = msi.organization_id
AND mp.organization_code = 'POR' -- Warehouse -- POR(Portland), ITM (Item Master), TAC (Tacoma), TEM (Temecula), CMP (Composites)
AND micg.ITEM_CATALOG_GROUP_ID =
msi.ITEM_CATALOG_GROUP_ID
AND mde.ITEM_CATALOG_GROUP_ID =
micg.ITEM_CATALOG_GROUP_ID
AND mdev.element_name = mde.element_name
AND mdev.inventory_item_id = msi.inventory_item_id
AND mde.element_name IN ('Length',
'Angle Left',
'Angle Right',
'Wt Ht Flag',
'Fabrication Number',
'Panel Width',
'Panel Height',
'Glass Dim 1',
'Glass Dim 2',
'Dimension 1',
'Dimension 2',
'Dimension 3',
'Dimension 4',
'Dimension 5'))
PIVOT
(MAX (Element_value)
FOR (element_name)
IN ('Length' AS ITEM_LENGTH,
'Angle Left' AS ANGLE_LEFT,
'Angle Right' AS ANGLE_RIGHT,
'Wt Ht Flag' AS WT_HT_FLAG,
'Fabrication Number' AS FABRICATION_NUMBER,
'Panel Width' AS PANEL_WIDTH,
'Panel Height' AS PANEL_HEIGHT,
'Glass Dim 1' AS GLASS_DIM1,
'Glass Dim 2' AS GLASS_DIM2,
'Dimension 1' AS DIMENSION1,
'Dimension 2' AS DIMENSION2,
'Dimension 3' AS DIMENSION3,
'Dimension 4' AS DIMENSION4,
'Dimension 5' AS DIMENSION5))
ORDER BY inventory_item_id) Item_attribute
WHERE 1 = 1
AND item_Attribute.inventory_item_id(+) = msil.INVENTORY_ITEM_ID
AND BOM.ASSEMBLY_ITEM_ID = MSI.INVENTORY_ITEM_ID
AND BOM.ORGANIZATION_ID = MSI.ORGANIZATION_id
AND bom.bill_sequence_id = bic.bill_sequence_id
AND NVL (bic.disable_date, SYSDATE) >= SYSDATE
AND BIC.component_ITEM_ID = MSIL.INVENTORY_ITEM_ID
AND Bom.ORGANIZATION_ID = MSIL.ORGANIZATION_ID
AND mp.organization_id = msi.organization_id
AND mp.organization_code = 'POR' -- Warehouse -- POR(Portland), ITM (Item Master), TAC (Tacoma), TEM (Temecula), CMP (Composites)
AND micg.ITEM_CATALOG_GROUP_ID = msi.ITEM_CATALOG_GROUP_ID
AND MSI.ORGANIZATION_ID =
(SELECT DISTINCT OOL.SHIP_FROM_ORG_ID
FROM APPS.OE_ORDER_HEADERS_ALL OOH,
APPS.OE_ORDER_LINES_ALL OOL,
APPS.MTL_SYSTEM_ITEMS MSI1
WHERE OOH.ORDER_NUMBER = '1483' --Oracle Sales Order Number
AND OOL.LINE_NUMBER = '1' -- Oracle Sales Order Line Number
AND OOL.HEADER_ID = OOH.HEADER_ID
AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM
--AND OOL.ORDERED_ITEM LIKE '%*%'
AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID)
CONNECT BY PRIOR BIC.COMPONENT_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
START WITH MSI.INVENTORY_ITEM_ID IN
(SELECT MSI1.INVENTORY_ITEM_ID
FROM APPS.OE_ORDER_HEADERS_ALL OOH,
APPS.OE_ORDER_LINES_ALL OOL,
APPS.MTL_SYSTEM_ITEMS MSI1
WHERE OOH.ORDER_NUMBER = '1483' --Oracle Sales Order Number
AND OOL.LINE_NUMBER = '1' -- Oracle Sales Order Line Number
AND OOL.HEADER_ID = OOH.HEADER_ID
AND MSI1.SEGMENT1 = OOL.ORDERED_ITEM
--AND OOL.ORDERED_ITEM like '%*%'
AND MSI1.ORGANIZATION_ID = OOL.SHIP_FROM_ORG_ID)
And thoughts would be fantastic, I have tired multiple drivers and installs of Oracle, connection does not seem to be my issue, it is how the query is executed.
As asked for here is my connection code...
Private Const ConnectionString = "Driver={Microsoft ODBC for Oracle}; CONNECTSTRING=string; uid=APPSRO; pwd=APPSRO;"
' ADO Connection Global Variable - Declared here so that, once the connection is opened, it can be used by any part of the code'
Public ADOConn As Object
Private OracleOrder As ADODB.Recordset
Private Const AppName = "Oracle BOM Data"
Private Const Version = "v1.0.0"
Public Const BoxTitle = AppName & " " & Version
Public Function ADOOpen(ByRef ADOConn As Object) As Boolean
' Open the ADO connection to the database and link it to the Object we've been passed'
' Handle errors here'
On Error Resume Next
' Clear the Error table'
Err.Clear
' Create a new connection and link it to the Object passed in'
Set ADOConn = CreateObject("ADODB.Connection")
' Now open the ADO connection to the database'
ADOConn.Open ConnectionString
'ADOConn.Properties("PLSQLRSet") = True'
' Now check for errors. Err.Number will be zero if there's been no error' since we cleared the Error table
If Err.Number = 0 Then
' So if there's been no error, return true'
ADOOpen = True
Else
' Otherwise, return false'
ADOOpen = False
End If
End Function
Ok, here is the actual function using the connections we know work...
Public Function LoadOracleOrder(OracleOrderNumber As Double, OracleLineNumber As Double)
Dim SQLString As String
Dim TargetSheet As Worksheet
Dim TargetCell As Range
Dim SQLQuery As String
On Error Resume Next
SQLString = "MONSTROUS QUERY HERE"
Debug.Print SQLString
Set OracleOrder = ADOFetch(SQLQuery, ADOConn)
If Err.Number <> 0 Then
WarnMsgBox "Warning: Query failed." & Chr(10) & "Error No: " & Err.Number & Chr(10) & "Error Description: " & Err.Description, BoxTitle
Err.Clear
ElseIf OracleOrder.RecordCount = 0 Then
InfoMsgBox "Query Returned No Results.", BoxTitle
Else
Set TargetSheet = Nothing
Set TargetSheet = ThisWorkbook.Sheets("Oracle Order Data")
If TargetSheet Is Nothing Then
Set TargetSheet = ThisWorkbook.Sheets.Add
TargetSheet.Name = "Oracle Order Data"
End If
TargetSheet.Cells.ClearContents
TargetSheet.Range("A1") = "LEVEL"
TargetSheet.Range("B1") = "ITEM"
TargetSheet.Range("C1") = "DESC_COMPONENT"
TargetSheet.Range("D1") = "ITEM_TYPE"
TargetSheet.Range("E1") = "SUPPLY_TYPE"
TargetSheet.Range("F1") = "UOM"
TargetSheet.Range("G1") = "COMPONENT_QUANTITY"
TargetSheet.Range("H1") = "ITEM_LENGTH"
TargetSheet.Range("I1") = "ANGLE_LEFT"
TargetSheet.Range("J1") = "ANGLE_RIGHT"
TargetSheet.Range("K1") = "WT_HT_FLAG"
TargetSheet.Range("L1") = "FABRICATION_NUMBER"
TargetSheet.Range("M1") = "GLASS_DIM1"
TargetSheet.Range("N1") = "GLASS_DIM2"
TargetSheet.Range("O1") = "DIMENSION1"
TargetSheet.Range("P1") = "DIMENSION2"
TargetSheet.Range("Q1") = "DIMENSION3"
TargetSheet.Range("R1") = "DIMENSION4"
TargetSheet.Range("S1") = "DIMENSION5"
Set TargetCell = TargetSheet.Range("A2")
OracleOrder.MoveFirst
While Not OracleOrder.EOF
TargetCell.Value = OracleOrder.Fields(0).Value
TargetCell.Offset(0, 1).Value = OracleOrder.Fields(1).Value
TargetCell.Offset(0, 2).Value = OracleOrder.Fields(2).Value
TargetCell.Offset(0, 3).Value = OracleOrder.Fields(3).Value
TargetCell.Offset(0, 4).Value = OracleOrder.Fields(4).Value
TargetCell.Offset(0, 5).Value = OracleOrder.Fields(5).Value
TargetCell.Offset(0, 6).Value = OracleOrder.Fields(6).Value
TargetCell.Offset(0, 7).Value = OracleOrder.Fields(7).Value
TargetCell.Offset(0, 8).Value = OracleOrder.Fields(8).Value
TargetCell.Offset(0, 9).Value = OracleOrder.Fields(9).Value
TargetCell.Offset(0, 10).Value = OracleOrder.Fields(10).Value
TargetCell.Offset(0, 11).Value = OracleOrder.Fields(11).Value
TargetCell.Offset(0, 12).Value = OracleOrder.Fields(12).Value
TargetCell.Offset(0, 13).Value = OracleOrder.Fields(13).Value
TargetCell.Offset(0, 14).Value = OracleOrder.Fields(14).Value
TargetCell.Offset(0, 15).Value = OracleOrder.Fields(15).Value
TargetCell.Offset(0, 16).Value = OracleOrder.Fields(16).Value
TargetCell.Offset(0, 17).Value = OracleOrder.Fields(17).Value
TargetCell.Offset(0, 18).Value = OracleOrder.Fields(18).Value
TargetCell.Offset(0, 19).Value = OracleOrder.Fields(19).Value
Set TargetCell = TargetCell.Offset(1, 0)
OracleOrder.MoveNext
Wend
End If
On Error GoTo 0
End Function
ADO Fetch, as asked...
Public Function ADOFetch(SQLQuery As String, ByRef ADOConn As Object) As Object
' Takes an existing, open ADO connection and uses it to return a Recordset, Nothing if no data is returned, or False if there's an error
' Local Object for the Recordset
Dim ADORecSet As Object
' Handle errors internally
On Error Resume Next
' Clear the Error table
Err.Clear
' Set up the Recordset by executing the SQL query
Set ADORecSet = ADOConn.ExecuteSQL(SQLQuery)
' Now check for errors. Err.Number will be zero if there's been no error since we cleared the Error table
If Err.Number = 0 Then
' So if there's been no error, return the record set
Set ADOFetch = ADORecSet
End If
' And either way, clear our temporary Recordset
ADORecSet = Nothing
On Error GoTo 0
End Function