工作表中的多个工作表的VBA循环

时间:2018-08-24 21:45:59

标签: vba

我有一个VBA宏,它可以正常工作以遍历一列直到最后一行。我需要的是通过excel文件中的多个选项卡或工作表运行。这是我到目前为止的内容:

Sub Stocks()

    Dim Ticker As String

    Dim Total_Stock_Volume As Double
    Total_Stock_Volume = 0

    Dim Summary_Table_Row As Integer
    Summary_Table_Row = 2
    Dim lastRow As Long

    Dim ws As Worksheet
    For Each ws In Worksheets
        ws.Activate
    Next ws

    Set sht = Worksheet
    lastRow = ws.Cells(sht.Rows.Count, "A").End(xlUp).Row

    For i = 2 To lastRow

        Total_Stock_Volume = Total_Stock_Volume + ws.Cells(i, 7).Value

        If ws.Cells(i + 1, 1).Value <> ws.Cells(i, 1).Value Then

            Ticker = ws.Cells(i, 1).Value

            ws.Range("J" & Summary_Table_Row).Value = Ticker
            ws.Range("K" & Summary_Table_Row).Value = Total_Stock_Volume

            Summary_Table_Row = Summary_Table_Row + 1

            Total_Stock_Volume = 0

        End If
    Next i

End Sub

2 个答案:

答案 0 :(得分:1)

这里是通用语法

 dim wb as workbook
 dim sheet as worksheet
 set wb = ThisWorkbook
 for each sheet in wb.WorkSheets
      'processing logic
 next sheet

答案 1 :(得分:1)

下面的代码就是我所说的无用垃圾箱之火。

Dim ws As Worksheet
For Each ws In Worksheets
    ws.Activate
Next ws

Set sht = Worksheet
lastRow = ws.Cells(sht.Rows.Count, "A").End(xlUp).Row

之所以这么称呼,是因为使用ws.Activate is the equivalent of clicking the worksheet tab(因此在这种情况下没有用),而您的ws变量仅引用 最后一个工作表,如果您打算设置对上一个工作表的引用,则可以使用:

Set ws = Excel.Application.ThisWorkbook.Worksheets(YourLastWorksheetName)

现在,以下几个原因使我感到困惑:

Set sht = Worksheet
  • 哪个工作表?
  • 您从哪个工作簿引用工作表?
  • 我什至不知道有人可以引用 Worksheet
  • 中的任何内容

为了简化起见,我假设ws == sht是因为我假设目标是在您要求遍历多个工作表之前先测试一下是否可以使用1个工作表,因此可以通过为您正在使用的1个工作表设置1个引用-我之前是用ws进行的-而不是为任何工作表sht引用设置另一个引用。

此外,sht没有明确声明,所以我建议在您编写的每个模块或类模块的第一行中编写Option Explicit,因为在编译时,它将向您显示哪些变量您尚未明确声明,如果您误将任何变量拼写错误,它将通知您。

这就是我所说的垃圾箱火:

lastRow = ws.Cells(sht.Rows.Count, "A").End(xlUp).Row

因为我假设您的目标是使用1个工作表,所以这一行代码看起来像是在使用2个引用不充分的工作表,而这些工作表可能在行下的某个地方无法按预期工作。

这是我更改代码的方法:

编辑:该代码在Excel中编译,因此应该起作用,但是您必须对其进行运行时错误测试。

'i like this because i know when i have
'incorrectly named a variable // otherwise
'VBA will just create the incorrectly-named variable
'and set its type to Variant
Option Explicit

'i like to explicitly state whether a sub or function
'will be able to be called from outsite the module (public)
'or if i want it to only be called from within the module (private)
Public Sub Stocks()
    'i prefer to keep all my 'Dim' statements in 1 block so they're
    'easier to find later when i need to change something
    Dim Total_Stock_Volume As Double
    Dim Summary_Table_Row As Integer
    Dim lastRow As Long
    Dim ws As Worksheet
    Dim j As Long
    Dim i As Long
    Dim Ticker As String

    'i prefer to clump my like assignments together in a block
    Summary_Table_Row = 2
    Total_Stock_Volume = 0

    'iterate through the collection of worksheets in your workbook
    For j = 1 To Excel.Application.ThisWorkbook.Worksheets.Count
        'set a reference to a worksheet // this will go through
        'the different worksheets in the workbook as the loop
        'progresses
        Set ws = Excel.Application.ThisWorkbook.Worksheets(j)

        With ws
            'this is a better way to get the last column in a worksheet
            lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
        End With

        For i = 2 To lastRow
            'i prefer to explicitly cast anything i get from a cell to the type
            'i intend to use because .Value returns a Variant type by default
            Total_Stock_Volume = Total_Stock_Volume + CDbl(ws.Cells(i, 7).Value)

            If ws.Cells(i + 1, 1).Value <> ws.Cells(i, 1).Value Then
                'me explicitly casting the value of the cell to a string
                Ticker = CStr(ws.Cells(i, 1).Value)

                'i like with statements because it looks nicer to me.
                'i'm sure there's a better reason to use these, but that's
                'my reason!
                With ws
                    .Range("J" & Summary_Table_Row).Value = Ticker
                    .Range("K" & Summary_Table_Row).Value = Total_Stock_Volume
                End With
                Summary_Table_Row = Summary_Table_Row + 1

                'i'm unsure about the intention with this, so i'll leave it alone
                Total_Stock_Volume = 0
            End If
        Next i

    Next
End Sub

希望有帮助!

编辑:添加了运行我时上述代码输出的屏幕截图。正如我在评论中所说,如果没有有关您希望此代码执行的操作的进一步信息,我将无能为力。

Sheet1: enter image description here

Sheet2: enter image description here

Sheet3: enter image description here