Preserve QExcell gridline visibility in XLSX

This commit is contained in:
Курнат Андрей
2026-06-01 17:38:08 +03:00
parent f72c79d5e9
commit 1117d8bbf0
4 changed files with 76 additions and 9 deletions
+35 -7
View File
@@ -14,6 +14,7 @@ export interface ImportedExcellWorkbook {
tabColor?: string;
columnWidths?: Record<string, number>;
rowHeights?: Record<string, number>;
showGridLines?: boolean;
cells: Record<string, string>;
mergedCells?: MergedCellRange[];
hyperlinks?: Record<string, string>;
@@ -66,6 +67,7 @@ interface ParsedSheet {
tabColor?: string;
columnWidths?: Record<string, number>;
rowHeights?: Record<string, number>;
showGridLines?: boolean;
cells: Record<string, string>;
mergedCells?: MergedCellRange[];
hyperlinks?: Record<string, string>;
@@ -273,7 +275,8 @@ export async function exportXlsxBlob(workbook: Workbook): Promise<Blob> {
sheet.autoFilter,
sheet.tabColor,
sheet.columnWidths,
sheet.rowHeights
sheet.rowHeights,
sheet.showGridLines
)
);
const relationshipsXml = buildWorksheetRelationshipsXml(
@@ -311,6 +314,7 @@ export function parsedWorksheetToSheet(
const tabColor = worksheetXmlToTabColor(worksheetXml, themeColors);
const columnWidths = worksheetXmlToColumnWidths(worksheetXml);
const rowHeights = worksheetXmlToRowHeights(worksheetXml);
const showGridLines = worksheetXmlToShowGridLines(worksheetXml);
return {
id: sheet.id || `sheet-${index + 1}`,
@@ -321,6 +325,7 @@ export function parsedWorksheetToSheet(
...(tabColor ? { tabColor } : {}),
...(Object.keys(columnWidths).length > 0 ? { columnWidths } : {}),
...(Object.keys(rowHeights).length > 0 ? { rowHeights } : {}),
...(showGridLines === false ? { showGridLines } : {}),
cells: worksheetXmlToCells(worksheetXml, sharedStrings),
mergedCells: worksheetXmlToMergedCells(worksheetXml),
hyperlinks: worksheetXmlToHyperlinks(worksheetXml, relationshipsXml),
@@ -439,6 +444,18 @@ export function worksheetXmlToFrozenPane(worksheetXml: unknown): SheetFrozenPane
};
}
export function worksheetXmlToShowGridLines(worksheetXml: unknown): boolean | undefined {
const worksheet = childRecord(worksheetXml, "worksheet");
const sheetViews = childRecord(worksheet, "sheetViews");
const sheetView = asRecord(toArray(sheetViews.sheetView)[0]);
const value = sheetView.showGridLines;
if (value === undefined) {
return undefined;
}
return !isFalseXmlBoolean(value);
}
export function worksheetXmlToAutoFilter(worksheetXml: unknown) {
const worksheet = childRecord(worksheetXml, "worksheet");
const autoFilter = childRecord(worksheet, "autoFilter");
@@ -663,7 +680,8 @@ export function buildWorksheetXml(
autoFilter?: string,
tabColor?: string,
columnWidths: Record<string, number> = {},
rowHeights: Record<string, number> = {}
rowHeights: Record<string, number> = {},
showGridLines?: boolean
) {
const normalizedRowHeights = normalizedSheetRowHeights(rowHeights);
const rows = sortedWorksheetEntries(cells, cellFormats).reduce<Record<number, Array<[string, string]>>>((grouped, entry) => {
@@ -694,7 +712,7 @@ export function buildWorksheetXml(
const hyperlinksXml = buildHyperlinksXml(hyperlinks);
const drawingXml = drawingRelationshipId ? `<drawing r:id="${escapeXmlAttribute(drawingRelationshipId)}"/>` : "";
const sheetPrXml = buildSheetPrXml(tabColor);
const sheetViewsXml = buildSheetViewsXml(frozenPane);
const sheetViewsXml = buildSheetViewsXml(frozenPane, showGridLines);
const colsXml = buildColumnWidthsXml(columnWidths);
return xmlDeclaration(
@@ -755,13 +773,18 @@ export function buildHyperlinksXml(hyperlinks: Record<string, string> = {}) {
return `<hyperlinks>${hyperlinkXml}</hyperlinks>`;
}
export function buildSheetViewsXml(frozenPane?: SheetFrozenPane) {
export function buildSheetViewsXml(frozenPane?: SheetFrozenPane, showGridLines?: boolean) {
const pane = normalizedFrozenPane(frozenPane);
if (!pane) {
if (!pane && showGridLines !== false) {
return "";
}
const attributes = [
const sheetViewAttributes = ["workbookViewId=\"0\"", showGridLines === false ? 'showGridLines="0"' : ""].filter(Boolean).join(" ");
if (!pane) {
return `<sheetViews><sheetView ${sheetViewAttributes}/></sheetViews>`;
}
const paneAttributes = [
pane.columns > 0 ? `xSplit="${pane.columns}"` : "",
pane.rows > 0 ? `ySplit="${pane.rows}"` : "",
`topLeftCell="${escapeXmlAttribute(pane.topLeftCell)}"`,
@@ -771,7 +794,7 @@ export function buildSheetViewsXml(frozenPane?: SheetFrozenPane) {
.filter(Boolean)
.join(" ");
return `<sheetViews><sheetView workbookViewId="0"><pane ${attributes}/></sheetView></sheetViews>`;
return `<sheetViews><sheetView ${sheetViewAttributes}><pane ${paneAttributes}/></sheetView></sheetViews>`;
}
export function buildSheetPrXml(tabColor?: string) {
@@ -1451,6 +1474,11 @@ function booleanAttribute(value: unknown) {
return normalized === "1" || normalized === "true";
}
function isFalseXmlBoolean(value: unknown) {
const normalized = String(value ?? "").trim().toLowerCase();
return normalized === "0" || normalized === "false";
}
function normalizedNumberFormat(value?: string) {
const raw = value?.trim() ?? "";
if (!raw || raw.toLowerCase() === "general") {