marcoborn
Goto Top

Suchen in Word-Textfeldern

Hallo Forum,
ich habe folgendes Problem. In einer Word-Datei habe ich pro Seite normalen Text und jeweils ein Textfeld. Diese sehen immer gleich aus. Per Schleife gehe ich durch den Text und muss jeweils einzelne Stellen im normalen Text und im Textfeld durch andere Werte ersetzen. Ich habe im Text und im Textfeld die zu ersetzenden Stellen durch Platzhalter "AAAA", "BBBB", "CCCC" etc. markiert.

Wie muss der Code aussehen, bei dem ich beim Suchen und Ersetzen auch das Textfeld mit ansteuern und hinterher wieder verlassen kann? Kann mir jemand einen kurzen Beispielcode basteln?

Vielen Dank,
M. Born

Content-ID: 302897

Url: https://administrator.de/contentid/302897

Ausgedruckt am: 21.11.2024 um 21:11 Uhr

114757
Lösung 114757 26.04.2016 aktualisiert um 15:10:10 Uhr
Goto Top
Mit einer FOR EACH Schleife über die Collection aller Felder iterieren:
https://msdn.microsoft.com/de-de/library/microsoft.office.tools.word.doc ...

Die Result Eigenschaft enthält den Text.

Gruß jodel32
MarcoBorn
MarcoBorn 26.04.2016 um 15:09:24 Uhr
Goto Top
Leider funktioniert das mit For Each nicht. Der Platzhalter "AAAA" kommt auf jeder Seite im Textfeld vor. Ich muss jedoch Seite für Seite den Platzhalter durch einen anderen Wert (der abhängig von der Schleife ist) ersetzen. Meine Idee ist, auf der ersten Seite über Suchen-Ersetzen die einzelnen Platzhalter durch die Werte auszutauschen, dann zur nächsten Seite zu springen und dort erneut zu ersetzen.

Solange ich mich im normalen Text befinde, funktioniert das Ganze auch problemlos, aber ich weiß nicht, wie ich per VBA-Code das Textfeld ansteuere, dort die Platzhalter ersetze und dann wieder zur vorigen Position im Text zurückspringe.

Ist mein Ansatz umsetzbar?
114757
Lösung 114757 26.04.2016 um 15:14:32 Uhr
Goto Top
Leider funktioniert das mit For Each nicht
Quatsch, natürlich funktioniert das... Du kannst nur den Inhalt jeder einzelnen Seite markieren dann bekommst du einen Range in dem du nur die Felder bekommst die sich auf dieser Seite befinden.
Die FormFields-Collection gibt es auch für das RANGE-Objekt:
https://msdn.microsoft.com/de-de/library/office/ff834816.aspx
MarcoBorn
MarcoBorn 26.04.2016 um 15:45:30 Uhr
Goto Top
Das heisst, ich gehe zur ersten Seite, markiere den gesamten Text der Seite, dann habe ich ein RANGE-Objekt, über das ich die FormFields dieser Seite erreichen kann? Und danach springe ich zur 2. Seite und mache das Ganze erneut?
114757
Lösung 114757 26.04.2016 um 15:45:58 Uhr
Goto Top
Korrekt.
MarcoBorn
MarcoBorn 26.04.2016 um 15:46:50 Uhr
Goto Top
Ok, dann werde ich das mal testen. Habe bisher mit Word-VBA kaum gearbeitet und muss mich in das Objektmodell erst noch einarbeiten. Vielen Dank schon mal.
MarcoBorn
MarcoBorn 26.04.2016 um 16:22:35 Uhr
Goto Top
Hier mal ein kurzes Test-Makro, was aber leider noch nicht funktioniert:
Sub TestMakro()
  For i = 1 To 268
    Selection.MoveDown Unit:=wdLine, Count:=11, Extend:=wdExtend
    For j = 1 To Selection.Range.FormFields.Count
      With Selection.Range.FormFields(j)
        .Select
        Selection.Find.Execute FindText:="AAAA"  
        Selection.TypeText Text:="2016_" & Right("0000" & i, 4)  
      End With
    Next
  Next
End Sub

Ich habe insgesamt 268 Seiten; daher die erste For-Schleife. Ich versuche hier, den Platzhalter "AAAA" durch einen Wert zu ersetzen, bekomme aber kein Ergebnis, da FormFields.Count immer 0 ist. Wie müsste ich den Code abändern, damit es funktioniert?
colinardo
Lösung colinardo 26.04.2016 aktualisiert um 17:19:53 Uhr
Goto Top
Hallo Marco,
hier ein kleines Beispiel:
Sub ReplaceFormFieldTextOnPages()
    Dim intPage As Integer, rngPage As Range, f As FormField
    ' Startseite  
    intPage = 1
    ' Gehe zur ersten Seite  
    Selection.GoTo wdGoToPage, wdGoToAbsolute, intPage
    'setze Range initial auf den Anfang  
    Set rngPage = Selection.Range
    'Loope so lange wir nicht am Ende angekommen sind  
    Do
        ' setze den Range auf die aktuelle Seite  
        Set rngPage = selectPageRange(intPage, intPage)
        'Loope durch die Felder dieser Seite  
        For Each f In rngPage.FormFields
            'je nach dem was das Feld enthält den Inhalt passend ersetzen  
            Select Case f.Result
                Case "AAAA"  
                    f.Result = "REPLACEMENT A"  
                Case "BBBB"  
                    f.Result = "REPLACEMENT B"  
                'usw.  
            End Select
        Next
        'Nächste Seite  
        intPage = intPage + 1
    Loop Until rngPage.End = ActiveDocument.Range.End - 1
End Sub

'Function: select specific page range and return Range-Object  
Function selectPageRange(pageFrom As Integer, Optional pageTo As Integer = 0, Optional selectRange As Boolean = False) As Range
    Dim rngPages As Range
    Set rngPages = Selection.GoTo(wdGoToPage, wdGoToAbsolute, pageFrom)
    If pageTo <> 0 Then
        Selection.GoTo wdGoToPage, wdGoToAbsolute, pageTo
    End If
    rngPages.End = Selection.Bookmarks("\Page").Range.End  
    Set selectPageRange = rngPages
    If selectRange Then
        rngPages.Select
    End If
End Function
Grüße Uwe
MarcoBorn
MarcoBorn 26.04.2016 um 16:59:03 Uhr
Goto Top
Hallo Uwe,
danke auch für Deinen Code. Leider funktioniert er nicht Ich habe ihn 1:1in mein Dokument eingefügt und durchlaufen lassen, aber alle Platzhaltersind weiterhin vorhanden. Der Code springt immer über die For-Each-Schleife hinweg; scheinbar wird f nicht mit einem Wert belegt.
Ähnlich war es bei meinem Beispiel-Code. Dort kam ich auch nicht an das Textfeld heran. Kann es sein, dass es mehrere Arten von Feldern in Word gibt, die in unterschiedlichen Objekten gespeichert werden? Ich habe mein Textfeld mit den Platzhaltern über Einfügen-Textfeld-Einfaches Textfeld erstellt.

Viele Grüße,
M. Born
114757
Lösung 114757 26.04.2016 aktualisiert um 17:03:04 Uhr
Goto Top
Hi, der Code von @colinardo funktioniert hier testweise einwandfrei wenn es sich um die klassischen Formularfelder handelt. Es gibt in Word auch aber auch noch die normale Fields Collection. Dann wirst du damit arbeiten müssen.
MarcoBorn
MarcoBorn 26.04.2016 um 17:08:04 Uhr
Goto Top
Ich habe keine Formularfelder, sondern Textfelder. Ich werde mal sehen, ob ich Uwe's Code auf die Fields-Collection anwenden kann.
colinardo
Lösung colinardo 26.04.2016 aktualisiert um 17:19:42 Uhr
Goto Top
Da gebe ich @114757 recht. Willst du alle Felder(Feldfunktionsfelder) und nicht nur die klassischen Formfelder durchsuchen änderst du die FOR-Schleife der Felder so ab:
For Each f In rngPage.Fields
    'je nach dem was das Feld enthält den Inhalt passend ersetzen  
    Select Case f.Result
        Case "AAAA"  
            f.Result.Text = "REPLACEMENT A"  
        Case "BBBB"  
            f.Result.Text = "REPLACEMENT B"  
        'usw.  
    End Select
Next
und Wichtig: Oben in der Deklaration der Variablen den Typ der Variablen f ändern.
dim f As Field
Es kann aber auch sein das deine Felder sich in Sub-Stories befinden, dann muss man weiter Rekursiv hinein tauchen. Dazu wäre es gut wenn du mal eine Seite des Dokuments zur Verfügung stellen könntest.

Grüße Uwe
colinardo
Lösung colinardo 26.04.2016 aktualisiert um 17:18:03 Uhr
Goto Top
Zitat von @MarcoBorn:
Ich habe keine Formularfelder, sondern Textfelder. Ich werde mal sehen, ob ich Uwe's Code auf die Fields-Collection anwenden kann.
D.h. die neuartigen ContentControls? Dann muss der Code geändert werden , denn dieser bezieht sich momentan auf die Feldfunktionsfelder und nicht die "ContentControls", die werden anders angesprochen.

Mach doch einfach mal schnell einen Screenshot, dann reden wir hier nicht andauernd aneinander vorbei. Danke!
colinardo
Lösung colinardo 26.04.2016 aktualisiert um 17:24:45 Uhr
Goto Top
Wenn es die neuen "ContentControls" sind in denen dein Text steht - diese sehen so aus,

screenshot

dann sieht der Code folgendermaßen aus:
Sub ReplaceFormFieldText()
    Dim intPage As Integer, rngPage As Range, f As ContentControl
    ' Startseite  
    intPage = 1
    ' Gehe zur ersten Seite  
    Selection.GoTo wdGoToPage, wdGoToAbsolute, intPage
    'setze Range initial auf den Anfang  
    Set rngPage = Selection.Range
    'Loope so lange wir nicht am Ende angekommen sind  
    Do
        ' setze den Range auf die aktuelle Seite  
        Set rngPage = selectPageRange(intPage, intPage)
        'Loope durch die Felder dieser Seite  
        For Each f In rngPage.ContentControls
            'je nach dem was das Feld enthält den Inhalt passend ersetzen  
            Select Case f.Range.Text
                Case "AAAA"  
                    f.Range.Text = "REPLACEMENT A"  
                Case "BBBB"  
                    f.Range.Text = "REPLACEMENT B"  
                'usw.  
            End Select
        Next
        'Nächste Seite  
        intPage = intPage + 1
    Loop Until rngPage.End = ActiveDocument.Range.End - 1
End Sub

'Function: select specific page range and return Range-Object  
Function selectPageRange(pageFrom As Integer, Optional pageTo As Integer = 0, Optional selectRange As Boolean = False) As Range
    Dim rngPages As Range
    Set rngPages = Selection.GoTo(wdGoToPage, wdGoToAbsolute, pageFrom)
    If pageTo <> 0 Then
        Selection.GoTo wdGoToPage, wdGoToAbsolute, pageTo
    End If
    rngPages.End = Selection.Bookmarks("\Page").Range.End  
    Set selectPageRange = rngPages
    If selectRange Then
        rngPages.Select
    End If
End Function
Jetzt hast du alle Varianten für alle Arten von Feldern face-smile
MarcoBorn
MarcoBorn 27.04.2016 um 08:15:06 Uhr
Goto Top
Guten Morgen,
ich habe mal den Code aufgezeichnet, wenn ich ein neues Feld anlege. Dort wird folgender Code angelegt:
  ActiveDocument.Shapes.Range(Array("Textfeld 2")).Select  
  Application.Templates("C:\Users\BornMa\AppData\Roaming\Microsoft\Document Building Blocks\1031\14\Built-In Building Blocks.dotx").BuildingBlockEntries(" Einfaches Textfeld").Insert Where:=Selection.Range, RichText:=True  

Scheinbar sind die Textfelder eine Art on Shapes. Ich werde damit mal weiter experimentieren. Einige Code-Schnipsel als Vorlage habe ich ja zwischenzeitlich erhalten.

Viele Grüße,
M. Born
colinardo
colinardo 27.04.2016 aktualisiert um 08:39:06 Uhr
Goto Top
Wie gesagt stell eine Seite davon zum Download dann kann ich dir effektiv helfen, ohne raten zu müssen!! Danke!!
MarcoBorn
MarcoBorn 27.04.2016 um 08:44:38 Uhr
Goto Top
Hallo Uwe,
habe soeben das Problem gelöst. Mit folgendem Code kann man das Shape verlassen und zum Anfang der Seite springen:
  If Selection.ShapeRange.Count > 0 Then
    Selection.GoTo wdGoToPage, wdGoToAbsolute, Selection.Information(wdActiveEndPageNumber)
  End If

Vielen Dank für Deine und Jodel's Hilfe,
M. Born