Excel“Do While”循环在第一次迭代后无法正常运行

时间:2016-05-28 16:46:06

标签: excel vba excel-vba iteration do-loops

我有一个Sub进行一些轻量级格式化,然后我需要它来评估和计算列是否包含“1”或什么都没有,如果该列有一个是否为数字的标题。

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

非常感谢任何见解。

2 个答案:

答案 0 :(得分:0)

首先不要使用select ...你不需要并且会变得很慢并且将依赖于所选择的单元格。

我没有详细看到你的代码,但是如果你第一次正确地运行它,而不是第二次...这通常会发生这种情况,因为在第二次运行中所选的单元格是不同的。

如何避免这个问题:

  • 第一个解决方案:将起始单元强加于函数

    范围(“a1”)。选择“这是一个例子

  • 第二种解决方案:将您的代码独立于activeCell ou selectedCell。也许只是在开始时才开始算法。

    sheet1.range(“A1”).....(不在代码中使用select和activeCell)

第一种解决方案使您的系统始终处于相同的起始条件。第二种解决方案与开始条件无关(更好)。

答案 1 :(得分:0)

原因在于

ActiveCell.End(xlUp).Value = "Total Numbered Books"

作为循环的结束条件

您的真正目标是在ActiveCell列是第一行中包含“总编号”值的列时立即结束行循环

  • 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

我还添加了行循环

但请确保真正的解决方案是避免所有选择/激活