Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 为什么';这个循环处理完整的数据集吗?_Vba_Excel_Loops_For Loop - Fatal编程技术网

Vba 为什么';这个循环处理完整的数据集吗?

Vba 为什么';这个循环处理完整的数据集吗?,vba,excel,loops,for-loop,Vba,Excel,Loops,For Loop,背景 我有一个活动门票分配的电子表格。电子表格的每一行上都有一个名称和分配的票证数量 我需要更改电子表格,以便每张票据的每个名称在单独的行上复制一次,如下所示: 我有一个宏来执行此操作,但是它显示出奇怪的行为 问题 宏不会循环遍历整个数据集。单步遍历代码表明,尽管故意增加了LastRow的值,For循环只循环指定的原始值的多少倍。每次迭代结束时,LastRow的新值似乎被忽略 这似乎特别奇怪,因为等效的Do-While循环工作得很好(参见下面使用Do-While循环的工作代码) 问题 为什么

背景

我有一个活动门票分配的电子表格。电子表格的每一行上都有一个名称和分配的票证数量

我需要更改电子表格,以便每张票据的每个名称在单独的行上复制一次,如下所示:

我有一个宏来执行此操作,但是它显示出奇怪的行为

问题

宏不会循环遍历整个数据集。单步遍历代码表明,尽管故意增加了
LastRow
的值,For循环只循环指定的原始值的多少倍。每次迭代结束时,
LastRow
的新值似乎被忽略

这似乎特别奇怪,因为等效的Do-While循环工作得很好(参见下面使用Do-While循环的工作代码)

问题

为什么会出现问题部分(上文)中描述的行为,为什么与等效结构不一致

For循环宏

Sub InsertSurnames()

    Dim LastRow As Long
    Dim r As Long
    Dim surname As String
    Dim tickets As Integer
    Dim surnameCol As Integer
    Dim ticketCol As Integer
    Dim targetCol As Integer

    surnameCol = 1
    ticketCol = 3
    targetCol = 4
    LastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row

    For r = 1 To LastRow

        surname = Cells(r, surnameCol).Value
        tickets = Cells(r, ticketCol).Value


        If (Not (Len(surname) = 0)) Then

            Cells(r, targetCol).Value = surname

            For x = 1 To tickets - 1

                Cells(r + x, 1).EntireRow.Insert
                Cells(r + x, targetCol).Value = surname



            Next x

            LastRow = LastRow + tickets - 1

        End If


    Next r

End Sub
Sub InsertSurnames()

    Dim LastRow As Long
    Dim r As Long
    Dim surname As String
    Dim tickets As Integer
    Dim surnameCol As Integer
    Dim ticketCol As Integer
    Dim targetCol As Integer

    surnameCol = 1
    ticketCol = 3
    targetCol = 4
    LastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
    r = 1

    Do While r <= LastRow

        surname = Cells(r, surnameCol).Value
        tickets = Cells(r, ticketCol).Value


        If (Not (Len(surname) = 0)) Then

            Cells(r, targetCol).Value = surname

            For x = 1 To tickets - 1

                Cells(r + x, 1).EntireRow.Insert
                Cells(r + x, targetCol).Value = surname



            Next x

            LastRow = LastRow + tickets - 1

        End If

        r = r + 1
    Loop

End Sub
执行While循环宏

Sub InsertSurnames()

    Dim LastRow As Long
    Dim r As Long
    Dim surname As String
    Dim tickets As Integer
    Dim surnameCol As Integer
    Dim ticketCol As Integer
    Dim targetCol As Integer

    surnameCol = 1
    ticketCol = 3
    targetCol = 4
    LastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row

    For r = 1 To LastRow

        surname = Cells(r, surnameCol).Value
        tickets = Cells(r, ticketCol).Value


        If (Not (Len(surname) = 0)) Then

            Cells(r, targetCol).Value = surname

            For x = 1 To tickets - 1

                Cells(r + x, 1).EntireRow.Insert
                Cells(r + x, targetCol).Value = surname



            Next x

            LastRow = LastRow + tickets - 1

        End If


    Next r

End Sub
Sub InsertSurnames()

    Dim LastRow As Long
    Dim r As Long
    Dim surname As String
    Dim tickets As Integer
    Dim surnameCol As Integer
    Dim ticketCol As Integer
    Dim targetCol As Integer

    surnameCol = 1
    ticketCol = 3
    targetCol = 4
    LastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
    r = 1

    Do While r <= LastRow

        surname = Cells(r, surnameCol).Value
        tickets = Cells(r, ticketCol).Value


        If (Not (Len(surname) = 0)) Then

            Cells(r, targetCol).Value = surname

            For x = 1 To tickets - 1

                Cells(r + x, 1).EntireRow.Insert
                Cells(r + x, targetCol).Value = surname



            Next x

            LastRow = LastRow + tickets - 1

        End If

        r = r + 1
    Loop

End Sub
子插入姓氏()
最后一排一样长
变暗,变长
字串
将票据变暗为整数
作为整数的整数
Dim ticketCol作为整数
Dim targetCol为整数
姓氏=1
票面成本=3
targetCol=4
LastRow=ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
r=1

这是用VB设计的。for循环的限制只计算一次,并在循环开始之前保存在临时变量中。因此,如果更改用于计算限制的变量的值,则temp变量不受影响。虽然这会产生您遇到的意外效果,但它还有一个优点,即限制只计算一次,因此此计算中使用的任何方法只输入一次,这可能会加快循环速度。

编译器以不同的方式解释“For”循环结构,并使用不同的汇编调用将临时变量放入CPU缓存中,因此每次迭代后,它不需要返回RAM来读取变量,只需从CPU缓存中获取它即可。这是为了提高性能而设计的,这就是为什么“For”循环通常比“While”循环快。“for”循环的限制变量仍然存在于内存中,但它不会在每次迭代中读取它。因此,如果您更改最初用于设置上限的变量,则循环仍将运行到您将其设置为的原始边界。While循环在每次迭代时检查其exit子句,不缓存is变量。一般来说,当您有一定的迭代次数时,应该使用“For”循环,而不是当您不确定需要循环多少次并且需要更多的动态控制时使用while循环。

要继续使用
For…Next
循环,您可以:

For r = LastRow To 1 Step -1
    surname = Cells(r, surnameCol).Value
    tickets = Cells(r, ticketCol).Value

    If (Not (Len(surname) = 0)) Then
        Cells(r, targetCol).Value = surname

        For x = 1 To tickets - 1
            Cells(r + x, 1).EntireRow.Insert
            Cells(r + x, targetCol).Value = surname
        Next x

        LastRow = LastRow + tickets - 1
    End If
Next r

每当您想从循环中插入或删除
工作表
上的行时,通常最好从循环的末尾开始,然后向后操作。这意味着,在大多数情况下,您不必像我所怀疑的那样调整循环索引

,尽管奇怪的是,不同的循环构造之间的索引并不一致