VBScript — эффективное закрытие книги и приложения Excel

Я запускаю макрос VBS в нашей ERP, который открывает целевой документ Excel и заполняет форму данными из рабочей книги. Программа работает, но время выполнения составляет примерно полторы минуты.

Я поместил sMsgBox в разные точки сценария, чтобы увидеть, откуда идет задержка, и весь сценарий выполняется примерно за 4–5 секунд, но при просмотре активных процессов в диспетчере задач я вижу, что Execl остается открытым примерно для 1 и полминуты, и когда он закрывается, приложение ERP обновляется и заполняется данными. Скрипт ниже

Dim WshShell 
Set WshShell = CreateObject("WScript.Shell")


Dim yr
yr = InputBox("Please enter the payroll year")


Dim wk
wk = InputBox("Please enter the payroll week")


Dim path
path = "K:\Accounting\Payroll\JE\" & yr & "\Hourly\WK " & wk & "\RZU Payroll Template.xlsx"


Function FileExists(FilePath)
     Set fso = CreateObject("Scripting.FileSystemObject")
     If fso.FileExists(FilePath) Then
          FileExists=CBool(1)
     Else
          FileExists=Cbool(0)
     End If
End Function


If FileExists(path) Then
     Dim objExcel, objWorkbook, objSheet
     Set objExcel = CreateObject("Excel.Application")
     Set objWorkbook = objExcel.Workbooks.Open(path)
     Set objSheet = objExcel.ActiveWorkbook.Worksheets(3)


     Dim row
     row = 3


     Do While row <=28 
          val1 = objSheet.Cells(row,2).value
          val2 = objSheet.Cells(row,4).value
          val3 = objSheet.Cells(row,5).value
          WshShell.SendKeys "{INSERT}"
          WshShell.SendKeys val1
          WshShell.SendKeys "{TAB}"
          WshShell.SendKeys val2
          WshShell.SendKeys "{TAB}"
          WshShell.SendKeys val3
          row = row + 1
     Loop


     objExcel.ActiveWorkbook.Close
     objExcel.Workbooks.Close
     objExcel.Application.Quit
     Set objExcel = Nothing
Else
     MsgBox("Your entries resulted in an invalid File Path.  Please check the file location and try again")
End If

MsgBox(val1)

Я считаю, что использую неэффективный код для закрытия файла Excel, я ожидаю, что приложение закроется, как только команда будет выполнена, но, похоже, это не так.

Любая помощь будет оценена

Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
0
0
511
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы создаете несколько объектов, не избавляясь от них, устанавливая для них значение Ничего, например fso, WshShell, objWorkbook и objSheet. Это может вызвать задержку, которую вы испытываете.

Кроме того, скрипт использует только глобальные переменные (объявленные вне функции или подпрограммы), и эти переменные не выходят за пределы области действия (получают «сбор мусора») до тех пор, пока VBScript не будет сброшен или уничтожен. По этой причине я переписал ваш код так, чтобы все действия Excel выполнялись внутри вспомогательной функции.

Option Explicit

Dim yr, wk, path, lastInsertedValue
yr = InputBox("Please enter the payroll year")
wk = InputBox("Please enter the payroll week")
path = "K:\Accounting\Payroll\JE\" & yr & "\Hourly\WK " & wk & "\RZU Payroll Template.xlsx"

Dim WshShell, fso
Set WshShell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")

If fso.FileExists(path) Then
    lastInsertedValue = Do_ExcelStuff(path)
    'you may check this lastInsertedValue if you like:
    'MsgBox(lastInsertedValue)
Else
    MsgBox("Your entries resulted in an invalid File Path.  Please check the file location and try again")
End If

'clean up objects
Set fso = Nothing
Set WshShell = Nothing


Function Do_ExcelStuff(ByVal path)
    'Helper function to do all Excel work using variables local to the function.
    'This means they go out of scope when the function ends and should be freed immediately.
    Dim objExcel, objWorkbook, objSheet, row, val1, val2, val3

    Set objExcel = CreateObject("Excel.Application")
    objExcel.DisplayAlerts = False

    Set objWorkbook = objExcel.Workbooks.Open(path)
    Set objSheet = objExcel.ActiveWorkbook.Worksheets(3)

    row = 3
    Do While row <= 28 
        val1 = objSheet.Cells(row,2).value
        val2 = objSheet.Cells(row,4).value
        val3 = objSheet.Cells(row,5).value
        WshShell.SendKeys "{INSERT}"
        WshShell.SendKeys val1
        WshShell.SendKeys "{TAB}"
        WshShell.SendKeys val2
        WshShell.SendKeys "{TAB}"
        WshShell.SendKeys val3
        row = row + 1
    Loop

    objExcel.ActiveWorkbook.Close
    objExcel.Workbooks.Close
    objExcel.Quit
    'clean up objects
    Set objWorkbook = Nothing
    Set objSheet = Nothing
    Set objExcel = Nothing

    'return the last value inserted to prove the code did something
    Do_ExcelStuff = val1
End Function

P.S. Очень грубый способ избавления от процесса Excel - убить его сразу после последнего
Set WshShell = Nothing заявление.
Это может привести к потере данных, и риск полностью на вас, но если вы хотите знать, как это сделать, вот вам небольшая вспомогательная функция:

Function KillExcel()
   On Error Resume Next

   Dim objWMIService, colProcess
   Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}" & "!\\.\root\cimv2")

   Set colProcess = objWMIService.ExecQuery ("Select * From Win32_Process",,48)
   For Each objProcess in colProcess
      If LCase(objProcess.Name) = "excel.exe" Then
         objWshShell.Run "TASKKILL /F /T /IM " & objProcess.Name, 0, False
         objProcess.Terminate()
      End If
   Next
End Function

Спасибо, Тео, там много полезной информации, к сожалению, время выполнения по-прежнему составляет 1 минуту 20 секунд, даже с функцией убийства. Может это сеть? ERP и файл Excel находятся на разных дисках, доступ к которым ограничен. Как программист, я вызывающе новичок, с сетями я нечто большее

Dru 01.06.2019 00:21

@Dru Я не вижу ничего, что можно было бы сделать в VBScript для ускорения процесса, разве что установив objExcel.Visible = False после создания объекта. Тогда у задержки должна быть какая-то другая причина. Возможно, вы можете попробовать запустить это на своем локальном компьютере, используя копию файла Excel, чтобы увидеть разницу в скорости выполнения?

Theo 01.06.2019 10:57

Еще раз спасибо, Тео, кое-что узнал, и теперь у меня есть направление. Очень признателен

Dru 03.06.2019 17:57

Другие вопросы по теме