您可以中断vba代码来进行工作表选择吗?

时间:2018-09-27 07:35:44

标签: excel vba excel-vba

我会在说明中尽量保持清楚,因此这里什么也没做:

我创建了一个代码,用户在其中选择自己的excel文件,然后宏将文件中的Sheet复制到我的宏Workbook中。

MyFile = Application.GetOpenFilename()
    Workbooks.Open (MyFile)
        ActiveSheet.Copy After:=wbook.Sheets(1)
        ActiveSheet.Name = "Selected file"
    Workbooks.Open (MyFile)
ActiveWorkbook.Close SaveChanges:=False

这是可行的,但我意识到的是,在某些情况下,所选文件可能具有多个Sheets

有没有一种写宏的方法,如果我选择的文件有1张纸,它将运行上面的代码,并且如果有多张纸,让我选择我想要的表,然后运行其余的代码,是否可以编写宏?

2 个答案:

答案 0 :(得分:5)

编辑:

  • 我想到了另一种方式来处理此问题-也许更接近于您要查找的内容。 。 。

    img

这只是我偶尔使用的基本 暂停 例程的扩展。

这是我的“常规” Pause例程(使用Timer function):

Sub Pause(seconds As Single)
    Dim startTime As Single
    startTime = Timer                          'get current timer count
    Do
        DoEvents                               'let Windows "catch up"
    Loop Until Timer > startTime + seconds     'repeat until time's up
End Sub

...所以,它给了我一个主意。

老实说,我发现它确实有效,因为它基本上是同时运行两个代码段


WaitForUserActivity的代码:

这是我在上面的演示中使用的代码:

Option Explicit
Public isPaused As Boolean

Sub WaitForUserActivity()                   'THE 'RUN DEMO' BUTTON runs this sub.

    Dim origSheet As String
    isPaused = True                                   'flag "pause mode" as "on"
    origSheet = ActiveSheet.Name                'remember current worksheet name

    MsgBox "This will 'pause' code execution until you" & vbLf & _
           "click the 'Continue' button, or select a different a worksheet."
    Application.StatusBar = "PAUSED: Click ""Continue"", or select a worksheet."

    Do                                       'wait for button click or ws change
        DoEvents        'yield execution so that the OS can process other events
    Loop Until (Not isPaused) Or (ActiveSheet.Name <> origSheet)

    If isPaused Then                           'the active worksheet was changed
        MsgBox "Worksheet '" & ActiveSheet.Name & "' was selected." _
              & vbLf & vbLf & "Now the program can continue..."
    Else                                                 'the button was clicked
        MsgBox "The 'Continue' button was clicked." _
              & vbLf & vbLf & "Now the program can continue..."
    End If
    Application.StatusBar = "Ready"
End Sub

Sub btnContinue()                          'THE 'CONTINUE' BUTTON runs this sub.
    isPaused = False                                 'flag "pause mode" as "off"
End Sub

要运行演示

  • 将以上代码放入常规模块中
  • 确保工作簿至少有两个工作表
  • 创建两个命令按钮:
    • 为“ 运行演示”按钮之一,分配宏:WaitForUserActivity
    • 使用一个“ 继续”按钮,分配宏:btnContinue
  • 点击“ 运行演示”按钮

代码中的关键命令是DoEvents Function,它“产生执行力,以便操作系统可以处理其他事件。”

  

DoEvents将控制权传递给操作系统。在操作系统完成处理其队列中的事件并且已发送SendKeys队列中的所有键之后,将返回控件。

     

DoEvents对于简单的事情最为有用,例如允许用户在进程启动后取消进程,例如搜索文件。对于长时间运行的进程,使用计时器或将任务委派给ActiveX EXE组件可以更好地完成处理器的生产-操作系统负责多任务处理和time slicing

     

每次在事件过程中暂时让处理器产生结果时,确保在第一次调用返回之前不会从代码的其他部分再次执行该过程;这可能会导致不可预测的结果。

     

source上的其他详细信息(和警告)。



原始答案:

一些建议的解决方案:

  1. 您可以提示用户来指定哪个工作表,而不是“停止”代码。

    • 最简单的方法是使用InputBox,用户可以输入ID号或以其他方式标识工作表。

    • 更复杂但更健壮和更专业的外观是借助用户窗体的自定义对话框。在线上有一些示例和教程,例如this one

  2. 您可以“暂停”执行,以简单的计时器循环为用户提供一定的时间来选择工作表,甚至可以检查工作表名称以查看用户是否选择了一个新的文件,如下所示:

    Dim startTime As Single, shtName As String
    If ThisWorkbook.Worksheets.Count = 1 Then
        MsgBox "There is only one worksheet in this workbook."
    Else
        shtName = ActiveSheet.Name 'get name of active sheet
        MsgBox "You have 5 seconds to select a worksheet after clicking OK.", _
            vbOKOnly + vbInformation, "Select a worksheet... fast!"
        startTime = Timer
        Do
            DoEvents
        Loop Until Timer > startTime + 5
    
        'check if user picked a new worksheet
        If ActiveSheet.Name = shtName Then
            MsgBox "You didn't select a new worksheet!"
        Else
            MsgBox "Thanks for selecting a new worksheet!"
        End If
    End If
    

    这有点曲折,但可以使用,尤其是如果进行适当检查以确保您现在拥有正确的工作表。

  3. 我想您可以创建一个工作表事件过程,该事件过程将在激活工作表时运行,并检查一个全局变量以查看您的“导入过程” 是否是运行,如果是这样,则继续您的代码...,但这会造成混乱和混乱,并且要求代码在您要“导入”的工作簿中存在。

    < / li>
  4. 或者,优于任何一个将是基于工作表的内容以编程方式/ 逻辑地确定所需的工作表。有标题吗?某个日期?也许最新的工作表?某个单元中有东西吗?必须有一些与众不同的地方。

希望这会为您提出一些非线性解决方案的想法。

答案 1 :(得分:1)

  

总体而言,我会推荐ashleedawg的解决方案,但如果您   坚持维护您的代码结构,您的代码可以看起来   像这样的东西:

您可以使用.Count对象(或Sheets)的Worksheets属性来区分工作簿具有的工作表数量(如果您不想包括Chart s),然后使用InputBox检查要查找的工作表。

MyFile = Application.GetOpenFilename()
Workbooks.Open (MyFile)

If ThisWorkbook.Sheets.Count = 1 Then
  ThisWorkbook.ActiveSheet.Copy After:=wbook.Sheets(1)
  ThisWorkbook.ActiveSheet.Name = "Selected File"
Else
  Dim checkfor As String
  checkfor = InputBox("What Sheet should I execute the code for?")

  Dim i As Integer
  For i = 0 To ThisWorkbook.Sheets.Count
     If Trim(LCase(checkfor)) = Trim(LCase(Sheets(i).Name))) Then
        ThisWorkbook.Sheets(i).Copy After := wbook.Sheets(1)
        ThisWorkbook.Sheets(i).Name = "Selected file"
     End If
  Next i
End If

Workbooks.Open (MyFile)
ActiveWorkbook.Close SaveChanges:=False

可能需要进一步调整,因为我不确定您到底想要实现什么。