跨多张纸求和

时间:2019-05-18 13:09:36

标签: excel vba

我需要汇总多张纸上的值。工作表将始终具有不同的名称,因为它们是由日期设置的。

我的工作簿中有一个摘要表作为第一页。

我想从摘要表中的一个字段中通读每个表,如果这些字段的值匹配,它将它们加在一起。

例如,伪代码为:遍历每个工作表,如果SummarySheet.Range("A24").value在范围(G1:G200)内,则求和范围(“ H1:H200”)中的相应单元格。

我已经尝试过对if和求和。

我尝试了以下代码。哪个炸了!

For Each Cell In Range("A24:A224")
For Each ws In ThisWorkbook.Worksheets
  For Each i In ThisWorkbook.ActiveSheet.Range("G2:H200")
    If Cell.Value = i.Value Then
    ActiveCell.Offset(0, 1).Select
    Cell.Value = Cell.Value + i.Value
    End If
  Next i
  Next ws
  Next Cell

3 个答案:

答案 0 :(得分:0)

您的代码引用了“ ActiveSheet”和“ ActiveCell”,但未激活循环中的任何内容。

答案 1 :(得分:0)

很难猜测您的代码正在尝试做什么。这个答案更多地是关于良好的编码实践,而不是具体的建议。我希望这将使您能够更正自己的代码。

ActiveCell.Offset(0, 1).Select无用。 ActiveCell是包含光标的单元格。您不会将光标放在例程的开头到第一个单元格,并且在宏的其余部分中都不会读取或写入ActiveCell。

For Each ws In ThisWorkbook.Worksheets无用,因为您不使用ws。在For Each i In ThisWorkbook.ActiveSheet.Range("G2:H200")中,您的意思是写For Each i In ws.Range("G2:H200")吗?我看不到您可能打算使用ws的其他地方。

Each Cell In Range("A24:A224")引用ActiveSheet。这是启动宏时工作表碰巧处于活动状态的任何内容。我的猜测是Range("A24:A224")在摘要工作表中。如果用户恰巧在启动宏时正看着另一个工作表,则该另一个工作表是ActiveSheet,而不是摘要工作表。我假设您要在汇总工作表中累积总计。如果启动宏时错误的工作表处于活动状态,则该工作表将被破坏,无法恢复。撤消无法撤消宏所做的操作,因此您将不得不还原到工作簿的上一个副本。我希望您在尝试实验宏之前先创建工作簿的新副本,以便可以恢复到未损坏的版本。您需要类似的东西:

Dim WshtSumm As Worksheet

Set WshtSumm = Worksheets("Summary")

For Each Cell In WshtSumm.Range("A24:A224")
   :      :      :      :      :      :      :
Next

我认为您不应使用Cell之类的名称,因为它与保留字Cells太相似。您不应该使用i之类的名称,因为这样的名称是没有意义的。在一个如此小的宏中也许没关系,但是随着您的宏变大,当您或其他人在六个或十二个月内查看此宏时,有意义的名称将是真正的帮助。很少有宏可以永远保持不变。它们每几个月更新一次,以解决不断变化的需求。我不知道Celli代表什么,但也许CellSummCellData是更好的名字。

考虑ThisWorkbook.WorksheetsRange("A24:A224")。我刚刚告诉过您,您应该已经确定哪个工作表包含Range("A24:A224")。这是因为您的工作簿包含几个工作表,其中任何一个都可以处于活动状态。如果您的工作簿只有一个工作表,则Range("A24:A224")可能没问题。就个人而言,我避免使用不合格的范围,因为添加新工作表非常容易。但是,您是否有可能打开两个或两个以上的工作簿?是的,可以在另一个工作簿中的一个工作簿中运行宏,但这可能吗? ThisWorkbook标识包含宏的工作簿。如果您担心错误的工作簿将被激活,则绝对正确地指定要访问的工作表集合,因为每个工作簿都有自己的集合。但是,Worksheets本身通常就足够了。这是您需要考虑的事情,尤其是当您的宏变得越来越复杂时:我是否需要限定此范围或工作表或您可能拥有多个的任何内容?

考虑:

For Each ws In ThisWorkbook.Worksheets
  For Each i In ws.Range("G2:H200")

我没有限定ws的资格,因为工作表具有标识其工作簿的属性Parent。创建ws后,您就可以对其进行限定。

ThisWorkbook.Worksheets中的工作表之一将是摘要工作表。您是否要检查摘要工作表中的单元格?我认为不是。您需要类似的东西:

Dim WshtSumm As Worksheet
Dim WshtOther As Worksheet

Set WshtSumm = Worksheets("Summary")

For Each WshtOther In Worksheets
  If WshtOther.Name <> WshtSumm.Name Then
     :      :      :      :      :      :      :
  End If
Next

此代码仅检查名称与摘要工作表名称不匹配的工作表。每当您浏览所有东西时,都需要问自己:我真的想看看所有人吗?

考虑:

If Cell.Value = i.Value Then
  ActiveCell.Offset(0, 1).Select
  Cell.Value = Cell.Value + i.Value
End If

在您写过ActiveCell的地方,我怀疑您的意思是Cell给予:

If Cell.Value = i.Value Then
  Cell.Offset(0, 1).Select
  Cell.Value = Cell.Value + i.Value
End If

这会更有意义,但意义不大。您在每个工作表的Range(“ G2:H200”)中搜索与摘要工作表的Range(“ A24:A224”)中的值匹配的值。如果找到该匹配值,则将其添加到Range(“ A24:A224”)中的下一个单元格。您没有告诉我们有关汇总工作表或数据工作表的信息,因此这可能是明智的,但感觉并不明智。如果在“ A30”上找到匹配项,则将“ A30”的值添加到“ A31”。但是然后您在修改后的“ A31”上搜索匹配项。我无法想象有什么明智的要求。

即使我认为这很明智,我也不认为这会奏效。如果我写:

For X = 1 to 10
     :      :
Next

我无法在For循环中更改X的值。我最近没有尝试过,但是我的回忆是更改X的尝试被忽略了。您正在尝试为For Each语句更改X的等效项。我没有尝试过,但是我怀疑您更改Cell的尝试将失败。即使它可以更改Cell,也不应更改。 Select是一个缓慢的命令,仅在必要时才应使用它。尝试类似的东西:

If Cell.Value = i.Value Then
  Cell.Offset(0, 1).Value = Cell.Offset(0, 1).Value + i.Value
End If

希望以上内容对您有所帮助。如果没有,请提供这两个范围的详细信息,以便我更好地了解您要做什么。

答案 2 :(得分:0)

我刚刚尝试过,效果很好。

import pandas as pd

df = pd.read_csv('filename.csv')

## Fastest would be using length of index

print("Number of rows ", len(df.index))

## If you want the column and row count then

row_count, column_count = df.shape

print("Number of rows ", row_count)
print("Number of columns ", column_count)


这里的想法:

Excel VBA Sum from Multiple Sheets