【问题标题】:Calling an Excel sheet in VBScript在 VBScript 中调用 Excel 工作表
【发布时间】:2014-04-12 07:54:26
【问题描述】:

我有以下代码:

Option Explicit
Randomize
Dim a, song, album
a = Int((Rnd*195)+1)
song = "B" & a
album = "A" & a

Dim objApp, objWbs, objWorkbook, objSheet

Set objApp = CreateObject("Excel.Application")
Set objWbs = objApp.WorkBooks
objApp.Visible = False
Set objWorkbook = objWbs.Open("C:\Users\Name\Documents\Music.xlsx")
Set objSheet = objWorkbook.Sheets("Sheet1")

song = objSheet.Range(song).Value 
album = objSheet.Range(album).Value

objWorkbook.Close False
objWbs.Close 
objApp.Quit 

Set objSheet = Nothing
Set objWorkbook = Nothing
Set objWbs = Nothing
Set objApp = Nothing

MsgBox("Album name: " & album & vbNewLine & "Song name: " & song)

它从 Excel 工作表“音乐”的第 1 行和第 195 行之间打印两个随机单元格。其中一个 - A 列中的一个 - 代表专辑,另一个代表歌曲。问题是返回结果需要相当长的时间,大约 20 秒。

我想知道是否有更有效的方法可以让我更快地获得结果。

【问题讨论】:

    标签: excel vbscript


    【解决方案1】:

    我认为Ansgar Wiechers' answer 可能是正确的,即启动 Excel 是脚本中最慢的部分。您可以尝试使用 ADO 连接到 Excel 文件,就好像它是一个数据库一样。这样可以避免启动 Excel:

    Option Explicit
    
    Randomize
    Dim conn, rst, song, album
    
    Set conn = CreateObject("ADODB.Connection")
    conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=C:\Users\Name\Documents\Music.xlsx;" & _
        "Extended Properties='Excel 12.0 Xml;HDR=NO';"
    
    ' Select a random record; reference https://stackoverflow.com/a/9937263/249624
    ' Asc(album) is just a way to get some numeric value from the existing data
    Set rst = conn.Execute("SELECT TOP 1 F1 AS album, F2 as song FROM [Sheet1$] ORDER BY Rnd(-(100000*Asc(F1))*Time())")
    
    If rst.EOF Then
        song = "[NO RECORDS]"
        album = "[NO RECORDS]"
    Else
        song = rst("song").Value
        album = rst("album").Value
    End If
    
    MsgBox("Album name: " & album & vbNewLine & "Song name: " & song)
    

    这里的一个可能问题是 VBScript 默认使用 64 位版本的 wscript.exe 运行,而 64 位 ACE.OLEDB 仅在您安装了 64 位版本的 Office 2010 或更高版本时可用.不过,这可以通过使用 32 位版本的 wscript.exe 运行脚本来解决(例如,请参阅 How do I run a VBScript in 32-bit mode on a 64-bit machine?)。

    如果您决定走这条路并且可以控制输入的 Excel 文件,我建议您在电子表格中添加一个标题行并将连接字符串中的 HDR=NO 更改为 HDR=YES。这样,您可以在查询中按名称引用列(例如,SELECT TOP 1 album, song ...),而不是依赖“F1”语法。

    【讨论】:

      【解决方案2】:

      脚本中最耗时的步骤最有可能

      • 启动 Excel 和
      • 打开工作簿。

      您可以做的一件事是使用已经运行的 Excel 实例,而不是一直创建一个新实例:

      quitExcel = False
      
      On Error Resume Next
      Set objApp = GetObject(, "Excel.Application")
      If Err Then
        Set objApp = CreateObject(, "Excel.Application")
        quitExcel  = True
      End If
      On Error Goto 0
      

      变量quitExcel 指示您是否需要在脚本结束时(当您创建新实例时)关闭 Excel(当您使用已经运行的实例时)。

      您还可以检查工作簿是否已打开:

      wbOpen = False
      For Each wb In objWbs
        If wb.Name = "Music.xlsx" Then
          Set objWorkbook = wb
          wbOpen = True
          Exit For
        End If
      Next
      
      If Not wbOpen Then
        Set objWorkbook = objWbs.Open("C:\Users\Name\Documents\Music.xlsx")
      End If
      

      除了你唯一的选择是改变数据的存储方式或购买更快的硬件,AFAICS。

      【讨论】:

        【解决方案3】:

        Cheran,我不同意这里的答案。

        我刚刚在我用了 5 年的笔记本电脑上运行了您的脚本,并在大约 2 秒内得到了答案。 Excel 实例是否已打开对运行时间没有影响。

        (我创建了一个测试 Music.xlsx 电子表格,方法是在单元格 A1 中输入“A1”,在单元格 B1 中输入“B1”,然后将这些单元格拖到第 195 行以获得一组不错的独特样本数据)。

        为什么不让 Excel 在运行时可见,以便您自己查看发生了什么?

        您可能会看到,例如,Excel 需要一秒钟才能打开,而您拥有的 Excel 加载项需要另外 15 秒钟来初始化。您的机器和/或硬盘驱动器也可能很慢,并且确实需要 20 秒才能运行它。谁知道...

        要获得一些见解,请使 objApp.Visible = True 并重新运行。

        您还可以注释掉最后八行,除了 MsgBox 行,以便您的 Excel 文件在脚本完成后保持打开状态,以便您可以看到其他线索。

        其他意见: 1) 您使用 .vbs 脚本中的 CreateObject 打开 Excel 的方法似乎是自动化 Excel 的最可靠/公认的方法。

        2) 这里没有说明您是如何运行 .vbs 脚本的(命令行与资源管理器中的双击)。您的脚本正在运行,但请注意,当人们尝试自动执行此操作时,使用 cscript.exe 运行 .vbs 也很常见。

        3) 我不习惯看到外部 vbs 与 Excel 中的数据交互...我习惯于让 vbs 打开 Excel.xlsm,然后让宏进行数字运算。但是,宏带来了完全不同的一系列问题。我不是说你的方法是好是坏……只是不习惯那种方法。

        祝你好运!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-23
          • 2017-09-22
          • 2011-10-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多