Executive Summary
Issues Found: Two separate but related table layout bugs in Aspose.Words PDF conversion:
- “Around” Text Wrapping Bug: Top-level tables with “Text Wrapping: Around” property cause overlapping in PDFs
- Negative Left Indent Bug: Tables with negative left indents misalign when breaking across pages
Severity: High - Affects PDF readability and customer satisfaction
Workaround Status:
Issue #1: Temporary workaround implemented (change TextWrapping.AROUND → TextWrapping.NONE)
Issue #2: Temporary workaround implemented (normalize negative indents to 0)
Requesting: Investigation and permanent fix for both issues in Aspose.Words SDK
Environment Details
Aspose.Words Version: Check pom.xml/build.gradle (using Aspose.Total for Java)
License Type: Aspose.Total for Java (Enterprise, Site OEM)
Platform: Java 17
Operating System: Linux (containerized)
Document Formats Affected: DOCX, DOCM (Office Open XML)
Problem Description
What’s Happening
When converting Word documents to PDF using Aspose.Words, top-level tables (tables NOT nested inside other tables) that have the “Text Wrapping: Around” property set are incorrectly positioned, causing content overlapping in the PDF output.
Specific Tables Affected
Top-level tables with table.getTextWrapping() == TextWrapping.AROUND→
AFFECTED
Nested tables with “Around” wrapping →
NOT AFFECTED (or different behavior)
Visual Impact
- Tables overlap with surrounding text content
- Tables overlap with other tables
- Content may be displaced to incorrect positions
- Page layout is significantly corrupted
Test Case
Test Document
File: test_tableproperties.docm (attached)
Document Structure:
- Total Pages: 4
- Total Tables: 7
Affected Tables:
- Table 5 (Page 2): Top-level table with “Around” text wrapping →
Overlapping in PDF - Table 6 (Page 2): Top-level table with “Around” text wrapping →
Overlapping in PDF
Unaffected Tables:
- Tables 1-4, 7: Normal tables without “Around” wrapping →
Convert correctly
Table 5 Properties (AFFECTED)
Text Wrapping: AROUND (1)
Alignment: 0 (LEFT)
Allow Auto Fit: true
Rows: 11
Is Nested: false
Location: Page 2
// Positioning Properties
Absolute Horizontal Distance: 0.0 points
Absolute Vertical Distance: 129.6 points
Relative Horizontal Alignment: 2 (CENTER)
Relative Vertical Alignment: 0 (TOP)
Horizontal Anchor: 0 (COLUMN)
Vertical Anchor: 1 (PARAGRAPH)
Table 6 Properties (AFFECTED)
Text Wrapping: AROUND (1)
Alignment: 0 (LEFT)
Allow Auto Fit: true
Rows: 9
Is Nested: false
Location: Page 2
// Positioning Properties
Absolute Horizontal Distance: -21.85 points
Absolute Vertical Distance: 118.2 points
Relative Horizontal Alignment: 0 (NONE)
Relative Vertical Alignment: 0 (TOP)
Horizontal Anchor: 0 (COLUMN)
Vertical Anchor: 1 (PARAGRAPH)
Reproduction Code
Minimal Reproduction (Demonstrates Bug)
import com.aspose.words.*;
public class TableWrappingBugDemo {
public static void main(String[] args) throws Exception {
// Load test document
Document doc = new Document("test_tableproperties.docm");
// Convert to PDF - Bug occurs during this step
PdfSaveOptions saveOptions = new PdfSaveOptions();
doc.save("output_with_bug.pdf", saveOptions);
// Result: Tables 5 and 6 on Page 2 overlap with content
System.out.println("PDF generated - check Page 2 for overlapping tables");
}
}
Analysis Code (Identifies Affected Tables)
import com.aspose.words.*;
public class TableWrappingAnalysis {
public static void main(String[] args) throws Exception {
Document doc = new Document("test_tableproperties.docm");
NodeCollection tables = doc.getChildNodes(NodeType.TABLE, true);
System.out.println("=== TABLE WRAPPING ANALYSIS ===");
System.out.println("Total tables: " + tables.getCount());
for (int i = 0; i < tables.getCount(); i++) {
Table table = (Table) tables.get(i);
if (table.getTextWrapping() == TextWrapping.AROUND) {
// Check if nested
boolean isNested = isTableNested(table);
System.out.println("\nTable " + (i + 1) + ":");
System.out.println(" Text Wrapping: AROUND");
System.out.println(" Is Nested: " + isNested);
System.out.println(" Rows: " + table.getRows().getCount());
System.out.println(" Abs Horizontal Dist: " +
table.getAbsoluteHorizontalDistance());
System.out.println(" Abs Vertical Dist: " +
table.getAbsoluteVerticalDistance());
if (!isNested) {
System.out.println(" ⚠️ TOP-LEVEL TABLE - AFFECTED BY BUG");
}
}
}
}
private static boolean isTableNested(Table table) {
Node parent = table.getParentNode();
int depth = 0;
while (parent != null && depth < 20) {
if (parent.getNodeType() == NodeType.TABLE) {
return true;
}
parent = parent.getParentNode();
depth++;
}
return false;
}
}
Expected vs Actual Behavior
Expected Behavior
- Tables with “Around” text wrapping should maintain their positioning relative to the page and surrounding content
- Text should wrap around the table as defined in the Word document
- No content overlapping should occur
- PDF layout should match Word document layout
Actual Behavior
- Top-level tables with “Around” text wrapping are positioned incorrectly
- Tables overlap with text content and/or other elements on the page
- Page layout is significantly different from Word document
- Content may be displaced or unreadable due to overlapping
Temporary Workaround (Applied)
To prevent PDF corruption while awaiting a permanent fix, we apply this workaround:
/**
* Workaround: Change TextWrapping.AROUND to TextWrapping.NONE
* for all top-level (non-nested) tables to prevent overlapping bug.
*/
private int fixTopLevelTableWrapping(Document doc) {
int fixedCount = 0;
NodeCollection tables = doc.getChildNodes(NodeType.TABLE, true);
for (int i = 0; i < tables.getCount(); i++) {
Table table = (Table) tables.get(i);
// Only process tables with Around wrapping
if (table.getTextWrapping() != TextWrapping.AROUND) {
continue;
}
// Check if nested (nested tables don't exhibit this bug)
boolean isNested = false;
Node parent = table.getParentNode();
int depth = 0;
while (parent != null && depth < 20) {
if (parent.getNodeType() == NodeType.TABLE) {
isNested = true;
break;
}
parent = parent.getParentNode();
depth++;
}
// Only fix top-level tables
if (!isNested) {
table.setTextWrapping(TextWrapping.NONE);
fixedCount++;
}
}
return fixedCount;
}
Workaround Impact:
Prevents overlapping issues
Produces readable PDFs
May alter intended layout (text no longer wraps around tables)
Not ideal for documents where “Around” wrapping is semantically important
Business Impact
Customer Impact
- High Severity: PDFs with overlapping content are difficult or impossible to read
- Professional Image: Corrupted PDFs reflect poorly on our product quality
- Compliance Risk: In regulated industries, unreadable PDFs may fail compliance requirements
Current Mitigation
- Temporary workaround prevents overlapping but changes intended layout
- Customers may notice different text wrapping behavior
- Not all use cases may be adequately addressed by workaround
Desired Resolution
- Permanent fix in Aspose.Words SDK to correctly handle top-level tables with “Around” text wrapping
- Maintain original layout intent while preventing overlapping
- Eliminate need for workaround that changes document appearance
Attachments
- test_tableproperties.docm - Test document demonstrating both issues
- output_with_bugs.pdf - PDF generated WITHOUT workarounds (shows overlapping + misalignment)
- output_with_workarounds.pdf - PDF generated WITH both workarounds applied
- TableWrappingAnalysis.java - Analysis code for Issue #1 (Around wrapping)
- NegativeIndentTableTest.java - Analysis code for Issue #2 (Negative indents)
- AsposeSettingsInvestigationTest.java - Settings investigation for Issue #2
- Reproduction code - Minimal examples demonstrating both bugs
Issue #2: Negative Left Indent Alignment Bug
Problem Description
When converting Word documents to PDF, tables with negative left indents exhibit two distinct issues:
Problem 1 - Incorrect Pagination:
- Tables that should remain on one page (as in the source .docx) are incorrectly split across pages
- Example: Table 3 appears entirely on page 3 in Word, but Aspose breaks it across pages 2-3
Problem 2 - Alignment Issues When Broken:
- When tables DO break across pages, negative indents are inconsistently applied
- Header row (on first page): Correctly positioned with negative indent applied
- Body rows (on continuation page): Negative indent NOT applied, causing right-shift misalignment
- This creates a visual disconnect where table headers and body columns don’t align
Visual Impact
- Pagination: Tables appear on wrong pages or break incorrectly
- Alignment: Table headers and body columns misaligned when broken across pages
- Layout Mismatch: PDF layout differs significantly from source Word document
- Readability: Content difficult to read due to misalignment and incorrect breaks
Affected Tables in test_tableproperties.docm
Total Tables with Negative Left Indent: 5 out of 7 tables
| Table | Left Indent | Rows | Spans Pages | Issue Visible |
|---|---|---|---|---|
| Table 1 | -21.55 points | 2 | No (page 1) | N/A (single page) |
| Table 2 | -15.9 points | 3 | No (page 2) | N/A (single page) |
| Table 3 | -15.9 points | 5 | Yes (2-3) | ✓ Misaligned |
| Table 4 | -21.55 points | 2 | No (page 2) | N/A (single page) |
| Table 7 | -21.55 points | 2 | No (page 4) | N/A (single page) |
Critical Finding: Issue only manifests when tables with negative indents break across pages.
Test Case: Table 3 (Primary Example)
Table 3 Properties:
Text Wrapping: NONE (0)
Left Indent: -15.9 points
Rows: 5
Location: Pages 2-3 (breaks across page boundary)
Observed Behavior:
-
Page 2 (Header row):
- Table header positioned correctly
- Negative left indent (-15.9 points) properly applied
- Aligns with other page content
-
Page 3 (Body rows):
- Body rows shifted RIGHT
- Negative left indent NOT applied
- Body columns misaligned with header columns
- Visual disconnect between header and body
Reproduction Code
import com.aspose.words.*;
public class NegativeIndentBugDemo {
public static void main(String[] args) throws Exception {
// Load test document
Document doc = new Document("test_tableproperties.docm");
// Analyze tables with negative indents
NodeCollection tables = doc.getChildNodes(NodeType.TABLE, true);
System.out.println("=== TABLES WITH NEGATIVE LEFT INDENT ===");
for (int i = 0; i < tables.getCount(); i++) {
Table table = (Table) tables.get(i);
if (table.getLeftIndent() < 0) {
System.out.println("Table " + (i + 1) + ":");
System.out.println(" Left Indent: " + table.getLeftIndent() + " points");
System.out.println(" Rows: " + table.getRows().getCount());
}
}
// Convert to PDF - Bug occurs when tables break across pages
PdfSaveOptions saveOptions = new PdfSaveOptions();
doc.save("output_with_negative_indent_bug.pdf", saveOptions);
// Result: Table 3 body rows (page 3) misaligned with header (page 2)
System.out.println("PDF generated - check Table 3 alignment on pages 2-3");
}
}
Settings Investigation Results
Investigated Settings (no solution found):
- ✗
Document.LayoutOptions- No table indent settings available - ✗
Document.CompatibilityOptions.optimizeFor()- Tested Word 2003-2019 versions (no fix) - ✗
PdfSaveOptions- No table indent settings available
Conclusion: Aspose.Words does NOT provide any setting to correctly handle negative left indents when tables break across pages. This is a layout engine bug requiring a workaround.
Expected vs Actual Behavior
Expected Behavior
- Negative left indent consistently applied to ALL table rows
- Header and body rows maintain alignment across page breaks
- Table appearance matches Word document layout
- No visual disconnect between pages
Actual Behavior
- Negative left indent applied to header row (first page)
- Negative left indent NOT applied to body rows (continuation page)
- Body rows shifted right, misaligned with headers
- Visual disconnect makes table difficult to read
Attempted Fixes That Do NOT Work
We attempted multiple approaches to fix the negative left indent issues. None of these work reliably with Aspose.Words:
1. Row-Level setAllowBreakAcrossPages(false)
// DOES NOT WORK - Aspose ignores this setting for tables with negative indents
for (int r = 0; r < table.getRows().getCount(); r++) {
table.getRows().get(r).getRowFormat().setAllowBreakAcrossPages(false);
}
Result: Tables still break across pages despite this setting.
2. Paragraph-Level KeepTogether and KeepWithNext
// DOES NOT WORK - Doesn't prevent table breaks
for (int r = 0; r < table.getRows().getCount(); r++) {
Row row = table.getRows().get(r);
for (int c = 0; c < row.getCells().getCount(); c++) {
for (int p = 0; p < row.getCells().get(c).getParagraphs().getCount(); p++) {
row.getCells().get(c).getParagraphs().get(p).getParagraphFormat().setKeepTogether(true);
row.getCells().get(c).getParagraphs().get(p).getParagraphFormat().setKeepWithNext(true);
}
}
}
Result: Tables still break across pages.
3. Page Break Insertion Before Table
// DOES NOT WORK - Doesn't reliably force table to new page
Node prevNode = table.getPreviousSibling();
if (prevNode != null && prevNode.getNodeType() == NodeType.PARAGRAPH) {
((Paragraph) prevNode).getParagraphFormat().setPageBreakBefore(true);
}
Result: Tables still break incorrectly.
4. Row Count Filtering (Selective Fix)
// DOES NOT WORK - getRows().getCount() returns incorrect values
int rowCount = table.getRows().getCount(); // Returns wrong counts!
if (rowCount >= 4) {
// Only fix "large" tables
}
Result: getRows().getCount() returns incorrect values, possibly counting nested table structures. Cannot be used to filter which tables to fix.
- Table with 2 rows reports 5 rows
- Table with 3 rows reports 1 row
- Table with 5 rows reports 29 rows
5. LayoutCollector Pre-Conversion Page Detection
// DOES NOT WORK - Cannot detect which tables will break
doc.updatePageLayout();
LayoutCollector layoutCollector = new LayoutCollector(doc);
int startPage = layoutCollector.getStartPageIndex(table);
int endPage = layoutCollector.getEndPageIndex(table);
Result: All tables show as single-page (page 0 to 0) before conversion. The pagination issues occur during the PDF save operation itself, so we cannot detect them in advance.
Final Workaround (Applied)
After exhausting all other options, the ONLY fix that works is to normalize the negative indent to 0 for ALL tables with negative indents:
/**
* Workaround: Fix negative left indent alignment issues.
*
* ROOT CAUSE: Aspose.Words has a critical bug where tables with negative left indents that break
* across pages lose alignment - the body rows shift right while header rows stay correctly aligned.
*
* ATTEMPTED FIXES THAT DON'T WORK:
* - setAllowBreakAcrossPages(false) - Aspose ignores this for tables with negative indents
* - KeepTogether/KeepWithNext on paragraphs - Doesn't prevent the break
* - Page break insertion before table - Doesn't reliably work
* - Row count filtering - getRows().getCount() returns incorrect values
* - LayoutCollector page detection - Shows all tables as single-page before conversion
*
* FINAL WORKAROUND: Normalize ALL tables with negative indents to indent 0.
* This is the ONLY fix that prevents the alignment bug when tables break across pages.
*/
private int fixNegativeTableIndents(Document doc) {
int fixedCount = 0;
NodeCollection tables = doc.getChildNodes(NodeType.TABLE, true);
for (int i = 0; i < tables.getCount(); i++) {
Table table = (Table) tables.get(i);
// Check if table has negative left indent
if (table.getLeftIndent() < 0) {
double originalIndent = table.getLeftIndent();
// Normalize negative indent to 0 (only fix that prevents alignment bug)
table.setLeftIndent(0);
fixedCount++;
log.info("Fixed table at index {} with negative indent {}: normalized indent to 0",
i, originalIndent);
}
}
return fixedCount;
}
Workaround Impact:
Prevents alignment issues (body rows no longer shift right from headers)
Produces readable PDFs with consistent column alignment
Simple, reliable fix that always works
All tables with negative indents lose their negative positioning (slight visual shift left/right)
Cannot selectively fix only “problem” tables due to Aspose limitations listed above
Tables may still break across pages (we cannot prevent this), but alignment is preserved
Trade-Off Analysis:
This workaround accepts minor cosmetic position shifts for ALL tables with negative indents in exchange for preventing a critical alignment bug that makes tables unreadable. This is an acceptable trade-off because:
- Without fix: Tables break AND body rows misalign with headers → Unreadable tables
- With fix: Tables break BUT body rows stay aligned with headers → Readable tables with minor position shifts
Summary of Issues
Two Distinct Bug Manifestations
Issue #1: Top-level tables with “Around” text wrapping cause overlapping
- Affects top-level (non-nested) tables only
- Nested tables with “Around” wrapping appear to have different behavior (not covered in this report)
Issue #2: Tables with negative left indents have alignment problems when breaking across pages
- Incorrect pagination (tables break that should stay together)
- Misalignment when breaking (body rows shift right from headers)
Note: These are two distinct bugs in Aspose.Words’ PDF conversion, both related to table layout but with different root causes and requiring separate fixes.
Request for Aspose Support
Primary Request
Please investigate TWO separate but related table layout bugs in Aspose.Words PDF conversion:
Issue #1: Why Aspose.Words incorrectly positions top-level tables with “Text Wrapping: Around” during PDF conversion, causing content overlapping.
Issue #2: Critical alignment bug with tables that have negative left indents. When these tables break across pages during PDF conversion:
- Header rows: Negative indent correctly applied
- Body rows (on continuation pages): Negative indent NOT applied, causing body rows to shift right and misalign with header columns
- This makes tables unreadable as columns no longer align across the page break
Additional Issues Discovered with Issue #2:
setAllowBreakAcrossPages(false)is ignored: Setting this property on table rows has no effect - tables still break across pagesgetRows().getCount()returns incorrect values: This method appears to count nested table structures incorrectly:- A table with 2 rows reports 5 rows
- A table with 3 rows reports 1 row
- A table with 5 rows reports 29 rows
- Paragraph-level formatting ignored: Setting
KeepTogetherandKeepWithNexton paragraphs within table cells does not prevent table breaks - Page break insertion unreliable: Setting
setPageBreakBefore(true)on paragraphs before tables does not reliably force tables to start on new pages
Desired Outcome
Permanent fixes in Aspose.Words SDK that:
For Issue #1 (Around Wrapping):
- Correctly positions top-level tables with “Around” text wrapping
- Maintains the intended layout from the Word document
- Prevents content overlapping in PDF output
- Eliminates the need for our TextWrapping.NONE workaround
For Issue #2 (Negative Indents):
- Consistently applies negative left indents to ALL table rows across page breaks
- Maintains header/body alignment when tables span multiple pages
- Matches Word document layout for tables with negative indents
- Eliminates the need for our indent normalization workaround
Questions for Aspose Team
General:
- Are these known issues in the current version of Aspose.Words?
- What is the expected timeline for fixes?
- Which Aspose.Words version introduced these bugs, and is there a stable version we should revert to?
Issue #1 (Around Wrapping):
- Is there a recommended approach that doesn’t require changing the TextWrapping property?
- Are there specific document properties or table configurations that trigger this bug?
Issue #2 (Negative Indents) - Critical Alignment Bug:
- Primary Bug: Why does the layout engine apply negative indents inconsistently (header vs body rows)?
- Root Cause: Is this a known limitation of the PDF conversion engine?
- API Issues We Discovered:
- Why does
setAllowBreakAcrossPages(false)have no effect on tables with negative indents? - Why does
getRows().getCount()return incorrect values (appears to count nested structures)? - Why do paragraph-level properties (
KeepTogether,KeepWithNext) not prevent table breaks? - Why does
setPageBreakBefore(true)not reliably force tables to new pages?
- Why does
- Workaround Validation: Is normalizing negative indents to 0 the only reliable workaround?
- Detection: Is there any way to detect which tables will break across pages BEFORE calling
save()?LayoutCollectorshows all tables as single-page before conversion. - Alternative Approaches: Are there any other table properties or document settings that could prevent this alignment bug?
test_documents.zip (839.5 KB)


