2016-01-12 113 views
1

我有一个宏,它可以逐行读取.txt文件。我检查每一行,如果它等于一个新页面的代码,说它是“下一个” - 如果是的话,那么插入一个分页符。在出现一定量的“NEXT”后,整个文档将被导出为pdf。然后.doc的内容被删除,我继续阅读&导出txt文件,直到EOF。每次执行VBA宏都会变慢

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

我的测试文件有27300行/ 791 kB(真实文件介于10到100MB之间)。在我启动宏之前,WINWORD进程需要40K的内存。每次执行宏后,内存使用量都会变得更大。

 Time Max.MemoryUsage MemoryUsageAfterwards 
Run1 11.9s 70K    64K 
Run2 19.7s 90K    84K 
Run3 22.3s 99K    92K 

我知道的局部解决方案是关闭和重新打开手动.doc文件,并用下一个.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 

宏用于打印PDF:

Sub PrintAsPDF() 

Dim newPdfFileName As String   ' path + name for current .pdf file 

newPdfFileName = ActiveDocument.Path & "\" & filePrefix & "-" & numOfPdfs & ".pdf" 

Selection.WholeStory     ' set font 
With Selection.Font 
    .Name = "Courier New" 
    .Size = 10.5 
End With 

ActiveDocument.SaveAs2 newPdfFileName, 17 

numOfPdfs = numOfPdfs + 1 

Selection.WholeStory 
Selection.Delete 

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 
+0

我认为我们需要看到你的整个代码来回答什么是放慢你的宏。也许尝试将您的整个代码发布到codereview.stackexchange.com? –

+0

对于[codereview.se],这可能是一个好问题,只要:**(A)** _代码works_,**和(B)** _it不以任何方式假设或不完整。在发布之前,请阅读[主题指南](http://codereview.stackexchange.com/help/on-topic),如果您选择转到[代码评论](http://codereview.stackexchange.com/问题/卖出)。如果您有任何问题或疑虑,请加入我们的[CR帮助台](http://chat.stackexchange.com/rooms/34045)。 – Quill

+0

你真的关闭过sFileName吗? –

回答

3

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

  1. 清除撤销缓冲区(ActiveDocument.UndoClear)
  2. 保存(空)文件定期

,以免费资源。

相关问题