2012-10-21 73 views
0

我遇到了用于从Access数据库访问数据的Inner Join语句的问题。我期望发生的事情是我通过每个产品的记录集。当产品多次订购时,我不会将其添加到Excel表格,而是增加订购的数量和总成本。Excel VBA - INNER JOIN问题

我遇到的问题是,它不是按照上面描述的方式工作,而是每次订购时都向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

工作表是否已包含数据?如果没有,为什么你不使用TransferSpreadsheet和分组查询?您可以遍历供应商列表(+1不是一个好主意),并将查询的sql更改为每个供应商的expoer。 VBA中的连接符是&,不是+,所以''公司名称 - “&Activ ...'加号可能导致空值问题,所以它通常只用于特殊情况。 – Fionnuala

回答

1

我不知道如果我错过了点。但是,你能澄清你的最终目标吗?它是否必须通过Excel VBA完成?

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

通过这种方式,您可以在每个选项卡上添加一个可刷新的查询,并使用VBA单独或全部刷新它们,以满足您的需求。

我总是试图避免复杂的VBA编码,因为它在最好的时候是越野车,一旦分布就变得难以维护。

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

正如我在开始时说的,我可能会忽略这一点,但如果不是这样,并且您希望帮助我的选项,请告诉我,如果我请澄清您的问题。

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

问候 凯文

0

你当前的产品名称永远只能比较最后一行添加到工作表,但没有在您的SQL查询强制任何排序的结果。

如果数据返回这样这将是确定:

ProductName, Quantity 

foo, 7 
foo, 4 
bar, 3 

但如果数据返回喜欢这不会是OK:

ProductName, Quantity 

foo, 7 
bar, 3 
foo, 4 

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