Excel "Do While" 循环在第一次迭代后无法正常运行
Excel "Do While" Loop Not functioning correctly after first iteration
我有一个 Sub 可以进行一些简单的格式化,然后我需要它来评估和计算列是否包含“1”或什么都不包含,以及该列是否具有 header 是否为数字.
Do...Until 循环的第一次迭代完全正常运行。但是,如果我第二次尝试 运行 它,它会将活动单元格一直扔到工作表 (XFD) 中最右边的列。我总共有大约 114,000 行需要循环。
请看下面的代码,只有第一个循环;这将需要嵌套在另一个循环中以循环遍历所有行:
Sub TotalBookCountsProcess()
Dim ws As Excel.Worksheet
Dim numberedBooks As Integer 'Total Number of physical books
Dim virtualBooks As Integer 'Total Number of virtual books
Dim firstBookCol As Integer 'First Column with a book number
Dim ispeecCol As Integer 'ISPEC Column
Dim lastWorksheetCol As Integer 'Last Column in the worksheet after adding total book count columns
Dim loopColOffset As Integer 'Offset column amounts for new row reset after loop
Dim lastItem As String 'Last item number in last row of the worksheet
ActiveCell.End(xlDown).Select
lastItem = ActiveCell.Value
ActiveCell.End(xlUp).End(xlToRight).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total Numbered Books"
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total CS Books"
lastWorksheetCol = ActiveCell.Column
Columns.AutoFit
numberedBooks = 0
virtualBooks = 0
Cells.Range("1:1").Find("ISPEC").Select
ispecCol = ActiveCell.Column
firstBookCol = ispecCol + 1
ActiveCell.Offset(1, 1).Select
loopColOffset = ((lastWorksheetCol - firstBookCol) * -1)
Do Until ActiveCell.End(xlUp).Value = "Total Numbered Books"
If ActiveCell.Value = 1 And IsNumeric(ActiveCell.End(xlUp).Value) = True Then
numberedBooks = numberedBooks + 1
ActiveCell.Offset(0, 1).Select
ElseIf ActiveCell.Value = 1 And IsNumeric(ActiveCell.End(xlUp).Value) = False Then
virtualBooks = virtualBooks + 1
ActiveCell.Offset(0, 1).Select
Else
ActiveCell.Offset(0, 1).Select
End If
Loop
ActiveCell.Value = numberedBooks
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = virtualBooks
ActiveCell.Offset(1, loopColOffset).Select
End Sub
非常感谢任何见解。
首先不要使用 select ...你不需要,而且你的代码会变得很慢,并且会依赖于 selected 的单元格。
我没有详细看到你的代码,但是如果你第一次告诉它 运行 是正确的,但第二次不是......通常会发生这种情况,因为在第二次 运行 selected 单元格不同。
如何避免问题:
第一个解决方案:在函数中强加起始单元格
Range("a1").Select '这是一个例子
第二种解决方案:将您的代码独立于 activeCell 或 selectedCell。只是也许只是在开始时才开始算法。
sheet1.range("A1") .....(代码中没有使用select和activeCell)
第一个解决方案使您的系统始终处于相同的起始条件。第二种解决方案与开始条件无关(更好)。
原因在于
ActiveCell.End(xlUp).Value = "Total Numbered Books"
作为循环的结束条件
您的真正目标是在 ActiveCell
列是第一行中具有 "Total Numbered Books" 值的列时立即结束行循环
但是
ActiveCell.End(xlUp).Value
将引用 ActiveCell
上方的第一个非空单元格
从第二次迭代开始,列第一行值实际上是 "Total Numbered Books" 的单元格也有其正上方的单元格填充了 numberedBooks
值
所以它一直跳到下一列直到列结束...
您的代码可能如下所示:
Option Explicit
Sub TotalBookCountsProcess()
Dim ws As Excel.Worksheet
Dim numberedBooks As Integer 'Total Number of physical books
Dim virtualBooks As Integer 'Total Number of virtual books
Dim firstBookCol As Integer 'First Column with a book number
Dim ispeecCol As Integer 'ISPEC Column
Dim lastWorksheetCol As Integer 'Last Column in the worksheet after adding total book count columns
Dim loopColOffset As Integer 'Offset column amounts for new row reset after loop
Dim lastItem As String 'Last item number in last row of the worksheet
Dim ispecCol As Long
ActiveCell.End(xlDown).Select
lastItem = ActiveCell.Value
ActiveCell.End(xlUp).End(xlToRight).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total Numbered Books"
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total CS Books"
lastWorksheetCol = ActiveCell.Column
Columns.AutoFit
numberedBooks = 0
virtualBooks = 0
Cells.Range("1:1").Find("ISPEC").Select
ispecCol = ActiveCell.Column
firstBookCol = ispecCol + 1
ActiveCell.Offset(1, 1).Select
loopColOffset = ((lastWorksheetCol - firstBookCol) * -1)
Do
numberedBooks = 0
virtualBooks = 0
Do Until Cells(1, ActiveCell.Column) = "Total Numbered Books"
If ActiveCell.Value = 1 Then
If IsNumeric(Cells(1, ActiveCell.Column)) Then
numberedBooks = numberedBooks + 1
Else
virtualBooks = virtualBooks + 1
End If
End If
ActiveCell.Offset(0, 1).Select
Loop
ActiveCell.Value = numberedBooks
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = virtualBooks
ActiveCell.Offset(1, loopColOffset).Select
Loop Until Cells(ActiveCell.Row - 1, 1) = lastItem
End Sub
我还添加了行循环
但要确保真正的解决方案是避免所有这些 selecting/activating
我有一个 Sub 可以进行一些简单的格式化,然后我需要它来评估和计算列是否包含“1”或什么都不包含,以及该列是否具有 header 是否为数字.
Do...Until 循环的第一次迭代完全正常运行。但是,如果我第二次尝试 运行 它,它会将活动单元格一直扔到工作表 (XFD) 中最右边的列。我总共有大约 114,000 行需要循环。
请看下面的代码,只有第一个循环;这将需要嵌套在另一个循环中以循环遍历所有行:
Sub TotalBookCountsProcess()
Dim ws As Excel.Worksheet
Dim numberedBooks As Integer 'Total Number of physical books
Dim virtualBooks As Integer 'Total Number of virtual books
Dim firstBookCol As Integer 'First Column with a book number
Dim ispeecCol As Integer 'ISPEC Column
Dim lastWorksheetCol As Integer 'Last Column in the worksheet after adding total book count columns
Dim loopColOffset As Integer 'Offset column amounts for new row reset after loop
Dim lastItem As String 'Last item number in last row of the worksheet
ActiveCell.End(xlDown).Select
lastItem = ActiveCell.Value
ActiveCell.End(xlUp).End(xlToRight).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total Numbered Books"
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total CS Books"
lastWorksheetCol = ActiveCell.Column
Columns.AutoFit
numberedBooks = 0
virtualBooks = 0
Cells.Range("1:1").Find("ISPEC").Select
ispecCol = ActiveCell.Column
firstBookCol = ispecCol + 1
ActiveCell.Offset(1, 1).Select
loopColOffset = ((lastWorksheetCol - firstBookCol) * -1)
Do Until ActiveCell.End(xlUp).Value = "Total Numbered Books"
If ActiveCell.Value = 1 And IsNumeric(ActiveCell.End(xlUp).Value) = True Then
numberedBooks = numberedBooks + 1
ActiveCell.Offset(0, 1).Select
ElseIf ActiveCell.Value = 1 And IsNumeric(ActiveCell.End(xlUp).Value) = False Then
virtualBooks = virtualBooks + 1
ActiveCell.Offset(0, 1).Select
Else
ActiveCell.Offset(0, 1).Select
End If
Loop
ActiveCell.Value = numberedBooks
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = virtualBooks
ActiveCell.Offset(1, loopColOffset).Select
End Sub
非常感谢任何见解。
首先不要使用 select ...你不需要,而且你的代码会变得很慢,并且会依赖于 selected 的单元格。
我没有详细看到你的代码,但是如果你第一次告诉它 运行 是正确的,但第二次不是......通常会发生这种情况,因为在第二次 运行 selected 单元格不同。
如何避免问题:
第一个解决方案:在函数中强加起始单元格
Range("a1").Select '这是一个例子
第二种解决方案:将您的代码独立于 activeCell 或 selectedCell。只是也许只是在开始时才开始算法。
sheet1.range("A1") .....(代码中没有使用select和activeCell)
第一个解决方案使您的系统始终处于相同的起始条件。第二种解决方案与开始条件无关(更好)。
原因在于
ActiveCell.End(xlUp).Value = "Total Numbered Books"
作为循环的结束条件
您的真正目标是在 ActiveCell
列是第一行中具有 "Total Numbered Books" 值的列时立即结束行循环
但是
ActiveCell.End(xlUp).Value
将引用ActiveCell
上方的第一个非空单元格
从第二次迭代开始,列第一行值实际上是 "Total Numbered Books" 的单元格也有其正上方的单元格填充了
numberedBooks
值所以它一直跳到下一列直到列结束...
您的代码可能如下所示:
Option Explicit
Sub TotalBookCountsProcess()
Dim ws As Excel.Worksheet
Dim numberedBooks As Integer 'Total Number of physical books
Dim virtualBooks As Integer 'Total Number of virtual books
Dim firstBookCol As Integer 'First Column with a book number
Dim ispeecCol As Integer 'ISPEC Column
Dim lastWorksheetCol As Integer 'Last Column in the worksheet after adding total book count columns
Dim loopColOffset As Integer 'Offset column amounts for new row reset after loop
Dim lastItem As String 'Last item number in last row of the worksheet
Dim ispecCol As Long
ActiveCell.End(xlDown).Select
lastItem = ActiveCell.Value
ActiveCell.End(xlUp).End(xlToRight).Select
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total Numbered Books"
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = "Total CS Books"
lastWorksheetCol = ActiveCell.Column
Columns.AutoFit
numberedBooks = 0
virtualBooks = 0
Cells.Range("1:1").Find("ISPEC").Select
ispecCol = ActiveCell.Column
firstBookCol = ispecCol + 1
ActiveCell.Offset(1, 1).Select
loopColOffset = ((lastWorksheetCol - firstBookCol) * -1)
Do
numberedBooks = 0
virtualBooks = 0
Do Until Cells(1, ActiveCell.Column) = "Total Numbered Books"
If ActiveCell.Value = 1 Then
If IsNumeric(Cells(1, ActiveCell.Column)) Then
numberedBooks = numberedBooks + 1
Else
virtualBooks = virtualBooks + 1
End If
End If
ActiveCell.Offset(0, 1).Select
Loop
ActiveCell.Value = numberedBooks
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = virtualBooks
ActiveCell.Offset(1, loopColOffset).Select
Loop Until Cells(ActiveCell.Row - 1, 1) = lastItem
End Sub
我还添加了行循环
但要确保真正的解决方案是避免所有这些 selecting/activating