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
This commit is contained in:
432
create_template.js
Normal file
432
create_template.js
Normal file
@@ -0,0 +1,432 @@
|
||||
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);
|
||||
Reference in New Issue
Block a user