【发布时间】:2015-01-12 22:24:15
【问题描述】:
我为代码转储道歉,但经过两天的调试,我想我开始失去它了,我越来越绝望了。我已经开发了如下所示的代码
intColumnCount = wsStaff.Cells(1, Columns.Count).End(xlToLeft).Column
intColumnLoop = 2
intStaffCount = 0
wsDisplay.Range("A2").EntireRow.UnMerge
wsDisplay.Range("A2").EntireRow.Value = ""
Do
intRowCount = wsStaff.Cells(Rows.Count, intColumnLoop).End(xlUp).Row
intRowLoop = 2
Do
If IsEmpty(wsStaff.Cells(intRowLoop, intColumnLoop)) And intRowLoop <> 2 Then
wsStaff.Range(wsStaff.Cells(intRowLoop, intColumnLoop).Address).Delete Shift:=xlUp
intRowCount = wsStaff.Cells(Rows.Count, intColumnLoop).End(xlUp).Row
Else
intStaffCount = intStaffCount + 1
If wsDisplay.Cells(1, intStaffCount + 2).Value <> wsStaff.Cells(intRowLoop, intColumnLoop).Value And wsDisplay.Cells(1, intStaffCount + 2).Value <> wsStaff.Cells(intRowLoop + 1, intColumnLoop).Value And wsDisplay.Cells(1, intStaffCount + 2).Value <> wsStaff.Cells(2, intColumnLoop + 1).Value And wsDisplay.Cells(1, intStaffCount + 2).Value <> "" Then
wsDisplay.Range(wsDisplay.Cells(1, intStaffCount + 2).Address).EntireColumn.Delete Shift:=xlToLeft
intRowCount = wsStaff.Cells(Rows.Count, intColumnLoop).End(xlUp).Row
intStaffCount = intStaffCount - 1
ElseIf wsDisplay.Cells(1, intStaffCount + 2).Value = wsStaff.Cells(intRowLoop + 1, intColumnLoop).Value Or wsDisplay.Cells(1, intStaffCount + 2).Value = wsStaff.Cells(2, intColumnLoop + 1).Value Or wsDisplay.Cells(1, intStaffCount + 2).Value = "" Then
wsDisplay.Range(wsDisplay.Cells(1, intStaffCount + 2).Address).EntireColumn.Insert Shift:=xlToRight
wsDisplay.Cells(1, intStaffCount + 2).Value = wsStaff.Cells(intRowLoop, intColumnLoop).Value
intRowLoop = intRowLoop + 1
Else
intRowLoop = intRowLoop + 1
End If
If wsDisplay.Cells(1, intStaffCount + 2).Value = wsDisplay.Cells(1, intStaffCount + 1).Value Then
wsDisplay.Range(wsDisplay.Cells(1, intStaffCount + 2).Address).EntireColumn.Delete Shift:=xlToLeft
intRowCount = wsStaff.Cells(Rows.Count, intColumnLoop).End(xlUp).Row
intStaffCount = intStaffCount - 1
End If
wsDisplay.Cells(1, intStaffCount + 2).Interior.Color = RGB(255 - (0.1 * (255 - intColourPalette(intColumnLoop Mod 6 + 1, 1))), 255 - (0.1 * (255 - intColourPalette(intColumnLoop Mod 6 + 1, 2))), 255 - (0.1 * (255 - intColourPalette(intColumnLoop Mod 6 + 1, 3))))
End If
Loop While Not intRowLoop > intRowCount
wsDisplay.Range(wsDisplay.Cells(2, 4 + intStaffCount - intRowCount).Address, wsDisplay.Cells(2, 2 + intStaffCount).Address).Merge
wsDisplay.Range(wsDisplay.Cells(2, 4 + intStaffCount - intRowCount).Address).Interior.Color = RGB(intColourPalette(intColumnLoop Mod 6 + 1, 1), intColourPalette(intColumnLoop Mod 6 + 1, 2), intColourPalette(intColumnLoop Mod 6 + 1, 3))
wsDisplay.Cells(2, 4 + intStaffCount - intRowCount).Value = wsStaff.Cells(1, intColumnLoop).Value
wsDisplay.Cells(2, 4 + intStaffCount - intRowCount).Font.Bold = True
wsDisplay.Cells(2, 4 + intStaffCount - intRowCount).Font.Color = RGB(255, 255, 255)
intColumnLoop = intColumnLoop + 1
Loop While Not intColumnLoop > intColumnCount
wsDisplay.Cells(1, 1).EntireRow.Orientation = -45
wsDisplay.Cells(1, 1).EntireRow.HorizontalAlignment = xlRight
wsDisplay.Range(wsDisplay.Cells(1, 3), wsDisplay.Cells(2, intStaffCount + 2)).Borders.LineStyle = xlContinuous
intDisplayRowLength = wsDisplay.Cells(1, Columns.Count).End(xlToLeft).Column
intEraser = intStaffCount + 3
wsDisplay.Range(wsDisplay.Cells(1, intEraser), wsDisplay.Cells(1, intDisplayRowLength)).EntireColumn.Delete Shift:=xlToLeft
End Sub
所以我有两个问题,都涉及代码跳回行和重新执行代码。我通过在不同的变量条件下将几乎所有代码都放在断点上的代码单步执行数百次来弄清楚这一点。
每当重新定义 intRowCount 时,代码经常会跳回到开头,此错误对输出无害,但会显着增加计算时间。我知道这可能内置在 Do 循环中,因此很不方便,但不是最大的问题。
最大的问题是倒数第二行,删除所有不必要的列后,代码会跳回最后一个 end if 语句,它位于嵌套的 do 循环内。我不知道它为什么会跳回来,最重要的是,intRowCount、intRowLoop、intColumnCount 和 intColumnLoop 变量似乎发生了变化,以允许代码的重复循环。
之所以如此灾难性,是因为 intStaffCount 没有改变,这意味着数据被添加了两次。
如果有人能提供任何见解,将不胜感激。
编辑:它跳到代码中添加新项目的位置,并在到达倒数第二行时选择无限这样做。
编辑 2:它实际上到达了 End Sub 行,只是没有结束
编辑 3:在所示代码之外找到解决方案,必须在调用子之前禁用事件并在之后重新启用事件
【问题讨论】:
-
您是否一直在使用Locals Window和Immediate Window来帮助您调试?
-
不,我没有,不确定那是什么,但我会查一下,只是一直在使用断点并将鼠标悬停在变量上以查找它们的值。我只使用 vba for excel 大约两个星期。
-
运行可能删除行或列的循环时的标准建议是向后工作 - 从最底部的行或最右侧的列开始。否则,您会通过尝试跟踪您当前应该查看的行/列来增加复杂性。此外,
wsStaff.Range(wsStaff.Cells(intRowLoop, intColumnLoop).Address).Delete Shift:=xlUp与wsStaff.Cells(intRowLoop, intColumnLoop).Delete Shift:=xlUp相同 -
山姆,这是你的幸运日。因为他们太棒了。转到查看,本地窗口,然后单步执行您的代码。你不需要研究它,因为它是不言自明的。立即窗口非常适合仅输入变量并查看与其关联的立即值。研究如何使用即时窗口。
-
调用
Worksheet_Change过程是否在调用此Sub 之前禁用事件?如果不是,那么如果Worksheet_Change过程与wsStaff或wsDisplay相关,您很可能会重复触发该事件。尝试暂停程序的执行并查看调用堆栈(通过 View > Call Stack)