Performance VBA宏每次执行都会变慢

Performance VBA宏每次执行都会变慢,performance,vba,ms-word,Performance,Vba,Ms Word,我有一个宏可以逐行读取.txt文件。我检查每一行是否等于某个新页面的代码,说它是“下一个”——如果是,则插入分页符。在出现一定数量的“下一步”之后,整个文档将导出为pdf。然后删除.doc的内容,我继续读取并导出txt文件,直到EOF 问题:宏每次执行都会变慢 我的测试文件有27300行/791KB(实际文件在10到100MB之间)。在启动宏之前,WINWORD进程占用40K内存。每次执行宏后,内存使用量都会增加 Time Max.MemoryUsage MemoryUs

我有一个宏可以逐行读取.txt文件。我检查每一行是否等于某个新页面的代码,说它是“下一个”——如果是,则插入分页符。在出现一定数量的“下一步”之后,整个文档将导出为pdf。然后删除.doc的内容,我继续读取并导出txt文件,直到EOF

问题:宏每次执行都会变慢

我的测试文件有27300行/791KB(实际文件在10到100MB之间)。在启动宏之前,WINWORD进程占用40K内存。每次执行宏后,内存使用量都会增加

        Time    Max.MemoryUsage  MemoryUsageAfterwards
Run1    11.9s   70K              64K
Run2    19.7s   90K              84K
Run3    22.3s   99K              92K
我知道部分解决方案是手动关闭并重新打开.doc文件,然后以next.txt文件作为输入运行宏。但是,即使在运行一次宏之后关闭Word也需要很长时间,尽管文件中没有我可以看到的内容

我想问的是,是否有其他方法可以解决这个问题,我认为这是一个记忆清除问题

我的代码:

打开文档时:

Private Sub Document_Open()
    ReadAndSplit
End Sub
全局变量和声明:

Option Explicit
'---------------------------------------------------------------------------
'                                       GLOBAL VARIABLES
'---------------------------------------------------------------------------
Public numOfBreaks  As Integer          ' number of page breaks made
Public numOfPdfs    As Integer          ' number of currently printed pdf
Public filePrefix   As String           ' name prefix for .pdf files
Public sFileName    As String           ' name of Input File
Public breakAfter   As Integer          ' print after this number of NEXT
Public cancelActive As Boolean          ' cancel Button pressed? (for exit)
主要宏:

Sub ReadAndSplit()
'---------------------------------------------------------------------------
'                                       VARIABLES
'---------------------------------------------------------------------------
Dim sLine           As String           ' line from text file
Dim numOfLines      As Long             ' number of lines read from .txt input
Dim execStart       As Single           ' starting time of script execution
Dim nextPage        As Boolean          ' indicates if new document beginns

'---------------------------------------------------------------------------
'                                       INITIAL PROCESSING
'---------------------------------------------------------------------------    
Application.Visible = False              
Application.ScreenUpdating = False       
Selection.WholeStory                    ' clear the document
Selection.Delete
UserForm1.Show                          ' show user dialog
If cancelActive Then                    ' Cancel button handling
    Application.Visible = True
    Exit Sub
End If

With ActiveDocument.PageSetup           ' set page margins & orientation
    .TopMargin = 0.1
    .BottomMargin = 0.1
    .LeftMargin = 0.1
    .RightMargin = 0.1
End With
'---------------------------------------------------------------------------
'                                       MAIN PROCESSING
'---------------------------------------------------------------------------
numOfBreaks = 0                         ' GLOBALS
numOfPdfs = 1
numOfLines = 0                          ' LOCALS
nextPage = True
execStart = Timer

Open sFileName For Input As #1

Do While Not EOF(1)

    If nextPage Then                                    ' write 2 empty lines
        Selection.TypeText (vbNewLine & vbNewLine)
        nextPage = False
    End If

    Line Input #1, sLine                                ' read 1 line from input
    numOfLines = numOfLines + 1                         ' count lines

    If sLine <> "NEXT" Then                             ' test for NEXT
        Selection.TypeText (sLine) & vbNewLine          ' write line from input .txt
    Else
        Selection.InsertBreak Type:=wdPageBreak         ' NEXT -> new page
        numOfBreaks = numOfBreaks + 1                   ' count new receipts

        If numOfBreaks = breakAfter Then                ' compare with PARAM
            PrintAsPDF                                  ' export to pdf
            numOfBreaks = 0
        End If

        nextPage = True                                 ' switch new page on
    End If
Loop

If numOfBreaks <> 0 Then                                ' print out the last part
    PrintAsPDF
End If

Close #1

Debug.Print vbNewLine & "-----EXECUTION-----"
Debug.Print Now
Debug.Print "Lines: " & numOfLines
Debug.Print "Time: " & (Timer - execStart)
Debug.Print "-------------------" & vbNewLine

Selection.WholeStory                                    ' clear the word document
Selection.Delete

Application.Visible = True

End Sub
用户表单代码:

'---------------------------------------------------------------------------
'                                       OK BUTTON
'---------------------------------------------------------------------------
Private Sub OKButton_Click()

Dim inputFileOk     As Boolean  ' input file path
Dim inputSplitOk    As Boolean  ' split
Dim prefixOk        As Boolean  ' prefix

If FileTxtBox.Text = vbNullString Then          ' validate file path
    inputFileOk = False
    MsgBox ("File path missing!")
Else
    inputFileOk = True
End If

If IsNumeric(SplitTxtBox.Text) Then             ' validate breakAfter
    breakAfter = SplitTxtBox.Text
    inputSplitOk = True
Else
    MsgBox ("Non-numeric value for SPLIT!")
End If

If PrefixTxtBox <> vbNullString Then            ' validate prefix
    filePrefix = PrefixTxtBox.Text
    prefixOk = True
Else
    MsgBox ("Missing prefix!")
End If

                                                ' check if all inputs are ok
If inputFileOk And inputSplitOk And prefixOk Then
    cancelActive = False
    Unload Me
End If

End Sub
'---------------------------------------------------------------------------
'                                       CANCEL BUTTON
'---------------------------------------------------------------------------
Private Sub CancelButton_Click()
cancelActive = True             ' for script termination
Unload Me
End Sub
'---------------------------------------------------------------------------
'                                       FILE BUTTON
'---------------------------------------------------------------------------
Private Sub FileButton_Click()    
Dim i           As Integer      ' file selection index

' show file chooser dialog and assign selected file to sFileName
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
i = Application.FileDialog(msoFileDialogOpen).Show

If i <> 0 Then
    sFileName = Application.FileDialog(msoFileDialogOpen).SelectedItems(1)
    FileTxtBox.Text = sFileName
End If

End Sub
'---------------------------------------------------------------------------
'确定按钮
'---------------------------------------------------------------------------
私有子按钮点击()
Dim inputFileOk作为布尔输入文件路径
Dim inputSplitOk作为布尔值“拆分”
作为布尔“前缀”的Dim prefixOk
如果FileTxtBox.Text=vbNullString,则“验证文件路径”
inputFileOk=False
MsgBox(“文件路径丢失!”)
其他的
inputFileOk=True
如果结束
如果是数字(SplitTxtBox.Text),则“验证breakAfter”
breakAfter=SplitTxtBox.Text
inputSplitOk=True
其他的
MsgBox(“拆分的非数值!”)
如果结束
如果PrefixtBox vbNullString,则“验证前缀”
filePrefix=prefixtxbox.Text
prefixOk=True
其他的
MsgBox(“缺少前缀!”)
如果结束
'检查所有输入是否正常
如果inputFileOk和inputSplitOk以及prefixOk,则
取消活动=错误
卸下我
如果结束
端接头
'---------------------------------------------------------------------------
'取消按钮
'---------------------------------------------------------------------------
专用子按钮取消单击()
对于脚本终止,cancelActive=True
卸下我
端接头
'---------------------------------------------------------------------------
'文件按钮
'---------------------------------------------------------------------------
私有子文件按钮\单击()
Dim i作为整数的文件选择索引
'显示文件选择器对话框并将所选文件分配给sFileName
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect=False
i=Application.FileDialog(msoFileDialogOpen.Show)
如果我是0那么
sFileName=Application.FileDialog(msoFileDialogOpen)。选择editems(1)
FileTxtBox.Text=sFileName
如果结束
端接头

Word在“临时”文件中存储大量信息,以便跟踪“无限”撤消。如果在不保存文件或不清除撤消缓冲区的情况下执行大量操作,则会减慢Word的速度。因此,我建议:

  • 清除撤消缓冲区(ActiveDocument.UndoClear)
  • 定期保存(空)文档

  • 为了释放资源。

    我认为我们需要查看您的全部代码,以回答是什么让宏变慢了。也许试着把你的全部代码发布到codereview.stackexchange.com上?这可能是一个很好的问题,只要:(a)代码有效,(B)它不是假设的或不完整的。如果您选择转到,请在发帖前阅读。如果您有任何问题或担忧,请加入我们的网站。您是否尝试过在没有打印PDF的情况下运行。我在过去遇到过pdf的问题,可能值得将此过程作为一个原因加以消除。在您的位置上,我将看1)清除撤消缓冲区和2)保存(空)文档。Word存储所有内容以启用“撤消”,这可能会减慢速度。我在移动设备上,因此无法检查清除撤消的确切语法,但类似于Document.Undo.Clear…请不要编辑问题以包含解决方案(即答案)。这里关于堆栈溢出的正确方法是“回答”这个问题。
    '---------------------------------------------------------------------------
    '                                       OK BUTTON
    '---------------------------------------------------------------------------
    Private Sub OKButton_Click()
    
    Dim inputFileOk     As Boolean  ' input file path
    Dim inputSplitOk    As Boolean  ' split
    Dim prefixOk        As Boolean  ' prefix
    
    If FileTxtBox.Text = vbNullString Then          ' validate file path
        inputFileOk = False
        MsgBox ("File path missing!")
    Else
        inputFileOk = True
    End If
    
    If IsNumeric(SplitTxtBox.Text) Then             ' validate breakAfter
        breakAfter = SplitTxtBox.Text
        inputSplitOk = True
    Else
        MsgBox ("Non-numeric value for SPLIT!")
    End If
    
    If PrefixTxtBox <> vbNullString Then            ' validate prefix
        filePrefix = PrefixTxtBox.Text
        prefixOk = True
    Else
        MsgBox ("Missing prefix!")
    End If
    
                                                    ' check if all inputs are ok
    If inputFileOk And inputSplitOk And prefixOk Then
        cancelActive = False
        Unload Me
    End If
    
    End Sub
    '---------------------------------------------------------------------------
    '                                       CANCEL BUTTON
    '---------------------------------------------------------------------------
    Private Sub CancelButton_Click()
    cancelActive = True             ' for script termination
    Unload Me
    End Sub
    '---------------------------------------------------------------------------
    '                                       FILE BUTTON
    '---------------------------------------------------------------------------
    Private Sub FileButton_Click()    
    Dim i           As Integer      ' file selection index
    
    ' show file chooser dialog and assign selected file to sFileName
    Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
    i = Application.FileDialog(msoFileDialogOpen).Show
    
    If i <> 0 Then
        sFileName = Application.FileDialog(msoFileDialogOpen).SelectedItems(1)
        FileTxtBox.Text = sFileName
    End If
    
    End Sub