> /beleg/rechnung/
Invoice as a PDF with pdf-lib
- A page is
doc.addPage([SEITE.b, SEITE.h])with 595.28 × 841.89 points: A4, 1 point = 1/72 inch. - The origin is at the bottom left. The code plans from the top and converts every line with
Y = SEITE.h - oben. - The code calculates totals and tax in whole cents: Inputs are read as a sequence of digits (BigInt). Only for the text in the EPC QR code (GiroCode) does this become a euro amount with two decimal places.
- The EPC QR code is not an image but a path of rectangles (PDF command
re), filled once (f). Sharp at any size. - Font: Helvetica, one of the standard fonts of PDF. No font file, nothing from the network.
View code: lib/beleg.js
lib/beleg.js · baueBelegPdf() · shortened, otherwise verbatim (the comments are German in the original)
const doc = await PDFDocument.create();
const fonts = { n: await doc.embedFont(StandardFonts.Helvetica), b: await doc.embedFont(StandardFonts.HelveticaBold) };
…
const page = doc.addPage([SEITE.b, SEITE.h]);
const Y = (oben) => SEITE.h - oben;
…
if (o.t === 'text') page.drawText(o.s, { x: o.x, y: Y(o.y), size: o.size, font: fonts[o.fett ? 'b' : 'n'], color: farbe(o.farbe) });
…
else if (o.t === 'qr') {
// Vektor-Rechtecke: ein Pfad, eine Füllung. Kein Bild, in jeder Größe scharf, keine Nähte zwischen den Modulen.
const n = o.matrix.length;
const m = o.groesse / n;
const ops = [pushGraphicsState(), setFillingRgbColor(0, 0, 0)];
for (const l of qrLaeufe(o.matrix)) ops.push(rectangle(o.x + l.c * m, Y(o.y + (l.r + 1) * m), l.len * m, m));
ops.push(fill(), popGraphicsState());
page.pushOperators(...ops);
}
…
const bytes = await doc.save({ useObjectStreams: false });
On request, the same tool writes the e-invoice (E-Rechnung) as an XRechnung (CII XML), also in the tab.