Serien-PDF - PDF-Dateiname aus den Quelldaten

cumulonimbus8

Fleet Admiral
Registriert
Apr. 2012
Beiträge
18.403
Moin!

Ausgangspunkt sei eine Tabelle Marke Excel. Eine der Spalten soll einen Dateinamen vorgeben - da ist der große Haken. Der Rest möge aussehen wie für normale Serienbriefe.
Das weist natürlich in Richtung MSO, aber es muss nicht MS und ggf. auch nicht O sein.

Ich habe mit ein paar Tools und VBA die Aktion leidlich reibungslos hinbekommen: Serienbrief-Datei normal erzeugen, in Gänze als PDF ausspeichern, Splitten (ggf. nach n Seiten) und dann mit einem Kommandozeilentool jede PDF als TXT ablegen um aus dieser den Dateinamen (teils als ein verstecktes Formularfeld - Weiße Schrift auf Weiß…) zu extrahieren um damit die PDF umzubenennen.

Oder mehr händisch - Dummydokumet ›mit Feldern‹ erstellen (Word). Excel wirft Werte als CSV = TXT [??] aus. Word öffnet den Dummy und in Suchen-Ersetzen–Läufen werden die »Formularfelder« mit den aus der TXT entnommenen befüllt, Speichern-Unter mit dem Namen (auch aus der TXT), Schließen. Nächstes…
Excel offen zu halten um direkt Zellen zu lesen könnte besser sein da viele ›Sonderzeichen‹ (Fremdsprachen mit anderen Schriften) im Spiel sind. Damit erfände man aber den Serienbrief neu.
Oder ganz normal analog oben Serienbrief bauen, als PDF splitten und dann von Excel aus die Dateien umbenennen; in der Hoffnung, dass auch die Datei 146.PDF mit Zeile 147 (Spaltenköpfe) übereinstimmt.

Gibt es einen Weg das wesentlich einfacher hinzubekommen? Und vor allem: nicht auf einem Preisniveau das einen aus den Socken haut. Anschaffen und Vorhalten eines Spezialwerkzeugs wollen überlegt sein (siehe mein Werkzeugkeller & die Küche…)

CN8
 
Sorry, aber du hast das alles so unnötig kompliziert und verworren geschrieben.
Ich bin MSO 2016 Expert zertifiziert und kann mir vorstellen, was du möchtest, bin mir aber dabei überhaupt nicht sicher.
Du schreibst viel zu viel über Nebensächlichkeiten und wirfst zu viele doppeldeutige Begriffe oder Formeln in einen Satz.

Was ist die Frage?

Nur ein paar Beispiele:
CSV = TXT? Was soll das bedeuten? Ist das eine Frage? Ja, CSV besteht aus Text. Nein, .cvs ist kein .txt.
Werden die Formularfelder aus einer Textdatei gelesen?
Was meinst du mit Serienbrief bauen und als PDF splitten? Womit Serienbrief bauen? Word? PDF-Editor? Excel? Wie splitten? Separat abspeichern und als neue Quelle verwenden? Konvertieren? Splitten wie Abschnitte aufteilen?
Was meinst du mit Preisniveau? Was ist dein Preisniveau, das dich nicht aus den Socken haut? 20 Euro? 500 Euro? 3000 Euro? Willst du ein Gerät, welches alles selbst kann? Eine Software? Beides? Einen Programmierer?

Deshalb: Was ist die Frage?

Welchen von diesen vielen Wegen willst du einfacher hinbekommen? Serienbrief? Konvertierung? Umbenennung? Sortierung? Anschaffung eines Gerätes/Software?
 
Ich denke es geht einfach mal wieder um die gefühlt schon tausendmal aufgeworfene Frage, wie man Serienbriefe in Einzel pdfs "druckt". Und ja, in einer makrofreien Office-Welt gibt es m. W. dafür bislang keine Automatisierung. Dafür gibt es eben im Netz auch tausende Skripte, die das bewerkstelligen. Bevorzugt übrigens aus meiner Sicht aus Word heraus, dort die Serienbrieffunktion datensatzweise triggern und automatisiert Dateinamen vergeben. Ich selbst hab mir auch mal so was gebaut, damals mit AHK, was wohl CN8 auch nicht ganz unbekannt ist.
Ich glaube aber, das alles ist CN8 schon klar, hier ging es nur darum. sich zu vergewissern, dass auch neuere Office Versionen oder Tools keinen einfacheren kostenlosen Weg bieten, den er übersehen haben könnte.
 
UhrenPeter schrieb:
Was ist die Frage?
cumulonimbus8 schrieb:
Gibt es einen Weg das wesentlich einfacher hinzubekommen?

«Du schreibst viel zu viel über Nebensächlichkeiten und wirfst zu viele doppeldeutige Begriffe oder Formeln in einen Satz.»
Und dann muss ich damit rechnen gesagt zu beklommen, dass ich wenig Infos liefere?! Wo sind…
Nebensächlichkeiten (und welche?)
doppeldeutige Begriffe (zähle sie auf!)
Formeln (ich sehe keine?!)

Da steht klar was getan werden soll: «Serien-PDF - PDF-Dateiname aus den Quelldaten» - mit eben deutlichem Hinweis auf das Problem mit dem PDF-Dateinamen.

Ich habe mir die Mühe gemacht zu schildern was ich derzeit tue - auch, damit niemand diese Wege vorschlägt. Aber auch um klarzumachen wo das Problem ist.


halwe schrieb:
Ich denke es geht einfach mal wieder um die gefühlt schon tausendmal aufgeworfene Frage, wie man Serienbriefe in Einzel pdfs "druckt".
Nein, das ist es ja nun eben nicht. Da dürften wir uns auch schon indirekt ausgetauscht haben wie man mit Makros den fertigen Serienbrief »vereinzelt«.

Das Problem ist der Dateiname der künftigen PDF. XL kennt ihn (kann aber nicht Serienbreif). Word übersieht ihn geflissentlich. Und PDF-Tools kennen ihn gansz und gar nicht.

halwe schrieb:
Ich glaube aber, das alles ist CN8 schon klar, hier ging es nur darum. sich zu vergewissern, dass auch neuere Office Versionen oder Tools keinen einfacheren kostenlosen Weg bieten, den er übersehen haben könnte.
Office ist der Aufhänger, dass es ggf. nun eben nicht Office, MSO, sein müssen muss. Der Acrobat wird das vermutlich können, aber der Preis kippt einen aus den Latschen das das Verhältnis von ihm und der Einsatzfrequenz nicht passt. Kostenlos muss gar nicht sein.

CN8
 
Ich verstehe das nicht ganz. Du hast eine Tabelle mit n Zeilen (jede Zeile ein Dateiname) und ein PDF mit n Seiten. Jede Seite soll einzeln gespeichert werden und die Seite i soll den Dateinamen der i-ten Zeile der Tabelle haben. Richtig verstanden?
 
pseudopseudonym schrieb:
Du hast eine Tabelle mit n Zeilen (jede Zeile ein Dateiname)
Gewissermaßen. Eine Tabelle mit viel Inhalt wie für Serienbriefe, und eine Spalte gibt den Dateinamen her (das kann eine sein die als Feld verwendet wird oder auch nicht).

pseudopseudonym schrieb:
und ein PDF mit n Seiten
Nein.
Es sollen erst / daraus n PFDs mit individuellem Inhalt (vgl. Serienbriefe) erzeugt werden - wobei diese einen Dateinamen bekommen sollen der sich in der Tabelle befindet - mit im Datensatz (Zeile) für die individuellen Inhalte.

pseudopseudonym schrieb:
Jede Seite soll einzeln gespeichert werden
Jein.
PDFs können auch z.B. zwei Seiten umfassen (dann natürlich sämtliche innerhalb der Aufgabe). Jeder «Brief» (= Zeile in Excel, letztlich) soll einzeln als PDF mit bestimmtem Namen gespeichert werden.

pseudopseudonym schrieb:
und die Seite i soll den Dateinamen der i-ten Zeile der Tabelle haben
Das PDF-Dokument i (mit n Seiten) bekommt seinen Dateinamen in der Tat aus dem i.-ten Datensatz - sei das ein separater Wert oder Teil der Brief-Daten (oder noch schlimmer daraus entnommen und bearbeitet [Pfadlänge…])

CN8
 
cumulonimbus8 schrieb:
Nein, das ist es ja nun eben nicht. Da dürften wir uns auch schon indirekt ausgetauscht haben wie man mit Makros den fertigen Serienbrief »vereinzelt«.
Wäre das jemals die Frage gewesen, hätte ich eigentlich direkt empfehlen müssen, das nicht zu tun sondern gleich Einzel-PDFs zu erzeugen.
Also geht's um das "wie drucke ich Serienbriefe in Einzel-pdfs"-Thema. Dass die einen Namen bekommen, der sich irgendwie aus den Excel Datensätzen ergibt bzw. darin steht, ist elementarer Bestandteil dieses schon zigmal diskutierten und leicht zu googlenden Themas. Du kannst ja aus Word auf die Excel-Felder zugreifen (z. B. über ActiveDocument.MailMerge.DataSource.DataFields("dateiname").Value).
Für mich ist das eben auch die naheliegendste und am besten erforschte Variante, viel einfacher, also sich in ein extra Tool einzuarbeiten.
 
Ahhh. Müsste ich sowas machen, würde ich mir schnell etwas mit Python und Latex zusammenscripten.
Also den Dummy mit Latex schreiben und dann mit Python der Tabelle nach die Dummy-Felder ersetzen und das PDF dann dem gewünschten Dateinamen entsprechend exportieren. Aber keine Ahnung, ob Latex für dich infrage kommt.

Statt mit Latex könnte man das wohl auch mit ner DOCX machen, wird aber sicher nicht einfacher:
https://stackoverflow.com/a/24813382

Du siehst schon, bei endanwenderfreundlichen Lösungen bin ich dann doch raus. Für das reine Zerteilen der PDF hätte es vielleicht ein Script getan, dass es immer wieder tut.
 
pseudopseudonym schrieb:
Ahhh. Müsste ich sowas machen, würde ich mir schnell etwas mit Python und Latex zusammenscripten.
Würde ich nicht mal widersprechen.
Leider (und ich kann nicht alles Aspekte hier aufführen) bekomme ich echten »Word-Experten« Serienbriefe vor die Tür (z.B. in Fremdsprachen, die ich nicht anzufassen wage…) mit denen ich leben muss.
Ginge es nach mir würde ich nach Vorgaben denen ein Layout aufbrummen (sinngemäß LaTex) mit dem man wirtschaften kann. Leider ist man nicht besser als seine Quellen - Layout von da, Rohdaten von dort…

Der Link ist im Endeffekt meine Suche-Ersetzen–Lösung - Tabellen als Raster sind vermutlich handlicher als direktes ersetzen.

Der Plan von halwe (ich habe bei Office-Lösungen Code gefunden, mal ansehen) scheint mir aber auch auf die obige hinauszulaufen: nit intern wird verarbeitet sondern Quelle-auf – Speichern Unter – Zumachen – Quelle auf… Ich fürchte, dass das langsamer ausgeht als meine modulare Lösung. Word halt.

So, und nun klopft eine andere Problem an (Ironie: in Handbetrieb erzeugte PDFs die umgeräumt werden wollen; auf einen Server für Tests…)

CN8
 
cumulonimbus8 schrieb:
Quelle-auf – Speichern Unter – Zumachen – Quelle auf…
Wie kommst du darauf?
Einfach die Datensätze einzeln als Serienbrief erzeugen und dabei jeweils den im Seriendruckfeld vermerkten Datennamen verwenden. Die Quelle bleibt offen.

Mit meinem AHK-Skript lief das ähnlich, aber gut. Da war dann eben immer eine Kaffeepause angesagt.
 
halwe schrieb:
Wie kommst du darauf?
Nur eine Vermutung beim betrachten des Codes. Es muss ja Brief für Brief gefüllt werden - aber das sehe ich mir bei Gelegenheit an. Im Augenblick ärgert mich der Server - und, ich vermisse was…

CN8
 
Da werde ich wohl hinzulernen müssen…
Der Code auf den mich halwe gestupst hat…

http://www.office-loesung.de/ftopic645755_0_0_asc.php
http://www.office-loesung.de/ftopic531017_0_0_asc.php#2632365
Code:
Sub Serienbrief_im_PDF_Format_speichern()
Dim S As String
Dim DD As Double
Dim SS As Single
Dim AppShell As Object
Dim BrowseDir As Variant
Dim Path As String
 On Error GoTo ErrorHandling
 
'' Set BrowseDir = AppShell.BrowseForFolder(0, "Speicherort für Serienbriefe auswählen", 0, 16)
'' If BrowseDir = "Desktop" Then
''  Path = CreateObject("WScript.Shell").SpecialFolders("Desktop")
'' Else
''  Path = BrowseDir.items().Item().Path
'' End If
'' Path = Path & "\Serienbrief-" & Format(Now, "dd.mm.yyyy-hh.mm.ss") & "\"
'' MkDir Path
 Path = "C:\A\D\"

 DD = Timer / 86400
 SS = Timer - Int(Timer)
 Debug.Print Hour(DD) & ":" & Minute(DD) & ":" & Format(Second(DD) + SS, "00.00")
 Application.Visible = False

 With ActiveDocument.MailMerge
  .DataSource.ActiveRecord = 1
  Do
   .Destination = wdSendToNewDocument
   .SuppressBlankLines = True
   With .DataSource
    .FirstRecord = .ActiveRecord
    .LastRecord = .ActiveRecord
    S = Path & .DataFields("LINKpassword").Value & ".pdf"
   End With
   .Execute Pause:=False
   If .DataSource.DataFields("LINKpassword").Value > "" Then
    ActiveDocument.SaveAs FileName:=S, FileFormat:=wdFormatPDF
   End If
   ActiveDocument.Close False
   If .DataSource.ActiveRecord < .DataSource.RecordCount Then
    .DataSource.ActiveRecord = wdNextRecord
   Else
    Exit Do
   End If
  Loop
 End With

 ' error handling
ErrorHandling:
 Application.Visible = True
 DD = Timer / 86400
 SS = Timer - Int(Timer)
 Debug.Print Hour(DD) & ":" & Minute(DD) & ":" & Format(Second(DD) + SS, "00.00")

 If Err.Number = 76 Then
     MsgBox "Der ausgewählte Speicherort ist ungültig", vbOKOnly + vbCritical
 ElseIf Err.Number = 5852 Then
     MsgBox "Das Dokument ist kein Serienbrief"
 ElseIf Err.Number = 4198 Then
     MsgBox "Der ausgewählte Speicherort ist ungültig", vbOKOnly + vbCritical
 ElseIf Err.Number = 91 Then
     MsgBox "Exportieren von Serienbriefen abgebrochen", vbOKOnly + vbExclamation
 ElseIf Err.Number > 0 Then
     MsgBox "Unbekannter Fehler: " & Err.Number & " - Bitte Makro erneut ausführen.", vbOKOnly + vbCritical
 Else
     MsgBox "Serienbriefe erfolgreich exportiert", vbOKOnly + vbInformation
 End If
 
End Sub
…und an dem ich ein wenig geschnippselt habe - der feste Zielordner, die Zeitanzeige, das Feld - hat für 100 Zeilen in XL bei einer simplen Serienquelle hier 13 Sekunden gebraucht. Das dürfte sich schlussendlich rechnen. Wenn der nächste Großauftrag kommt beginnt das große Testen 🙂

CN8
 
  • Gefällt mir
Reaktionen: halwe
Wenn ich »klaue« dann nicht heimlich sondern unheimlich 😇
 
Allmächtiger!:D
Nachdem ich beim dritten Mal lesen so einigermaßen verstanden habe, worum es hier geht, würde ich ein solches Vorhaben mit PowerShell und PdfSharp-gdi.dll umsetzen.

Über ein PS-Skript die Word-Dokumente erstellen, die Dateinamen aus dem Excel-Dokument einlesen und dann mit PdfSharp die Daten zusammenführen ("mergen") und als PDF-Dateien speichern.
Die man dann anschließend, ebenfalls mit PdfSharp, wieder splitten und als Textdateien speichern kann. Wenn man denn tatsächlich Textdateien benötigen sollte.

Aber gut, wenn es über ein Makro sein soll und es funktioniert, dann soll es so sein.
Das Aktivieren und Ausführen von Makros birgt allerdings ein erhebliches Sicherheitsrisiko in sich und es kommt nicht von ungefähr, dass immer wieder davor gewarnt wird.
Muss aber jeder selbst wissen.
 
Momentchen mal..?!
Mit PS Word so fernsteuern, dass ein Serienbrief erstellt wird, aus einer Excel-Quelle? Ich staune.
Haken ist - dem Skript muss ich doch erst mal einimpfen was alles mitspielt und wo es hin muss (Word-Formular, Excel-Mappe, Spalten nach Word, wo Dateiname entnehmen, Zielort). Kommt mir umständlich vor, ohne GUI; besonders bei mehreren Durchläufen. (Woher kämen übrigens die bewussten Daten die ich erst mal mergen müsste?)

Aber zur Erklärung.
Ich hatte früher schon der Not gehorcht PDFs daselbst zu öffnen um ihnen Infos zum Namen u.a.m. zu entnehmen. Teils per Automatik gemäß AutoIt zu öffnen und den Inhalt (Strg+A Strg+C…) in die Zwischenablage im die per Makro zu filzen. Ständlich und umständlich - aber es lief.
Also wurde das Grundkonzept im Umgang unter weiterer Denkfaulheit fortgeführt [die PDFs brauchte es ja so oder so, also kann man sie ja auch wieder als Quellen hernehmen]. Ganz normal Serienbriefe erstellen, dabei aber Infos zum Namen(-sbestandteil) hineinmogeln, alles als eine PDF speichern. Die splitten (erstes Fremdtool; liefert immerhin eine nummerische Folge der Namen). Nun Excel als VBA-Oberfläche greifen und mit Angaben darin die PDFs (zweites Fremdtool) in TXT wandeln. Die wiederum auslesen und die so gewonnen Infos zum Dateinamen machen. Aus plumper Vorsicht alle REN-Befehle in eine Batch schreiben und die final rennen lassen, zuletzt TXTs entsorgen.
Das ging gut zum Testen (weil man die Bestandteile einsehen konnte) und war auch recht flott - und weit besser als voriger Krampf (aus eigener Küche). Aber auch umständlich weil man immer schauen musste wann Word einmal mit dem SB und dann dem Speichern fertig war.
Damit kam dann heute die Frage auf das zu vereinfachen. Militärisch gesagt - Fire & Forget.

NotNerdNotDau schrieb:
Das Aktivieren und Ausführen von Makros birgt allerdings ein erhebliches Sicherheitsrisiko in sich und es kommt nicht von ungefähr, dass immer wieder davor gewarnt wird.
Formulieren wir es mal so: dieses Gedankengut ist (dann) großer Käse wenn man daraus ableitet seiner eigenen Arbeit nicht zu vertrauen. Makros sind für mich Alltagswerkzeuge - so sehr wie für Andere z.B. die Kreissäge. 😉

CN8
 
Hier mal zur Anregung ein paar Codeschnipsel, die aufzeigen, wie ich es evtl. umsetzen würde.
Nur als Anregung und ich weise ausdrücklich darauf hin, dass es sich dabei um keinen funktionierenden und um einen ungetesteten Code handelt!

-Als Erstes ein leeres Worddokument erstellen.
-Danach in dem Worddokument entsprechende Markierungen setzen:
Zeile1
Zeile2
usw.
-Worddatei in einem Verzeichnis speichern

PowerShell:
$ExcelDoc = "D:\MeinExcel.xlsx"
# Vorhandenes Exceldokument öffnen
$ExcelApp = New-Object -ComObject Excel.Application
$ExcelApp.AutomationSecurity = [Microsoft.Office.Core.MsoAutomationSecurity]::MsoAutomationSecurityForceDisable
$ExcelApp.EnableEvents = $False
$ExcelApp.DisplayAlerts = $False
$ExcelApp.Visible = $False
# Tabelle 1 definieren
$WorkBook = $ExcelApp.WorkBooks.Open($ExcelDoc)
$Sheet1 = $WorkBook.WorkSheets.Item(1)

# Pfad zum Worddokument definieren
$FolderPath = "D:\MeinWord"
$FileType = "*.docx"

# Daten aus Tabelle 1 des Exceldokuments in Variablen speichern
$Sheet1.Activate()
$DateiName = $Sheet1.Range("A1").Text
$Daten1 = $Sheet1.Range("A2").Text
$Daten2 = $Sheet1.Range("A3").Text

# Variablen für das Worddokument
$TextToReplace = @{
"Zeile1" = "$Daten1"
"Zeile2" = "$Daten2"
}
# Vorgang Ersetzen der Markierungen durch die Daten
$Word = New-Object -ComObject Word.Application
$Word.Visible = $False

$MatchCase = $True
$MatchWholeWord = $True
$MatchWildcards = $False
$MatchSoundsLike = $False
$MatchAllWordForms = $False
$Forward = $True
$FindWrap = [Microsoft.Office.Interop.Word.WdFindWrap]::WdFindContinue
$Format = $False
$Replace = [Microsoft.Office.Interop.Word.WdReplace]::WdReplaceOne

$CountFiles = 0
$CountReplace = 0
$CountAll = 0

Function FindAndReplace($ObjFind, $FindText, $ReplaceWith){
 $ObjFind.Execute($FindText, $MatchCase,$MatchWholeWord,$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,`
 $Forward,$FindWrap,$Format,$ReplaceWith,$Replace)
}

Function FindAndReplaceAll($ObjFind,$FindText,$ReplaceWith){
 $Count = 0
 $Count += FindAndReplace $ObjFind $FindText $ReplaceWith
 While ($ObjFind.Found){
  $Count += FindAndReplace $ObjFind $FindText $ReplaceWith
  }
  Return $Count
}

Function FindAndReplaceMultiple($ObjFind,$LookupTable){
 $Count = 0
 $LookupTable.GetEnumerator() | ForEach-Object{
  $Count += FindAndReplaceAll $ObjFind $_.Key $_.Value
 }
 Return $Count
}

Function FindAndReplaceWholeDoc($Document,$LookupTable){
 $Count = 0
 ForEach ($StoryRange in $Document.StoryRanges){
  Do{
       $Count += FindAndReplaceMultiple $StoryRange.Find $LookupTable
       $StoryRange = $StoryRange.NextStoryRange
    } Until (!$StoryRange)
 }
    $Shapes = $Document.Sections.Item(1).Headers.Item(1).Shapes
    If ($Shapes.Count){
        ForEach ($Shape in $Shapes | Where-Object {[Bool]$_.TextFrame.HasText}){
         $Count += FindAndReplaceMultiple $Shape.TextFrame.TextRange.Find $LookupTable
        }
    }
    Return $Count
}

Function ProcessDoc{
 $Doc = $Word.Documents.Open($_.FullName)
 $Count = FindAndReplaceWholeDoc $Doc $TextToReplace
 $Doc.Close([Ref]$True)
 Return $Count
}

$StopWatch = [Diagnostics.Stopwatch]::StartNew()
Get-ChildItem -Path $FolderPath -Recurse -Filter $FileType | ForEach-Object{
 $CountReplace = ProcessDoc
 $CountAll += $CountReplace
 $CountFiles++
}
$StopWatch.Stop()
$Elapsed = $StopWatch.Elapsed.ToString()

$Word.Quit()
$Word = $Null
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Word) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Doc) | Out-Null

Start-Sleep 3

# Worddokument als PDF-Datei speichern
$FilePath = "D:\TempWord.docx"
$Word1 = New-Object -ComObject Word.Application
$Word1.Visible = $False
$Doc1 = $Word1.Documents.Open($FilePath)
Add-Type -AssemblyName "Microsoft.Office.Interop.Word"
$OutputPath = "D:\TempWord.pdf"
$Doc1.SaveAs([Ref]$OutputPath, [Ref] [Microsoft.Office.Interop.Word.WdSaveFormat]::WdFormatPDF)
$Doc1.Close([Microsoft.Office.Interop.Word.WdSaveOptions]::WdDoNotSaveChanges)
$Word1.Quit()
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$Word1) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$Doc1) | Out-Null

Start-Sleep 3

$AnwFiles = "D:\PdfMerge.dll"
$PdfFiles = Get-ChildItem "D:\" -Filter "*.pdf"
$DocFiles = Get-ChildItem "D:\" -Filter "*.docx"
$DestPdfF = "D:\$DateiName.pdf"

Start-Sleep 10
   
MergePdf -Files $PdfFiles -Docs $DocFiles -DestinationFile $DestPdfF -PdfSharpPath $AnwFiles -Force #-RemoveSourceFiles -RemoveSourceDocs

Function MergePdf
{
    Param
    (
        [Parameter(Mandatory=$True)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript({$True})]
        [System.IO.FileInfo[]]$Files,
        [Parameter(Mandatory=$True)]
        [System.IO.FileInfo[]]$Docs,
        [Parameter(Mandatory=$True)]
        [ValidateNotNullOrEmpty()]
        [System.IO.FileInfo]$DestinationFile,
        [Parameter(Mandatory=$True)]
        [ValidateNotNullOrEmpty()]
        $PdfSharpPath,
        [Switch]$Force,
        [Switch]$RemoveSourceFiles,
        [Switch]$RemoveSourceDocs
    )
    Add-Type -LiteralPath $PdfSharpPath
    [System.IO.DirectoryInfo]$DestinationDirectory = $DestinationFile | Split-Path -Parent
    $Pdf = New-Object PdfSharp.Pdf.PdfDocument

    ForEach ($File in $Files)
    {
        $InputDocument = [PdfSharp.Pdf.IO.PdfReader]::Open($File.FullName, [PdfSharp.Pdf.IO.PdfDocumentOpenMode]::Import)
        For ($Index = 0; $Index -Lt $InputDocument.PageCount; $Index++)
        {
            $Page = $InputDocument.Pages[$Index]
            $Null = $Pdf.AddPage($Page)
        }
    }
    If ((Test-Path $DestinationFile.FullName) -And $Force)
    {
        Remove-Item $DestinationFile.FullName -Force
    }
    $Pdf.Save($DestinationFile.FullName)

    If ($RemoveSourceFiles)
    {
        ForEach($File in $Files)
        {
            Remove-Item -Path $File.FullName -Force:$Force
        }
    }
   
    If ($RemoveSourceDocs)
    {
        ForEach($Doc in $Docs)
        {
            Remove-Item -Path $Doc.FullName -Force:$Force
        }
    }
}
 
👍 Erst mal ein Lob für diesen Aufwand 👍

PS (für mich nach wie vor eine Fremd-Sprache zu viel die ich würde lernen wollen) wird mir immer suspekter… Nicht, dass man nicht mehr Office untereinander steuern könnte, jetzt kann ein MS-Betriebssystem-Bestandteil direkt in Applikationssteuerungen eingreifen und (in dem Sinne) VBA nachahmen.
Und in gewissem Sinne werden hier Räder neu erfunden (was letztlich ärgerlich genug ist - MSO, VBA auber auch PS könne alles Unmögliche, beim Möglichen versagen sie) - aber ich würde in einem Plan nichts Anderes tun.

Was mich etwas wundert, und dazu spreche ich zu wenig PS, da wird eine «Vorlage» mit Ersetzen gefüllt und gespeichert - allein, für sich, als PDF mit bestimmbarem Namen. Wozu müsste dann noch gemerged werden? Das Ziel ist (sind) ja individuelle PDFs auf einer Bord-Basis mit XL gefüllt. (Im Gegenteil wäre beim Serienbrief ›Klassik‹ das Thema ja den zu zerschnipseln; und die schnipsel zu benamsen.)

Ich bin mir aber reichlich Sicher, dass mit dieser Grundstruktur noch eine gaaanze Menge angestellt werden kann 🙂

CN8
 
Ich find's ein interessantes Beispiel dafür, dass man VBA über die Einbindung des Objektmodells auch "fernsteuern" kann, bis dahin, dass man die gesamte Mailmerge-Funktionalität extern nachbaut.
Im Prinzip könnte ich das fast 1:1 auch in AHK verwenden. Allerdings geht das natürlich viel einfacher direkt mit VBA und dem in Office integrierten VBA-Editor, weil der eben neben der integrierten VBA-Hilfe auch das Objektmodell und alle Konstanten kennt und überwacht.

Es ist allerdings richtig: Man sollte User (sofern man es nicht selbst ist) nicht zu sehr darauf konditionieren, VBA-behaftete Dokumente zu öffnen. Stehe gerade selbst vor dem Dilemma, dass ich in einen sicherheitssensiblen Anwendungsbereich VBA-Code ausrollen muss. Das gänge am einfachsten mit einer XLSM-Datei, aber die muss dort erst durch irgendwelche Sicherheitsabteilungen durch, deren Maßgaben und Reaktionsgeschwindigkeit ich nicht kenne.
Es ist aber auch die Frage, ob ein Powershell- oder Autohotkey-Skript hier einfacher auszurollen wäre.
 
Zuletzt bearbeitet:
halwe schrieb:
Es ist allerdings richtig: Man sollte User (sofern man es nicht selbst ist) nicht zu sehr darauf konditionieren, VBA-behaftete Dokumente zu öffnen. Stehe gerade selbst vor dem Dilemma, dass ich in einen sicherheitssensiblen Anwendungsbereich VBA-Code ausrollen muss. Das gänge am einfachsten mit einer XLSM-Datei, aber die muss dort erst durch irgendwelche Sicherheitsabteilungen durch, deren Maßgaben und Reaktionsgeschwindigkeit ich nicht kenne.
Das lohnt sich zu zitieren und zu unterschreiben.

Nur ist’s halt so - die Schwimmflügel helfen dem Anfänger, aber sie behindern den Könner. Ich nehme VBA als Werkzeug.

CN8
 
Zurück
Oben