diff --git a/src/main/capabilities/excel-common.ts b/src/main/capabilities/excel-common.ts index e61a1aa..cd8e9cd 100644 --- a/src/main/capabilities/excel-common.ts +++ b/src/main/capabilities/excel-common.ts @@ -625,13 +625,13 @@ function toArgb(color: string): string { return hex.length === 6 ? "FF" + hex : hex.padStart(8, "F"); } -function parseFormatSpec(raw: unknown): { bold?: boolean; italic?: boolean; underline?: boolean; fontSize?: number; color?: string; bgColor?: string; numFmt?: string } { - if (typeof raw === "object" && raw !== null) return raw as ReturnType; +function parseFormatSpec(raw: unknown): { bold?: boolean; italic?: boolean; underline?: boolean; fontSize?: number; color?: string; bgColor?: string; numFmt?: string; fontName?: string } { + if (typeof raw === "object" && raw !== null) return normalizeFormatSpec(raw as Record); const text = String(raw ?? "").trim(); if (!text) return {}; try { const parsed = JSON.parse(text) as Record; - if (typeof parsed === "object" && parsed) return parsed as ReturnType; + if (typeof parsed === "object" && parsed) return normalizeFormatSpec(parsed); } catch { /* fall through to keywords */ } const spec: ReturnType = {}; const lower = text.toLowerCase(); @@ -640,6 +640,26 @@ function parseFormatSpec(raw: unknown): { bold?: boolean; italic?: boolean; unde if (/下划线|underline/.test(lower)) spec.underline = true; const sizeMatch = text.match(/(\d+)号|font-size[::]\s*(\d+)/i); if (sizeMatch) spec.fontSize = Number(sizeMatch[1] || sizeMatch[2]); + // 无关键词命中时视为数字格式代码(如 "0.00"、"G/通用格式"、"yyyy-mm-dd") + if (!Object.keys(spec).length) spec.numFmt = text; + return spec; +} + +/** 兼容厂商格式 JSON(FontColor/BoldAndItalic/FontSize/BackgroundColor/DigitalFormat)与内部 camelCase 键 */ +function normalizeFormatSpec(parsed: Record): ReturnType { + const spec: ReturnType = {}; + const flags = Number(parsed.BoldAndItalic ?? 0); + if (flags & 1) spec.bold = true; + if (flags & 2) spec.italic = true; + if (parsed.FontFormat) spec.fontName = String(parsed.FontFormat); + if (parsed.FontSize !== undefined && parsed.FontSize !== null && String(parsed.FontSize).trim() !== "") spec.fontSize = Number(parsed.FontSize); + if (parsed.FontColor) spec.color = String(parsed.FontColor); + if (parsed.BackgroundColor) spec.bgColor = String(parsed.BackgroundColor).split(",")[0].trim(); + const digital = parsed.DigitalFormat as { formatstring?: unknown } | undefined; + if (digital?.formatstring && String(digital.formatstring).trim() !== "") spec.numFmt = String(digital.formatstring); + for (const key of ["bold", "italic", "underline", "fontSize", "color", "bgColor", "numFmt"] as const) { + if (parsed[key] !== undefined) (spec as Record)[key] = parsed[key]; + } return spec; } @@ -670,6 +690,7 @@ registerMany(["Excel_Cs_SetCellFormat", "Excel_Cs_SetCellFormat_V2", "Excel_Cs_S italic: spec.italic, underline: spec.underline, size: spec.fontSize, + name: spec.fontName ?? cell.font?.name, color: spec.color ? { argb: toArgb(spec.color) } : undefined }; } @@ -697,11 +718,15 @@ register("Excel_Cs_ExcelFilter", async (ctx, node, args) => { register("Excel_Cs_ShowTableStyle", async (ctx, node, args) => { const source = await loadWorkbook(args, node.id, node.componentId); const sheet = worksheetOf(source.workbook, args); - const headerRow = sheet.getRow(1); - headerRow.font = { ...headerRow.font, bold: true }; - headerRow.fill = { type: "pattern", pattern: "solid", fgColor: { argb: "FFD9E8F5" } }; - headerRow.commit(); - sheet.autoFilter = { from: { row: 1, column: 1 }, to: { row: Math.max(1, sheet.rowCount), column: Math.max(1, sheet.columnCount) } }; + // 必须逐单元格设置:exceljs 的行级样式(row.font/row.fill + commit)会覆盖 + // 该行已设置的单元格样式(如先执行过的设置单元格格式) + const lastCol = Math.max(1, sheet.columnCount); + for (let c = 1; c <= lastCol; c += 1) { + const cell = sheet.getRow(1).getCell(c); + cell.font = { ...cell.font, bold: true }; + cell.fill = { type: "pattern", pattern: "solid", fgColor: { argb: "FFD9E8F5" } }; + } + sheet.autoFilter = { from: { row: 1, column: 1 }, to: { row: Math.max(1, sheet.rowCount), column: lastCol } }; await saveWhenRequested(source, args, true); ctx.log("已应用表格样式(表头加粗 + 筛选)", "info", node.id); return { styled: true };