2013-10-30 75 views
0

我想使用WorksheetFunction.Sum來總結結果中所有行上的相同字段,但是,它似乎並沒有這樣做。它不會拋出一個錯誤,它只是不計算任何東西。我知道一些行應該拋出多於一行的結果。Application.WorksheetFunction.Sum不適用於篩選結果VBA

這就是我想要做的事:

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 

我試過,而不使用與InventorySheet,採用全

Applicaiton.WorksheetFunction.Sum

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

遍歷所有但如果我評論如果結構,它總是顯示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和我自己學習。

編輯:

我切換總和小計,雖然它的循環,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 
+2

您是否嘗試過使用SUBTOTAL()函數而不是SUM()函數? –

+0

我同意加里你可以在整個專欄上使用小計。這就是它的目的,爲什麼你必須'使用InventorySheet'在兩個語句之間只有一行,也可以使用with命令? – user2140261

+0

同意加里在這一個。 SUBTOTAL似乎更適合這項法案。但是,爲了更好地編寫代碼,請參閱下面的答案。 – Manhattan

回答

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在它之前並不意味着變量將從那裏被取出。如果您的宏正從另一個工作表中調用,並且最後一行是從活動工作表取得的,則它將返回錯誤的值。

正確的處理方法是,如上所示,將其鎖定到InventorySheet列Q.這樣,該值不會來自模糊的來源。這也促進了更好的編碼風格,因爲Set現在將rangeFilteredInventory簡化爲更易讀的代碼。

另外,請注意位置。它在應用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之後放置它。

其次,請注意我是如何去除輔助With InventorySheet的。我在你的代碼中看到你必須聲明With InventorySheet兩次,但第二個塊根本沒有用處。由於rangeFilteredInventory已被宣佈,因此無需將其包含在With區塊中。

現在,即使編碼風格固定,您的方法也可以使用一些工作。第一,我第二次使用SUBTOTAL而不是SUM。但是,我不會認爲這是必要的,因爲您的情況可能會有所不同,或者您可能希望將其用於其他原因。

請測試上述並讓我們知道結果。

+0

我將其更改爲SUBTOTAL,因爲總和似乎沒有做循環,請參閱我編輯的問題。 – Splendonia