123. Suchen und Ersetzen in Stapelverarbeitung von Docx-Dokumenten: Modifizierung der unter GNU-Lizenz existierenden wreplace.HTA der PC-Welt

Einleitung

Das Ersetzen von Wörtern oder kleinen Sätzen in Worddokumenten gehört im Büroalltag zu den alltäglichen Aufgaben. Schlimm wird es, wenn  in einem ganzen Ordner Wörter wie z. B. Namen in mehreren Docx-Dokumenten verändert werden müssen.

Dabei geht das ganz easy mit einem Makro (Makrorekorder - ist aber nicht jedermanns/ jeder frau Sache) oder mit dem angepassten VBS-Code in einer HTA.

Die PC-Welt veröffentlichte 2002 für doc-Dokumente die wreplace.HTA, die genau diese Aufgabe für Dokumente im veralteten *.doc - Format erledigt und die sie sich für diesen Zweck gern bei PC-Welt herunterladen können.

Im Quelltext steht dann ausdrücklich, dass man im Rahmen der GNU-Lizenz die Software modifizieren und veröffentlichen darf - genau das machte der Sternenhimmelstuermer, nennt diese Weiterentwicklung Version 1.1 und modifizierte Sie für docx- Dateien. Das ist sinnvoller, als ein Konkurrenztool zu kreieren, wozu der Sternenhimmelstuermer fähig gewesen wäre - aber lange nicht so professionell, man muss das Rad nicht neu erfinden, besonders wenn das neue Rad mehr eine Ellipsen statt Kreisform hat...

Die Änderungen sind rot hervorgehoben - um genau zu sein: entscheidend sind die zweimaligen "doc", die in docx geändert wurden.

Ist alles nur geklaut? Nein, definitiv wurde eine absolut geniale einfache und professionelle Software (Logdatei wird erstellt, Design absolut Top und Fehlerprüfung bei Eingabe) wieder reaktiviert. Denn die Software arbeitete unter Windows 7 mit Office 2007 klaglos - also auch unter 2010 mit 99 % Wahrscheinlichkeit...

Bild

Bild von Grafikoberfläche
Bild der Grafikoberfläche der modifizierten HTA wreplace.HTA



modifizierter Quellcode (Änderungen rot - Autor der Änderungen ist nicht haftbar für evtl. Fehlfunktionen der Modifizierung)

Der Name der HTA ist eigentlich unbedeutend: wdocxreplace.HTA

Den folgenden Inhalt so in ein Textdokument kopieren (ausführliche Beschreibung danach):

<HTML><!--

Use: Dieses Tool sucht und ersetzt angegebene Wörter in allen
Word-Dokumenten (DOCX-Format) eines Ordners. Auf Wunsch
berücksichtigt die Suche auch Dateien in aller
Unterverzeichnissen des Ordners mit. Die Liste der durchsuchten
Dateien lässt sich als Log-File speichern. Obwohl dieses Script
nicht als Marko in Word läuft, sondern als eigenständige
Script-Anwendung, muss Office 2000, 2007 oder 2010 auf dem Rechner
vorhanden sein.

Author: Copyright (C) 2002 David G. Wolski (admi@india.com)
for PC-WELT, IDG Magazine Verlag GmbH (http://www.pcwelt.de),
für DOCX modifiziert 2012 vom Sternenhimmelstuermer.eu
    
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

Dieses Programm ist freie Software. Sie können es unter
den Bedingungen der GNU General Public License, wie von der
Free Software Foundation herausgegeben, weitergeben und/oder
modifizieren, entweder unter Version 2 der Lizenz oder (wenn
Sie es wünschen) jeder späteren Version.

Die Veröffentlichung dieses Programms erfolgt in der
Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE JEDE
GEWÄHRLEISTUNG - sogar ohne die implizite Gewährleistung
der MARKTREIFE oder der EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
Details finden Sie in der GNU General Public License.

Voraussetzungen: - IE ab 5.0 besser 6.0
-->
 <HEAD>
  <TITLE>Suchen &amp; Ersetzen in Word-Dokumenten
  </TITLE>
  <HTA:APPLICATION
   ID = "WordReplacer"
   APPLICATIONNAME = "WordReplacer"
   BORDER = "normal"
   CAPTION = "yes"
   SHOWINTASKBAR = "yes"
   SINGLEINSTANCE = "yes"
   SYSMENU = "yes"
   WINDOWSTATE = "normal"
   SCROLL = "no"
   SCROLLFLAT = "no"
   VERSION = "1.1"
   INNERBORDER = "Yes"
   SELECTION = "no"
   MAXIMIZEBUTTON = "no"
   MINIMIZEBUTTON = "yes"
   NAVIGABLE = "No"
   CONTEXTMENU = "no"
   BORDERSTYLE = "normal">

 <STYLE type="text/css">
 
body         {font-family:Tahoma,Verdana,Arial,Geneva;
        font-size:12px;
        background-color:Buttonface}

table        {font-family:Tahoma,Verdana,Arial,Geneva;
        font-size:12px;
        background-color:Buttonface}
               
.tablefading    {background-color:White;
        color:black;
        filter:Alpha(style=1, startX=49, finishX=109)}

.toggle        {font-family:Marlett}

#srchButton    {font-family:Marlett}


  </STYLE>
 <SCRIPT LANGUAGE="VBScript">

    Set oFs = CreateObject("Scripting.FileSystemObject")
    Set oAppShell= CreateObject("Shell.Application")
    Dim WordApp
    Dim IntervalID
'==========================================================================

     Sub SubInitFenster
        window.resizeTo 443, 505
        SubInitNeu
    End Sub

    Sub SubInitNeu
        document.all.OrdnerInput.Value    = ""
        document.all.SucheInput.Value    = ""
        document.all.ReplaceInput.Value    = ""
        document.all.OrdnerInput.style.backgroundColor    = "White"
        document.all.SucheInput.style.backgroundColor    = "White"
        document.all.ReplaceInput.style.backgroundColor    = "White"
    End Sub

'==========================================================================

    Sub SubZeigeHilfe
        Hilfe = Msgbox("Obwohl das " & Chr(34) & "Warum" & Chr(34) & " und " & Chr(34) & "Wie" & Chr(34) & " bei dieser HTA-Anwendung weitgehend selbsterklärend ist, will diese Hilfe noch einige Funktionen im Detail besprechen." & Chr(10) & "Von Oben nach Unten: Im Eingabefeld " & Chr(34) & "Ordner" & Chr(34) & " kommt hinein, welcher Pfad die Word-Dokumente enthält, die durchsucht werden sollen. Die Klickbox " & Chr(34) & "mit Unterverzeichnissen" & Chr(34) & " gibt an, ob die Suche auch die Unterordner des angegebenen Ordners berücksichtigt. Komfortabel ist der Button " & Chr(34) & "Durchsuchen" & Chr(34) & ", denn damit lässt sich ein Ordner auch per Mausklick auswählen." & Chr(10) & "Weiter geht´s zum gesuchten Wort: " & Chr(34) & "Zu ersetzendes Wort" & Chr(34) & " gibt an, welches Wort in einem Word-Dokument werden soll. Erlaubt ist alles, auch Leerzeichen." & Chr(10) & Chr(34) & "Ersetzen mit" & Chr(34) & " sagt der Suche, mit was die gefundene Zeichenkette ersetzt wird. Ein Klick auf " & Chr(34) & "Los" & Chr(34) & " macht schließlich ernst und ersetzt alle gefundenen Suchbegriffe mit dem Ersatz-Wort. Das untere Feld ist beim Aufruf dieser Anwendung noch leer. Hier stehen die Fehler, etwa wenn der Ordner nicht existiert, oder die Wortangaben nicht komplett sind",64,"PC-Welt Script: Word Text Replacer                        Hilfe")
    End Sub

'==========================================================================

    Sub SubBrowseQuelle
           Set AppFolder = oAppShell.BrowseForFolder(0, "Wählen Sie einen Ordner aus, in dem die Word-Dokumente (DOCX-Dateien) liegen:",  &H0001, 17)
           On Error Resume Next
               StrOrdner = AppFolder.ParentFolder.ParseName(AppFolder.Title).Path
               If err.number > 0 then
            i=instr(AppFolder, ":")
            StrOrdner = mid(AppFolder, i - 1, 1) & ":\"
        End If
        If StrOrdner = "" Then Exit Sub
        If Not (oFs.FolderExists(StrOrdner)) then
            g = MsgBox("Dieser Ordner ist nicht gültig." & Chr(10) & "Wählen Sie einen gültigen Ordner aus",16, "PC-WELT Script")
        End If
        document.all.OrdnerInput.Value = StrOrdner
    End Sub

'==========================================================================
   
    Sub SubCheckSelect
    document.all.OrdnerInput.style.backgroundColor    ="White"
    document.all.SucheInput.style.backgroundColor    ="White"
    document.all.ReplaceInput.style.backgroundColor    ="White"
       
    StrOrdner = document.all.OrdnerInput.Value
    StrSuche = document.all.SucheInput.Value
    StrReplace = document.all.ReplaceInput.Value
   
    If not oFs.FolderExists(StrOrdner) Then
        document.all.OrdnerInput.style.backgroundColor="salmon"
        TheFrame.document.write("<DIV style=" & Chr(34) & "font-size=12; color=Red; font-family=Tahoma,Verdana,Arial,Geneva" & Chr(34) & ">Fehler: Ordner ist nicht vorhanden!</DIV>")
        Exit Sub
    End If
   
    If StrSuche = "" Then
        document.all.SucheInput.style.backgroundColor="salmon"
        TheFrame.document.write("<DIV style=" & Chr(34) & "font-size=12; color=Red; font-family=Tahoma,Verdana,Arial,Geneva" & Chr(34) & ">Fehler: Kein Suchwort angegeben!</DIV>")
        Exit Sub
    End If
   
    If StrReplace = "" Then
        document.all.ReplaceInput.style.backgroundColor="salmon"
        TheFrame.document.write("<DIV style=" & Chr(34) & "font-size=12; color=Red; font-family=Tahoma,Verdana,Arial,Geneva" & Chr(34) & ">Fehler: Kein Ersatzwort angegeben!</DIV>")
        Exit Sub
    End If
   
    If StrSuche = StrReplace Then
        document.all.SucheInput.style.backgroundColor="salmon"
        document.all.ReplaceInput.style.backgroundColor="salmon"
        TheFrame.document.write("<DIV style=" & Chr(34) & "font-size=12; color=Red; font-family=Tahoma,Verdana,Arial,Geneva" & Chr(34) & ">Fehler: Wörter für Suche und Ersetzen sind gleich!</DIV>") : Exit Sub
        Exit Sub
    End If

    TheFrame.document.write("<DIV style=" & Chr(34) & "font-size=12; color=Black; font-family=Tahoma,Verdana,Arial,Geneva" & Chr(34) & "><B>Suchen & Ersetzen gestartet </B>" & Now & "</DIV><DIV style=" & Chr(34) & "font-size=12; color=Black; font-family=Tahoma,Verdana,Arial,Geneva" & Chr(34) & "><DIV><B>Suchbegriff: </B>" & StrSuche & "</DIV><DIV><B>Ersatzwort: </B>" &  StrReplace & "</DIV>")
    document.all.OrdnerInput.style.backgroundColor    ="Lightgreen"
    document.all.SucheInput.style.backgroundColor    ="Lightgreen"
    document.all.ReplaceInput.style.backgroundColor    ="Lightgreen"
    IntervalID=window.setInterval("FPreReplacer()", 10)
    End Sub


'==========================================================================
   
    Function FPreReplacer
        window.clearInterval(IntervalID)
        Set WordApp = CreateObject("Word.Application")
        StrOrdner = document.all.OrdnerInput.Value
        StrSuche = document.all.SucheInput.Value
        StrReplace = document.all.ReplaceInput.Value
        TheFrame.document.write("<hr><FONT size=2 color=Black>Durchsuchte Dateien:</FONT></br>")
        If document.all.BeachteSubfolder.checked = False Then
            FReplacer StrOrdner, StrSuche, StrReplace
        Else
            FReplacerSubDirs StrOrdner, StrSuche, StrReplace
        End If
        TheFrame.document.write("<hr><FONT size=2 color=Green>Suchen & Ersetzen beendet.  " & Now & "</FONT></br>")
        WordApp.Quit 0
        document.all.OrdnerInput.style.backgroundColor    = "White"
        document.all.SucheInput.style.backgroundColor    = "White"
        document.all.ReplaceInput.style.backgroundColor    = "White"
    End Function

'==========================================================================   

    Function FReplacerSubDirs(Wo, Welches, MitWas)
        Set lFolder = oFs.GetFolder(Wo)
        WordApp.Windowstate = 2
        For Each lFile in lFolder.Files
        If LCase(oFs.GetExtensionName(lFile.Name)) = "docx"  Then
        TheFrame.document.write("<FONT size=2  color=Black>" & lFile & "</FONT></br>")
       
        WordApp.Documents.Open(Chr(34) & lFile & Chr(34))
        WordApp.Selection.WholeStory
         With WordApp.Selection.Find
                .Text = Welches
                .Replacement.Text = MitWas
                .Forward = True
                .Wrap = wdFindAsk
                .Format = False
                .MatchCase = True
                .MatchWholeWord = False
                .MatchWildcards = False
                .MatchSoundsLike = False
                .MatchAllWordForms = False
            End With
        WordApp.Selection.Find.Execute ,,,,,,,,,,2
        WordApp.Documents.Save
        WordApp.Documents.Close
        End If
        Next
        Set lSubFolders = lFolder.SubFolders
              For Each lSubFolder in lSubFolders
                       WoSub = Wo & "\" & lSubFolder.Name
            FReplacerSubDirs WoSub, Welches, MitWas
        Next
    End Function

'==========================================================================
   
    Function FReplacer(Wo, Welches, MitWas)
    Set lFolder = oFs.GetFolder(Wo)
    WordApp.Windowstate = 2
    For Each lFile in lFolder.Files
        If LCase(oFs.GetExtensionName(lFile.Name)) = "docx"  Then
        TheFrame.document.write("<FONT size=2  color=Black>" & lFile & "</FONT></br>")
        WordApp.Documents.Open(Chr(34) & lFile & Chr(34))
        WordApp.Selection.WholeStory
         With WordApp.Selection.Find
                .Text = Welches
                .Replacement.Text = MitWas
                .Forward = True
                .Wrap = wdFindAsk
                .Format = False
                .MatchCase = True
                .MatchWholeWord = False
                .MatchWildcards = False
                .MatchSoundsLike = False
                .MatchAllWordForms = False
            End With
        WordApp.Selection.Find.Execute ,,,,,,,,,,2
        WordApp.Documents.Save
        WordApp.Documents.Close
        End If
    Next
    End Function

    Sub SubSaveIt
        StrFileName = Replace(NOW, ":", "-") & ".log"
        Set LogFile = oFs.CreateTextfile(StrFileName, True)
        LogFile.Write(document.frames("TheFrame").document.body.InnerText)
        LogFile.Close
        MsgBox "Log-Datei gespeichert als " & Chr(34) & StrFileName & Chr(34) &" im Verzeichnis der Programmdatei.",0,"Log-File"
    End Sub

'==========================================================================
' SubHideFrame,  SubResizeSmall, SubResizeBig, SubShowFrame sind eine eine Spielerei mit Fenstergrösse und Filtern.
' Sie verstecken das IFrame und passen dabei die Fenstergrösse neu an. Alles mit einem IE-Überblendeffekt:
'==========================================================================
   
    Sub SubHideFrame
        'On Error Resume Next
        document.all.TheFrame.filters.Item(0).Apply()
        document.all.TheFrame.style.visibility="hidden"
        document.all.TheFrame.filters.Item(0).play(0.200)
        document.all.HideBtn.Value="u"
        document.all.HideBtn.onclick = GetRef("SubResizeBig")
        IntervalID=window.setInterval("SubResizeSmall", 20)
    End Sub

'==========================================================================
   
    Sub SubResizeSmall
        YSize = document.body.clientHeight
        window.resizeTo 443, Ysize-3
        If Ysize <=303 Then window.clearInterval(IntervalID)
    End Sub

'==========================================================================
   
    Sub SubResizeBig
        window.resizeTo 443, 505
        IntervalID=window.setInterval("SubShowFrame", 110)
    End Sub

'==========================================================================
   
    Sub SubShowFrame
        On Error Resume Next
        document.all.TheFrame.filters.Item(0).Apply()
        document.all.TheFrame.style.visibility="visible"
        document.all.TheFrame.filters.Item(0).play(0.150)
        document.all.HideBtn.Value="t"
        document.all.HideBtn.onclick = GetRef("SubHideFrame")
        window.clearInterval(IntervalID)
    End Sub

'==========================================================================

    Sub SubQuitIt
        Set oFs            = Nothing
        Set oAppShell         = Nothing
        Set ExcelApp        = Nothing
        Window.Close
    End Sub

'==========================================================================

</SCRIPT>
 </HEAD>
 <BODY SCROLL="no" ONLOAD="SubInitFenster()">
  <FORM>
     <FIELDSET>
    <LEGEND>
     <B>Ordner: </B>
     <INPUT
       ID=BeachteSubfolder
       Name=BeachteSubfolder
       Type="checkbox"
       Title="Dokumente in Unterverzeichnissen auch durchsuchen?"
       Tabindex=1
       UNCHECKED> Mit Unterverzeichnissen
      </LEGEND>
    <TABLE WIDTH=100% CELLPADDING=4 CELLSPACING=1>
    <TR>
        <TD WIDTH=100%>
            <INPUT TYPE=text
              ID=OrdnerInput
              class=tablefading
              Value=""
              Size=45
              tabindex=2
              Name=Quelle
              Title="Wählen Sie den Ordner, der die Dokumente enthält">
           
            <Input
              ID=SrchButton
              Type="button"
              OnClick="SubBrowseQuelle"
              Title="Wählen Sie ein Quellverzeichnis"
              Value="4">
          </TD>
    </TR>
    </TABLE>
    </FIELDSET>
    <FIELDSET>
    <LEGEND><B>Zu ersetzendes Wort: </B></LEGEND>
    <TABLE WIDTH=100% CELLPADDING=4 CELLSPACING=1>
    <TR>
        <TD WIDTH=100%>
            <INPUT
              ID=SucheInput
              tabindex=3
              class=tablefading
              Type=text
              Value=""
              Size=50
              Title="Geben Sie hier das Wort ein, das gesucht werden soll">
        </TD>
    </TR>
    </TABLE>
    </FIELDSET>   
    <FIELDSET>
    <LEGEND><B>Ersetzen mit: </B></LEGEND>
    <TABLE Width=100% CELLPADDING=4 CELLSPACING=1>
    <TR>
        <TD WIDTH=100%>
            <Input
              ID=ReplaceInput
              tabindex=4
              class=tablefading
              Type=text
              Value=""
              Size=53
              Title="Mit diesem Wort werden die gefundenen Wörter ersetzt">
          </TD>
    </TR>
    </TABLE>
    </FIELDSET>
    <TABLE WIDTH=100% CELLPADDING=4 CELLSPACING=1>
      <TR>
        <TD WIDTH=100% STYLE="direction:rtl">
                <Input
              Name=HideBtn
              Type="button"
              Class=Toggle
              OnClick="SubHideFrame"
              Value="t"
              Title="Log aus- und einblenden"/>
            
             <Input
              Type="button"
              Class=Button
              OnClick="SubQuitIt"
              Value="Quit"
              Title="Beendet das Programm"/>
             
              <Input
              Type="button"
              Class=Button
              OnClick="SubSaveIt"
              Value="Log speichern"
              Title="Speichert die Log-Datei der durchsuchten Dateien"/>
 
            <Input
              Type="button"
              Class=Button
              OnClick="SubZeigeHilfe"
              Value="Hilfe"
              Title="Eine Hilfestellung mit den nötigsten Infos"/>
              
            <Input
            Type="button"
            Class=Button
              OnClick="SubCheckSelect"
              tabindex=5
              Value="!Los"
              Title="Ersetzt die gefundenen Wörter in allen Dokumenten im Ordner mit dem angegebenen Wort"/>
        </TD>
    </TR>
    <TR>
        <TD WIDTH=100%>
           <iframe src="" Name=TheFrame id=TheFrame style="WIDTH: 400px; HEIGHT: 232px; filter:blendTrans"></iframe>
          </TD>
    </TR>
   </TABLE>
  </FORM>
 </BODY>
</HTML>



Erstellung

Als erstes Erstellen Sie eine leere Textdatei, um daraus die HTA zu erstellen: Rechte Maustaste auf Desktop, aus dem Kontextmenü Neu - Textdokument. Dann die Datei mit einem aussagekräftigen Namen benennen: wdocxreplace.HTA . Wichtig ist die Dateiendung *.HTA. Der Name ist egal: Sonderzeichen und über sechs Buchstaben ist erstmal für Sie Tabu. Unterstrich _ ist erlaubt.

Wird ihnen die Dateiendung nicht angezeigt, so müssen Sie zuvor das Anzeigen von Dateiendungen auch bei bekannten Dateiendungen in einem beliebigen Ordner einstellen: Extras - Ordneroptionen - Registerkarte: Ansicht. Dann Häkchen bei  Erweiterungen bei bekannten Dateiendungen ausblenden entfernen. Sollte auch die Menüleiste mit Extras nicht angezeigt werden, so in das Dropdownmenü von Organisieren - Layout und Menüleiste anzeigen.

Warum so kompliziert? Der Sternenhimmelstuermer schreibt generell den Quellcode in Klartext - eine vertrauensbildende Maßnahme.

Voraussetzung

Installiertes Word Office, müsste auch bei 2002 und 2003 mit Erweiterung durch das Kompatibilitätspaket der Microsoft Corporation für Docx-Dokumente funktionieren, in so weit Sie die Dateien als DOCX abgespeichert haben...
Ansonsten laden Sie sich von der PC-Welt die Version des Tools für doc - Dokumente herunter..., Internet Explorer ab 6 und HTA muss auf dem Computer erlaubt sein. Einige Administratoren blockieren HTA...

Bedienung

Es werden drei Eingaben und eventuell ein Häkchen verlangt: Erstmal wird der Pfad angegeben. Das ganz bequem per Such-Button neben dem ersten Inputfeld. Im Dialogfenster wird im Explorerstil die Ordnerhierarchie angezeigt. Suchen Sie den Ordner aus, wo die DOCX-Dokumente liegen. Denken Sie daran, dass auch nur wirklich DOCX und nicht DOC-Dokumente geändert werden. Ob die Unterordner durchsucht werden, entscheiden Sie per Auswahl mit Häkchen.

Das nächste Feld beinhaltet den zu suchenden Text. Kleine Sätze, ü,ä,ö...  Sonderzeichen wie -:) waren beim Testen kein Problem.  Das Ganze kann in der nächsten Zeile  durch Wörter oder Sätze ergänzt werden.
Danach wird mit dem Button Los die HTA gestartet.

Sie sehen nun ein kurzes Aufflackern von  den  Dokumenten, die im Officeprogramm geöffnet werden, Text geändert und geschlossen werden. Am Ende wurden sämtliche Texte ersetzt. Danach können Sie sich einen Logfile  ausdrucken lassen, in welchen Dokumenten es zu einer  Ersetzung kam - zusätzlich gibt es noch eine integrierte Hilfe...

Fazit

Das Ego des Sternenhimmelstuermers lässt es zu, andere Software weiterzuentwickeln, besonders wenn im Quelltext dazu aufgefordert wird. Die nächste Abhandlung wird vermutlich von der Integration von einer Indexsuche in sein Suchmaschinenprojekt Merlin sein.
Das dauert aber noch, da der Sternenhimmelstuermer zwar schon ein paar aberwitzige Ideen hat, die aber fast nichts mit diesem hier veröffentlichten Quelltext zu tun haben, obwohl es erlaubt aber langweilig wäre. Das wird dann eine grausame Chimäre aus VBS und hauptsächlich aus einer Batch, also für den Sternenhimmelstuermer bekanntes und besser beherrschbares Terrain...




Impressum
Datenschutz