Excel VBA: End(xlUp) 和 End(xlDown) 都在第 244 行结束,这是空白?
Excel VBA: End(xlUp) and End(xlDown) all end up at row 244, which is blank?
我用公式填充 B2:GQ244,复制范围并按值粘贴,然后按列对范围进行排序。 B8:GQ244中的单元格全部为空白。然后,我想从第 2 行开始逐列连接非空白单元格。为此,我需要找到每列中的最后一个非空白单元格。
出于某种原因,End(xlUp) 和 End(xlDown) 都给出了第 244 行,该行是空的。我不知道为什么。我认为文件可能已损坏。所以,我将两张纸和模块复制到一个新创建的工作簿中,但无济于事。有什么解释为什么 End(xlUp) 和 End(xlDown) 都给出了第 244 行?
.Range("B2:GQ244").Formula = "=IF(ISERROR(FIND( B,Sheet9!$H34)),"""",Sheet9!$I34)"
'paste by value to get rid of formulae
.Range("B2:GQ244").Copy
.Range("B2").PasteSpecial Paste:=xlPasteValues
'sort by column
Dim last_row As Long
Dim j As Long
For i = 2 To 200 Step 1
Range(.Cells(2, i), .Cells(245, i)).Sort key1:=.Cells(2, i), order1:=xlAscending
Next i
For i = 2 To 200 Step 1
last_row = .Cells(65536, i).End(xlUp).Row
last_row = .Cells(1, i).End(xlDown).Row
我无法证实你的发现。有一个空白的 ActiveSheet 和一个空白的 Sheet9,下面的代码用零 B2:GQ244 填充了 ActiveSheet。然后它将最后一行 xlUp 读取为 244,将 xlDown 读取为 2。这两个值都符合预期。也许您有一个禁止显示零的设置。但是,正如我在上面的评论中所解释的那样,显示为空白的单元格不一定是空白的,这也适用于包含由您的公式插入的 NullString 的单元格,即使随后删除了该公式,在其位置留下了空字符串。
Sub Examine()
Dim last_row As Long
Dim i As Long
With ActiveSheet
.Range("B2:GQ244").Formula = "=IF(ISERROR(FIND( B,Sheet9!$H34)),"""",Sheet9!$I34)"
'paste by value to get rid of formulae
.Range("B2:GQ244").Copy
.Range("B2").PasteSpecial Paste:=xlPasteValues
'sort by column
For i = 2 To 200 Step 1
Range(.Cells(2, i), .Cells(245, i)).Sort Key1:=.Cells(2, i), Order1:=xlAscending
last_row = .Cells(.Rows.Count, i).End(xlUp).Row
Debug.Print last_row ' returns 244
last_row = .Cells(1, i).End(xlDown).Row
Debug.Print last_row ' returns 2
Next i
End With
End Sub
因此,剩下的唯一谜团就是为什么 .Cells(1, i).End(xlDown).Row
给您的值为 244。事实并非如此。因此,解决方案必须在您的测试中,而不是在其结果中。将您的测试方法与我上面使用的方法进行比较。
下面的代码将删除列底部的所有空字符串以及包含零的字符串。
Sub ClearBlankCells()
' 146
Dim Rng As Range ' working range
Dim R As Long ' intermediate: row
Dim C As Long ' loop counter: columns
Application.ScreenUpdating = False
With ActiveSheet
With .Range("B2:GQ244")
.Formula = "=IF(ISERROR(FIND( B,Sheet9!$H34)),"""",Sheet9!$I34)"
' replace formulas with their values
.Copy
.PasteSpecial Paste:=xlPasteValues
End With
Application.CutCopyMode = False
For C = 2 To 200 Step 1
Set Rng = .Columns(C)
R = Application.Evaluate("SUMPRODUCT((" & Rng.Address & "<>"""")*(" & _
Rng.Address & "<>0)*1)")
If R > 0 Then
Set Rng = Range(.Cells(R + 1, C), .Cells(Rows.Count, C))
Rng.ClearContents
End If
' sort by column
' Range(.Cells(2, C), .Cells(245, C)).Sort Key1:=.Cells(2, C), Order1:=xlAscending
Next C
End With
Application.ScreenUpdating = True
End Sub
请注意,每列底部上方的数据块中不得包含空格或零,包括标题。
必须在删除此类单元格后进行排序,但我将排序说明变暗了,因为它在语法或概念上都是错误的。如果您需要对每一列进行排序,则语法错误,因为该语法对整个 sheet 进行了排序。另一方面,如果您想对整个 sheet 进行排序,则不必循环执行 200 次。
代码运行非常缓慢,这引起了两个观察结果。
- 它花费 99% 的时间来修复它在第一行造成的损坏。
- 它查看的数据范围远远大于实际合理要求的范围。没有人愿意看 sheet 200 列和 244 行。
因此必须有更好的方法来实现您想要的。
我用公式填充 B2:GQ244,复制范围并按值粘贴,然后按列对范围进行排序。 B8:GQ244中的单元格全部为空白。然后,我想从第 2 行开始逐列连接非空白单元格。为此,我需要找到每列中的最后一个非空白单元格。
出于某种原因,End(xlUp) 和 End(xlDown) 都给出了第 244 行,该行是空的。我不知道为什么。我认为文件可能已损坏。所以,我将两张纸和模块复制到一个新创建的工作簿中,但无济于事。有什么解释为什么 End(xlUp) 和 End(xlDown) 都给出了第 244 行?
.Range("B2:GQ244").Formula = "=IF(ISERROR(FIND( B,Sheet9!$H34)),"""",Sheet9!$I34)"
'paste by value to get rid of formulae
.Range("B2:GQ244").Copy
.Range("B2").PasteSpecial Paste:=xlPasteValues
'sort by column
Dim last_row As Long
Dim j As Long
For i = 2 To 200 Step 1
Range(.Cells(2, i), .Cells(245, i)).Sort key1:=.Cells(2, i), order1:=xlAscending
Next i
For i = 2 To 200 Step 1
last_row = .Cells(65536, i).End(xlUp).Row
last_row = .Cells(1, i).End(xlDown).Row
我无法证实你的发现。有一个空白的 ActiveSheet 和一个空白的 Sheet9,下面的代码用零 B2:GQ244 填充了 ActiveSheet。然后它将最后一行 xlUp 读取为 244,将 xlDown 读取为 2。这两个值都符合预期。也许您有一个禁止显示零的设置。但是,正如我在上面的评论中所解释的那样,显示为空白的单元格不一定是空白的,这也适用于包含由您的公式插入的 NullString 的单元格,即使随后删除了该公式,在其位置留下了空字符串。
Sub Examine()
Dim last_row As Long
Dim i As Long
With ActiveSheet
.Range("B2:GQ244").Formula = "=IF(ISERROR(FIND( B,Sheet9!$H34)),"""",Sheet9!$I34)"
'paste by value to get rid of formulae
.Range("B2:GQ244").Copy
.Range("B2").PasteSpecial Paste:=xlPasteValues
'sort by column
For i = 2 To 200 Step 1
Range(.Cells(2, i), .Cells(245, i)).Sort Key1:=.Cells(2, i), Order1:=xlAscending
last_row = .Cells(.Rows.Count, i).End(xlUp).Row
Debug.Print last_row ' returns 244
last_row = .Cells(1, i).End(xlDown).Row
Debug.Print last_row ' returns 2
Next i
End With
End Sub
因此,剩下的唯一谜团就是为什么 .Cells(1, i).End(xlDown).Row
给您的值为 244。事实并非如此。因此,解决方案必须在您的测试中,而不是在其结果中。将您的测试方法与我上面使用的方法进行比较。
下面的代码将删除列底部的所有空字符串以及包含零的字符串。
Sub ClearBlankCells()
' 146
Dim Rng As Range ' working range
Dim R As Long ' intermediate: row
Dim C As Long ' loop counter: columns
Application.ScreenUpdating = False
With ActiveSheet
With .Range("B2:GQ244")
.Formula = "=IF(ISERROR(FIND( B,Sheet9!$H34)),"""",Sheet9!$I34)"
' replace formulas with their values
.Copy
.PasteSpecial Paste:=xlPasteValues
End With
Application.CutCopyMode = False
For C = 2 To 200 Step 1
Set Rng = .Columns(C)
R = Application.Evaluate("SUMPRODUCT((" & Rng.Address & "<>"""")*(" & _
Rng.Address & "<>0)*1)")
If R > 0 Then
Set Rng = Range(.Cells(R + 1, C), .Cells(Rows.Count, C))
Rng.ClearContents
End If
' sort by column
' Range(.Cells(2, C), .Cells(245, C)).Sort Key1:=.Cells(2, C), Order1:=xlAscending
Next C
End With
Application.ScreenUpdating = True
End Sub
请注意,每列底部上方的数据块中不得包含空格或零,包括标题。
必须在删除此类单元格后进行排序,但我将排序说明变暗了,因为它在语法或概念上都是错误的。如果您需要对每一列进行排序,则语法错误,因为该语法对整个 sheet 进行了排序。另一方面,如果您想对整个 sheet 进行排序,则不必循环执行 200 次。
代码运行非常缓慢,这引起了两个观察结果。
- 它花费 99% 的时间来修复它在第一行造成的损坏。
- 它查看的数据范围远远大于实际合理要求的范围。没有人愿意看 sheet 200 列和 244 行。
因此必须有更好的方法来实现您想要的。