0

I have a large 115 line SQL code that I have been tasked to put into Excel and allow the user with two cells to change the date range of the SQL code and show the results. I have tried several of the other topics with no luck. I am using Microsoft 365. Each user has a ODBC connection on their PC named "Reports55" In excel I have two tabs (Summary) and (SQLData). on the (Summary) tab Cell A2 is the 1StartDate and Cell B2 is the 2EndDate. The (SQLDate) tab is where the SQL Query data will be shown. Any help will be greatly appreciated.

Skill level

  • VBA: Beginner (Please dumb it down for this old guy)
  • SQL: Intermediate
  • Excel: Intermediate
DECLARE @1StartDate AS DATE
DECLARE @2EndDate AS DATE
SET @1StartDate = '2020-04-27'
SET @2EndDate = '2021-05-27'

SELECT 
    'SHIP' AS RPT ,
    SO_Detail_Ext.LateReason ,
    (SO_Detail.ordnum_28 + SO_Detail.linnum_28 + SO_Detail.delnum_28) AS "Order",   
    SO_Detail.custid_28 AS "CustID",
    SO_Detail.Prtnum_28 AS "Part",
    CONVERT(VARCHAR(10), SO_Master.ORDDTE_27, 101) AS "OrdDte",
    CONVERT(VARCHAR(10), SO_Detail.Shpdte_28, 101) AS "Shpdte",
    ExactMAX.dbo.NumShopDays(SO_Master.ORDDTE_27,SO_Detail.shpdte_28) AS "LT_ToShip",
    CONVERT(VARCHAR(10), SO_Detail.ORGDUE_28, 101) AS "OrgDue" ,
    CONVERT(VARCHAR(10), SO_Detail.Curdue_28, 101) AS "Curdue_PDSL",
    CONVERT(VARCHAR(10), SO_Detail.CUSDUE_28, 101) AS "Custdue_RDSL",
    SO_Detail.Price_28 AS "Price",
    SO_Detail.Shpqty_28 AS "ShpQty",
    Customer_Master.udfkey_23 AS "UDFKey",
    Customer_Master.Slster_23 AS "Territory",
    Account_Types.DESCRPTN_104 AS "AccType",
    Customer_Master.SLSTER_23 AS "WordArea" , --'Undefined World Area'
    Customer_Master_Ext.CustomerClass ,
    (SO_Detail.Price_28 * SO_Detail.Shpqty_28) AS "Extended", 
    CAST('1' AS INTEGER) AS "Shipped",
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.Curdue_28  THEN 1 ELSE 0 END AS "PDSL_OnTime", 
    CASE 
    WHEN SO_Detail_Ext.LateReason = 'SSI' THEN '1' --Customer caused late order
    WHEN SO_Detail.shpdte_28 <= SO_Detail.Cusdue_28  THEN 1 ELSE 0 END AS "RDSL_OnTime", 
    CASE WHEN Customer_Master_Ext.CustomerClass = 'TRADE' 
    THEN 1 ELSE 0 END AS "Trade_Shipped", --01 Total Trade Lines Shipped
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.Curdue_28
    AND Customer_Master_Ext.CustomerClass = 'TRADE' THEN 1 ELSE 0 END AS "Trade_Ontime_PDSL",
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.CUSDUE_28 
    AND Customer_Master_Ext.CustomerClass = 'TRADE' THEN 1 ELSE 0 END AS "Trade_Ontime_RDSL",
    CASE WHEN Customer_Master_Ext.CustomerClass = 'TRADE'
    AND isnull(Part_Master_Ext.ExpressShip, 0) = '1' THEN 1 ELSE 0 END AS "Trade_Exp_Shipped", 
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.CUSDUE_28 
    AND Customer_Master_Ext.CustomerClass = 'TRADE'
    AND isnull(Part_Master_Ext.ExpressShip, 0) = '1' THEN 1 ELSE 0 END AS "Trade_EXP_Ontime_RDSL", 
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.Curdue_28 
    AND Customer_Master_Ext.CustomerClass = 'TRADE'
    AND isnull(Part_Master_Ext.ExpressShip, 0) = '1' THEN 1 ELSE 0 END AS "Trade_EXP_Ontime_PDSL", 
    CASE WHEN Customer_Master_Ext.CustomerClass = 'TRADE'
    AND isnull(Part_Master_Ext.ExpressShip, 0) <> '1' THEN 1 ELSE 0 END AS "Trade_MTO_Shipped", 
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.CUSDUE_28 
    AND Customer_Master_Ext.CustomerClass = 'TRADE'
    AND isnull(Part_Master_Ext.ExpressShip, 0) <> '1' THEN 1 ELSE 0 END AS "Trade_MTO_Ontime_RDSL", 
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.Curdue_28 
    AND Customer_Master_Ext.CustomerClass = 'TRADE'
    AND isnull(Part_Master_Ext.ExpressShip, 0) <> '1' THEN 1 ELSE 0 END AS "Trade_MTO_Ontime_PDSL", 
    CASE WHEN Customer_Master_Ext.CustomerClass IN ('INTERCO', 'INTRA-CO') 
    THEN 1 ELSE 0 END AS "Intraco_Shipped", -- 03 Intraco Lines Shipped
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.Curdue_28 
    AND Customer_Master_Ext.CustomerClass IN ('INTERCO', 'INTRA-CO') 
    THEN 1 ELSE 0 END AS "Intraco_OnTime_PDSL",
    CASE 
    WHEN SO_Detail_Ext.LateReason = 'SSI' AND Customer_Master_Ext.CustomerClass IN ('INTERCO', 'INTRA-CO') THEN '1' --Customer caused late order
    WHEN SO_Detail.Shpdte_28 <= SO_Detail.CUSDUE_28 
    AND Customer_Master_Ext.CustomerClass IN ('INTERCO', 'INTRA-CO')
    THEN 1 ELSE 0 END AS "Intraco_Ontime_RDSL",
    CASE WHEN isnull(Part_Master_Ext.ExpressShip, 0) = '1'
    THEN 1 ELSE 0 END AS "EXP_Shipped",
    CASE WHEN SO_Detail.Shpdte_28 <= SO_Detail.CURDUE_28 
    AND isnull(Part_Master_Ext.ExpressShip, 0) = '1' THEN 1 ELSE 0 END AS "EXP_Ontime_PDSL",
    CASE 
    WHEN SO_Detail_Ext.LateReason = 'SSI' AND isnull(Part_Master_Ext.ExpressShip, 0) = '1' THEN '1'
    WHEN SO_Detail.Shpdte_28 <= SO_Detail.CUSDUE_28 
    AND isnull(Part_Master_Ext.ExpressShip, 0) = '1' THEN 1 ELSE 0 END AS "EXP_Ontime_RDSL" ,
ExactMAX.dbo.NumShopDays(SO_Master.ORDDTE_27,SO_Detail.shpdte_28) AS "AVG_LT_Days" ,
ExactMAX.dbo.NumShopDays(SO_Master.ORDDTE_27,SO_Detail.Cusdue_28) AS "RDSL_AVG_LT_Days" ,
ExactMAX.dbo.NumShopDays(SO_Master.ORDDTE_27,SO_Detail.Curdue_28) AS "PDSL_AVG_LT_Days" ,
CASE WHEN Customer_Master_Ext.CustomerClass = 'TRADE'
AND isnull(Part_Master_Ext.ExpressShip, 0) <> '1' 
THEN ExactMAX.dbo.NumShopDays(SO_Master.ORDDTE_27,SO_Detail.shpdte_28) 
ELSE NULL END AS "Trade_MTO_AVGLT" ,  
CASE WHEN Customer_Master_Ext.CustomerClass IN ('INTERCO', 'INTRA-CO')
THEN ExactMAX.dbo.NumShopDays(SO_Master.ORDDTE_27,SO_Detail.shpdte_28) 
ELSE NULL END AS "Intraco_AVG_LT" , 
CAST('0' AS FLOAT) AS "Trade_Backlog_PDSL" , --09 Trade $$ Past Due Backlog by PDSL
CAST('0' AS FLOAT) AS "Trade_Backlog_RDSL" ,  --10 Trade $$ Past Due Backlog by RDSL
CASE WHEN Customer_Master_Ext.CustomerClass = 'TRADE'
THEN (SO_Detail.Price_28 * SO_Detail.Shpqty_28)
ELSE NULL
END AS "Trade_Sales$$" ,
NULL AS "Total_PastDue_Dollars_RDSL" , 
NULL AS "Total_PastDue_Lines_RDSL" , 
NULL AS "Total_PastDue_Dollars_PDSL" , 
NULL AS "Total_PastDue_Lines_PDSL" ,  
SO_Detail.CreatedBy ,
SO_Detail.CreationDate ,
Part_Sales.CRTLTO_29
    
FROM 
    ExactMAX.dbo.SO_Detail LEFT JOIN
    ExactMAX.dbo.Part_Sales ON
    SO_Detail.PRTNUM_28 = Part_Sales.PRTNUM_29 LEFT JOIN
    ExactMAX.dbo.SO_Master ON
    SO_Detail.ORDNUM_28=SO_Master.ORDNUM_27 LEFT JOIN 
    ExactMAX.dbo.part_Master ON 
    SO_Detail.prtnum_28 = part_master.prtnum_01 LEFT JOIN
    ExactMAX.dbo.Account_Types ON
    Part_Master.ACTTYP_01=Account_Types.ACTTYP_104 LEFT JOIN 
    ExactMAX.dbo.CUSTOMER_MASTER ON 
    SO_Detail.CUSTID_28 = CUSTOMER_MASTER.CUSTID_23 LEFT JOIN
    ExactMAX.dbo.Part_Master_Ext ON
    SO_Detail.prtnum_28 = part_master_ext.prtnum_01 LEFT JOIN
    ExactMAX.dbo.Customer_Master_Ext ON
    Customer_Master.CUSTID_23 = Customer_Master_Ext.CUSTID_23 LEFT JOIN
    ExactMAX.dbo.SO_Detail_Ext ON
    SO_Detail_ext.ORDER_LIN_DEL = (SO_Detail.ORDNUM_28 + SO_Detail.LINNUM_28 + SO_Detail.DELNUM_28)

WHERE
    SO_Detail.Shpdte_28 BETWEEN @1StartDate AND @2EndDate
    AND SO_Detail.Status_28 IN ('4', '5') 
    AND Part_Master.Acttyp_01 <> '' 
    AND Part_Master.TYPE_01 IN ('A', 'C', 'P', 'S', 'X')
1
  • This article should get you there. Commented May 19, 2021 at 20:35

1 Answer 1

1

Consider the following steps for parameterized querying:

SQL

  1. Keep your long, intricate SQL in an .sql text file. Format with line breaks and indentation any way you need. Keep in same folder as workbook or centralized location for all users to read in VBA.

  2. Remove DECLARE and SET lines, keeping only the single SELECT command.

  3. In SELECT query replace every @ variable with qmarks ? for parameterization in VBA.

    WHERE
        SO_Detail.Shpdte_28 BETWEEN ? AND ?
    

VBA

  1. Start a VBA Sub subroutine in Workbooks module or standalone module.

  2. Set up an ADO ODBC connection to your database. Many online examples and tutorials.

  3. Read in SQL query into a string variable:

    ' READ SQL QUERY FROM FILE INTO STRING
    With CreateObject("Scripting.FileSystemObject")
          strSQL = .OpenTextFile("C:\path\to\my\SQL\Query.sql", 1).readall
    End With
    
  4. Open an ADO Command object using connection object and query. Create and bind the two date parameters from wherever cells they are located in workbook. Then execute command to render an ADO recordset.

    ' DEFINE COMMAND OBJECT
    
    Set cmd = New ADODB.Command
    With cmd
        .ActiveConnection = conn   ' CONNECTION OBJECT
        .CommandType = adCmdText
        .CommandText = strSQL      ' SQL QUERY
    
        ' BIND DATE PARAMETERS FOR ? IN SQL, ASSUMING startDate AND endDate ARE VBA DATES
        .Parameters.Append .CreateParameter("dtparam1", adDate, adParamInput, , startDate)
        .Parameters.Append .CreateParameter("dtparam2", adDate, adParamInput, , endDate)
    
        ' BIND OUTPUT TO RECORDSET
        Set rs = .Execute
    End With
    
  5. Use Range.CopyFromRecordset to output recordset to sheet starting at left most column. Do note: columns do not populate. Loop through recordset Fields for such column names.

    ThisWorkbook.Worksheets("SQLData").Range("A2").CopyFromRecordset rs
    

(In entire VBA code, be sure to specify Dim variables with Option Explicit at very top and incorporate proper error handling that closes recordset and connection and release ASO resources by setting objects to Nothing with or without runtime errors.)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.