Top-Themen

Aktuelle Themen (A bis Z)

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

gelöst Automatisierte Verzeichnisstruktur und Dokument Anpassungen

Mitglied: SIPSIP

SIPSIP (Level 1) - Jetzt verbinden

17.08.2018 um 14:22 Uhr, 942 Aufrufe, 12 Kommentare, 3 Danke

Hallo zusammen

Ich soll für folgendes Szenario eine halb automatisierte Lösung finden.
1. Projektnummer und Name wird durch ein bestehendes Tool erfasst
2. Dieses Tool erstellt ein Verzeichnis auf einem Share mit Projektnummer und Namen
3. Das Tool kopiert eine Vorlagen-Ordner mit diversen Unterverzeichnissen, Word und Excel Dokumente in das neu erstellte Verzeichnis auf dem Share
4. Nun sollen in allen Word und Excel Dokumenten gewisse Platzhalter ersetzt werden. Die Werte die in den Platzhaltern eingefügt werden sollen, müssen natürlich irgendwie vorher definiert werden.

Mein Vorgänger wollte dies alles mit einem Frage/Antwort Powershell Script lösen. Unsere Anwender die das Script bedienen, sollen aber selber Anpassungen machen können, was die Lösung für mich unbrauchbar macht. Außerdem verzeiht das Script keine Schreibfehler und mann muss von vorne beginnen. Des weiteren möchte ich nicht zu viel Zeit aufwenden und ein riesiges Script schreiben. Wir reden von ca. 50 Eingaben und entsprechend vielen Platzhaltern in den Dokumenten verteilt.

Ich dachte mir sowas wie eine Excel Tabelle wo unsere Anwender alle Werte für die Platzhalter eintragen können. Auf irgendeine Art und weise sollen diese Werte nun in die Dokumente geschrieben werden, dabei ging mir der Serienbrief von Word durch den Kopf. Jedoch soll es bei mir ja mehrere Dokumente anpassen und unter anderem auch Excel.

Mein weiteres Vorgehen wäre eine Lösung mit Serienbrief und Powershell gemischt aber ich wollte mich zuerst erkundigen ob es nicht einen einfacheren Weg gibt. Evtl. kennt ihr ja sogar eine fertige Lösung, ohne dass ich das Rad neu erfinden muss.

Grüsse
Mitglied: manuel-r
LÖSUNG 17.08.2018 um 14:47 Uhr
Mein Vorgänger wollte dies alles mit einem Frage/Antwort Powershell Script lösen.

Frage-Antwort ist doof. Da hast du recht.

Was du machen kannst wäre folgendes:
  • Zuerst nimmst du alle deine Word- und Excel-Dokumente und baust dir daraus Kopiervorlagen. In den Dokumenten schreibst du überall wo irgendwas ausgefüllt werden soll deine Platzhalter (bspw: [Kunde], [Projekt], ...)
  • Dann erstellst du das Excel-Sheet mit den Quellangaben. In einer der Spalten muss deine Projektnummer stehen.
  • Jetzt schreibst du ein Script - Powershell bietet sich da an - das zuerst in dem Excel-Sheet die Zeile sucht in der die Projektnummer steht. Danach holt es in dieser Zeile alle notwendigen Informationen
  • Mit diesen Informationen machst du jetzt in jeder deiner Vorlagen ein Suchen-Ersetzen und tauschst Platzhalter durch die echte Info.
  • Zum guten Schluss dann die Vorlagendokumente unter neuem Namen im Projektverzeichnis speichern.
  • Fertig.

Ich würde allerdings die Projektinformationen nicht in einem Excel-Sheet ablegen sondern eine Datenbank (geht auch mit Access) dafür nehmen.

Des weiteren möchte ich nicht zu viel Zeit aufwenden und ein riesiges Script schreiben.

So ganz ohne Zeitaufwand wird es aber nichts werden. Solche Scripte/Tools fallen nicht vom Himmel und ich kennen auch keinen Generator, der das mal eben zusammenklicken lässt.

Manuel
Bitte warten ..
Mitglied: NetzwerkDude
LÖSUNG 17.08.2018 um 15:53 Uhr
Naja, die User müssen es ja nicht "live" in die Konsole eingeben, sondern die können es in eine "Eingabedatei" machen, die dann das Powershellskript auswertet.

Was du dazu brauchst steht in dem Artikel:
https://kevinmarquette.github.io/2016-11-06-powershell-hashtable-everyth ...
1. Reading directly from a file
2. Splatting hashtables at cmdlets

Dabei muss dein PS Skript natürlich die eingabeparameter richtig intepretieren, also über "ValueFromPipelineByPropertyName" die Werte einlesen.

Die Word/Excel dokumente kannst du mit Powershell über "Com Objekte" editieren
Bitte warten ..
Mitglied: colinardo
LÖSUNG 17.08.2018, aktualisiert 14.09.2018
Servus.
Zitat von NetzwerkDude:
Die Word/Excel dokumente kannst du mit Powershell über "Com Objekte" editieren
Oder schneller geht's bei Bedarf auch ohne das lahme COM .

01.
function Replace-StringsInOfficeFiles {
02.
    [CmdletBinding()]
03.
    Param
04.
    (
05.
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=0)][string[]]$FullName,
06.
        [Parameter(Mandatory=$true)][hashtable]$replacements
07.
    )
08.

09.
    Begin{
10.
        # Benötigt wird mindestens NET-Framework 4.5 und Powershell 3.0
11.
        Add-Type -AssemblyName System.IO.Compression
12.
        Add-Type -AssemblyName System.IO.Compression.Filesystem
13.
    }
14.

15.
    Process{
16.
        foreach($file in $fullname){
17.
            try{
18.
                write-verbose "Working on file '$($file)'..."
19.
                # Word-Dokument als ZIP-Datei im Update-Modus öffnen
20.
                $zipfile = [System.IO.Compression.ZipFile]::Open($file,[System.IO.Compression.ZipArchiveMode]::Update)
21.
                
22.
                $entries = $null
23.
                $remove = @()
24.

25.
                # Zu durchsuchende XML-Files des Office Dokumentes selektieren
26.
                switch -regex ([IO.Path]::GetExtension($file)){
27.
                    '^\.doc[xm]$' {
28.
                        $entries = $zipfile.Entries | ?{$_.FullName -match '^(word/(document|footnotes|endnotes)\.xml|word/(header|footer)\d*\.xml)$'}
29.
                        break
30.
                    }
31.
                    '^\.xls[xm]$' {
32.
                        $entries = $zipfile.Entries | ?{$_.FullName -match '^xl/(worksheets/|sharedStrings).*\.xml$'} 
33.
                        break
34.
                    }
35.
                    default{
36.
                        throw "Extension of file '$file' not supported."
37.
                    }
38.
                }
39.
                
40.
                foreach($entry in $entries){
41.
                    $tmp = "$env:TEMP\$($entry.Name)"
42.
                    Remove-Item $tmp -Force -EA SilentlyContinue | out-null
43.

44.
                    # *.xml extrahieren
45.
                    [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry,$tmp)
46.

47.
                    # Datei als XML Object laden
48.
                    $xml = new-object xml
49.
                    $xml.Load($tmp)
50.
                    $found = $false
51.
                    foreach($searchitem in $replacements.GetEnumerator()){
52.
                        if ($xml.DocumentElement.InnerText -match [regex]::Escape($searchitem.Key)){
53.
                            $found = $true
54.
                            # Einträge in Nodes ersetzen
55.
                            $xml.SelectNodes("//*/text()") | ?{$_.InnerText -match [regex]::Escape($searchitem.Key)} | %{
56.
                                write-verbose "Replacement found in text '$($_.InnerText)' => Replacing : $($searchitem.Key) => $($searchitem.Value)"
57.
                                $_.InnerText = $_.InnerText -replace [regex]::Escape($searchitem.Key),$searchitem.Value
58.
                            }
59.
                        }
60.
                    }
61.
                    if ($found){
62.
                        $xml.Save($tmp)
63.
                        # geänderte Datei wieder hinzufügen
64.
                        [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zipfile,$tmp,$entry.FullName) | out-null
65.
                        $remove += $entry
66.
                    }
67.
                
68.
                    # Temporäre Files löschen
69.
                    del $tmp -Force -ErrorAction SilentlyContinue
70.
                }
71.
                # lösche ersetzte Dokumentteile im ZIP
72.
                $remove | %{$_.Delete()}
73.

74.
                write-verbose "Done => '$file'."
75.
            }catch{
76.
                Write-Error -Message $_.Exception.Message
77.
            }finally{
78.
                # Zipfile-Resourcen freigeben
79.
                $zipfile.Dispose()
80.
            }
81.
        }
82.
    }
83.

84.
    End{
85.
    }
86.
}
87.

88.
# Ordner der zu verarbeiten ist
89.
$folder = 'D:\Ordner'
90.

91.
<# Datei mit folgendem Aufbau(Format) erstellen und ins Skriptverzeichnis als 'parameters.txt' speichern
92.

93.
Search1 = Replace1
94.
Search2 = Replace2
95.
Search3 = Replace3
96.
#>
97.
$parameterfile = "$PSScriptRoot\parameters.txt"
98.

99.
# Parameter-Datei als Hashtable einlesen
100.
[hashtable]$parametertable = gc $parameterfile -raw | ConvertFrom-StringData
101.

102.
# In einem Ordner rekursiv *.xlsx und *.docx verarbeiten
103.
gci $folder -Include *.xlsx,*.docx -File -Recurse | Replace-StringsInOfficeFiles -replacements $parametertable -Verbose
Grüße Uwe
Bitte warten ..
Mitglied: NetzwerkDude
17.08.2018 um 21:04 Uhr
Ah, sehr schön, damit braucht man nicht mal office installiert zu haben
Bitte warten ..
Mitglied: SIPSIP
06.09.2018 um 18:17 Uhr
Hallo Uwe

Besten Dank für das Script, scheint genau das richtige für mein Anliegen zu sein.
Dabei habe ich nur die Frage ob dies auch mit einer Excel Tabelle statt einem einer txt funktionieren würde.
Ich weiss, ich sollte dabei auch noch etwas zu tun haben, jedoch fehlt mir gerade die Zeit und evtl. hast du ja bereits ein solches Script oder weisst wie das am Einfachsten lösbar gemacht wird....

excel - Klicke auf das Bild, um es zu vergrößern

Danke!

Grüsse
Patrick
Bitte warten ..
Mitglied: colinardo
LÖSUNG 06.09.2018 um 18:44 Uhr
Klar, mach dir einfach eine CSV, die Importierst du via Import-CSV und arbeitest die Zeilen per ForEach ab.
Bitte warten ..
Mitglied: SIPSIP
14.09.2018, aktualisiert um 16:13 Uhr
Hast du eine Idee wieso ich den Fehler erhalte, habe nur den Pfad im Script angepasst. .Net Framework 4.5 und Powershell 3 sind auch installiert...?

ps-fehler - Klicke auf das Bild, um es zu vergrößern

Wenn ich vor die Letzte Zeile noch "Write-Output $parametertable" schreibe, werden mir meine im parameters.txt definierten Werte aus meiner Sicht richtig dargestellt. Hab nun 2 Stunden damit verbracht herauszufinden was das Problem sein soll, leider ohne Erfolg....
Bitte warten ..
Mitglied: colinardo
LÖSUNG 14.09.2018, aktualisiert um 16:56 Uhr
Kleiner Typo beim Einlesen mit Get-Content, da kam dann ein Array statt einer Hashtable raus, sorry.
Bitte warten ..
Mitglied: SIPSIP
17.09.2018 um 11:04 Uhr
Perfekt, funktioniert nun, vielen Dank du bist der Beste.

Bei Excel Tabellen funktionierte es bei meinen bisherigen Tests einwandfrei, jedoch hat es bei Word Dokumenten teils Probleme alle Platzhalter zu erkennen und ersetzen. Auch bei mehrmaliger Ausführung findet er die dann nicht aber bei einem neuen Test funktionieren dann einige davon wieder....

Umlaute habe ich aus den Platzhaltern entfernt um Fehler dadurch zu vermeiden. Wenn ich das Script richtig verstehe ersetzt es die Platzhalter nicht direkt im Word, sondern das Dokument wird in reiner Textform geöffnet. Also sollte doch die Formatierung hier kein mögliches Problem dafür sein oder?
Sollte ich bei den Platzhaltern auf eine spezielle Schreibweise oder Formatierung achten?

Momentan sehen meine Platzhalter wie folgende aus und stehen auch so irgendwo im Dokument:
<PLZ>
<Datum>
<Ansprechspartner>
etc.

Noch eine andere Frage, habe bisher keine Lösung dazu gefunden... Kann ich Powershell irgendwie beibringen, dass es in den zu ersetzenden Texten (z.B. oben Replace1) Umlaute benutzen kann/soll?
Bitte warten ..
Mitglied: colinardo
LÖSUNG 17.09.2018, aktualisiert um 11:42 Uhr
Zitat von SIPSIP:
Umlaute habe ich aus den Platzhaltern entfernt um Fehler dadurch zu vermeiden.
Die machen nichts wenn du beim Import der Textdatei das richtige Encoding verwendest. Der Rest wird alles intern in UTF8 erledigt.
Wenn ich das Script richtig verstehe ersetzt es die Platzhalter nicht direkt im Word, sondern das Dokument wird in reiner Textform geöffnet.
Nein, das Dokument wird als ZIP-Archiv geöffnet und die entsprechenden XML-Parts als XML-Document eingelesen, dann die Nodes auf die Platzhalter durchsucht, ersetzt, gespeichert und das ganze wieder dem ZIP hinzugefügt.

Sollte ich bei den Platzhaltern auf eine spezielle Schreibweise oder Formatierung achten?
Ja deine Platzhalter nutzen leider größer und kleiner Zeichen (<>), das ist gerade bei XML ein Problem da müsste man noch aufwendiger eingreifen da diese im Dokument in &lt; und &gt; gewandelt werden und in separaten XML-Knoten landen. Also am besten keine XML oder HTML spezifischen Sonderzeichen nutzen, sondern z.B. doppelte Hashes (##Platzhalter##) oder ähnliches.
Das Skript ist für einfache Ersetzungen gedacht ohne dabei komplexe Formatierungen mit einzubeziehen.
Noch eine andere Frage, habe bisher keine Lösung dazu gefunden... Kann ich Powershell irgendwie beibringen, dass es in den zu ersetzenden Texten (z.B. oben Replace1) Umlaute benutzen kann/soll?
Klar das Encoding beim Import (Get-Content) mit dem Parameter -Encoding anpassen. bei UTF8 Datei so
[hashtable]$parametertable = gc $parameterfile -raw -Encoding UTF8 | ConvertFrom-StringData 
Oder -Encoding Default wenn es sich um Standard ANSI handelt. Das Encoding erkennt Powershell normalerweise automatisch, aber nur sofern die Datei es im Header auch definiert.
Bitte warten ..
Mitglied: SIPSIP
21.09.2018, aktualisiert um 16:13 Uhr
Super, danke für deine Unterstützung!

Habe noch etwas herausgefunden, das ich hier auch noch erwähnen möchte, falls jemand das gleiche Problem haben sollte.

Es gibt leider etwas sehr unschönes bei dieser Lösung mit zip und XML Dateien. Dies war wahrscheinlich auch mein letztes Problem bei dem ich für Platzhalter immer < und > verwendete. Die Zeichen sind in XML wohl nicht die beste Wahl, jedoch war dies wohl nicht mein Problem.

Im XML werden Änderungen separat geschrieben. Wenn ich also meinen Platzhalter im Word von <Projekttitel> ändere zu rplcProjektTitel ohne das ganze Wort in Word zu ersetzen, wird dies im XML separat geschrieben. siehe Zeilen 11, 23 & 35.

01.
-<w:r w:rsidRPr="00C476AC" w:rsidR="00C476AC">
02.
-<w:rPr>
03.
<w:rFonts w:cstheme="minorHAnsi" w:eastAsia="Times New Roman"/>
04.
<w:bCs/>
05.
<w:color w:val="000000"/>
06.
<w:sz w:val="24"/>
07.
<w:szCs w:val="24"/>
08.
<w:highlight w:val="yellow"/>
09.
<w:lang w:eastAsia="de-CH"/>
10.
</w:rPr>
11.
<w:t>rplc</w:t>
12.
</w:r>
13.
-<w:r w:rsidRPr="00C476AC" w:rsidR="00F647C6">
14.
-<w:rPr>
15.
<w:rFonts w:cstheme="minorHAnsi" w:eastAsia="Times New Roman"/>
16.
<w:bCs/>
17.
<w:color w:val="000000"/>
18.
<w:sz w:val="24"/>
19.
<w:szCs w:val="24"/>
20.
<w:highlight w:val="yellow"/>
21.
<w:lang w:eastAsia="de-CH"/>
22.
</w:rPr>
23.
<w:t>Projekt</w:t>
24.
</w:r>
25.
-<w:r w:rsidR="00614022">
26.
-<w:rPr>
27.
<w:rFonts w:cstheme="minorHAnsi" w:eastAsia="Times New Roman"/>
28.
<w:bCs/>
29.
<w:color w:val="000000"/>
30.
<w:sz w:val="24"/>
31.
<w:szCs w:val="24"/>
32.
<w:highlight w:val="yellow"/>
33.
<w:lang w:eastAsia="de-CH"/>
34.
</w:rPr>
35.
<w:t>Titel</w:t>
36.
</w:r>
Bitte warten ..
Mitglied: colinardo
21.09.2018, aktualisiert um 17:37 Uhr
Im XML werden Änderungen separat geschrieben
Wie oben geschrieben für "einfache" Platzhalter ohne einzelne separate Formatierungen von einzelnen Wörtern oder Zeichen des Platzhalters klappt das noch. Sobald du also auf den Platzhaltertext unterschiedliche Formatierungen vornimmst Rechtschreibung anwendest etc. geht es nicht mehr. Wie sollte der Algorithmus also jetzt die Formatierung die du auf den Platzhalter angewendet hast auf deinen ersetzten Text anwenden ? Dafür bräuchte man schon eine Glaskugel.
Bitte warten ..
Ähnliche Inhalte
Batch & Shell
Script anpassung
gelöst Frage von MultiplexyBatch & Shell14 Kommentare

Hallo zusammen, Ich benötige mal eure Hilfe, es geht darum den folgenden Code anzupassen, das die letzten 2 Ordner ...

Windows Server
Massen Anpassung AD
gelöst Frage von XY2018Windows Server10 Kommentare

Hallo, ich möchte bei allen Userkonten im Active Directory die Rufnummer auf das E.164 Standard anpassen. Kurze google Suche ...

Vmware
VCenter - Anpassung der Struktur
Frage von Ghost108Vmware8 Kommentare

Hallo zusammen, gerne würde ich euch mal einen zensierten Screenshot meines vCenters zeigen (Anhand der Symbole kann man aber ...

Batch & Shell

Rekursives Auslesen einer Verzeichnisstruktur

gelöst Frage von MinionBatch & Shell4 Kommentare

Hallo all, heute habe ich mal ein Powershellproblem. Ich möchte den Inhalt eines Laufwerkes auslesen, in Abhängigkeit der Struktur. ...

Neue Wissensbeiträge
LAN, WAN, Wireless
Sophos RED50 stürzt ab und ist danach tot
Information von Ex0r2k16 vor 2 TagenLAN, WAN, Wireless3 Kommentare

Hey, nach meinem Thread bin ich durch Zufall auf das hier gestoßen: Also wenn ihr UTMs und RED50's im ...

Windows 10

Microsoft macht Bluetooth absichtlich kaputt: Windows 10 Update blockiert Bluetooth-Verbindungen zu Android

Tipp von 1Werner1 vor 3 TagenWindows 107 Kommentare

Moin, jetzt spinnt MS total , was muss ich da auf Chip.de lesen: Auch im Juni schließt Microsoft im ...

Soziale Netzwerke

Facebook - künftig ohne Account des Bundeslandes Sachsen-Anhalt

Information von VGem-e vor 3 TagenSoziale Netzwerke3 Kommentare

Servus, mal sehen, ob andere öffentliche Einrichtungen folgen wollen/können Gruß

Humor (lol)
Facebook Mailer auf NIX-Spamlist
Information von Henere vor 3 TagenHumor (lol)

Eben aus dem Log meines Postfix gefischt. Recht haben Sie. FB ist SPAM :-) lachende Grüße, Henere

Heiß diskutierte Inhalte
Router & Routing
Synology NAS in anderem Subnetz nicht erreichbar
Frage von Tech1KonniRouter & Routing25 Kommentare

Hallo Leute, ich bin Software-Entwickler und daher auch etwas bewandert in den Grundkenntnissen der Netzwerktechnik. Aktuell habe ich allerdings ...

Netzwerke
Zugriff auf mehrere Clients via RDP
Frage von xXMariusXxNetzwerke11 Kommentare

Moin, ich würde gerne auf mehrere Clients in einem Netzwerk via RDP zugreifen. Gibt es eine elegantere Lösung als ...

Ubuntu
Notfall VMs sind alle runtergefahren
Frage von JohnWorksUbuntu10 Kommentare

Hallo Zusammen, ich habe einen kleinen Notfall und zwar sind alle VMs runtergefahren. Ich dachte erst an den Speicherplatz ...

Windows Server
Probleme Installation Windows Server 2019
Frage von AK-47.2Windows Server8 Kommentare

Hallo zusammen, ich habe das Problem einen Windows Server 2019 auf ein Testsystem zu bringen. Das Mainboard ist ein ...