Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Vorlagen: Briefkopf und Dokumenteninhalt trennen #1552

Open
5 of 10 tasks
LazyGuy21No opened this issue Feb 3, 2022 · 20 comments
Open
5 of 10 tasks

[FEATURE] Vorlagen: Briefkopf und Dokumenteninhalt trennen #1552

LazyGuy21No opened this issue Feb 3, 2022 · 20 comments
Labels
enhancement New feature or request
Milestone

Comments

@LazyGuy21No
Copy link

LazyGuy21No commented Feb 3, 2022

Eine Änderung im Briefkopf zieht die Bearbeitung vieler Vorlagen nach sich.

Es wäre daher toll, wenn man eine Briefkopf-Datei einer Person oder Gruppe (Standort X-Stadt) zuordnen könnte

  • Bei RAin Öztürk mit Zusatz: zertifizierte Testamentsvollstreckerin und Logo und Standorthinweis für den Standort Münster, aber
  • Bei RAin Brand mit Handynummer für Verteidigerhotline und Angabe des Anderkontos in der Fußzeile, außerdem Parkplatzhinweis für den Standort Heidelberg

Die Inhalte der Dokumente Vorlagen würden dann in die Briefkopfvorlage "gesaugt", anschließend werden alle Skripte /Platzhalter in beiden Vorlagen ausgewertet (so macht es das Vorlagenmanagement der Stadt München LiMux/Wollmux). Dafür steht in der Briefkopfvorlage ein Platzhalter der anzeigt, dass hier der Textkörper aus der Vorlagendatei eingefügt wird.

----- @j-dimension 2023-05-12 ------

  • Briefkopfverwaltung in der GUI
  • Briefkopfverwaltung im Backend
  • Dokumenterstellung
  • Datensicherungen erweitern, um Briefköpfe mit zu sichern
  • zuletzt genutzten Briefkopf speichern und automatisch selektieren
  • neuen Backupmanager in Release aufnehmen

----- @j-dimension 2023-05-20 ------

  • testen: Datensicherungen Briefköpfe
  • testen: Rücksicherung Briefköpfe
  • testen: Style-Übernahme Vorlage (nicht Briefkopf) ODT
  • testen: Style-Übernahme Vorlage (nicht Briefkopf) DOCX
@LazyGuy21No LazyGuy21No added the enhancement New feature or request label Feb 3, 2022
@j-dimension
Copy link
Member

@guidobo kannst Du den letzten Satz noch fertigstellen? :-)

@j-dimension j-dimension added this to the 2.2 milestone Feb 3, 2022
@j-dimension j-dimension added this to To do in j-lawyer.org 2.2 via automation Feb 3, 2022
@j-dimension j-dimension moved this from To do to In progress in j-lawyer.org 2.2 Apr 5, 2022
@j-dimension j-dimension removed this from In progress in j-lawyer.org 2.2 Jul 25, 2022
@j-dimension j-dimension modified the milestones: 2.2, 2.3 Jul 25, 2022
@stm9x9
Copy link

stm9x9 commented Aug 26, 2022

geht das in ODT/DOCX so einfach? Ist ja auch ne Menge Layout-Zeugs, was an so einem Briefkopf hängt? Aber cool wäre das!

@j-dimension j-dimension added this to To do in j-lawyer.org 2.2 via automation Sep 21, 2022
@j-dimension j-dimension modified the milestones: 2.3, 2.2 Sep 21, 2022
@LazyGuy21No
Copy link
Author

LazyGuy21No commented Oct 5, 2022

Möglicherweise dieselbe Technik: Inhalte aus anderen Vorlagen per Skript einfügen und auch dort alle Script-Befehle auflösen.

[[SCRIPT:WENNGROESSER(AKTE_GEGENSTANDSWERT,"5000", "/bausteine/Landgericht.odt", "/bausteine/Amtsgericht.odt");]]

Pfadangabe relativ zum Ordner "Vorlagen" auf dem Server

@j-dimension j-dimension added this to To do in j-lawyer.org 2.3 via automation Oct 23, 2022
@j-dimension j-dimension removed this from To do in j-lawyer.org 2.2 Oct 23, 2022
@j-dimension j-dimension modified the milestones: 2.2, 2.3 Oct 23, 2022
@j-dimension j-dimension moved this from To do to In progress in j-lawyer.org 2.3 Nov 13, 2022
@j-dimension
Copy link
Member

tdf/odftoolkit#186

@LazyGuy21No
Copy link
Author

LazyGuy21No commented Nov 13, 2022 via email

@j-dimension j-dimension moved this from In progress to To do in j-lawyer.org 2.3 Jan 10, 2023
@j-dimension j-dimension removed this from To do in j-lawyer.org 2.3 Feb 22, 2023
@j-dimension j-dimension modified the milestones: 2.3, 2.3.1 Feb 22, 2023
@j-dimension
Copy link
Member

ODT:

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
import org.odftoolkit.odfdom.doc.OdfDocument;
import org.odftoolkit.odfdom.doc.OdfTextDocument;
import org.odftoolkit.odfdom.dom.element.office.OfficeTextElement;
import org.odftoolkit.odfdom.dom.element.style.StyleMasterPageElement;
import org.odftoolkit.odfdom.dom.element.style.StylePageLayoutElement;
import org.odftoolkit.odfdom.dom.element.text.TextPElement;
import org.odftoolkit.odfdom.dom.element.text.TextSElement;
import org.odftoolkit.odfdom.dom.element.text.TextSpanElement;
import org.odftoolkit.odfdom.dom.element.text.TextUserFieldGetElement;
import org.odftoolkit.odfdom.dom.element.text.TextUserFieldInputElement;

public class ODFDocumentMerger {

    public static void main(String[] args) throws Exception {

        // Load sender address and recipient address document
        OdfTextDocument senderDoc = OdfTextDocument.loadDocument(new File("sender.odt"));
        OdfTextDocument recipientDoc = OdfTextDocument.loadDocument(new File("recipient.odt"));

        // Load body document
        OdfTextDocument bodyDoc = OdfTextDocument.loadDocument(new File("body.odt"));

        // Create a new document to store the merged documents
        OdfTextDocument mergedDoc = OdfTextDocument.newTextDocument();

        // Get the content root element of the new document
        OfficeTextElement contentRoot = mergedDoc.getContentRoot();

        // Copy the sender and recipient addresses to the new document
        OfficeTextElement senderContent = senderDoc.getContentRoot();
        OfficeTextElement recipientContent = recipientDoc.getContentRoot();
        contentRoot.appendChild(senderContent.cloneNode(true));
        contentRoot.appendChild(recipientContent.cloneNode(true));

        // Copy the body document to the new document
        OfficeTextElement bodyContent = bodyDoc.getContentRoot();
        contentRoot.appendChild(bodyContent.cloneNode(true));

        // Update the page layout to use the first page style for the first page and the default style for all other pages
        StylePageLayoutElement defaultPageLayout = mergedDoc.getStylesDom().getPageLayouts().get(0);
        StylePageLayoutElement firstPageLayout = mergedDoc.getStylesDom().getPageLayouts().getByName("First_20_Page");
        StyleMasterPageElement masterPage = mergedDoc.getStylesDom().getMasterPages().get(0);
        masterPage.getStyleHeader().setStylePageLayoutNameAttribute(firstPageLayout.getStyleNameAttribute());
        masterPage.getStyleFooter().setStylePageLayoutNameAttribute(defaultPageLayout.getStyleNameAttribute());

        // Save the merged document
        mergedDoc.save(new FileOutputStream("merged.odt"));

        // Close all the documents
        senderDoc.close();
        recipientDoc.close();
        bodyDoc.close();
        mergedDoc.close();
    }
}

@j-dimension
Copy link
Member

DOCX:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

public class MergeDocxDocuments {
    public static void main(String[] args) {
        try {
            // Load the sender address and recipient address document
            XWPFDocument doc1 = new XWPFDocument(
                MergeDocxDocuments.class.getResourceAsStream("doc1.docx"));
            // Load the body document
            XWPFDocument doc2 = new XWPFDocument(
                MergeDocxDocuments.class.getResourceAsStream("doc2.docx"));
            
            // Create a new merged document
            XWPFDocument mergedDoc = new XWPFDocument();
            
            // Add the sender address and recipient address table to the merged document
            XWPFTable table1 = doc1.getTables().get(0);
            XWPFTable mergedTable1 = mergedDoc.createTable(table1.getRows().size(), 
                table1.getRow(0).getTableCells().size());
            copyTable(table1, mergedTable1);
            
            // Add the body paragraphs to the merged document
            for (XWPFParagraph paragraph : doc2.getParagraphs()) {
                XWPFParagraph newParagraph = mergedDoc.createParagraph();
                copyParagraph(paragraph, newParagraph);
            }
            
            // Save the merged document as a new file
            File mergedFile = new File("merged.docx");
            FileOutputStream fos = new FileOutputStream(mergedFile);
            mergedDoc.write(fos);
            fos.close();
            
            System.out.println("Documents merged successfully!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // Helper method to copy a table from one document to another
    private static void copyTable(XWPFTable sourceTable, XWPFTable targetTable) {
        for (int rowIndex = 0; rowIndex < sourceTable.getRows().size(); rowIndex++) {
            XWPFTableRow sourceRow = sourceTable.getRow(rowIndex);
            XWPFTableRow targetRow = targetTable.getRow(rowIndex);
            
            for (int cellIndex = 0; cellIndex < sourceRow.getTableCells().size(); cellIndex++) {
                XWPFTableCell sourceCell = sourceRow.getCell(cellIndex);
                XWPFTableCell targetCell = targetRow.getCell(cellIndex);
                
                targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
                for (XWPFParagraph paragraph : sourceCell.getParagraphs()) {
                    XWPFParagraph newParagraph = targetCell.addParagraph();
                    copyParagraph(paragraph, newParagraph);
                }
            }
        }
    }
    
    // Helper method to copy a paragraph from one document to another
    private static void copyParagraph(XWPFParagraph sourceParagraph, XWPFParagraph targetParagraph) {
        for (XWPFRun run : sourceParagraph.getRuns()) {
            XWPFRun newRun = targetParagraph.createRun();
            newRun.setText(run.getText(0));
            newRun.setFontFamily(run.getFontFamily());
            newRun.setFontSize(run.getFontSize());
            newRun.setBold(run.isBold());
            newRun.setItalic(run.isItalic());
            newRun.setUnderline(run.getUnderline());
        }
    }
}

@j-dimension
Copy link
Member

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

/**
 *
 * @author jens
 */
public class DocxMergeTestClass2 {

    public static void main(String[] args) {
        try {
            
            Path merged = Paths.get("/home/jens/dev/projects/experiments/src/merged.docx");
            Path originalPath = Paths.get("/home/jens/dev/projects/experiments/src/header.docx");
            Files.copy(originalPath, merged, StandardCopyOption.REPLACE_EXISTING);
            
            
            // Load the sender address and recipient address document
            XWPFDocument headerDoc = new XWPFDocument(
                    new FileInputStream("/home/jens/dev/projects/experiments/src/header.docx"));
            // Load the body document
            XWPFDocument bodyDoc = new XWPFDocument(
                    new FileInputStream("/home/jens/dev/projects/experiments/src/body.docx"));

            // Create a new merged document
            XWPFDocument mergedDoc = new XWPFDocument(
                    new FileInputStream("/home/jens/dev/projects/experiments/src/merged.docx"));

            

            // Add the body paragraphs to the merged document
            for (XWPFParagraph paragraph : bodyDoc.getParagraphs()) {
                XWPFParagraph newParagraph = mergedDoc.createParagraph();
                copyParagraph(paragraph, newParagraph);
            }

            // Save the merged document as a new file
            File mergedFile = new File("/home/jens/dev/projects/experiments/src/merged.docx");
            FileOutputStream fos = new FileOutputStream(mergedFile);
            mergedDoc.write(fos);
            fos.close();

            System.out.println("Documents merged successfully!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // Helper method to copy a table from one document to another
    private static void copyTable(XWPFTable sourceTable, XWPFTable targetTable) {
        for (int rowIndex = 0; rowIndex < sourceTable.getRows().size(); rowIndex++) {
            XWPFTableRow sourceRow = sourceTable.getRow(rowIndex);
            XWPFTableRow targetRow = targetTable.getRow(rowIndex);

            for (int cellIndex = 0; cellIndex < sourceRow.getTableCells().size(); cellIndex++) {
                XWPFTableCell sourceCell = sourceRow.getCell(cellIndex);
                XWPFTableCell targetCell = targetRow.getCell(cellIndex);

                targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
                for (XWPFParagraph paragraph : sourceCell.getParagraphs()) {
                    XWPFParagraph newParagraph = targetCell.addParagraph();
                    copyParagraph(paragraph, newParagraph);
                }
            }
        }
    }

    // Helper method to copy a paragraph from one document to another
    private static void copyParagraph(XWPFParagraph sourceParagraph, XWPFParagraph targetParagraph) {
        for (XWPFRun run : sourceParagraph.getRuns()) {
            XWPFRun newRun = targetParagraph.createRun();
            newRun.setText(run.getText(0));
            newRun.setFontFamily(run.getFontFamily());
            newRun.setFontSize(run.getFontSize());
            newRun.setBold(run.isBold());
            newRun.setItalic(run.isItalic());
            newRun.setUnderline(run.getUnderline());
        }
    }

}

@j-dimension
Copy link
Member

Demo mit LibreOffice (Briefkopf und Vorlageninhalt getrennt). Microsoft Office funktioniert analog:

briefkopf-vorlage-libreoffice.mp4

@PBaumfalk
Copy link

PBaumfalk commented May 20, 2023 via email

@Dickmaulruessler
Copy link

ja, ich muss auch sagen: Das ist super!
Danke Jens!

@stm9x9
Copy link

stm9x9 commented May 21, 2023

Top!

Zwei Nachfragen: Können in der Brief**kopf**-Datei auch Fußzeilen und so gemacht werden? Und alternative Inhalte für die zweite und weitere Seiten?

Und: Im Beispiel gibt es in dem Briefkopf und der eigentlichen Textvorlage die MANDANT-Variablen. Ich würde aber meinen Briefkopf ja zb für Mandantenschreiben und Schriftsätze verwenden. Da gibt es zwar vielleicht auch MANDANT oder aber KLÄGER, aber im Briefkopf müßte ich ja sowas wie EMPFÄNGER haben. Gibt es dafür schon eine Lösung? Einem Beteiligten dann zwei Rollen in der Brieferstellung zuweisen?

@j-dimension
Copy link
Member

Zwei Nachfragen: Können in der Brief**kopf**-Datei auch Fußzeilen und so gemacht werden? Und alternative Inhalte für die zweite und weitere Seiten?

Ja und ja.

Gibt es dafür schon eine Lösung? Einem Beteiligten dann zwei Rollen in der Brieferstellung zuweisen?

Ja, das geht ja jetzt schon. Man könnte sich also eine ganz generische Rolle "Empfänger" anlegen, die nie in einer Akte verwendet wird, nur für die Auswahl bei Dokumenterstellung. Dann ist der Mandant eben sowohl Mandant als auch Empfänger.

@j-dimension
Copy link
Member

Werde das Feature trotzdem als "Prototypen" liefern, da beim "Zusammenfügen" sicher noch die eine oder andere Konstellation genutzt werden wird, die ich nicht bedacht habe.

@j-dimension
Copy link
Member

  • Reihenfolge der Elemente (MS Office)
  • Formatierung (LibreOffice)
  • Unterstützung für Grafiken (LibreOffice)

@j-dimension
Copy link
Member

ODT: Unklar, wie Formatierungen ermittelt werden können
tdf/odftoolkit#242

@hackvokat
Copy link

Freue mich sehr über das 2.4 Update!

Kann der Briefkopf nur vor der Dokumentenvorlage eingefügt werden? Ich würde gerne in den Briefkopf auch die Signatur+Unterschrift einbauen wollen, das müsste dann aber erst nach der Dokumentenvorlage eingefügt werden. Bzw. die Dokumentenvorlage müsste dann an die Stelle eines Platzhalters des Briefkopfes in der Mitte eingefügt werden.

Gibt es hierfür eine Variable oä? Oder ist der aktuelle Stand einfach nur BriefKOPF?

Danke und LG

@j-dimension
Copy link
Member

Der Briefkopf ist nicht nur "Briefkopf" im Sinne von: er kann auch Fußzeilen beinhalten, die übernommen werden. Er ist aber kein Mittel, um Unterschriften etc. zu übernehmen. Das müsste separat entwickelt werden.

@hackvokat
Copy link

hackvokat commented Oct 5, 2023

  1. Signaturen
    Wir haben das mit den Signaturen und Unterschriften jetzt über Autotext gelöst: In jeder Vorlage wird Signatur_Benutzer eingefügt und dann mit Autotext mit Bild der Unterschrift und Signatur ersetzt (LibreOffice einfach F3 drücken). Gibt es vielleicht die Möglichkeit Autotext-Ersetungen am Ende der automatischen Dokumentenerstellung automatisch zu triggern?

  2. Formatierung
    Allerdings habe ich das Problem, dass Formatierungen am Anfang der eingefügten Vorlage nicht übernommen werden. Ist die erste Zeile in der Vorlage also fett geschrieben, landet sie in normaler Breite im finalen Dokument. Zentriert funktioniert es, nur fett wird beim Einsetzen entfernt. Eine Idee, woran das liegen könnte?

@j-dimension
Copy link
Member

Am besten mal die Dokumente bereit stellen.

@j-dimension j-dimension modified the milestones: 2.5, 2.6 Oct 22, 2023
@j-dimension j-dimension modified the milestones: 2.6, 2.7 Feb 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: In Progress
Development

No branches or pull requests

6 participants