This document defines how client-side .xlsx exports should look and behave. Implementation: exportChartToXlsx.ts and exportMultiSheetToXlsx() — use these helpers for new reports so styling stays consistent.
| Export path | Follows this .md? |
|---|---|
Next.js builds the file via exportChartToXlsx / exportMultiSheetToXlsx (e.g. PO 入倉記錄 / rep-014) |
Yes — rules are enforced in code. |
Backend returns ready-made .xlsx or Excel bytes (JasperReports, Apache POI, etc.; most print-* report endpoints) |
No — not automatically. That code does not use this TypeScript module. To match the same look (grey headers, number formats, alignment), implement equivalent styling in Java/Kotlin or Jasper templates. See the backend companion doc below. |
Backend companion (visual parity):
FPSMS-backend/docs/EXCEL_EXPORT_STANDARD.md — same rules, for POI/Jasper implementers.
| Item | Value |
|---|---|
| Package | xlsx-js-style (not the plain xlsx community build) |
| Reason | Plain SheetJS does not persist cell styles (fill, alignment, numFmt) in the written file. xlsx-js-style is a compatible fork that does. |
Record<string, unknown>[] (array of plain objects).number values for amounts where possible; the exporter will apply number formats. Strings that look like numbers (e.g. "1,234.56") are parsed for money columns.After json_to_sheet(rows):
!cols — column width heuristic (see §4).applyHeaderRowStyle — header row styling (see §5).applyMoneyColumnNumberFormats — money columns only, data rows (see §6).applyNumericColumnRightAlign — money + quantity columns, all rows including header (see §7).!cols)wch = max(12, headerText.length + 4).Applied to every header cell first; numeric columns get alignment overridden in step 4.
| Property | Value |
|---|---|
| Font | Bold, black rgb: "000000" |
| Fill | Solid, fgColor: "D9D9D9" (light grey) |
| Alignment (default) | Horizontal center, vertical center, wrapText: true |
Detection: header label matches (case-insensitive):
金額 | 單價 | Amount | Unit Price | Total Amount
(Also matches bilingual headers that contain these fragments, e.g. Amount / 金額, Unit Price / 單價, Total Amount / 金額.)
Rules:
#,##0.00 (thousands separator + 2 decimals). Stored on the cell as z.t: "n" for numeric values.Naming new reports: use header text that matches the patterns above so columns pick up formatting automatically.
Detection: header label matches:
Qty | 數量 | Demand
(Covers e.g. Qty / 數量, Demand Qty / 訂單數量.)
Detection: union of money (§6) and quantity (§7) header patterns.
| Alignment | Value |
|---|---|
| Horizontal | right |
| Vertical | center |
wrapText |
Preserved / defaulted to true where applicable |
Existing style objects are merged (fill, font from header styling are kept).
| Rule | Detail |
|---|---|
| API | exportMultiSheetToXlsx({ name, rows }[], filename) |
| Sheet name length | Truncated to 31 characters (Excel limit) |
| Each sheet | Same pipeline as §3 if rows.length > 0 |
If rows.length === 0, a minimal sheet is written; no header styling pipeline runs.
| Feature | Location |
|---|---|
| Chart export | Uses exportChartToXlsx |
GRN / PO 入倉記錄 (rep-014) |
src/app/(main)/report/grnReportApi.ts — builds row objects, calls exportChartToXlsx / exportMultiSheetToXlsx |
Most other reports on /report download Excel/PDF generated on the server (Jasper, etc.). Those do not run this TypeScript pipeline; use FPSMS-backend/docs/EXCEL_EXPORT_STANDARD.md if you want the same visual rules there.
xlsx-js-style only if building sheets manually; otherwise call exportChartToXlsx or exportMultiSheetToXlsx.exportChartToXlsx.ts and update this document.| File | Role |
|---|---|
exportChartToXlsx.ts |
Single-sheet export + styling pipeline |
grnReportApi.ts |
Example: bilingual headers, money values, multi-sheet GRN report |
FPSMS-backend/docs/EXCEL_EXPORT_STANDARD.md |
Backend Excel (POI/Jasper) — same rules, separate code |
Last aligned with implementation in exportChartToXlsx.ts (header fill #D9D9D9, money format #,##0.00, right-align numeric columns).