fix: 修复设置单元格格式不生效与表格样式覆盖单元格样式
- SetCellFormat V1/V2/V3:格式解析补厂商 JSON 键映射(FontColor/FontSize/ BoldAndItalic 位标志/BackgroundColor 带透明度/DigitalFormat.formatstring/ FontFormat 字体名),纯格式代码(如 0.00)回落为数字格式——此前全部被静默忽略 - ShowTableStyle:行级样式(row.font/fill+commit)在 exceljs 中会覆盖该行 已设置的单元格样式,改为逐单元格设置表头样式 - 经 18 节点覆盖流程实测:V3 红字宋体加粗、V2 蓝字、V1 数字格式 0.00 均落盘
This commit is contained in:
parent
4163b57d38
commit
8cedf45628
@ -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<typeof parseFormatSpec>;
|
||||
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<string, unknown>);
|
||||
const text = String(raw ?? "").trim();
|
||||
if (!text) return {};
|
||||
try {
|
||||
const parsed = JSON.parse(text) as Record<string, unknown>;
|
||||
if (typeof parsed === "object" && parsed) return parsed as ReturnType<typeof parseFormatSpec>;
|
||||
if (typeof parsed === "object" && parsed) return normalizeFormatSpec(parsed);
|
||||
} catch { /* fall through to keywords */ }
|
||||
const spec: ReturnType<typeof parseFormatSpec> = {};
|
||||
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<string, unknown>): ReturnType<typeof parseFormatSpec> {
|
||||
const spec: ReturnType<typeof parseFormatSpec> = {};
|
||||
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<string, unknown>)[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 };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user