繁体   English   中英

通过 Excel 数据“日期范围”到 SQL 查询

[英]Pass Excel Data "Date Range" to SQL Query

我有一个大的 115 行 SQL 代码,我的任务是放入 Excel 并允许具有两个单元格的用户更改 Z9778840A0100CB30C9822876741B05B 代码的日期范围我已经尝试了其他几个主题,但没有成功。 我正在使用 Microsoft 365。每个用户在其 PC 上都有一个名为“Reports55”的 ODBC 连接。在 excel 中,我有两个选项卡(摘要)和(SQLData)。 在(摘要)选项卡上,单元格 A2 是 1StartDate,单元格 B2 是 2EndDate。 (SQLDate) 选项卡将显示 SQL 查询数据。 任何帮助将不胜感激。

技能等级

  • VBA:初学者(请给这个老家伙哑巴)
  • SQL:中级
  • Excel:中级
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')

考虑参数化查询的以下步骤:

SQL

  1. 将长而复杂的 SQL 保存在.sql文本文件中。 以您需要的任何方式使用换行符和缩进进行格式化。 保存在与工作簿相同的文件夹或集中位置,供所有用户在 VBA 中阅读。

  2. 删除DECLARESET行,仅保留单个SELECT命令。

  3. SELECT查询中用 qmarks 替换每个@变量? 用于 VBA 中的参数化。

     WHERE SO_Detail.Shpdte_28 BETWEEN? AND?

VBA

  1. 在 Workbooks 模块或独立模块中启动 VBA Sub例程。

  2. 设置与数据库的 ADO ODBC 连接。 许多在线示例和教程。

  3. 将 SQL 查询读入字符串变量:

     ' 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. 使用连接 object 打开 ADO 命令 object 并查询。 从它们位于工作簿中的任何单元格创建并绑定两个日期参数。 然后执行命令来呈现一个 ADO 记录集。

     ' 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. 使用Range.CopyFromRecordset到 output 记录集到从最左侧列开始的工作表。 请注意:不填充列。 循环遍历此类列名的记录集Fields

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

(在整个 VBA 代码中,请务必在最顶部使用Option Explicit指定Dim变量,并结合适当的错误处理,通过将对象设置为Nothing (有或没有运行时错误)来关闭记录集和连接并释放 ASO 资源。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM