VBA基于用户输入以全局方式更改查询SQL

VBA基于用户输入以全局方式更改查询SQL,vba,ms-access,Vba,Ms Access,我正在尝试创建一个宏,该宏基于用户输入(在excel工作表上),将从我在Access中进行的查询中提取数据。为了只提取适用的数据行,它需要相应地编辑WHERE语句。我已经根据前面的问题改编了以下代码,但在尝试替换SQL时遇到了问题 Private Sub CommandButton4_Click() Const DbLoc As String = "MYfilepath" Dim db As DAO.Database Dim rs As DAO.Recordset Dim wb1 As Work

我正在尝试创建一个宏,该宏基于用户输入(在excel工作表上),将从我在Access中进行的查询中提取数据。为了只提取适用的数据行,它需要相应地编辑WHERE语句。我已经根据前面的问题改编了以下代码,但在尝试替换SQL时遇到了问题

Private Sub CommandButton4_Click()
Const DbLoc As String = "MYfilepath"
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim wb1 As Workbook, ws1 As Worksheet, ws2 As Worksheet, SQL As String, recCount As Long
Set wb1 = Workbooks("mytool.xlsm")
Set ws1 = wb1.Sheets("Inputs")
Set ws2 = wb1.Sheets("raw")
Set db = OpenDatabase(DbLoc)
Set userinput = ws1.Range("D6")


SQL = "SELECT Dock_Rec_Problems.Merch_Name, Dock_Rec_Problems.Vendor_Error_Code, Dock_Rec_Problems.DC, Dock_Rec_Problems.Vendor_ID_IP, Dock_Rec_Problems.Vendor_Name, Dock_Rec_Problems.PO_Number, Dock_Rec_Problems.SKU_No, Dock_Rec_Problems.Item_Description, Dock_Rec_Problems.Casepack, Dock_Rec_Problems.Retail, Dock_Rec_Problems.Num_Of_Cases, Dock_Rec_Problems.Dock_Rec_Problems_DGID"
SQL = SQL & "FROM Dock_Rec_Problems;"
SQL = SQL & "WHERE [Dock_Rec_Problems_DGID] =" & userinput

Set rs = db.OpenRecordset(SQL, dbOpenSnapshot)
If rs.RecordCount = 0 Then
    MsgBox "Not found in database", vbInformation + vbOKOnly, "No Data"
    GoTo SubExit
End If

ws2.Range("A1").CopyFromRecordset rs

SubExit:
On Error Resume Next
    Application.Cursor = xlDefault
    rs.Close
    Set rs = Nothing
Exit Sub

End Sub
如果有什么我可以澄清的,请告诉我…谢谢

原始查询SQL

SELECT Dock_Rec_Problems.Merch_Name, Dock_Rec_Problems.Vendor_Error_Code, 
Dock_Rec_Problems.DC, Dock_Rec_Problems.Vendor_ID_IP, 
Dock_Rec_Problems.Vendor_Name, Dock_Rec_Problems.PO_Number, 
Dock_Rec_Problems.SKU_No, Dock_Rec_Problems.Item_Description, 
Dock_Rec_Problems.Casepack, Dock_Rec_Problems.Retail, 
Dock_Rec_Problems.Num_Of_Cases, Dock_Rec_Problems.Dock_Rec_Problems_DGID
FROM Dock_Rec_Problems;
单输入SQL

SELECT Dock_Rec_Problems.Merch_Name, Dock_Rec_Problems.Vendor_Error_Code, Dock_Rec_Problems.DC, Dock_Rec_Problems.Vendor_ID_IP, Dock_Rec_Problems.Vendor_Name, Dock_Rec_Problems.PO_Number, Dock_Rec_Problems.SKU_No, Dock_Rec_Problems.Item_Description, Dock_Rec_Problems.Casepack, Dock_Rec_Problems.Retail, Dock_Rec_Problems.Num_Of_Cases, Dock_Rec_Problems.Dock_Rec_Problems_DGID
FROM Dock_Rec_Problems
WHERE (((Dock_Rec_Problems.Dock_Rec_Problems_DGID)="D040323000"));
SELECT Dock_Rec_Problems.Merch_Name, Dock_Rec_Problems.Vendor_Error_Code, Dock_Rec_Problems.DC, Dock_Rec_Problems.Vendor_ID_IP, Dock_Rec_Problems.Vendor_Name, Dock_Rec_Problems.PO_Number, Dock_Rec_Problems.SKU_No, Dock_Rec_Problems.Item_Description, Dock_Rec_Problems.Casepack, Dock_Rec_Problems.Retail, Dock_Rec_Problems.Num_Of_Cases, Dock_Rec_Problems.Dock_Rec_Problems_DGID
FROM Dock_Rec_Problems
WHERE (((Dock_Rec_Problems.Dock_Rec_Problems_DGID)="D040323000")) OR (((Dock_Rec_Problems.Dock_Rec_Problems_DGID)="D040323012"));
双输入SQL

SELECT Dock_Rec_Problems.Merch_Name, Dock_Rec_Problems.Vendor_Error_Code, Dock_Rec_Problems.DC, Dock_Rec_Problems.Vendor_ID_IP, Dock_Rec_Problems.Vendor_Name, Dock_Rec_Problems.PO_Number, Dock_Rec_Problems.SKU_No, Dock_Rec_Problems.Item_Description, Dock_Rec_Problems.Casepack, Dock_Rec_Problems.Retail, Dock_Rec_Problems.Num_Of_Cases, Dock_Rec_Problems.Dock_Rec_Problems_DGID
FROM Dock_Rec_Problems
WHERE (((Dock_Rec_Problems.Dock_Rec_Problems_DGID)="D040323000"));
SELECT Dock_Rec_Problems.Merch_Name, Dock_Rec_Problems.Vendor_Error_Code, Dock_Rec_Problems.DC, Dock_Rec_Problems.Vendor_ID_IP, Dock_Rec_Problems.Vendor_Name, Dock_Rec_Problems.PO_Number, Dock_Rec_Problems.SKU_No, Dock_Rec_Problems.Item_Description, Dock_Rec_Problems.Casepack, Dock_Rec_Problems.Retail, Dock_Rec_Problems.Num_Of_Cases, Dock_Rec_Problems.Dock_Rec_Problems_DGID
FROM Dock_Rec_Problems
WHERE (((Dock_Rec_Problems.Dock_Rec_Problems_DGID)="D040323000")) OR (((Dock_Rec_Problems.Dock_Rec_Problems_DGID)="D040323012"));

您显示的代码有一些问题。例如,在将strNewFields变量设置为任何值之前,尝试在此处使用该变量:

strNewSQL = strNewSQL & Replace(WHERE_FIELDS, "<INSERT FIELDS>", strNewFields)
  • 现在您已经填充了strNewFields,只需运行replace()即可

    Replace(其中_字段,”,strNewFields)
    
  • 您需要查看设置变量的顺序,尽管如上所述,您已经有了一些事件顺序问题


    米迦勒

    < P>,因为您的用户输入的大小是开放式的,请考虑使用具有精确结构的MS访问中保存的临时表作为查询(可以用“MyQualue/Cuth>中的代码> >选择*进入TimeSt表”。然后,每次调用Excel宏时:

  • DELETE
    清除临时表
  • 使用
    插入到…选择
    遍历用户输入Excel单元格范围,将所需行追加到表中
  • 从临时表创建记录集
  • 再一次,这里是SQL参数化的主要用例,特别是因为查询接收用户输入。聪明、恶意的用户可能会清除您的数据库!但至少,代码可以说更易于维护。因为您正在使用DAO,请考虑将参数值绑定到已准备好的、保存的查询,然后绑定到记录集。

    SQL(另存为MS Access存储的操作查询)

    参数[userparam]文本(255);
    插入Excel表格(商品名称、供应商错误代码、DC、供应商ID、IP、,
    供应商名称、采购订单编号、SKU编号、项目描述、,
    箱包、零售、箱包数量、码头记录问题(ID)
    选择d.Merch\u名称、d.Vendor\u错误代码、d.DC、d.Vendor\u ID\u IP、,
    d、 供应商名称、d.PO编号、d.SKU编号、d.Item描述、,
    d、 箱子包装、d.零售、d.箱子数量、d.码头记录问题
    从Dock_Rec_d
    其中d.[Dock_Rec_Problems_DGID]=[userparam];
    
    VBA

    ...
    Dim qdef As DAO.QueryDef
    Dim cel As Range
    
    Set qdef = db.QueryDefs("mySavedQuery")
    
    ' CLEAN OUT TEMP EXCEL TABLE
    db.Execute "DELETE FROM Excel_Table"
    
    ' ITERATIVELY APPEND TO EXCEL TABLES
    For Each cel In userinput.Cells
        qdef!userparam = cel.Value            ' BIND PARAM
        qdef.Execute dbFailOnError            ' EXECUTE ACTION
    Next cel
    
    ' OPEN RECORDSET TO TABLE
    Set rs = db.OpenRecordset("Excel_Table", dbOpenSnapshot)
    
    If rs.RecordCount = 0 Then
        MsgBox "Recieving problem not found in database", vbInformation+vbOKOnly, "No Data"
        GoTo SubExit
    End If
    
    ws2.Range("A1").CopyFromRecordset rs
    .......
    

    你能更清楚地解释问题是什么吗?您期望发生什么,实际发生了什么?是的,因此我得到的错误在我的“替换SQL注释”下面的一行。如果用户将D040323000放入单元格并运行“我的宏”,则应仅将一行数据拉回到工作表中。如果用户输入了D040323000,D040323012,它应该返回两行。这不应该是([逗号分隔值])中[column]所在的
    ?另外,。因此,我添加了在access中手动编辑SQL时SQL的外观,但是否有一种方法可以让VBA根据用户的实际输入为我执行此操作?谢谢,你最多能有多少选择?10?OP还必须从处理第二部分的
    BASIC_字段中删除
    strNewFields
    和相关的replace。。。currentdb.mydataset。这是对Access DB的整体引用还是对特定表名的引用?@Mnathan:好的,那么currendb.mydataset部分引用的是输入表,用户可以在其中说出他们要查找的索引,这只是一个示例,因为我不知道您在使用什么。它可能看起来更像:set rs=currentdb.OpenRecordset(italic\u yourdatatablename\u italic,dbOpenDynaset)。很抱歉,由于某些原因,我的格式在这个问题上无法正常工作。好的,谢谢!因此,用户输入位于工作表上。所以像set rs=ws1.Range(“D6”)这样的东西?当存在分隔符时,我可能还需要在某个位置使用拆分操作,但目前我只是想让它使用单个输入。@我将代码更改为我认为更容易解决的特殊情况。这也可能更容易告诉我要完成什么。我仍然有相同的最终目标,但你怎么看?我现在遇到的错误是我的行集rs=db.openrecordset(SQL,dbOpenSnapshot)非常感谢您的帮助!谢谢你的回答。我在正确保存操作查询时遇到了一些问题(Access非常糟糕)。你介意陪我走过吗?当我尝试运行您的SQL时,一个消息框显示“在SQL语句结束后找到字符。哇!我不小心用了一个过早的分号。我把它拿走了。现在将SQL保存在MS Access的查询设计中(SQL模式)。确保事先已创建Excel_表。在set qdef=db.querydefs(“myquery”)行上获取应用程序定义的错误。其他保存的查询可以工作,但我们出于某种原因保存的操作查询会出现此错误。。。有什么想法吗?MS Access不允许您保存带有语法错误的查询。是否确定数据库已完全保存名为myquery的查询对象?我假设
    db
    是一个
    DAO.Database
    。它实际上被命名为“RAG\u query”,并且正确地保存在数据库中。需要注意的是。。。当我尝试运行操作查询(RAG_query)并手动输入userparam时,它会显示“INSERT-INTO语句包含以下未知字段名‘Vendor_Error_Code’”
    Replace(WHERE_FIELDS, "<INSERT FIELDS>", strNewFields)
    
    ...
    Dim qdef As DAO.QueryDef
    Dim cel As Range
    
    Set qdef = db.QueryDefs("mySavedQuery")
    
    ' CLEAN OUT TEMP EXCEL TABLE
    db.Execute "DELETE FROM Excel_Table"
    
    ' ITERATIVELY APPEND TO EXCEL TABLES
    For Each cel In userinput.Cells
        qdef!userparam = cel.Value            ' BIND PARAM
        qdef.Execute dbFailOnError            ' EXECUTE ACTION
    Next cel
    
    ' OPEN RECORDSET TO TABLE
    Set rs = db.OpenRecordset("Excel_Table", dbOpenSnapshot)
    
    If rs.RecordCount = 0 Then
        MsgBox "Recieving problem not found in database", vbInformation+vbOKOnly, "No Data"
        GoTo SubExit
    End If
    
    ws2.Range("A1").CopyFromRecordset rs
    .......