https://mastercontrol.atlassian.net/browse/PEX-18664

We are using Aspose.Cells for Java 26.6 to convert Excel workbooks to PDF via Workbook.save(path, PdfSaveOptions) . When a worksheet contains cells styled with CellBorderType.DOUBLE on the top and bottom borders and the cell text uses a small font size (e.g. 10pt), the double-line border in the produced PDF visibly clips the top and bottom of the text in every row. In Microsoft Excel the same workbook prints/exports to PDF with the double-line border sitting cleanly outside the text.

The row height Aspose picks for the PDF output does not appear to reserve space for the second line of the double-line border, so the inner stroke of the border and the top/bottom of the glyphs occupy the same vertical pixels.

Environment

  • Aspose.Cells for Java: 26.6
  • Aspose.Total license: yes (also reproduced under evaluation)
  • JDK: OpenJDK 21 (Zulu 21.0.2)
  • OS: macOS 15 / Linux (both reproduce)

Reproduction

  1. Open the attached reproducer.xlsx in Microsoft Excel and print / export to PDF from Excel. The double-line borders sit outside the text; no overlap.
  2. Convert the same reproducer.xlsx to PDF using the code below.
  3. Open the produced PDF (output-baseline.pdf, also attached, rendered as output-baseline.png for reference). In every row the top and bottom double-line borders visibly clip the top and bottom of the cell text — “Requirement”, “Description”, “Owner”, “Status”, and every data row are affected.

Code used to reproduce

Workbook wb = new Workbook("reproducer.xlsx");
PdfSaveOptions options = new PdfSaveOptions();
options.setCompliance(PdfCompliance.PDF_17);
options.setOnePagePerSheet(false);
options.setAllColumnsInOnePagePerSheet(false);
options.setPrintingPageType(PrintingPageType.IGNORE_BLANK);
options.setOptimizationType(PdfOptimizationType.STANDARD);
options.setFontSubstitutionCharGranularity(true);
options.setCheckFontCompatibility(true);
wb.save("output.pdf", options);

The reproducer workbook itself is built with a minimal style — 10pt Calibri, CellBorderType.DOUBLE on all four sides of every populated cell, Color.BLACK , no other formatting. Source used to generate reproducer.xlsx:

Workbook workbook = new Workbook();
Worksheet sheet = workbook.getWorksheets().get(0);
Cells cells = sheet.getCells();

Style style = workbook.createStyle();
style.getFont().setSize(10);
style.getFont().setName("Calibri");
style.setBorder(BorderType.LEFT_BORDER,   CellBorderType.DOUBLE, Color.getBlack());
style.setBorder(BorderType.RIGHT_BORDER,  CellBorderType.DOUBLE, Color.getBlack());
style.setBorder(BorderType.TOP_BORDER,    CellBorderType.DOUBLE, Color.getBlack());
style.setBorder(BorderType.BOTTOM_BORDER, CellBorderType.DOUBLE, Color.getBlack());

String[] header = { "Requirement", "Description", "Owner", "Status" };
for (int row = 0; row < 6; row++) {
    for (int col = 0; col < 4; col++) {
        String text = row == 0
            ? header[col]
            : "Row " + row + " Col " + col + " with narrow text";
        cells.get(row, col).putValue(text);
        cells.get(row, col).setStyle(style);
    }
}
workbook.save("reproducer.xlsx");

Expected behavior

Double-line borders in the produced PDF are drawn outside the cell’s text area, matching what Microsoft Excel produces when printing/exporting the same file to PDF.

Actual behavior

The top and bottom double-line borders visibly clip the top and bottom of the cell text in every row of the produced PDF.

Workarounds attempted (none resolve the issue)

  • Calling Worksheet.autoFitRows() before Workbook.save(...) — row heights change marginally but the top/bottom double-line borders still overlap the glyphs. Attached as output-autofit-rows.pdf / output-autofit-rows.png for reference.
  • Calling Worksheet.autoFitRows() + Worksheet.autoFitColumns() — column widths grow enough to fit the horizontal text but the vertical border-vs-glyph overlap is unchanged.

Notes

  • This was surfaced by a real customer file (Excel worksheet with 10pt text and Excel’s “double” border preset applied via the Format Cells → Border dialog). The reproducer above is a fully synthetic, public-safe minimal example that produces the same symptom.
  • Please confirm any fix targets Aspose.Cells for Java, not only .NET.

Thank you.

original csv
image.png (3.7 KB)

output pdf
image.png (3.8 KB)

another output pdf image
image.png (37.4 KB)

@rwheeler

Hello,

Thank you for providing the code snippet and the test files: image.png, image.png, and image.png.

We have successfully reproduced the issue using Aspose.Cells for Java 26.6. Our internal testing confirms that when a cell is styled with double-line borders, the inner strokes of both the top and bottom borders overlap the text content. Specifically, the lower line of the top border clips the tops of capital letters, while the upper line of the bottom border cuts through the text baseline and descenders.

This behavior indicates that the rendering engine is drawing the double border within the cell’s content area, or the auto-fit row height calculation is failing to account for the additional thickness required by the double-line style.

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): CELLSJAVA-46776

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

@rwheeler ,

I uses the code you shared, adds autoFitColumns and autoFitRows, the output is OK. The cell text and double line borders(top/bottom) are not overlapped.
Code:

Workbook workbook = new Workbook();
Worksheet sheet = workbook.getWorksheets().get(0);
Cells cells = sheet.getCells();

Style style = workbook.createStyle();
style.getFont().setSize(10);
style.getFont().setName("Calibri");
style.setBorder(BorderType.LEFT_BORDER,   CellBorderType.DOUBLE, Color.getBlack());
style.setBorder(BorderType.RIGHT_BORDER,  CellBorderType.DOUBLE, Color.getBlack());
style.setBorder(BorderType.TOP_BORDER,    CellBorderType.DOUBLE, Color.getBlack());
style.setBorder(BorderType.BOTTOM_BORDER, CellBorderType.DOUBLE, Color.getBlack());

String[] header = { "Requirement", "Description", "Owner", "Status" };
for (int row = 0; row < 6; row++) {
    for (int col = 0; col < 4; col++) {
        String text = row == 0
            ? header[col]
            : "Row " + row + " Col " + col + " with narrow text";
        cells.get(row, col).putValue(text);
        cells.get(row, col).setStyle(style);
    }
}
workbook.save("CELLSJAVA-46776_Java.xlsx");


Workbook wb = new Workbook("CELLSJAVA-46776_Java.xlsx");

System.out.println(wb.getWorksheets().get(0).getCells().getRowHeight(0));

wb.getWorksheets().get(0).autoFitColumns();
wb.getWorksheets().get(0).autoFitRows();

System.out.println(wb.getWorksheets().get(0).getCells().getRowHeight(0));

PdfSaveOptions options = new PdfSaveOptions();
options.setCompliance(PdfCompliance.PDF_17);
options.setOnePagePerSheet(false);
options.setAllColumnsInOnePagePerSheet(false);
options.setPrintingPageType(PrintingPageType.IGNORE_BLANK);
options.setOptimizationType(PdfOptimizationType.STANDARD);
options.setFontSubstitutionCharGranularity(true);
options.setCheckFontCompatibility(true);
wb.save("CELLSJAVA-46776_Java.pdf", options);

CELLSJAVA-46776_Java.pdf (22.3 KB)