0

我正在尝试使用 WorksheetFunction.Sum 对结果中所有行的相同字段求和,但是,它似乎没有这样做。它不会抛出错误,它只是不总结任何东西。我知道有些行应该抛出超过 1 行的结果。

这就是我想要做的:

For Each Code In BomCodes

                        With InventorySheet
                            .AutoFilterMode = False
                            .Range("B1").AutoFilter Field:=2, Criteria1:="Project"
                            .Range("D1").AutoFilter Field:=4, Criteria1:="ContractNumber"
                            .Range("N1").AutoFilter Field:=14, Criteria1:="Code"
                            .Range("Q1").AutoFilter Field:=17, Criteria1:=">0"
                        End With

                        'Do a search through the filtered inventory
                        Set rangeFilteredInventory = InventorySheet.Range("Q2:Q" & Cells(Rows.Count, "Q").End(xlUp).Row)

                            'Get the sum of all results
                            With InventorySheet
                            TotalQty = WorksheetFunction.Sum(rangeFilteredInventory.SpecialCells(xlCellTypeVisible))
                             If TotalQty <> 0 Then
                                Debug.Print TotalQty, vbNewLine, vbNewLine
                             End If
                            End With
                         Next Code

我试过不使用 With InventorySheet,而是使用整个

Applicaiton.WorksheetFunction.Sum,

Set rangeFilteredInventory = InventorySheet.Range("Q2:Q" & Cells(Rows.Count, "Q").End(xlUp).Row)

遍历所有但如果我评论 If 结构,它总是显示 0。

改变为

Set rangeFilteredInventory = InventorySheet.Range("Q2:Q" & Rows.Count).End(xlUp).Row

它甚至不访问第一条记录

并且

Set rangeFilteredInventory = InventorySheet.Range("Q" & Rows.Count).End(xlUp).Row

它也不访问第一条记录。

所以,我的想法是我把范围弄错了。它应该总结该表中的所有“Q”。

如果我在那张纸上做一个宏

With Worksheets("sbom")
                            .AutoFilterMode = False
                            .Range("B1").AutoFilter Field:=2, Criteria1:="5522970"
                            .Range("D1").AutoFilter Field:=4, Criteria1:="0008621302140U"
                            .Range("N1").AutoFilter Field:=14, Criteria1:="LVE70001372"
                            .Range("Q1").AutoFilter Field:=17, Criteria1:=">0"
 End With

它返回多条记录。

很抱歉,如果我以错误的方式在那里有新的东西,我是 VBA 的新手,我正在自学。

编辑:

我将 SUM 切换为 Subtotal,虽然它执行循环,但 TotalQty 仍然为 0。我使用 BK201 给我的部分答案来改进一些事情。

For Each Code In BomCodes
                       Debug.Print "Grabbed Code:", Code, vbNewLine
                        With InventorySheet
                            .AutoFilterMode = False
                             LRowOnQ = .Columns("Q").End(xlUp).Row
                            .Range("B1").AutoFilter Field:=2, Criteria1:="Project"
                            .Range("D1").AutoFilter Field:=4, Criteria1:="ContractNumber"
                            .Range("N1").AutoFilter Field:=14, Criteria1:="Code"
                            .Range("Q1").AutoFilter Field:=17, Criteria1:=">0"
                            Set rangeFilteredInventory = .Range("Q2:Q" & LRowOnQ)
                        End With

                        'Do a search through the filtered inventory

                            'Get the sum of all results
                           ' With InventorySheet
                            TotalQty = WorksheetFunction.Subtotal(9, rangeFilteredInventory.SpecialCells(xlCellTypeVisible))
                                If TotalQty <> 0 Then
                                    Debug.Print TotalQty, vbNewLine, vbNewLine
                                End If
                         Next Code
4

1 回答 1

1

在查找最后一行时,请始终应用With. 基本上,请注意要在哪个工作表中找到哪一行。更加明确。我认为部分错误源于简单的糟糕编码风格,而不是糟糕的代码,因为尽管结果不存在,但方法是合理的。

为了更好的编码,也许是一个解决方案,请看下面的代码和后面的评论。

For Each Code In BomCodes
    With InventorySheet
        .AutoFilterMode = False
        LRowOnQ = .Columns("Q").End(xlUp).Row
        .Range("B1").AutoFilter Field:=2, Criteria1:="Project"
        .Range("D1").AutoFilter Field:=4, Criteria1:="ContractNumber"
        .Range("N1").AutoFilter Field:=14, Criteria1:="Code"
        .Range("Q1").AutoFilter Field:=17, Criteria1:=">0"
        Set rangeFilteredInventory = .Range("Q2:Q" & LRowOnQ)
    End With

    'Get the sum of all results
    TotalQty =WorksheetFunction.Sum(rangeFilteredInventory.SpecialCells(xlCellTypeVisible))
    If TotalQty <> 0 Then
        Debug.Print TotalQty, vbNewLine, vbNewLine
    End If
Next Code

两件事情:

首先,注意变量 LRowOnQ。与您的代码的不同之处在于您在Cells(Rows.Count...没有明确说明应该在哪里使用的情况下使用。仅仅因为InventorySheet在它之前并不意味着将从那里获取变量。如果从另一个工作表调用您的宏并且从活动工作表中获取最后一行,它将返回错误值。

如上所示,处理此问题的正确方法是将其锁定到InventorySheetQ 列。这样,该值将不会来自模糊的来源。这也促进了更好的编码风格,因为现在SettingrangeFilteredInventory被简化为更具可读性的代码。

另外,注意放置。它是在AutoFilter应用之前设置的。原因很简单:在应用过滤器之后放置它会检查过滤列的最后一行,而不是数据表的最后一行。提供测试代码供参考。

Sub Test()
    Dim Rng As Range
    Set Rng = ActiveSheet.Columns("Q")
    Debug.Print Rng.Cells(Rows.Count, 1).End(xlUp).Row
End Sub

返回过滤表的最后一行比整个未过滤表更麻烦的原因有很多,但我不会在这里讨论。但是,如果您想要相反,只需在AutoFilter应用所有 s 后放置它。

其次,请注意我是如何删除辅助的With InventorySheet。我在您的代码中看到您必须声明With InventorySheet两次,但第二个块根本没有用。由于rangeFilteredInventory已经声明,因此无需将其包含在With块中。

现在,即使编码风格固定,您的方法也可以使用一些工作。我,一,二使用 ofSUBTOTAL而不是SUM. 但是,我不会认为这是必要的,因为您的情况可能会有所不同,或者您可能出于其他原因想使用它。

请测试上述内容并让我们知道结果。

于 2013-10-31T03:06:23.213 回答