[英]Pass Excel Data "Date Range" to SQL Query
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.我有一个大的 115 行 SQL 代码,我的任务是放入 Excel 并允许具有两个单元格的用户更改 Z9778840A0100CB30C9822876741B05B 代码的日期范围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).
我正在使用 Microsoft 365。每个用户在其 PC 上都有一个名为“Reports55”的 ODBC 连接。在 excel 中,我有两个选项卡(摘要)和(SQLData)。 on the (Summary) tab Cell A2 is the 1StartDate and Cell B2 is the 2EndDate.
在(摘要)选项卡上,单元格 A2 是 1StartDate,单元格 B2 是 2EndDate。 The (SQLDate) tab is where the SQL Query data will be shown.
(SQLDate) 选项卡将显示 SQL 查询数据。 Any help will be greatly appreciated.
任何帮助将不胜感激。
Skill level技能等级
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')
Consider the following steps for parameterized querying:考虑参数化查询的以下步骤:
SQL SQL
Keep your long, intricate SQL in an .sql
text file.将长而复杂的 SQL 保存在
.sql
文本文件中。 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.
保存在与工作簿相同的文件夹或集中位置,供所有用户在 VBA 中阅读。
Remove DECLARE
and SET
lines, keeping only the single SELECT
command.删除
DECLARE
和SET
行,仅保留单个SELECT
命令。
In SELECT
query replace every @
variable with qmarks ?
在
SELECT
查询中用 qmarks 替换每个@
变量?
for parameterization in VBA.用于 VBA 中的参数化。
WHERE SO_Detail.Shpdte_28 BETWEEN? AND?
VBA VBA
Start a VBA Sub
subroutine in Workbooks module or standalone module.在 Workbooks 模块或独立模块中启动 VBA
Sub
例程。
Set up an ADO ODBC connection to your database.设置与数据库的 ADO ODBC 连接。 Many online examples and tutorials.
许多在线示例和教程。
Read in SQL query into a string variable:将 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
Open an ADO Command object using connection object and query.使用连接 object 打开 ADO 命令 object 并查询。 Create and bind the two date parameters from wherever cells they are located in workbook.
从它们位于工作簿中的任何单元格创建并绑定两个日期参数。 Then execute command to render an ADO recordset.
然后执行命令来呈现一个 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
Use Range.CopyFromRecordset to output recordset to sheet starting at left most column.使用Range.CopyFromRecordset到 output 记录集到从最左侧列开始的工作表。 Do note: columns do not populate.
请注意:不填充列。 Loop through recordset
Fields
for such column names.循环遍历此类列名的记录集
Fields
。
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.) (在整个 VBA 代码中,请务必在最顶部使用
Option Explicit
指定Dim
变量,并结合适当的错误处理,通过将对象设置为Nothing
(有或没有运行时错误)来关闭记录集和连接并释放 ASO 资源。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.