excel VBA对一列中的所有行跨工作表执行Sumif函数,然后对不同的列和求和范围重复该任务

ssgvzors  于 2023-01-27  发布在  其他
关注(0)|答案(2)|浏览(286)

我有一个包含235列的工作表(名为RsOut)。我只需要用另一个工作表(名为rsTrans)中的数据覆盖某些列中的值。这两个工作表都有一个唯一的标识符,我将使用该标识符进行匹配。
1.我决定使用Sumif函数来填充rsOut工作表,但遇到的一个问题是,我不知道如何为列中所有有数据的行运行脚本。
1.一旦我们弄明白了这一点,我需要对大约15个其他列重复这个过程。
我的首要问题是,即使在我们使sumif正常工作之后,执行代码以使其重复15次以上的最有效方法是什么?
"条件"列表和"条件范围"将始终具有相同的位置。但是,对于15列中的每一列,"求和范围"和插入结果的列将发生变化。
所以,思考最有效的方法来继续...也许分开sumif代码作为它自己的块,并调用它,而不是重复步骤一遍又一遍,和/或列出所有的求和范围和所有的插入范围,所以脚本只是循环通过他们..
问题:我认为我的主要问题是我试图使用rngList作为标准。我还试图将sumif作为单独的代码块来调用。我可能在那里也搞砸了一些事情。
该错误突出显示在Set sumRange行上。(运行时错误1004-对象'_Worksheet'的方法'Range'失败。
您能提供的任何帮助将不胜感激!!

Sub SumifmovewsTransdatatowsOut()
    Dim wb As Workbook, wsOut As Worksheet
    Dim wsTrans As Worksheet, rngList As Range
    
    Dim sumRange As Range
    Dim criteriaRange As Range
    Dim criteria As Long  'Setting as long because the IDs (criteria) are at least 20 characters. Should this be a range??
    
    Set wb = ThisWorkbook
    Set wsTrans = Worksheets("DEL SOURCE_Translator")  'Worksheet that contains analysis and results that need to be inserted into wsOut
        
    Set wsOut = Worksheets("FID GDMR - Output_2") 'Worksheet where you are pasting results from wsTrans
    Set rngList = wsOut.Range("B2:B" & wsOut.Cells(Rows.Count, "B").End(xlUp).Row)  'this range of IDs will be different every run, thus adding in the count to find last row...or do I not need the rnglist at all? Just run the sumif for all criteria B2:b
    
    Set sumRange = wsTrans.Range("ag21:ag")  'Values in wsTrans that need to be added to wsOut
    Set criteriaRange = wsTrans.Range("AA21:AA")  'Range of IDs found on wsTrans
    criteria = rngList
                   
    Sumif
  
End Sub

'Standard Sumif formula
Sub Sumif()
     wsOut.Range("AT2:AT") = WorksheetFunction.SumIfs(sumRange, criteriaRange, criteria)
End Sub
'OR should the Sumif formula be:   rng.Formula = "=SUMIF(criteriaRange,rngList,sumRange)"

收到建议后的后续测试:我使用第二个建议进行测试,只是因为如果列在wsout模板上移动,未来的用户可以很容易地更改数组值。
结果问题:
1.每个更改的单元格中的结果为#NAME?
1.对于每个请求,都会显示一个弹出框。它正在查找翻译器。请参见下面的屏幕截图。如果每个弹出框中都有I x,则脚本完成,每个单元格都有#NAME?enter image description here
想想哪里出了问题?
代码:

Sub test2()
Dim wsTrans As Worksheet: Dim wsOut As Worksheet
Dim rgCrit As String: Dim rgSum As String
Dim rgR As Range: Dim i As Integer: Dim arr

arr = Array("AG:AT", "AJ:BB", "AM:BJ", "AT:BR", "AZ:CA", "BP:DE", "BW:DO") 'change as needed
Set wsTrans = Sheets("DEL SOURCE_Translator")         'change as needed
Set wsOut = Sheets("FID GDMR - Output_2")           'change as needed
rgCrit = wsTrans.Name & "!" & wsTrans.Columns(27).Address  'Column 27 is AA in wsTrans which contains the criteria range
Set rgR = wsOut.Range("B2", wsOut.Range("B2").End(xlDown)) 'change as needed
startCell = "$" & Replace(rgR(1, 1).Address, "$", "")

For i = LBound(arr) To UBound(arr)
    rgSum = wsTrans.Name & "!" & Split(arr(i), ":")(0) & ":" & Split(arr(i), ":")(0)
        With rgR.Offset(0, Range(Split(arr(i), ":")(1) & 1).Column - rgR.Column)
            .Value = "=SUMIF(" & rgCrit & "," & startCell & "," & rgSum & ")"
            .Value = .Value
        End With
Next

End Sub

'Sum Ranges in wsTrans:     AG, AJ, AM, AT, AZ, BP, BW
'Result Columns in wsOut:   AT, BB, BJ, BR, CA, DE, DO
ycggw6v2

ycggw6v21#

好的,你的问题对这个网站来说有点太宽泛了。一般的规则是每个问题应该针对一个具体的问题。
话虽如此,我想我可以帮你解决几个容易解决的问题。

1)使Sumif工作:

在Sub中使用Sumif()函数与在Excel公式中使用Sumif()函数相同。首先需要两个full范围,然后需要一个要查找的值。

完整范围:wsTrans.Range("ag21:ag")不起作用,因为它没有结束行。相反,它需要是wsTrans.Range("AG21:AG100")。现在,由于您似乎不知道您的最后一行,我建议您先找到它,然后将其集成到您的所有范围中。我使用下面的变量lRow

Option Explicit
Sub TestSum2()
    
    Dim WB As Workbook
    Dim wsTrans As Worksheet
    Dim wsOut As Worksheet
    Dim criteriaRange As Range
    Dim sumRange As Range
    Dim rngList As Range
    Dim aCriteria    'Array
    Dim lRow As Long
    
    Set WB = ThisWorkbook
    Set wsTrans = WB.Worksheets("DEL SOURCE_Translator")
    
    Set wsOut = WB.Worksheets("FID GDMR - Output_2")
    
    lRow = wsOut.Range("B" & Rows.Count).End(xlUp).Row
    Set rngList = wsOut.Range("B2:B" & lRow)
    aCriteria = rngList  'Transfer Range to array
    
    lRow = wsTrans.Range("AA" & Rows.Count).End(xlUp).Row
    Set sumRange = wsTrans.Range("AG21:AG" & lRow)
    Set criteriaRange = wsTrans.Range("AA21:AA" & lRow)
    
    Debug.Print Application.WorksheetFunction.SumIf(criteriaRange, aCriteria(1, 1), sumRange)
    
End Sub

上面的sub返回:

考虑到以下表格,这是正确的:

2)使其在条件列表中循环

通过将rngList导入到一个数组中,您已经在循环遍历这个条件列表方面有了一个很好的开始。接下来,我们只需要像这样循环该数组:

Option Explicit
Sub TestSum2()
    
    Dim WB As Workbook
    Dim wsTrans As Worksheet
    Dim wsOut As Worksheet
    Dim criteriaRange As Range
    Dim sumRange As Range
    Dim rngList As Range
    Dim aCriteria    'Array
    Dim lRow As Long
    Dim I As Long
    
    Set WB = ThisWorkbook
    Set wsTrans = WB.Worksheets("DEL SOURCE_Translator")
    
    Set wsOut = WB.Worksheets("FID GDMR - Output_2")
    
    lRow = wsOut.Range("B" & Rows.Count).End(xlUp).Row
    Set rngList = wsOut.Range("B2:B" & lRow)
    aCriteria = rngList  'Transfer Range to array
    
    lRow = wsTrans.Range("AA" & Rows.Count).End(xlUp).Row
    Set sumRange = wsTrans.Range("AG21:AG" & lRow)
    Set criteriaRange = wsTrans.Range("AA21:AA" & lRow)
    
    For I = 1 To UBound(aCriteria, 1)
        Debug.Print "Sum of " & aCriteria(I, 1) & "=" & _
            Application.WorksheetFunction. _
            SumIf(criteriaRange, aCriteria(I, 1), sumRange)
    Next I
    
End Sub

这将产生以下输出:

最后,你需要检查一下要把它放在哪一列,也许是列标题的.Find,也许是Match(),但是我不知道你的数据是什么样子的,但是,如果你只想把这个范围输出到输出工作表,下面是怎么做的:

Sub TestSum2()
    
    Dim WB As Workbook
    Dim wsTrans As Worksheet
    Dim wsOut As Worksheet
    Dim criteriaRange As Range
    Dim sumRange As Range
    Dim rngList As Range
    Dim aCriteria    'Array
    Dim OutputSums
    Dim lRow As Long
    Dim I As Long
    
    Set WB = ThisWorkbook
    Set wsTrans = WB.Worksheets("DEL SOURCE_Translator")
    
    Set wsOut = WB.Worksheets("FID GDMR - Output_2")
    
    lRow = wsOut.Range("B" & Rows.Count).End(xlUp).Row
    Set rngList = wsOut.Range("B2:B" & lRow)
    aCriteria = rngList  'Transfer Range to array
    
    lRow = wsTrans.Range("AA" & Rows.Count).End(xlUp).Row
    Set sumRange = wsTrans.Range("AG21:AG" & lRow)
    Set criteriaRange = wsTrans.Range("AA21:AA" & lRow)
    
    ReDim OutputSums(1 To UBound(aCriteria, 1), 1 To 1)
    For I = 1 To UBound(aCriteria, 1)
        OutputSums(I, 1) = Application.WorksheetFunction. _
            SumIf(criteriaRange, aCriteria(I, 1), sumRange)
    Next I
    wsOut.Range("C2").Resize(UBound(OutputSums, 1), 1) = OutputSums
    
End Sub

导致:

dsekswqp

dsekswqp2#

如果我没理解错的话,除了卡梅隆先生的答案,另一种方法也许你可以使用公式。
在运行潜艇之前是这样的:

运行sub后(预期结果)如下所示:

请忽略填充颜色、排序和值,因为使用它们只是为了更容易手动计算预期结果。
"条件"列表和"条件范围"将始终具有相同的位置。但是,对于15列中的每一列,"求和范围"和插入结果的列将发生变化。
由于您没有提到Sum Range的列将位于何处,因此此代码假定它将位于列ID右侧的连续列中,如sheet1---〉rgSUM1、rgSUM2、rgSUM3的图像所示。
由于您也没有提到结果在sheet2的哪一列中,因此此代码假定它将位于列ID右侧的连续列中,如sheet2的图像所示---〉SUM1、SUM2、SUM3。
如果"求和范围"列是随机列和(或)"求和结果"列是随机列,则不能使用此代码。例如:您rgSum1位于D列工作表1-rgSum1Result工作表2 Z列,rgSum2位于AZ列工作表1-rgSum2Result工作表2 F列,rgSum3位于Q列工作表1-rgSum3Result工作表2 DK列,依此类推,直到15列。我认为如果rgSum和rgSumResult是随机的,则它们都需要一个列字母数组。

Sub test()
Dim sh1 As Worksheet: Dim sh2 As Worksheet
Dim rgCrit As String: Dim rgSum As String
Dim rgR As Range: Dim col As Integer

col = 3 'change as needed
Set sh1 = Sheets("Sheet1") 'change as needed
Set sh2 = Sheets("Sheet2") 'change as needed
rgCrit = sh1.Name & "!" & sh1.Columns(1).Address 'change as needed
rgSum = sh1.Name & "!" & Replace(sh1.Columns(2).Address, "$", "") 'change as needed
Set rgR = sh2.Range("A2", sh2.Range("A2").End(xlDown)) 'change as needed
startCell = "$" & Replace(rgR(1, 1).Address, "$", "")

With rgR.Resize(rgR.Rows.Count, col).Offset(0, 1)
    .Value = "=SUMIF(" & rgCrit & "," & startCell  & "," & rgSum & ")"
    .Value = .Value
End With

End Sub

基本上,代码只是用SUMIF公式填充预期结果的范围。
col =求和范围有多少列
sh1(在您的例子中为wsTrans)是ID和多重求和范围所在的工作表。
sh2(在您的例子中为wsOut)是要求和的ID和多重求和结果所在的工作表。
rgCrit是条件范围列(本例中为列A,(ID))的sh1名称
rgSum是具有Sum Range第一列(本例中为B列)的sh1名称
rgR是sheet2中唯一ID的范围(在本例中,列A之间不能有空白单元格,因为它使用xldown),最后,startCell是rgR的第一个单元格地址
如果SumRange和ResultRange是随机列,则低于。

Sub test2()
Dim sh1 As Worksheet: Dim sh2 As Worksheet
Dim rgCrit As String: Dim rgSum As String
Dim rgR As Range: Dim i As Integer: Dim arr

arr = Array("B:G", "F:E", "D:B") 'change as needed
Set sh1 = Sheets("Sheet13") 'change as needed
Set sh2 = Sheets("Sheet14") 'change as needed
rgCrit = sh1.Name & "!" & sh1.Columns(1).Address 'change as needed
Set rgR = sh2.Range("A2", sh2.Range("A2").End(xlDown)) 'change as needed
startCell = "$" & Replace(rgR(1, 1).Address, "$", "")

For i = LBound(arr) To UBound(arr)
    rgSum = sh1.Name & "!" & Split(arr(i), ":")(0) & ":" & Split(arr(i), ":")(0)
        With rgR.Offset(0, Range(Split(arr(i), ":")(1) & 1).Column - rgR.Column)
            .Value = "=SUMIF(" & rgCrit & "," & startCell & "," & rgSum & ")"
            .Value = .Value
        End With
Next

End Sub

arr值成对:求和范围列-求和结果列。
代码中的arr示例:
第一圈:求和范围列是B(工作表1),结果将在G列(工作表2)。
第二圈:求和范围列为F(表1),结果将位于E列(表2)。
第三个循环:求和范围列是D(sheet1),其中结果将在列B(sheet2)中。

相关问题