我有一个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
答案 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
希望有帮助!
编辑:添加了运行我时上述代码输出的屏幕截图。正如我在评论中所说,如果没有有关您希望此代码执行的操作的进一步信息,我将无能为力。