概要
exceljsでシートの複製をしたいときに、セルのスタイルがうまくコピー出来ずに四苦八苦していましたが、自分なりの解決策を見つけたときの記録です。
本題
論より動くものなのでCodeSandBoxを参照ください。
https://codesandbox.io/p/devbox/exceljs-clonesheet-655dcj?file=%2Fsrc%2FExport.tsx%3A21%2C10
ポイントとしてはWorksheet.modelを新しいシートにコピーすればデータはコピー出来るのですがstyleはコピーされないため、styleは別途セル単位でコピーさせることです。
import { useCallback } from "react";
import { Workbook, Worksheet, Border } from "exceljs";
import saveAs from "file-saver";
export function Export() {
const cloneSheet = (
wb: Workbook,
baseWs: Worksheet,
newWsName: string,
): Worksheet => {
const newWs = wb.addWorksheet();
newWs.model = Object.assign(baseWs.model, {
name: newWsName,
mergeCells: baseWs.model.merges,
});
baseWs.eachRow((baseRow, rowIdx) => {
const newRow = newWs.getRow(rowIdx);
baseRow.eachCell((baseCell, colIdx) => {
newRow.getCell(colIdx).style = baseCell.style;
});
});
return newWs;
};
const save = async (wb: Workbook) => {
try {
const uint8Array = await wb.xlsx.writeBuffer();
const blob = new Blob([uint8Array], {
type: "application/octet-binary",
});
saveAs(blob, `sample.xlsx`);
} catch (err) {
console.error(err);
}
};
const handleClick = useCallback(() => {
const wb = new Workbook();
const ws = wb.addWorksheet("Sample1");
ws.mergeCells(1, 1, 2, 3);
const mergedCell = ws.getCell(1, 1);
mergedCell.value = "MergedCell";
const styledCell = ws.getCell(3, 1);
const borderStyle: Partial<Border> = {
style: "medium",
};
styledCell.value = "StyledCell";
styledCell.style = {
fill: {
type: "pattern",
pattern: "solid",
fgColor: { argb: "fff2dcdb" },
},
border: {
top: borderStyle,
left: borderStyle,
right: borderStyle,
bottom: borderStyle,
},
};
cloneSheet(wb, ws, "Clone1");
cloneSheet(wb, ws, "Clone2");
save(wb);
}, []);
return <button onClick={handleClick}>Export</button>;
}
まとめ
結合されたセルをコピーする方法は探したら色々ありましたが、それだけではセルのボーダーがおかしなことになったりして、セルのスタイルをコピーする記事は自分が探した限りでは見つからなかったです。
同じ悩みを抱えている方の参考になればと思います。