Доступ к Excel: сокращение времени выполнения Excel VBA - PullRequest
0 голосов
/ 19 февраля 2019

Подобные версии этого вопроса, вероятно, задавались ранее, но у меня были вопросы по этой проблеме.

В основном для своей функции я просто хочу запустить простую проверку орфографии для выбранных таблиц из Microsoft Access.Поскольку Access не поддерживает отдельную подсветку в отчетах, я экспортирую данные в файл Excel и запускаю тесты VBA на наличие ошибок.После поиска в Интернете советов, у меня есть текущий код, чтобы работать быстрее, чем у меня изначально.Но в идеале, независимо от размера таблицы, я хочу, чтобы функция выполнялась в течение 10 минут.Но в настоящее время для некоторых из них, для таблиц, которые имеют ячейки 500k +, время выполнения может все еще превышать 30 минут.Поэтому мне было интересно, можно ли что-нибудь сделать для улучшения времени выполнения этого.

Private Function Excel_Parser(outFile As String, errorCount As Integer, ByVal tName As String)

 ' EXCEL SETUP VARIABLES
 Dim OpenApp As Excel.Application
 Set OpenApp = CreateObject("Excel.Application")

 Dim parserBook As Excel.Workbook
 Dim parserSheet As Excel.Worksheet

 ' Opening exported file
 Set parserBook = OpenApp.Workbooks.Open(outFile, , , , , , , , , , , , , , XlCorruptLoad.xlRepairFile)

 If parserBook Is Nothing Then
    status2 = "Failed to set Workbook"
    Exit Function
 Else

     status3 = "Searching [" & tName & "] for errors"

     Set parserSheet = parserBook.Worksheets(1)

     ' --------------------------------------------------------------------------------
     ' Fetch Table information
     lastCellAddress = parserSheet.Range("A1").SpecialCells(xlCellTypeLastCell).Address

     Dim rng As Range
     Set rng = parserSheet.Range("A1:" & lastCellAddress)
     ' --------------------------------------------------------------------------------

     ' Populating entire table data from Excel into array to save runtime.
     Dim dataArr() As Variant, R As Long, C As Long
     dataArr = rng.Value2

     ' Parsing through table data array
     nRows = UBound(dataArr, 1)
     nCols = UBound(dataArr, 2)

     fileOuterLoop1 = Time

     For R = 1 To nRows

         For C = 1 To nCols

             cCell = CStr(dataArr(R, C))
             status4 = "Now running check on cell: [" & cCell & "]"

             If cCell <> "" Or Not (IsNull(cCell)) Then

                If Not OpenApp.Application.CheckSpelling(cCell) Then

                    errorCount = errorCount + 1

                    ' Change cell status
                    vArr = Split(parserSheet.Cells(1, C).Address(True, False), "$")
                    fCol = vArr(0)
                    xDef = fCol & R
                    parserSheet.Range(xDef).Interior.Color = RGB(255, 213, 124)

                End If

             End If  'End of cCell is null check
         Next C
     Next R

     fileOuterLoop2 = Time
     fCheck = Format(fileOuterLoop2 - fileOuterLoop1, "hh:mm:ss")

     ' --------------------------------------------------------------------------------

     parserSheet.Columns.AutoFit
     status7 = "Loop Finished. Runtime: " & fCheck

     ' Save and Cleanup
     OpenApp.DisplayAlerts = False
     parserBook.SaveAs FileName:=outFile, FileFormat:=xlWorkbookDefault, ConflictResolution:=xlLocalSessionChanges
     parserBook.Saved = True
     parserBook.Close SaveChanges:=False
     OpenApp.DisplayAlerts = True

     Set parserSheet = Nothing
     Set parserBook = Nothing
     Set OpenApp = Nothing

     ' Return errorCount for database
     Excel_Parser = errorCount

 End If

End Function

outFile - это строка PATH, где файл существует из команды TransferSpreadsheet.А переменные «status» - это просто текстовые поля журнала ошибок в форме доступа.Я попытался добавить в Access'е и Excel версии ScreenUpdating или Echo, но обнаружил, что эти команды на самом деле замедляют выполнение моей функции.

1 Ответ

0 голосов
/ 20 февраля 2019

Две вещи:

  1. Используете ли вы где-нибудь в своем коде status4, чтобы показать текущее состояние работы, и просто опустите его здесь, в примере?Если это так, подумайте о том, чтобы не отображать его для каждого цикла, но, возможно, только через каждые 50 шагов, используя оператор Mod.

    См. https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/mod-operator

  2. Следует избегать обновления экрана иподробнее о каждом цикле в Excel, установив его перед циклом:

    OpenApp.ScreenUpdating = False
    OpenApp.EnableEvents = False
    OpenApp.Calculation = Excel_XlCalculation.xlCalculationManual
    

    И это после цикла:

    OpenApp.ScreenUpdating = True
    OpenApp.EnableEvents = True
    OpenApp.Calculation = Excel_XlCalculation.xlCalculationAutomatic
    

Это может закончиться огромной скоростьювверх.Попробуйте.

...