0

我用于访问 Access 数据库中的数据的 Inner Join 语句存在问题。我期望发生的是,我遍历了每个产品的记录集。当产品订购不止一次时,我不会将其添加到 Excel 表中,而是增加订购的数量和总成本。

我遇到的问题是,它不是按照我上面描述的方式工作,而是在每次订购时将产品添加到 Excel 表中。我发现它正在按照我的代码中未包含的订购顺序(按他们的 OrderID)打印产品。

有什么帮助吗?

这是代码:

Public Sub WorksheetLoop()


Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim stDB As String, stSQL As String, stSQLTwo As String, stProvider As String
Dim sheetName As String, stProdName As String
Dim suppNum As Integer, prodNum As Integer
Dim WS_Count As Integer
Dim I As Integer

suppNum = 1
prodNum = 1

stDB = "Data Source= " & ThisWorkbook.Path & "\obsDatabase.accdb"
stProvider = "Microsoft.ACE.OLEDB.12.0"

'Opening connection to database
With cn

    .ConnectionString = stDB
    .Provider = stProvider
    .Open

End With


' Set WS_Count equal to the number of worksheets in the active
' workbook.
WS_Count = ActiveWorkbook.Worksheets.Count

' Begin the loop.
For I = 2 To WS_Count

    ActiveWorkbook.Worksheets(I).Range("A1") = "Company Name - " + ActiveWorkbook.Worksheets(I).Name + ""
    ActiveWorkbook.Worksheets(I).Range("A2") = "Item Number"
    ActiveWorkbook.Worksheets(I).Range("B2") = "Description"
    ActiveWorkbook.Worksheets(I).Range("C2") = "Unit"
    ActiveWorkbook.Worksheets(I).Range("D2") = "Cost Per Unit"
    ActiveWorkbook.Worksheets(I).Range("E2") = "Quantity"
    ActiveWorkbook.Worksheets(I).Range("F2") = "Total Cost"
    ActiveWorkbook.Worksheets(I).Range("G2") = "Amount Remaining"

    'Function to retrieve info!

    stSQL = "SELECT Products.ProductID, Products.ProductName, Products.ProductDescription, Products.ProductUnit, LineItems.UnitPrice, LineItems.Quantity, LineItems.TotalPrice " & _
    "FROM Products INNER JOIN LineItems ON LineItems.ProductID = Products.ProductID WHERE Products.SupplierID = " & suppNum & " "
    rs.Open stSQL, cn

    With rs

        Do Until .EOF


            If ActiveWorkbook.Worksheets(I).Range("A65536").End(xlUp) = rs.Fields("ProductName") Then

                If ActiveWorkbook.Worksheets(I).Range("D65536").End(xlUp) = rs.Fields("UnitPrice") Then

                    ActiveWorkbook.Worksheets(I).Range("E65536").End(xlUp) = ActiveWorkbook.Worksheets(I).Range("E65536").End(xlUp) + rs.Fields("Quantity")
                    ActiveWorkbook.Worksheets(I).Range("F65536").End(xlUp) = ActiveWorkbook.Worksheets(I).Range("F65536").End(xlUp) + rs.Fields("TotalPrice")

                End If

            Else

                ActiveWorkbook.Worksheets(I).Range("A65536").End(xlUp).Offset(1, 0) = rs.Fields("ProductName")
                ActiveWorkbook.Worksheets(I).Range("B65536").End(xlUp).Offset(1, 0) = rs.Fields("ProductDescription")
                ActiveWorkbook.Worksheets(I).Range("C65536").End(xlUp).Offset(1, 0) = rs.Fields("ProductUnit")
                ActiveWorkbook.Worksheets(I).Range("D65536").End(xlUp).Offset(1, 0) = rs.Fields("UnitPrice")
                ActiveWorkbook.Worksheets(I).Range("E65536").End(xlUp).Offset(1, 0) = rs.Fields("Quantity")
                ActiveWorkbook.Worksheets(I).Range("F65536").End(xlUp).Offset(1, 0) = rs.Fields("TotalPrice")

            End If
            rs.MoveNext

        Loop

    End With


    rs.Close
    suppNum = suppNum + 1

    ActiveWorkbook.Worksheets(I).Columns("A:A").EntireColumn.AutoFit
    ActiveWorkbook.Worksheets(I).Columns("B:B").EntireColumn.AutoFit
    ActiveWorkbook.Worksheets(I).Columns("C:C").EntireColumn.AutoFit
    ActiveWorkbook.Worksheets(I).Columns("D:D").EntireColumn.AutoFit
    ActiveWorkbook.Worksheets(I).Columns("E:E").EntireColumn.AutoFit
    ActiveWorkbook.Worksheets(I).Columns("F:F").EntireColumn.AutoFit
    ActiveWorkbook.Worksheets(I).Columns("G:G").EntireColumn.AutoFit

Next I

cn.Close


End Sub
4

2 回答 2

1

我不确定我是否错过了重点。但是你能澄清你的最终目标吗?是否必须通过 Excel VBA 完成?

如果您要实现的是每个供应商订单的选项卡,每个产品有一行并且该产品的总数量,那么我会考虑在数据库本身中创建一个查询并传递供应商 id 参数和任何其他参数到查询。然后查询可以处理产品和数量的分组和计数,因为这将是一个聚合查询。

通过这种方式,您可以在每个选项卡上进行可刷新的查询,并写入 VBA 以单独或一起刷新它们,以符合您的需要。

我总是尽量避免复杂的 VBA 编码,因为它在最好的时候是错误的,并且一旦分发就变得难以维护。

另一种选择是将所有产品数据拉到另一个选项卡中,您可以通过 VBA 隐藏该选项卡并使用 SUMPRODUCT 等公式在各个选项卡上显示信息。或者使用组合样式框来选择您的供应商并动态更改结果集。

正如我在开始时所说的那样,我可能会错过重点,但如果没有,并且您需要有关我的选择的帮助,请告诉我,如果我愿意,请澄清您的问题。

对于您的 INNER JOIN 问题,您需要使用聚合查询而不是直接选择。这是因为您的数据库(我假设)可以有一个供应商可以多次订购相同的产品(一对多关系),根据您提供的内容,您在 LineItems 表中有一个数量列,所以我假设重复的产品ID 来自同一供应商的两个或多个单独的订单。这是一个查询示例,还可以考虑给表名加上别名,这样可以更轻松地跟踪代码。

SELECT 
 p.ProductID
,p.ProductName
,p.ProductDescription
,p.ProductUnit
,SUM(l.UnitPrice)
,SUM(l.Quantity)
,SUM(l.TotalPrice)
FROM Products p
INNER JOIN LineItems l
ON l.ProductID = p.ProductID 
WHERE p.SupplierID = 1
GROUP BY 
 p.ProductID
,p.ProductName
,p.ProductDescription
,p.ProductUnit

问候凯文

于 2012-10-22T00:10:53.267 回答
0

您只是将当前产品名称与添加到工作表的最后一行进行比较,但 SQL 查询中的任何内容都不会强制对结果进行任何排序。

如果数据是这样返回的,那就没问题了:

ProductName, Quantity

foo, 7
foo, 4
bar, 3

但如果数据是这样返回的,那就不行了:

ProductName, Quantity

foo, 7
bar, 3
foo, 4

您可以使用 ORDER BY 子句并使用当前的宏,但是正如其他人指出的那样,您可以使用 SQL 来组合数据,这应该是一个更简单的解决方案

于 2012-10-28T02:59:16.800 回答