我是VBA和编程的新手。我正在使用excel中的大型数据表 - 我的工作表通常有65K行。
我想将两列作为输入,并将excel写入公式输出到两个新列。我不需要为所有行执行此操作,因此我尝试过滤我的数据并仅将计算输出应用于剩余的可见单元格。但是,我的代码似乎在底部添加了一堆额外的空白行(行计数气球到145K!),然后尝试计算这些行,这使得宏挂起。
如何解决此范围选择问题?另外,有更好的方法进行排序吗?谢谢!
Sub CalcSpec()
Dim s As Worksheet
For Each s In ActiveWorkbook.Sheets
If (Left(s.Name, 7) = "Channel" And Right(s.Name, 1) = "1") Then
s.Activate
UserMassInput.Show 1 'Sets up value in R2C21 referenced later
'Select only relevant data from cycles 1-5
With ActiveSheet
.AutoFilterMode = False
.Range("A1:Q1").AutoFilter
.Range("A1:Q1").AutoFilter Field:=6, Criteria1:="<=5"
.Range("A1:Q1").AutoFilter Field:=5, Criteria1:=Array("2", "3", "5"), Operator:=xlFilterValues
End With
'Here's where I try and fail to select only the relevant range
Dim cyCells As Range
Set cyCells = Columns("R:S").SpecialCells(xlCellTypeVisible)
'Apply formula to calculate specific capacities
For Each cell In cyCells
cell.FormulaR1C1 = "=RC[-9]*1000/R2C21"
Next cell
'Label all the new columns
ActiveSheet.Range("R1").Value = "Spec CC"
ActiveSheet.Range("S1").Value = "Spec DC"
ActiveSheet.AutoFilterMode = False
End If
Next s
End Sub
答案 0 :(得分:2)
看起来您的代码看起来没有向表单添加任何内容,也许空行已经存在并且您只是因为操作而注意到它们?因为你正在做:
.Range("A1:Q1").AutoFilter
Excel将范围解释为该大小。有很多方法可以找到&#34;最后使用的行&#34;在工作表或范围中。试试这个方法:
http://www.siddharthrout.com/2012/10/02/find-last-row-in-an-excel-sheetvbavb-net/
确定上次使用的行后,更改自动过滤器范围以明确定义要过滤的范围。
尝试这样的事情。在我(最完整)较小的工作表上使用一些虚拟数据进行了相当全面的测试。
Option Explicit
Sub CalcSpec()
Dim s As Worksheet
Dim lRow As Long
Dim filteredRange As Range
Dim cl As Range
Dim a As Range
'## First, disable automatic calculation and screenupdating
Application.ScreenUpdating = False
Application.Calculation = -4135 'xlCalculationManual
For Each s In ActiveWorkbook.Sheets
'## I modified this logic to use a GoTo instead of putting everything inside an If Block
If Not ((Left(s.Name, 7) = "Channel" And Right(s.Name, 1) = "1")) Then GoTo NextSheet
UserMassInput.Show 1 'Sets up value in R2C21 referenced later
'Select only relevant data from cycles 1-5
With s
'## Define our range using the LAST_ROW of the worksheet
Set filteredRange = .Range("A1:Q" & LastRow(s))
.AutoFilterMode = False
'## Apply autofilter Explicitly to the range defined above
filteredRange.AutoFilter Field:=6, _
Criteria1:="<=5"
filteredRange.AutoFilter Field:=5, _
Criteria1:=Array("2", "3", "5"), _
Operator:=xlFilterValues
'Here's where I try and fail to select only the relevant range
Dim cyCells As Range
Set cyCells = filteredRange.Resize(, 2).Offset(0, 17).SpecialCells(xlCellTypeVisible)
'Apply formula to calculate specific capacities
'## I'm pretty sure you need to iterate the AREAS in a filtered range,
' and then the cells/rows within each AREA
For Each a In cyCells.Areas
For Each cl In a.Cells
cl.FormulaR1C1 = "=RC[-9]*1000/R2C21"
Next
Next
'Label all the new columns
.Range("R1").Value = "Spec CC"
.Range("S1").Value = "Spec DC"
.AutoFilterMode = False
End With
NextSheet:
Next s
'## Remember to turn screenupdating and calculation back ON
Application.Calculation = -4105 'xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Function LastRow(Optional ws As Worksheet = Nothing) As Long
If ws Is Nothing Then Set ws = ActiveSheet
Dim r As Long
r = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
LastRow = r
End Function
<强>更新强>
关于多个条件......我确实试图避免使用GoTo
语句 - 它们会让人感到困惑,并且随着时间的推移难以维护代码。我在这种情况下使用它只是因为它真的出现了你只是想忽略不符合这些条件的纸张。
对于每个条件的多个条件和不同的操作,嵌套的If
语句和/或使用Select Case
语句通常是我喜欢的方式。你可以这样做:
For Each s In ActiveWorkbook.Sheets
If Left(s.Name,7) = "Channel" Then
Select Case Right(s.Name, 1)
Case "%"
'
'
' Within this block you put your code
' to do opertations on sheets like Channel*%
' or, call an appropriate subroutine
'
Case "1"
'
' Within this block you put your code
' do operations on sheets like Channel*1
' or, call an appropriate subroutine
'
'
' NOTE: You can add as many Case statements _
' as you need, BEFORE the "Case Else"
Case Else
' do operations on other sheets, or ignore them
'
'
'
End Select
End If
If Left(s.Name, 10) = "Statistics" Then
Select Case Right(s.Name, 1)
Case "%"
Case "1"
Case Else
End Select
End If
Next