vba - 您可以中断 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 张它运行上面的代码,如果它有不止一张让我选择我想要的工作表然后运行其余代码?
解决方案
编辑:
这只是我偶尔使用 的基本暂停例程的扩展。
这是我的“常规”Pause
例程(使用Timer
函数):
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
对于简单的事情最有用,例如允许用户在启动后取消进程,例如搜索文件。对于长时间运行的进程,通过使用 Timer 或将任务委派给ActiveX
EXE
组件来更好地完成让出处理器 - 并且操作系统负责多任务处理和时间切片。每当您在事件过程中临时让出处理器时,请确保在第一次调用返回之前不会从代码的不同部分再次执行该过程;这可能会导致不可预测的结果。
源中的更多详细信息(和警告)。
原答案:
一些建议的解决方案:
您可以提示用户指定哪个工作表,而不是“停止”代码。
您可以通过简单的计时器循环“暂停”执行以给用户一定的时间来选择工作表,甚至可以检查工作表名称以查看用户是否选择了新的工作表,如下所示:
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
这有点做作,但可以工作,特别是如果进行适当的检查以确保您现在拥有正确的工作表。
我想您可以创建一个工作表事件过程,该过程将在激活工作表时运行,并检查全局变量以查看您的“导入过程”是否正在运行,如果是,请恢复您的代码......但这会很混乱而且令人困惑,并且需要代码存在于您“导入”的工作簿中。
或者,比其中任何一个更好的是根据工作表的内容以编程/逻辑方式确定您需要哪个工作表。有标题吗?某个日期?也许是最新的工作表?某个牢房里有什么东西?必须有一些东西可以将它与其他东西区分开来。
希望这能给您一些关于非线性解决方案的想法。
推荐阅读
- javascript - 我是 JavaScript 新手,对如何观察、测试我的代码以查看它是否“有效”感到困惑
- firebase - Flutter --> Listile 和 Streambuilder
- ruby-on-rails - 排序嵌套属性
- c - 如何将我下载的库添加到我的 C 编译器?
- python - 从 Python (3.6) 开始,将具有给定用户权限的文件复制到根控制空间
- syntax - spss中是否有旋转托盘语法?
- php - 会话变量有时不存储
- android - adb 设备 - 不显示 iphone 设备
- react-admin - 每次更新后防止react-admin重定向到第一页?
- python - 如何在模糊c-means(python)中围绕集群绘制边界