如何暂停 VBA 脚本执行,直到打开下载的 .csv 文件以允许在 2 个工作簿之间复制工作表?

How to pause VBA script execution until downloaded .csv file opens to allow copying worksheets between the 2 workbooks?

我有一个脚本可以从 Yahoo Finance 下载 creates/opens 一个新的 Excel .csv 历史股票数据工作簿。然后,我从该 .csv 工作簿中复制 worksheet(1) 的内容,并在 ThisWorkbook(包含我的 macro/script 的那个)中创建一个新的 worksheet(最后)并粘贴的数据。我已将浏览器 (Chrome) 配置为始终打开 .csv 文件下载。这是一些示例代码:

Sub Macro1()

    Dim urlLink As String
    Dim csvWorkbook As Workbook
    
    urlLink = "https://query1.finance.yahoo.com/v7/finance/download/AAPL?period1=1592179200&period2=1623715200&interval=1d&events=history&includeAdjustedClose=true"
    ActiveWorkbook.FollowHyperlink Address:=urlLink, NewWindow:=True
    Set csvWorkbook = ActiveWorkbook
    csvWorkbook.Sheets(1).Copy after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)

End Sub

urlLink 是一个示例查询,用于以 .csv 格式从 Yahoo Finance 下载历史数据。将默认浏览器设置为始终打开 .csv 类型的文件。当执行 ActiveWorkbook.FollowHyperlink 时,另一个实例 Excel 将打开,并且 AAPL.csv 将打开。这个新的 AAPL.csv 将成为活动工作簿,然后下一行代码将在 ThisWorkbook(包含您的脚本的工作簿)中创建一个新的 sheet 并复制 AAPL.csv Sheet(1) 进去.

我的问题是,当我单步执行代码时,它工作正常,但当 运行 全速运行时(即不在调试模式下),它失败了。澄清一下,假设你从一个新的空白工作簿开始,如果你单步执行上面的代码,你会得到一个新的 sheet 命名为 AAPL 添加到你的工作簿中,其中包含 253 行数据(我想要的结果),但是如果你 运行 它全速你会得到一个新的空白 sheet 添加名为 Sheet1(2)。

我发现这是因为在全速下,新的 .csv 文件没有得到 created/open 所以当 Set csvWorkbook = ActiveWorkbook 是 运行 时仍然只有 1 个工作簿打开(ThisWorkbook) 所以下一个代码行只是将 ThisWorkbook 的 Sheet(1) 复制到一个新的 sheet 中,而不是将 Sheet(1) 从 AAPL.csv 复制到其中(因为当那行代码是 运行).

时它不存在

请注意,新创建的工作簿的名称并不总是已知的,因为如果该下载文件夹中已经有一个 APPL.csv,它会将下一个命名为 APPL(1).csv 和等等,所以我不能只使用新创建的 .csv 工作簿的名称来引用它,因为我不知道它会是什么。

所以我要求一种方法来在执行 ActiveWorkbook.FollowHyperlink 时或之后在调试模式下模拟单步执行代码。我试过简单地在 MsgBox 之后放置一个 MsgBox,它认为要求用户单击“确定”以继续执行会有所帮助,但事实并非如此,而且从我读到的内容来看,我认为 Wait 或类似的东西也没有帮助吗?这类似于 Pause execution of VBA script until another specific excel workbook opens? 中的问题 但我不明白该线程中给出的答案,不确定它是否真的适用?感谢您对此的任何帮助!

您可以将 URL 直接传递给 Workbooks.Open():

Dim wb, ws
Set wb = Workbooks.Open("https://query1.finance.yahoo.com/v7/finance/download/AAPL?period1=1592179200&period2=1623715200&interval=1d&events=history&includeAdjustedClose=true")
Set ws = wb.Sheets(1)
'run text to columns if only one column of data
If ws.UsedRange.Columns.Count = 1 Then
    ws.Columns(1).TextToColumns Destination:=ws.Range("A1"), DataType:=xlDelimited, _
    TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Comma:=True
End If