【问题标题】:How can I get this SQL query to see the VBA selection?如何获取此 SQL 查询以查看 VBA 选择?
【发布时间】:2019-06-22 17:18:51
【问题描述】:

我正在尝试在 Microsoft Access 查询设计器中编写一个查询,以查看我的 VBA 代码在表中所做的选择。

基本上我有以下 VBA 循环,它沿着表 TBL_ForQB 中的客户列向下移动,如果客户不同,则执行查询“QB_Make_Model”,然后运行不同的查询并且循环停止。

主要问题:

如何让“QB_Make_Model”看到 VBA 代码所在的客户,目前使用我的代码它只是插入来自所有客户的信息。

QB_Make_Model 查询:

INSERT INTO InvoiceLine ( InvoiceLineDesc, FQSaveToCache )
SELECT DISTINCT t.Make_Model, 1
FROM TBL_ForQB AS t;

VBA 循环:

Dim dbs As Database
Set dbs = CurrentDb

Dim rst As Recordset
Set rst = dbs.OpenRecordset("TBL_ForQB")

Dim cust As String
Stop

rst.MoveFirst

Dim fcust As String
fcust = rst!Customer
MsgBox rst!Customer

Do Until rst.EOF
    cust = rst!Customer
    If cust = fcust Then
        DoCmd.SetWarnings False
        MsgBox "Same Customer"
        DoCmd.OpenQuery "QB_Make_Model"
    Else
        DoCmd.OpenQuery "QB_Invoice_PK"
        MsgBox "Diffeent Customer, I have Stopped and Sent to QB!"
        'fcust = rst!Customer
        'DoCmd.OpenQuery "QB_Make_Model_PK"
        'DoCmd.OpenQuery "QB_Invoice_PK"

    End If
    rst.MoveNext
Loop

新问题

@Parfait 的答案似乎工作正常,现在的问题是:

假设表“TBL_ForQB”中有两条相同的客户记录,使用新参数查询“QB_Make_Model”匹配客户名称,VBA 执行它。问题是它发送“TBL_ForQB”的 Make_Model 列中与客户名称匹配的所有行。并且与同名客户的次数一样多。

例如:

我有一个名为“Customer1”的客户,它有 2 条记录,每条记录都包含表“TBL_ForQB”中的一条 Make_Model 记录(每条记录)。新的 VBA 代码将运行并执行查询“QB_Make_Model”,它将匹配客户参数但每次有客户记录时都会插入“QB_Make_Model”的两条记录。

看到问题了吗?

【问题讨论】:

  • 您是否收到任何错误日志。如果是这样,请发布。
  • 没有错误日志,我只想让我的查询查看 VBA 循环当前在哪个客户上,并且只对那个客户执行查询任务,而不是整个列表
  • 我无法具体回答,因为自从我完成它以来已经很久了,但是您需要在查询中添加 WHERE 子句,然后您需要将 fcust 作为参数传递给查询.有点像他们在这里所做的事情:stackoverflow.com/a/24535025/2174085。希望有人可以发布必要的特定代码,或者您可以自己弄清楚。抱歉,这是我现在能做的最好的了!
  • @RussellB 有什么建议吗?
  • 您不应按名称选择客户,而应按primary key。每张桌子都必须有一张。在 Access 通常是一个自动编号。然后,不要使用文本框进行客户选择,而是使用ComboBox that looks up this primary key

标签: sql vba ms-access


【解决方案1】:

由于您无法将客户作为参数传递给DoCmd.OpenQuery,您将需要另一种方法,例如在数据表视图中打开报告或表单

Dim filter AS String

filter = "Customer=""" & fcust & """" 'Assuming String type
DoCmd.OpenForm "frmMakeModel", View:=acFormDS, WhereCondition:=filter, DataMode:=acFormReadOnly

或者如果CustomerLong id:

filter = "Customer=" & fcust 'Assuming Long type

然后,表单或报表的记录源必须是适当的查询,在 SELECT 列表中包含 Customer 列。

【讨论】:

  • 查询是一个动作查询,我不认为 WhereCondition 参数适用于此。此外,您可以使用 DoCmd.SetParameterDoCmd.OpenQuery 来使用参数(在查询本身或 WhereCondition 参数中)
  • @ErikvonAsmuth 你能详细说明你的建议吗?如何做到这一点?
  • @AndrewG 我已经发布了一个替代答案,如果您发布表格设计以明确声明参数类型,我可以改进它。
  • @ErikvonAsmuth,DoCmd.OpenQuery 可以执行操作查询吗?顺便提一句。这与How can I make this loop work for a table with multiple customers? 的问题几乎相同,其中缺少表和查询详细信息。
  • @OlivierJacot-Descombes 是的,如果您选择 acViewNormal 并指定操作查询,DoCmd.OpenQuery 将执行操作查询,并且不会以可见的方式打开它。它会显示一个提示,除非它被DoCmd.SetWarnings False 抑制(就像在这种情况下一样)
【解决方案2】:

您可以尝试修改查询以接受参数,并使用DoCmd.SetParameter 传递该参数。

带参数的修改查询:

PARAMETERS pCustomer CHAR(255);
INSERT INTO InvoiceLine ( InvoiceLineDesc, FQSaveToCache )
SELECT DISTINCT t.Make_Model, 1
FROM TBL_ForQB AS t
WHERE Customer = pCustomer;

修改VBA传递参数:

Dim dbs As Database
Set dbs = CurrentDb

Dim rst As Recordset
Set rst = dbs.OpenRecordset("TBL_ForQB")

Dim cust As String
Stop

rst.MoveFirst

Dim fcust As String
fcust = rst!Customer
MsgBox rst!Customer

Do Until rst.EOF
    cust = rst!Customer
    If cust = fcust Then
        DoCmd.SetWarnings False
        MsgBox "Same Customer"
        DoCmd.SetParameter "pCustomer", cust
        DoCmd.OpenQuery "QB_Make_Model"
    Else
        DoCmd.OpenQuery "QB_Invoice_PK"
        MsgBox "Diffeent Customer, I have Stopped and Sent to QB!"
        'fcust = rst!Customer
        'DoCmd.OpenQuery "QB_Make_Model_PK"
        'DoCmd.OpenQuery "QB_Invoice_PK"

    End If
    rst.MoveNext
Loop

您可以在this answer 中阅读有关在 VBA 中使用参数的更多信息。我推荐 DAO 方法而不是依赖 DoCmd 语句的方法。

【讨论】:

  • 这是一种有趣的方法,但现在我收到一条错误消息“对象不包含自动化对象'customer-test1'。
  • 我不知道那是什么。您尚未分享有关名为 customer-test1 的对象的任何信息。
  • “Customer-test1”是表“TBL_ForQB”中第一个客户的名称。
  • 哦,在这种情况下尝试当前编辑(查询已调整为定义参数类型)
  • 不应该是`PARAMETERS pCustomer Text(255);
【解决方案3】:

还考虑将客户名称参数传递给操作查询的QueryDefs 方法,不需要包括DoCmd.SetWarnings 在内的DoCmd 调用。

SQL (使用 PARAMETERS 并为客户添加列)

PARAMETERS C_Param TEXT(255), P_Param LONG;
INSERT INTO InvoiceLine (InvoiceLineDesc, FQSaveToCache )
SELECT DISTINCT t.Make_Model, 1
FROM TBL_ForQB AS t
WHERE Customer = C_Param
AND ProjectID = P_Param;

此外,您可能希望在 InvoiceLine 表中维护 Customer 列(最好是其 ID),该表可以由相同的参数填充。

VBA

Dim dbs As Database
Dim qdef As QueryDef                  ' NEW OBJECT
Dim rst As Recordset
Dim cust As String, fcust As String

Set dbs = CurrentDb
Set qdef = CurrentDb.QueryDefs("QB_Make_Model")
Set rst = dbs.OpenRecordset("TBL_ForQB")

rst.MoveFirst    
fcust = rst!Customer
MsgBox rst!Customer

Do Until rst.EOF
    cust = rst!Customer
    If cust = fcust Then        
        MsgBox "Same Customer"
        qdef!C_Param = cust 
        qdef!C_Param = rst!ProjectID 
        qdef.Execute dbFailOnError
    Else
        dbs.Execute "QB_Invoice_PK"
        MsgBox "Different Customer, I have Stopped and Sent to QB!"
    End If
    rst.MoveNext
Loop

rst.Close 
Set rst = Nothing: Set qdef = Nothing: Set dbs = Nothing

【讨论】:

  • 这是您应该使用 CustomerIDs(唯一标识符)而不是客户名称的一个很好的理由。 TBL_ForQB中没有这样的ID吗?
  • 实际上它比这要复杂一些,非常感谢您的帮助,基本上我在 TBL_ForQB 中关心三列: 'ProjectID' 、 'Customer' 和 'Make_Model' ,但是TBL_ForQB 的设置方式可以有多行非常相似的数据。
  • 是否可以让查询和 vba 只关注 VBA 代码当前所在的行?也许为其设置某种参数以仅从表中严格逐行读取?
  • 为什么不使用 Customer 名称和 ProjectIDMake_Model?是什么创造了独特的记录?顺便说一句 - 这是表/数据库设计问题。在关联表时,通常应该使用整数 ID,而不是字符串值/数据点的专有名称。
  • 我会考虑,如何修改代码,以确保每个 Customer 和 ProjectID 在 INSERT 查询中使用一个 Make_Model?
猜你喜欢
  • 2020-08-21
  • 2014-11-02
  • 2020-09-03
  • 2011-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-26
  • 2016-10-29
相关资源
最近更新 更多