Excel VBA - INNER JOIN问题

时间:2012-10-21 23:54:01

标签: sql ms-access excel-vba vba excel

我遇到了一个内部连接语句的问题,我用来访问Access数据库中的数据。我期待发生的是我浏览每个产品的记录集。当产品订购多次,我不会将它添加到Excel工作表,而是增加订购数量和总成本。

我遇到的问题是,不是按照我上面描述的方式工作,而是每次订购时都会在excel表中添加产品。我发现它按照订购的顺序打印产品(通过订单ID),这些订单中没有包含。

有任何帮助吗?

以下是代码:

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

2 个答案:

答案 0 :(得分:1)

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

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

通过这种方式,您可以在每个标签上进行可刷新的查询,并通过VBA单独或全部刷新它们,以满足您的需求。

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

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

正如我在开始时说的那样,我可能会忽略这一点,但如果没有,你想帮助我的选择让我知道,如果我愿意,请澄清你的问题。

对于INNER JOIN问题,您需要使用agregate查询而不是直接前向选择。这是因为您的数据库(我假设)可以有一个供应商可以多次订购同一产品(一对多关系),从您提供的产品中您在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

此致 凯文

答案 1 :(得分:0)

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

如果像这样返回数据,那就没关系了:

ProductName, Quantity

foo, 7
foo, 4
bar, 3

但如果像这样返回数据则不行:

ProductName, Quantity

foo, 7
bar, 3
foo, 4

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