简体   繁体   English

VB,Excel宏暂停并在可能的情况下恢复工作

[英]VB, excel macro pause and resume working if possible

I cannot figure out the best way to do the following problem. 我无法找出解决以下问题的最佳方法。 Basically my macro (excel, VB) is checking several (100+) worksheets for correct values, if wrong value is found, I want it to stop, give me a warning, then I could have a look into the reason why the value is wrong, correct it manually and then I want to resume the macro, or remember the last value checked so if I return, it remembers where to continue (resume). 基本上我的宏(excel,VB)正在检查几张(100+)工作表中是否有正确的值,如果找到了错误的值,我希望它停止运行,给我一个警告,然后我可以查看该值为何错误,请手动更正它,然后再恢复宏,或者记住上次检查的值,这样如果返回,它就记住从哪里继续(恢复)。

My current problem is that it finds the wrong value, then I can either make it stop so I check the problem, or it goes through all the sheets and then I have to remember which sheets had the wrong value. 我当前的问题是它找到了错误的值,然后我可以使其停止以进行检查,或者遍历所有工作表,然后我必须记住哪些工作表具有错误的值。

What I thought of is make a list where the name of sheet is added every time a wrong value is found. 我想到的是做一个清单,每当发现错误的值时,便在其中添加工作表的名称。 The problem is that usually there is more than 1 wrong value in the same sheet if there is a wrong value at all and this added the same sheet name several times to the list. 问题是,如果根本上有一个错误的值,通常在同一工作表中会有多个错误的值,这会将相同的工作表名称多次添加到列表中。 Another problem with that is that I cannot correct the values straight away. 另一个问题是我无法立即更正值。

I'm very inexperienced with programming and so would appreciate your idea on how to best approach this problem (I don't want to spend a long time on coding something which wouldn't be efficient for such a "simple" problem). 我对编程没有经验,所以很感谢您提出的关于如何最好地解决此问题的想法(我不想花很长时间来编码对这种“简单”问题无效的代码)。

When the error is found (I'm assuming you've already been able to identify this), you can use the Application.InputBox function to prompt you for a new value. 发现错误后(假设您已经能够识别出此错误),可以使用Application.InputBox函数提示您输入新值。

For example, if rng is a Range variable that represents the cell being checked, and you have some logic to determine where the error happens, then you can just do: 例如,如果rng是一个Range变量,表示要检查的单元格 ,并且您具有确定错误发生位置的逻辑,则可以这样做:

rng.Value = Application.InputBox("Please update the value in " & rng.Address, "Error!", rng.Value)

The inputbox function effectively halts execution of the procedure, while waiting for input from the user. 输入框功能在等待用户输入的同时有效地停止了过程的执行。

If InputBox isn't robust enough, then you can create a custom UserForm to do the same sort of thing. 如果InputBox不够健壮,那么您可以创建一个自定义UserForm来做同样的事情。 But for modifying single range values, one at a time, the InputBox is probably the easiest to implement. 但是对于一次修改一个范围值,InputBox可能是最容易实现的。

I believe you can handle this task by using one or two static local variables in your macro. 我相信您可以通过在宏中使用一个或两个静态局部变量来完成此任务。 A variable declared with "static" rather than "dim" will remember its value from the last time that procedure was run. 用“ static”而不是“ dim”声明的变量将从上次运行过程开始记住其值。 This can hold where you left off so you can resume from there. 这可以保留您离开的地方,以便您可以从那里继续。

One thing that could be a problem with this solution would be if the macro gets recompiled. 此解决方案可能会引起问题的一件事是,如果重新编译了宏。 That would probably cause VBA to clear the value that the static variable was holding. 这可能会导致VBA清除静态变量持有的值。 Just doing a data edit in Excel should not cause a recompile, but you will want to watch for this case, just to make sure it doesn't come up. 仅在Excel中进行数据编辑不会导致重新编译,但是您需要注意这种情况,以确保不会出现这种情况。 It almost certainly will if you edit any code between executions. 如果您在两次执行之间编辑任何代码,几乎可以肯定。

Create a public variable that stores the cell address of the last checked cell and use a conditional statement to see if it's "mid-macro" for want of a better phrase. 创建一个公共变量,该变量存储最后检查的单元格的单元格地址,并使用条件语句来查看它是否为“中间宏”,以便缺少更好的短语。 here is a very crude example... 这是一个非常粗糙的例子...

Public lastCellChecked As String

Sub Check_Someting()

Dim cell As     Excel.Range
Dim WS As       Excel.Worksheet

If Not lastCellChecked = vbNullString Then Set cell = Evaluate(lastCellChecked)

'// Rest of code...

'// Some loop here I'm assuming...
lastCellChecked = "'" & WS.Name & "'!" & cell.Address
If cell.Value > 10 Then Exit Sub '// Lets assume this is classed as an error
'// Rest of loop here...

lastCellChecked = vbNullString
End Sub

The best way to do this is to create a userform and as mentioned by prior users create a public variable. 做到这一点的最佳方法是创建一个用户表单,并如先前的用户所提到的那样创建一个公共变量。 When the program finds an error store the cell and initiate the userform. 当程序发现错误时,存储单元并启动用户表单。 Your code will stop on the userform. 您的代码将停止在用户表单上。 When you're done checking the problem have a button on the userform that you can click to continue checking. 完成检查问题后,在用户表单上有一个按钮,您可以单击该按钮以继续检查。 Your loop can be something like the below. 您的循环可能如下所示。

public y as integer

sub temp1 ()       
  rw1= range("a500000").end(xlup).row  'any method to create a range will do
  if y = null then y=1

  for x = y to rw1
      cells(x,1).select 
      'check for the problem your looking for
      if errorX=true then
         userform1.show
         y = activecell.row
         exit sub
      end if
  next x
end sub

What about inserting a button (on the sheet or in a menubar) for stopping? 插入一个用于停止的按钮(在工作表或菜单栏中)怎么办?

Insert the code below: 在下面插入代码:

'This at the top of the module
Public mStop As Boolean

'This in the module
Sub MyBreak()
mStop = True
End Sub

'This is your macro
Sub YourMacro()
'This at the top of your code
mStop = False
'Your code
'...
    'This code where you want to break
    DoEvents '<<<< This makes possible the stop
    If mStop Then
        mCont = MsgBox("Do you want to continue?", vbYesNo)
        If mCont = vbNo Then
            Exit Sub
        Else
            mStop = False
        End If
    End If
'Your code
'...
End Sub

Now you need to create a button and link it to the macro called "MyBreak". 现在,您需要创建一个按钮并将其链接到名为“ MyBreak”的宏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM