VBA:缓慢的宏循环段落

时间:2017-02-22 11:49:17

标签: vba ms-word

我在VBA Word 2016(Win10)中的宏对于3页文档而言非常慢。我该怎么做才能让它更快?还是有另一种方式我可以计算不同风格的段落中的字符?我需要知道在普通风格,H1风格等中写了多少个字符。

Sub avsnittsteller()

'Optimize Code
Application.ScreenUpdating = False

'Rydd opp i formateringen
'Call stilFinner

intTittel = ActiveDocument.CustomDocumentProperties("malTittel").Value
intTittelI = ActiveDocument.CustomDocumentProperties("malTittelI").Value
intTittelX = ActiveDocument.CustomDocumentProperties("malTittelX").Value
intIngress = ActiveDocument.CustomDocumentProperties("malIngress").Value
intNormal = ActiveDocument.CustomDocumentProperties("malNormal").Value

'sett variablene til 0 før de avsnittene telles
Dim mlm(10) As String
tittel = 0
ingress = 0
mlm(1) = 0
mlm(2) = 0
mlm(3) = 0
mlm(4) = 0
mlm(5) = 0
mlm(6) = 0
mlm(7) = 0

' TELLE TEGN I ALLE AVSNITT
Dim Doc As Document
Set Doc = ActiveDocument
Dim para As Paragraph
Dim i As Long: i = 0
Dim j As Long: j = 0
Dim k As Long: k = 0

For Each para In Doc.Paragraphs
    If para.Style = Doc.Styles("instruksjon") Or _
    para.Style = Doc.Styles("Bildetekst") Or _
    para.Style = Doc.Styles("Byline") Or _
    para.Style = Doc.Styles("Byline email") Or _
    para.Style = Doc.Styles("Fakta punkt") Or _
    para.Style = Doc.Styles("tittel") Then
    Else
    If para.Style = Doc.Styles(wdStyleHeading1) Then
        tittel = para.Range.Characters.Count - 1
    Else
        If para.Style = Doc.Styles(wdStyleHeading2) Then
            ingress = para.Range.Characters.Count - 1
        Else
            If para.Style = Doc.Styles(wdStyleHeading3) Then
                i = i + 1
                mlm(i) = para.Range.Characters.Count - 1
            Else
                If para.Style = Doc.Styles(wdStyleNormal) Then
                    j = j + para.Range.Characters.Count - 1
                End If 'N
            End If 'H3
        End If 'H2
    End If 'H1
    End If 'alle andre stiler
Next para
normal = j
'MsgBox "Tittelen din har " & tittel & " tegn" & vbCrLf & " ingress " & ingress & vbCrLf & " mlm-3 " & mlm(3) & vbCrLf & " mlm-4 " & mlm(4) & vbCrLf & "Alle normal " & normal
'MsgBox "Dokumentet blir nå lagret og antall tegn du har skrevet blir oppdatert øverst i dokumentet."
'MsgBox ActiveDocument.Paragraphs.Count

'DEFINER DOC PROPERTIES VARIABLENE
ActiveDocument.CustomDocumentProperties("tittel").Value = tittel
ActiveDocument.CustomDocumentProperties("ingress").Value = ingress
ActiveDocument.CustomDocumentProperties("mlm1").Value = mlm(1)
ActiveDocument.CustomDocumentProperties("mlm2").Value = mlm(2)
ActiveDocument.CustomDocumentProperties("mlm3").Value = mlm(3)
ActiveDocument.CustomDocumentProperties("mlm4").Value = mlm(4)
ActiveDocument.CustomDocumentProperties("mlm5").Value = mlm(5)
ActiveDocument.CustomDocumentProperties("mlm6").Value = mlm(6)
ActiveDocument.CustomDocumentProperties("mlm7").Value = mlm(7)
ActiveDocument.CustomDocumentProperties("normal").Value = j

ActiveDocument.Fields.Update 'OPPDATER ALLE FELT nb, virker ikke i bunn og topptekst

 'MsgBox intTittelX

'Farg tittel og ingress rød om de er for lange, blå om de er passe korte
If tittel > intTittelX Then
    With ActiveDocument.Styles(wdStyleHeading1).Font
        .Color = wdColorRed
    End With
Else
    With ActiveDocument.Styles(wdStyleHeading1).Font
        .Color = -738148353
    End With
End If

If ingress > intIngress Then
    With ActiveDocument.Styles(wdStyleHeading2).Font
        .Color = wdColorRed
    End With
Else
    With ActiveDocument.Styles(wdStyleHeading2).Font
        .Color = -738148353
    End With
End If


'Optimize Code
Application.ScreenUpdating = True

End Sub

2 个答案:

答案 0 :(得分:0)

首先尝试将其加载到内存中,然后在将数据加载到数组后执行操作。我刚做了大约60页的测试,大约需要8秒才能将各种属性填充到数组中。一旦它在数组中,然后从那里操纵它。

以下是代码:

Option Explicit

Public Sub test()
    Debug.Print Now()
    Dim doc     As Document: Set doc = ActiveDocument
    Dim i       As Long
    Dim myArr   As Variant: ReDim myArr(1, 0 To doc.Paragraphs.Count - 1)
    Dim para    As Paragraph

    For Each para In doc.Paragraphs
        myArr(0, i) = para.Style
        myArr(1, i) = para.Range.Characters.Count
        i = i + 1
    Next

    Debug.Print Now()
    Debug.Print myArr(0, 0), myArr(1, 0)

End Sub

答案 1 :(得分:0)

我不确定这是否是正确的方法,但至少它是有效的!我希望这段代码可以帮助其他人寻找循环段落和计算字符的方法。谢谢Ryan!

            Option Explicit

            Public Sub avsnittsteller()
            'http://stackoverflow.com/questions/42390551/vba-slow-macro-looping-through-paragraphs
            Debug.Print Now()
            Application.ScreenUpdating = True

            'Rydd opp i formateringen
            Call stilFinner
                'deklarere variablene
                Dim doc     As Document: Set doc = ActiveDocument
                Dim i       As Long
                Dim j       As Long
                Dim k       As Long
                Dim H1       As Long
                Dim H2       As Long
                Dim H3       As Long
                Dim N       As Long
                Dim myArr   As Variant: ReDim myArr(1, 0 To doc.Paragraphs.Count - 1)
                Dim mlm(10) As String
                Dim para    As Paragraph
                'Hent fram verdier i globale variabler som angir riktig lengde
                intTittel = ActiveDocument.CustomDocumentProperties("malTittel").Value
                intTittelI = ActiveDocument.CustomDocumentProperties("malTittelI").Value
                intTittelX = ActiveDocument.CustomDocumentProperties("malTittelX").Value
                intIngress = ActiveDocument.CustomDocumentProperties("malIngress").Value
                intNormal = ActiveDocument.CustomDocumentProperties("malNormal").Value

                'sett variablene til 0 før de avsnittene telles
                tittel = 0
                ingress = 0
                mlm(1) = 0
                mlm(2) = 0
                mlm(3) = 0
                mlm(4) = 0
                mlm(5) = 0
                mlm(6) = 0
                mlm(7) = 0

                'Lag en matrise (array) i minnet og kjør søket fra den
            'Debug.Print doc.Paragraphs.Count
                For Each para In doc.Paragraphs
                    myArr(0, i) = para.Style
                    myArr(1, i) = para.Range.Characters.Count - 1 'ComputeStatistics(wdStatisticCharacters)
                    i = i + 1
                Next
                'For hvert avsnitt fra 0 til antall avsnitt i dokumentet
                   For j = 0 To doc.Paragraphs.Count - 1
                        'Hvis avsnittets stil er Normal eller en av overskriftene så legg sammen alle tegnene
                        If myArr(0, j) = "Normal" Then
                            N = N + myArr(1, j)
                        'Debug.Print j, myArr(0, j), myArr(1, j)
                        End If
                        If myArr(0, j) = "Overskrift 1" Or myArr(0, j) = "Heading 1" Then
                            H1 = H1 + myArr(1, j)
                        'Debug.Print j, myArr(0, j), myArr(1, j)
                        End If
                        If myArr(0, j) = "Overskrift 2" Or myArr(0, j) = "Heading 2" Then
                            H2 = H2 + myArr(1, j)
                        'Debug.Print j, myArr(0, j), myArr(1, j)
                        End If
                        If myArr(0, j) = "Overskrift 3" Or myArr(0, j) = "Heading 3" Then
                            'Alle avsnitt med H3 telles ett og ett, summeres ikke
                            k = k + 1
                            mlm(k) = myArr(1, j)
                        Debug.Print j, myArr(0, j), myArr(1, j)
                        End If
                    Next j 'Neste avsnitt
            'Debug.Print N & " " & H1 & " " & H2
            'Debug.Print mlm(1) & " " & mlm(2) & " " & mlm(3) & " " & mlm(4) & " " & mlm(5)

                        'DEFINER DOC PROPERTIES VARIABLENE
                        ActiveDocument.CustomDocumentProperties("tittel").Value = H1
                        ActiveDocument.CustomDocumentProperties("ingress").Value = H2
                        ActiveDocument.CustomDocumentProperties("mlm1").Value = mlm(1)
                        ActiveDocument.CustomDocumentProperties("mlm2").Value = mlm(2)
                        ActiveDocument.CustomDocumentProperties("mlm3").Value = mlm(3)
                        ActiveDocument.CustomDocumentProperties("mlm4").Value = mlm(4)
                        ActiveDocument.CustomDocumentProperties("mlm5").Value = mlm(5)
                        ActiveDocument.CustomDocumentProperties("mlm6").Value = mlm(6)
                        ActiveDocument.CustomDocumentProperties("mlm7").Value = mlm(7)
                        ActiveDocument.CustomDocumentProperties("normal").Value = N

                        ActiveDocument.Fields.Update 'OPPDATER ALLE FELT nb, virker ikke i bunn og topptekst

                        'Farg tittel og ingress rød om de er for lange, blå om de er passe korte
                        If tittel > intTittelX Then
                            With ActiveDocument.Styles(wdStyleHeading1).Font
                                .Color = wdColorRed
                            End With
                        Else
                            With ActiveDocument.Styles(wdStyleHeading1).Font
                                .Color = -738148353
                            End With
                        End If

                        If ingress > intIngress Then
                            With ActiveDocument.Styles(wdStyleHeading2).Font
                                .Color = wdColorRed
                            End With
                        Else
                            With ActiveDocument.Styles(wdStyleHeading2).Font
                                .Color = -738148353
                            End With
                        End If

            Application.ScreenUpdating = True
            Debug.Print Now()
            End Sub