Repository navigation
Replace benchmark PyMuPDF with PDFBox and fix XLSX rendering #210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,7 +51,7 @@ internal static List<ExcelSheet> ReadSheets(Stream stream, System.Globalization. | |
| var normalFontFamily = ReadNormalFontFamily(archive); | ||
| var normalFontSize = ReadNormalFontSize(archive); | ||
| var maxDigitWidthPx = ExcelSheet.LookupMaxDigitWidthPx(normalFontFamily, normalFontSize); | ||
| var fontStyles = ReadFontStyles(archive, themeColors); | ||
| var fontStyles = ReadFontStyles(archive, themeColors, normalFontFamily); | ||
| var fillColors = ReadFillColors(archive, themeColors); | ||
| var borders = ReadBorders(archive, themeColors); | ||
| var numberFormats = ReadNumberFormats(archive); | ||
|
|
@@ -87,7 +87,7 @@ internal static List<ExcelSheet> ReadSheets(Stream stream, System.Globalization. | |
| var drawingShapes = ReadSheetShapes(archive, entry.FullName, themeColors); | ||
| var (colWidths, defaultColWidth) = ReadColumnWidths(entry); | ||
| var mergedCells = ReadMergedCells(entry); | ||
| var (rowHeights, defaultRowHeight, customHeightRows) = ReadRowHeights(entry); | ||
| var (rowHeights, defaultRowHeight, customHeightRows) = ReadRowHeights(entry, normalFontFamily, normalFontSize); | ||
| if (rows.Count >= 1000 && colWidths.Count == 0 && defaultColWidth <= 0f && | ||
| Math.Abs(defaultRowHeight - 15f) < 0.001f) | ||
| { | ||
|
|
@@ -115,7 +115,7 @@ internal static List<ExcelSheet> ReadSheets(Stream stream, System.Globalization. | |
| var images = ReadSheetImages(archive, entry.FullName); | ||
| var (colWidths, defaultColWidth) = ReadColumnWidths(entry); | ||
| var mergedCells = ReadMergedCells(entry); | ||
| var (rowHeights, defaultRowHeight, customHeightRows) = ReadRowHeights(entry); | ||
| var (rowHeights, defaultRowHeight, customHeightRows) = ReadRowHeights(entry, normalFontFamily, normalFontSize); | ||
| var pageSetup = ReadPageSetup(entry); | ||
| var ignoreInferredFitToPage = pageSetup.FitToPageInferred && rows.Count >= 1000 && colWidths.Count == 0 && defaultColWidth <= 0f; | ||
| sheets.Add(new ExcelSheet("Sheet1", rows, images, colWidths, defaultColWidth, mergedCells: mergedCells, rowHeights: rowHeights, defaultRowHeight: defaultRowHeight, customHeightRows: customHeightRows, isLandscape: pageSetup.IsLandscape, printScale: pageSetup.Scale, paperSize: ignoreInferredFitToPage && pageSetup.PaperSize == 1 ? 9 : pageSetup.PaperSize, marginLeftPt: pageSetup.MarginLeftPt, marginRightPt: pageSetup.MarginRightPt, marginTopPt: pageSetup.MarginTopPt, marginBottomPt: pageSetup.MarginBottomPt, fitToPage: ignoreInferredFitToPage ? false : pageSetup.FitToPage, fitToWidth: ignoreInferredFitToPage ? 0 : pageSetup.FitToWidth, fitToHeight: ignoreInferredFitToPage ? 0 : pageSetup.FitToHeight, horizontalCentered: pageSetup.HorizontalCentered, verticalCentered: pageSetup.VerticalCentered, maxDigitWidthPx: maxDigitWidthPx)); | ||
|
|
@@ -333,7 +333,7 @@ private static string GetRelationshipPartPath(string partPath) | |
| : $"{directory}/_rels/{fileName}.rels"; | ||
| } | ||
|
|
||
| private static List<FontStyleInfo> ReadFontStyles(ZipArchive archive, List<PdfColor> themeColors) | ||
| private static List<FontStyleInfo> ReadFontStyles(ZipArchive archive, List<PdfColor> themeColors, string? normalFontFamily) | ||
| { | ||
| var styles = new List<FontStyleInfo>(); | ||
| var entry = archive.GetEntry("xl/styles.xml"); | ||
|
|
@@ -364,7 +364,7 @@ private static List<FontStyleInfo> ReadFontStyles(ZipArchive archive, List<PdfCo | |
| } | ||
|
|
||
| // Read font name | ||
| string? fontName = null; | ||
| var fontName = normalFontFamily; | ||
| var nameEl = font.Element(ns + "name"); | ||
| if (nameEl != null) | ||
| fontName = nameEl.Attribute("val")?.Value; | ||
|
|
@@ -2020,6 +2020,14 @@ private static IList<List<ExcelCell>> ReadSheet(ZipArchiveEntry entry, IList<str | |
| } | ||
| else | ||
| { | ||
| var fontStyle = ResolveFontStyle(0, fontStyles, cellXfFontIndices); | ||
| color = fontStyle.Color; | ||
| fontSize = fontStyle.Size; | ||
| bold = fontStyle.Bold; | ||
| italic = fontStyle.Italic; | ||
| underline = fontStyle.Underline; | ||
| strikethrough = fontStyle.Strikethrough; | ||
| fontName = fontStyle.FontName; | ||
| // Apply fill from row-level or column-level default style when cell has no explicit style. | ||
| // Priority: row default > column default. | ||
| if (rowDefaultFill != null) | ||
|
|
@@ -3255,7 +3263,8 @@ internal record PageSetupInfo( | |
| /// Reads row heights from the sheet XML. | ||
| /// Returns a dictionary of 0-based row index → height in points, plus the default row height. | ||
| /// </summary> | ||
| private static (Dictionary<int, float> heights, float defaultHeight, HashSet<int> customHeightRows) ReadRowHeights(ZipArchiveEntry entry) | ||
| private static (Dictionary<int, float> heights, float defaultHeight, HashSet<int> customHeightRows) ReadRowHeights( | ||
| ZipArchiveEntry entry, string? normalFontFamily, float normalFontSize) | ||
| { | ||
| var heights = new Dictionary<int, float>(); | ||
| var customHeightRows = new HashSet<int>(); | ||
|
|
@@ -3279,6 +3288,15 @@ private static (Dictionary<int, float> heights, float defaultHeight, HashSet<int | |
| } | ||
| } | ||
|
|
||
| // Automatic Calibri 11 rows use the Microsoft Excel print line height; | ||
| // custom sheet defaults and explicit row heights retain their authored size. | ||
| if (string.Equals(normalFontFamily, "Calibri", StringComparison.OrdinalIgnoreCase) && | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. normalFontFamily is resolved from the theme’s minor font before considering the explicit Normal style font. A workbook can retain its Calibri theme while explicitly using Arial for the Normal style. In that case, this condition incorrectly reduces the default row height from 15 pt to 14.52 pt, shifting content vertically and potentially changing pagination. I confirmed this with a focused regression test using an explicit Arial Normal style and a Calibri theme: it passes on main with 15 pt row spacing but fails on this PR with 14.52 pt. Please resolve the Normal style’s actual font, honoring its explicit family and theme scheme, before applying the Calibri-specific row-height adjustment. |
||
| Math.Abs(normalFontSize - 11f) < 0.001f && Math.Abs(defaultHeight - 15f) < 0.001f && | ||
| fmtPr?.Attribute("customHeight")?.Value is not "1" and not "true") | ||
|
Comment on lines
+3293
to
+3295
|
||
| { | ||
| defaultHeight = 14.52f; | ||
| } | ||
|
|
||
| // Read explicit row heights (hidden rows get height 0) | ||
| foreach (var row in doc.Descendants(ns + "row")) | ||
| { | ||
|
|
@@ -4932,6 +4950,7 @@ internal static float LookupMaxDigitWidthPx(string? fontName, float fontSizePt = | |
| { | ||
| baseMdw = fontName.Trim().ToLowerInvariant() switch | ||
| { | ||
| "calibri" => 7.52f, | ||
| "century gothic" => 8.13f, | ||
| "franklin gothic medium" => 8.5f, | ||
| "franklin gothic book" => 8.2f, | ||
|
|
@@ -4943,7 +4962,7 @@ internal static float LookupMaxDigitWidthPx(string? fontName, float fontSizePt = | |
| "corbel" => 7.6f, | ||
| "times new roman" => 6.8f, | ||
| "consolas" or "courier new" => 7.3f, | ||
| _ => 7.378f, // Calibri / Arial / Aptos and other common fonts | ||
| _ => 7.378f, // Arial / Aptos and other common fonts | ||
| }; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve the actual Normal font before applying the new defaults.
ReadNormalFontFamilyreturns the theme minor font before checking styles. With a Calibri theme and an explicit Arial 11 Normal style, this new argument makes unnamed fonts inherit Calibri instead of Arial. The new row-height calibration also reduces those Arial rows to 14.52 points.Resolve the family through the Normal style's
fontId, asReadNormalFontSizealready does. Use the theme only when that font requires theme resolution.