OfficeServerJs/create_template.js
OfficeServer dgsoft 1bd5654f6b Initial commit: DOCX Template Server mit API und Tabellen-Support
-  Node.js/Express Server mit DOCX Template-Verarbeitung
-  Automatische Tag-Erkennung und Demo-Daten-Generierung
-  Tabellen-Unterstützung mit Schleifen-Tags
-  REST-API /api/process-template für externe Integration
-  Web-Oberfläche mit vollständiger Dokumentation
-  SSL-Unterstützung (HTTPS Port 443 öffentlich)
-  Intelligente Spaltenerkennung für Tabellen
-  Detaillierte Statusmeldungen für alle Operationen
-  Flexible Custom-Daten + Auto-Generierung
-  Template- und Dokument-Management APIs
2025-10-04 22:04:25 +02:00

432 lines
13 KiB
JavaScript

const PizZip = require('pizzip');
const fs = require('fs');
const path = require('path');
// Erstelle ein richtiges DOCX-Template
function createAdvancedTemplate() {
const zip = new PizZip();
// Content Types
zip.file('[Content_Types].xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
</Types>`);
// Main relationships
zip.file('_rels/.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
</Relationships>`);
// Document relationships
zip.file('word/_rels/document.xml.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
</Relationships>`);
// Styles
zip.file('word/styles.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:docDefaults>
<w:rPrDefault>
<w:rPr>
<w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman"/>
<w:sz w:val="22"/>
<w:szCs w:val="22"/>
<w:lang w:val="de-DE"/>
</w:rPr>
</w:rPrDefault>
</w:docDefaults>
</w:styles>`);
// Document content with proper DOCX structure and table
zip.file('word/document.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
<w:sz w:val="32"/>
</w:rPr>
<w:t>RECHNUNG</w:t>
</w:r>
</w:p>
<w:p/>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Firma: </w:t>
</w:r>
<w:r>
<w:t>{firma}</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Ansprechpartner: </w:t>
</w:r>
<w:r>
<w:t>{vorname} {nachname}</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>E-Mail: </w:t>
</w:r>
<w:r>
<w:t>{email}</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Telefon: </w:t>
</w:r>
<w:r>
<w:t>{telefon}</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Adresse: </w:t>
</w:r>
<w:r>
<w:t>{adresse}, {plz} {stadt}</w:t>
</w:r>
</w:p>
<w:p/>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Rechnungsdatum: </w:t>
</w:r>
<w:r>
<w:t>{datum}</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Rechnungsnummer: </w:t>
</w:r>
<w:r>
<w:t>{nummer}</w:t>
</w:r>
</w:p>
<w:p/>
<!-- Seitenumbruch -->
<w:p>
<w:r>
<w:br w:type="page"/>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:b/>
<w:sz w:val="24"/>
</w:rPr>
<w:t>RECHNUNGSPOSITIONEN</w:t>
</w:r>
</w:p>
<w:p/>
<!-- Tabelle mit Kopfzeilen -->
<w:tbl>
<w:tblPr>
<w:tblStyle w:val="TableGrid"/>
<w:tblW w:w="5000" w:type="pct"/>
<w:tblBorders>
<w:top w:val="single" w:sz="4" w:space="0" w:color="000000"/>
<w:left w:val="single" w:sz="4" w:space="0" w:color="000000"/>
<w:bottom w:val="single" w:sz="4" w:space="0" w:color="000000"/>
<w:right w:val="single" w:sz="4" w:space="0" w:color="000000"/>
<w:insideH w:val="single" w:sz="4" w:space="0" w:color="000000"/>
<w:insideV w:val="single" w:sz="4" w:space="0" w:color="000000"/>
</w:tblBorders>
</w:tblPr>
<!-- Kopfzeile -->
<w:tr>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="D9D9D9"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Position</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="D9D9D9"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Beschreibung</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="D9D9D9"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Betrag (EUR)</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="D9D9D9"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Datum</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<!-- Template-Zeilen für Loop -->
<w:tr>
<w:tc>
<w:p>
<w:r>
<w:t>{#items}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t></w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t>{items_position}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t>{items_name}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:t>{items_value}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t>{items_date}</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr>
<w:tc>
<w:p>
<w:r>
<w:t>{/items}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t></w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:p>
<w:r>
<w:t></w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<!-- Summen-Zeile -->
<w:tr>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="F2F2F2"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>SUMME</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="F2F2F2"/>
</w:tcPr>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Gesamtbetrag</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="F2F2F2"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="right"/>
</w:pPr>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>{betrag}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:shd w:val="clear" w:color="auto" w:fill="F2F2F2"/>
</w:tcPr>
<w:p>
<w:r>
<w:t></w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
<w:p/>
<w:p/>
<w:p>
<w:r>
<w:rPr><w:b/></w:rPr>
<w:t>Zusätzliche Informationen:</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t>{beschreibung}</w:t>
</w:r>
</w:p>
<w:p/>
<w:p>
<w:r>
<w:t>Mit freundlichen Grüßen</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t>Ihr Team von {firma}</w:t>
</w:r>
</w:p>
</w:body>
</w:document>`);
return zip.generate({ type: 'nodebuffer' });
}
// Erstelle das Template
const templateBuffer = createAdvancedTemplate();
const templatePath = path.join(__dirname, 'templates', 'rechnung_template.docx');
fs.writeFileSync(templatePath, templateBuffer);
console.log('Erweiterte Rechnung Template erstellt:', templatePath);