1

それは可能ですか?おそらくそうではありませんか?次に、一致するすべての正確な出現とそれに応じたページ番号を見つけるにはどうすればよいですか?

編集:

正規表現が正しく機能しています。私が必要とするのは、各一致が表示されるすべてのページを取得することです。

例:

regex = \b\d{3}\b

123 appears on page 1,4,20
243 appear on page 3,5,7
523 appears on page 9

その情報を取得するにはどうすればよいですか (一致が発生したすべてのページですか?)

これは、ある種のインデックスを自動的に作成するためのものです。

編集2:

基本的な作業バージョン、スニペットを取得しました:

Set Matches = regExp.Execute(ActiveDocument.range.Text)

For Each Match In Matches    
    Set range = ActiveDocument.range(Match.FirstIndex, Match.FirstIndex + Len(Match.Value))    
    page = range.Information(wdActiveEndAdjustedPageNumber)

問題は、Match.FirstIndex が常に ActiveDocument.range 内の一致の最初の文字を指しているとは限らないことです。ActiveDocument.range.Text には、テーブル内の何かを表すテキストにない文字が含まれているため、Word テーブルはこれを台無しにします。

4

2 に答える 2

3

これはかなり複雑であることが判明し、私のソリューションがどのドキュメントでも機能するかどうかはわかりません。主な問題は、質問に示されているように、RegexMatch.FirstIndexを使用して、実際に一致するものがMSWordドキュメント内にあるかどうかを判断できないことです。これは、range.Textプロパティ(String)で正規表現の一致が行われ、文字列に含まれる文字数がrangeオブジェクトとは異なるため、インデックスが一致しないためです。

したがって、私の解決策は一致ごとに、その一致のドキュメント全体で検索を実行することです。findメソッドは、正しいページを判別できるRangeオブジェクトを提供します。

私の特別なケースでは、一致は同じものであり、値も異なる可能性があります。例:343私の場合はと同じになりPrefix-343ます。2番目の問題は、ドキュメントで最初に発生するものに関係なく、たとえば123前に一致を並べ替える必要があることでした。324

並べ替え機能が必要な場合は、「モジュール」に次のものも必要になります。

SortDictionary関数:

http://www.cpearson.com/excel/CollectionsAndDictionaries.htm

モジュール「modQSortInPlace」:

http://www.cpearson.com/Zips/modQSortInPlace.zip

並べ替えが必要ない場合は必要ありませんが、対応する関数呼び出しSortDictionary Dict, Trueをコードから削除する必要があります。

今私のコードに。削除できるSoemパーツ、特にフォーマットパーツ。これは私の場合に固有です。また、あなたの試合が「ユニーク」である場合、例えば。プレフィックスではないので、コードを単純化することもできます。「Microsoftスクリプトライブラリ」を参照する必要があります。

Option Explicit

Sub ExtractRNumbers()

    Dim Dict As Scripting.Dictionary
    Set Dict = CreateObject("Scripting.dictionary")

    Dim regExp, Match, Matches
    Dim rNumber As String
    Dim range As range

    Set regExp = CreateObject("VBScript.RegExp")
    regExp.Pattern = "\b(R-)?\d{2}-\d{4,5}(-\d)?\b"
    regExp.IgnoreCase = False
    regExp.Global = True

    ' determine main section, only extract R-Numbers from main section
    ' and not the Table of contents as example
    ' main section = section with most characters

    Dim section As section
    Dim maxSectionSize As Long
    Dim sectionSize As Long
    Dim sectionIndex As Integer
    Dim currentIndex As Integer
    maxSectionSize = 0
    currentIndex = 1
    For Each section In ActiveDocument.Sections
        sectionSize = Len(section.range.text)
        If sectionSize > maxSectionSize Then
            maxSectionSize = sectionSize
            sectionIndex = currentIndex
        End If
        currentIndex = currentIndex + 1
    Next


    Set Matches = regExp.Execute(ActiveDocument.Sections(sectionIndex).range.text)


    For Each Match In Matches

        ' If the Document contains Tables, ActiveDocument.range.Text will contain
        ' BEL charachters (chr(7)) that probably define the table structure. The issue
        ' is that then Match.FirstIndex does not point to the actual first charachter
        ' of a Match in the Document.
        ' Also there are other things (unknwon) that lead to the same issue, eg.
        ' Match.FirstIndex can not be used to find the actual "matching word" within the
        ' document. Because of that below commented apporach does not work on a generic document

        '   Set range = ActiveDocument.range(Match.FirstIndex, Match.FirstIndex + Len(Match.Value))
        '   page = range.Information(wdActiveEndAdjustedPageNumber)

        ' Maybe there is a simpler solution but this works more or less
        ' the exception beign tables again. see http://support.microsoft.com/kb/274003

        ' After a match is found the whole document is searched using the find method.
        ' For each find result the page number is put into an array (if it is not in the array yet)
        ' Then the match is formatted properly.
        ' After formatting, it is checked if the match was previously already found
        '
        '   If not, we add a new entry to the dictionary (key = formatted match, value = array of page numbers)
        '
        '   If match was already found before (but potentially in a different format! eg R-87-1000 vs 87-1000 as example),
        '   all additional pages are added to the already found pages.

        Set range = ActiveDocument.Sections(sectionIndex).range
        With range.Find
            .text = Match.Value
            .MatchWholeWord = True
            .MatchCase = True
            .Wrap = wdFindStop
        End With

        Dim page As Variant
        Dim pages() As Integer
        Dim index As Integer
        index = 0
        ReDim pages(0)

        Do While range.Find.Execute() = True
            page = range.Information(wdActiveEndAdjustedPageNumber)
            If Not IsInArray(page, pages) Then
                ReDim Preserve pages(index)
                pages(index) = page
                index = index + 1
            End If
        Loop

        ' FORMAT TO PROPER R-NUMBER: This is specific to my case
        rNumber = Match.Value
        If Not rNumber Like "R-*" Then
         rNumber = "R-" & rNumber
        End If
        ' remove possible batch number as r-number
        If Len(rNumber) > 11 Then
            rNumber = Left(rNumber, Len(rNumber) - 2)
        End If
        ' END FORMAT

        If Not Dict.Exists(rNumber) Then
            Dict.Add rNumber, pages
        Else
            Dim existingPages() As Integer
            existingPages = Dict(rNumber)
            For Each page In pages
                If Not IsInArray(page, existingPages) Then
                    ' add additonal pages. this means that the previous match
                    ' was formatted different, eg R-87-1000 vs 87-1000 as example
                    ReDim Preserve existingPages(UBound(existingPages) + 1)
                    existingPages(UBound(existingPages)) = page
                    Dict(rNumber) = existingPages
                End If
            Next
        End If

    Next
    'sort dictionary by key (R-Number)
    SortDictionary Dict, True
    Dim fso
    Set fso = CreateObject("Scripting.FileSystemObject")

    Dim stream
    ' Create a TextStream.
    Set stream = fso.CreateTextFile(ActiveDocument.Path & "\" & ActiveDocument.Name & "-rNumbers.txt", True)

    Dim key As Variant
    Dim output As String
    Dim i As Integer
    For Each key In Dict.Keys()
        output = key & vbTab
        pages = Dict(key)
        For i = LBound(pages) To UBound(pages)
            output = output & pages(i) & ", "
        Next
        output = Left(output, Len(output) - 2)
        stream.WriteLine output        
    Next
    Set Dict = Nothing
    stream.Close
End Sub

Private Function IsInArray(page As Variant, pages As Variant) As Boolean
    Dim i As Integer
    IsInArray = False
    For i = LBound(pages) To UBound(pages)
        If pages(i) = page Then
            IsInArray = True
            Exit For
        End If
    Next
End Function
于 2013-01-10T13:40:09.017 に答える
3

これはおそらく SuperUser の方が適していると思います。

質問に対する答えは「はい」です。

Selection.Information(wdActiveEndAdjustedPageNumber)

VBA の上記のプロパティは、選択範囲のページ番号を取得します。

また、VBA はいくつかの正規表現作業を行うことができます

于 2013-01-09T15:35:45.847 に答える