访问vba将单列查询连接成一行结果

时间:2019-01-23 13:39:16

标签: vba loops ms-access-2016

我有一个新的数据库来帮助生成文档以进行订单处理。

我有一个查询,该查询仅由主窗体上选择的顺序确定的一列结果(产品代码)构成。

我需要能够使用此信息来命名我的文件

(客户)(产品1)+(产品2)+(产品...)(位置)

我具有生成行(客户)(产品1)(位置)的代码,并试图获取连接功能或循环功能,或试图使所有产品在两者之间对齐并带有“ +”的代码每个“行”。

我设置了一个查询(Query1),可以为我提供所需的确切数据...

SELECT tblREF_Chemical.Abbr
FROM qry_AX_LineItems_DISTINCT INNER JOIN tblREF_Chemical ON 
qry_AX_LineItems_DISTINCT.ItemId = tblREF_Chemical.[Item Number]
GROUP BY tblREF_Chemical.Abbr, qry_AX_LineItems_DISTINCT.SALESID, 
tblREF_Chemical.[Proper Shipping Name]
HAVING (((qry_AX_LineItems_DISTINCT.SALESID)=[Forms]![frm_SalesOrderEntry]! 
[Combo617]) AND ((tblREF_Chemical.[Proper Shipping Name]) Is Not Null));

我在主窗体上设置了一个按钮来测试数据输出,然后打算将代码添加到DoCmd.Output文件名的代码中。

到目前为止,唯一起作用的代码是...

Private Sub Command1492_Click()
Dim i As Integer

Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim SQL As String

Set db = CurrentDb
SL = [Forms]![frm_SalesOrderEntry]![Combo617]

SQL = "SELECT * FROM  ALL_SalesOrderItemsLineDates WHERE 
ALL_SalesOrderItemsLineDates.SALESID = '" & SL & "';"
Set rst = db.OpenRecordset(SQL)

For i = 0 To DCount("*", "ALL_SalesOrderItemsLineDates", 
 "ALL_SalesOrderItemsLineDates.SALESID = '" & [Forms]![frm_SalesOrderEntry]! 
[Combo617] & "'") - 1
 Debug.Print DLookup("[Abbr]", "[tblREF_Chemical]", "[Item Number]= '" & 
rst.Fields("ItemID") & "'")
 rst.MoveNext
Next i

rst.Close

End Sub

我似乎无法在此代码中添加其他where语句或使用我的实际查询,或者系统在db.OpenRecordset代码行中显示错误(错误3061和3078)。

即使忽略这些问题,输出也是多行的,我需要将其用于文档名称的单个文本字符串中。

UPDATE1:

我正在使用代码直接使用查询...

Dim i As Integer

Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim SQL As String

Set db = CurrentDb
SL = [Forms]![frm_SalesOrderEntry]![Combo617]

SQL = "SELECT tblREF_Chemical.Abbr "
SQL = SQL & "FROM qry_AX_LineItems_DISTINCT INNER JOIN tblREF_Chemical ON qry_AX_LineItems_DISTINCT.ItemId = tblREF_Chemical.[Item Number] "
SQL = SQL & "GROUP BY tblREF_Chemical.Abbr, qry_AX_LineItems_DISTINCT.SALESID, tblREF_Chemical.[Proper Shipping Name] "
SQL = SQL & "HAVING ((qry_AX_LineItems_DISTINCT.SALESID)='" & SL & "'"
SQL = SQL & "AND ((tblREF_Chemical.[Proper Shipping Name]) Is Not Null));  "

Set rst = db.OpenRecordset(SQL)
Dim s As String

Do While rst(0) Is Not Null
   s = s & "+" & rst(0)
   rst.MoveNext
Loop
rst.Close
Debug.Print s

不幸的是,我现在遇到运行时错误3061-参数太少。预期为1。

我已经仔细检查了拼写并运行了查询,以确保无论查询得到多少结果(按预期运行),我仍然会收到此错误。

UPDATE2:

通过更多的研究,我了解到,由于缺少更好的词,查询可以具有隐形编码。我正在更新代码以从查询中删除内部查询,以简化VBA必须执行的“研究”数量。

Private Sub Command1492_Click()

Dim i As Integer

Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim SQL As String

Set db = CurrentDb
SL = [Forms]![frm_SalesOrderEntry]![Combo617]

SQL = "SELECT tblREF_Chemical.Abbr "
SQL = SQL & "FROM ALL_SalesOrderItemsLineDates INNER JOIN tblREF_Chemical ON ALL_SalesOrderItemsLineDates.ItemId = tblREF_Chemical.[Item Number] "
SQL = SQL & "GROUP BY tblREF_Chemical.Abbr, ALL_SalesOrderItemsLineDates.SALESID, tblREF_Chemical.[Proper Shipping Name]"
SQL = SQL & "HAVING ((ALL_SalesOrderItemsLineDates.SALESID)='" & SL & "'"
SQL = SQL & "AND ((tblREF_Chemical.[Proper Shipping Name]) Is Not Null));  "

Set rst = db.OpenRecordset(SQL)
Dim s As String

Do While rst(0) Is Not Null 'Debug error here!
   s = s & "+" & rst(0)
   rst.MoveNext
Loop
rst.Close
Debug.Print s

End Sub

不幸的是,我仍然遇到运行时错误,但是现在它是424个对象,调试使我进入“ Do While”行。

我认为这是向前迈出的一步,但仍然有些困难。

Update3: 由于调试使我进入“ Do While”行,因此我返回了我的运行代码,并用基于整数的代码替换了循环函数。

谢谢#骚扰爸爸!您的代码是巨大的帮助!用你的想法来写一个字符串而不是直接去debug.print是天才。

以下代码替换了我遇到问题时的代码。

Dim s As String

For i = 0 To DCount("*", "ALL_SalesOrderItemsLineDates", "ALL_SalesOrderItemsLineDates.SALESID = '" & SL & "'") - 1
 s = s & "+" & rst.Fields("Abbr")
 rst.MoveNext
Next i

 rst.Close
 Debug.Print s

我的结果只有打one显示。

+ CHA + DEEA + EEP + MEC + PERC + PM + PROP

开头有一个额外的“ +”,但是我敢肯定我可以找到解决这个小问题的方法。

我希望这些笔记将来能对某人有所帮助。谢谢大家的帮助!

2 个答案:

答案 0 :(得分:0)

Private Sub Command1492_Click()
Dim i As Integer

Dim db As DAO.Database
Dim rst As DAO.Recordset
Dim SQL As String

Set db = CurrentDb
SL = [Forms]![frm_SalesOrderEntry]![Combo617]
SQL = "SELECT tblREF_Chemical.Abbr "
SQL = SQL & "FROM qry_AX_LineItems_DISTINCT INNER JOIN tblREF_Chemical ON "
SQL = SQL & "qry_AX_LineItems_DISTINCT.ItemId = tblREF_Chemical.[Item Number] "
SQL = SQL & "GROUP BY tblREF_Chemical.Abbr, qry_AX_LineItems_DISTINCT.SALESID, "
SQL = SQL & "tblREF_Chemical.[Proper Shipping Name] "
SQL = SQL & "HAVING (((qry_AX_LineItems_DISTINCT.SALESID)='" &  SL & "'"  'edit here
SQL = SQL & "AND ((tblREF_Chemical.[Proper Shipping Name]) Is Not Null));  "  


Set rst = db.OpenRecordset(SQL)
Dim s as string

Do While rst(0) is not null
   s = s & "+" & rst(0)
   rst.MoveNext
Loop
rst.Close
Debug.print s
End Sub

答案 1 :(得分:0)

您的主要问题是AND子句中HAVING前面缺少空格。

出于可读性和可维护性的原因,考虑使用QueryDefs进行参数化查询(行业最佳实践)以在VBA中运行保存的查询,其原因如下:

  1. 通过有效地将SQL代码与VBA(应用程序层)代码区分开来,避免了连接或包围引号或转义文字的需求。
  2. MS Access不允许您保存带有语法问题的查询,但是VBA字符串查询可以在运行时发现此类问题。
  3. MS Access的引擎将保存的查询编译并缓存到最佳执行计划,这尤其有助于通过联接进行聚合查询。这就是为什么保存的查询通常比动态运行的VBA字符串查询更有效的原因。

SQL (下面另存为保存的查询)

查询现在使用表别名,并且由于未使用聚合,因此HAVING条件已移至WHERE

PARAMETERS idparam LONG;
SELECT t.Abbr
FROM qry_AX_LineItems_DISTINCT q
INNER JOIN tblREF_Chemical t ON q.ItemId = t.[Item Number]
WHERE (((q.SALESID) = [idparam]) 
  AND  ((t.[Proper Shipping Name]) Is Not Null))
GROUP BY t.Abbr, q.SALESID, t.[Proper Shipping Name];

VBA

Dim db As DAO.Database, qdef AS DAO.QueryDef, rst As DAO.Recordset
Dim SQL As String, s As String

Set db = CurrentDb
' INITIALIZE SAVED QUERY
Set qdef = db.QueryDefs("mySavedQuery")
' BIND PARAMETER
qdef![idparam] = [Forms]![frm_SalesOrderEntry]![Combo617]
' OPEN RECORDSET
Set rst = qdef.OpenRecordset()

Do While rst(0) Is Not Null
   s = s & "+" & rst(0)
   rst.MoveNext
Loop
rst.Close

Debug.Print s
Set rst = Nothing: Set qdef = Nothing: Set db = Nothing