F1. 技術研究|前端產生 Excel 內嵌圖表

針對「瀏覽器端 / 純前端免費產出 .xlsx 並內建圖表」的可行性評估。 本頁為高層次決策摘要,彙整六個面向的研究結論。

結論(TL;DR)

  • 不存在純前端、免費、可內嵌圖表的 xlsx 方案。所有可用的免費套件要嘛不支援圖表、要嘛僅限 Node 後端、要嘛已停止維護。
  • 現行 ClassDemo Ch4「DOCX(無圖) + PDF(含圖)」雙輸出, 已是免費方案中最務實的組合。
  • 若業主堅持 Excel 可編輯的圖表:選 SheetJS Pro(商用) 模板預埋(Template Pre-embed)
  • 若業主可接受「有圖但不可編輯」:ExcelJS + Chart.js PNG 嵌入為免費純前端可行解。

方案評分矩陣

方案免費瀏覽器端圖表支援維護狀態建議
SheetJS CE活躍純資料匯出可用
SheetJS Pro商用支援定價不公開,需洽詢
ExcelJS停滯(2023-10 之後無更新)圖表支援 issue 已開 10+ 年未解
xlsx-chart✗(Node only)廢棄(2021 停更)無法用於前端
ExcelJS + PNG 嵌入△(圖片、不可編輯)活躍(圖片 API 穩定)折衷方案:要圖不要編輯
模板預埋✓*自行維護*圖表需綁 Named Range
DOCX + PDF✓(PDF 截圖)活躍目前推薦

決策樹

需求:Excel 內嵌圖表
 │
 ├─ 圖表必須可編輯(在 Excel 中動資料會重繪)?
 │    ├─ 預算允許 → SheetJS Pro
 │    └─ 願意設計模板 + 使用者用 MS Excel 開啟 → 模板預埋
 │
 ├─ 只要「看得到圖」、不需可編輯?
 │    └─ ExcelJS + Chart.js PNG 嵌入(折衷推薦)
 │
 └─ 可改輸出格式(非 xlsx)?
      └─ DOCX + PDF(當前 ClassDemo Ch4 方案)

為何 Excel 圖表如此困難?

不是套件作者偷懶,而是 OOXML 規範本身的結構性複雜度遠高於 DOCX 圖片或 PDF 向量繪圖:

  • ChartSpace 規範:約 143 個複雜型別,單一圖表需產生 4+ 個 XML part 加 relationship 對應
  • numRef 雙快取:每筆資料同時需寫入公式字串與快取值,兩者不同步即破圖
  • AxisId 跨物件耦合:X/Y 軸 ID 需在 chart、plotArea、series 三處保持一致
  • TwoCellAnchor 座標:位置以 EMU(914,400 per inch)表達,非像素或 cell
  • 對照:DOCX 內嵌圖片只需 1 個 image part + 1 個 drawing 節點;PDF 向量繪圖由瀏覽器 canvas 直接產生

折衷方案:ExcelJS + Chart.js PNG 嵌入

當業主可以接受「圖表不可編輯、不隨資料重繪」時,有一條完全免費的純前端路徑: 先用 Chart.js 在 canvas 畫好圖,導出 PNG,再用 ExcelJS 以圖片方式嵌入 xlsx。

核心 API:ExcelJS 的 workbook.addImage + worksheet.addImage(雖然 ExcelJS 圖表功能停滯,但圖片嵌入 API 穩定且瀏覽器通用)。

const dataUrl = chartInstance.canvas.toDataURL('image/png')

const wb = new ExcelJS.Workbook()
const ws = wb.addWorksheet('報表')
ws.addRows(salesData)              // 先寫資料區

const imgId = wb.addImage({ base64: dataUrl, extension: 'png' })
ws.addImage(imgId, {
  tl:  { col: 6, row: 1 },          // 左上錨點
  ext: { width: 500, height: 300 }  // 尺寸(像素)
})

const buf = await wb.xlsx.writeBuffer()
項目說明
優點零授權費、純前端、Chrome/Numbers/WPS/Google Sheets 都認圖片
限制圖表為點陣圖,不可編輯、不隨資料重繪、放大會模糊
適用客戶只需「看」到圖,不在 Excel 中動資料或改樣式
不適用客戶要在 Excel 中調整圖表類型、篩選、改配色

模板預埋(Template Pre-embed)原理

  1. 設計者先在 Microsoft Excel 中建好模板:圖表、樣式、版面
  2. 圖表資料來源改為 Named Range,搭配動態公式:
    =OFFSET(Sheet1!$A$2, 0, 0, COUNTA(Sheet1!$A:$A)-1, N)
  3. 前端用 SheetJS CE 只寫資料區,不碰圖表 XML
  4. 使用者用 Excel 開啟 → 圖表自動依新資料重繪

限制:Google Sheets 不認動態 Named Range 公式;無法動態變更圖表類型或色系;模板改版需同步更新前端欄位定義。

風險與權衡

項目風險 / 限制
SheetJS Pro定價不公開、綁定單一供應商、License 條款需法務審核
模板預埋需使用者用 MS Excel 開啟;Google Sheets / Numbers 會失效
docxtemplater 內嵌圖表image module 為付費(約 €500 起)
html2pdf(目前 Ch4)圖表為點陣截圖、不可在 PDF 中選取數值、放大會模糊

最終建議

維持 ClassDemo Ch4 的現行設計:docxtemplater 產 DOCX(純文字/表格)+ html2pdf 產 PDF(含 Chart.js 截圖)。 這個組合在「零授權費用、瀏覽器可執行、使用者熟悉度、維護成本」四個軸度皆為當前最佳。

只有在下列兩個條件同時成立時,才需要升級方案: (1) 客戶明確要求在 Excel 中編輯圖表; (2) 願意採購 SheetJS Pro 授權或投入模板預埋的設計工時。