I am seeking help on how to fit very large tables within the margin in a document. A document may consist of many tables, and each table may have hundreds of rows with many columns, and the data placed in each cell is dynamic.
The current logic:
-
Creates a table by creating the header row, then creating each row, both via builder.insertCell()
, then ultimately builder.insertHtml(html)
with builder.endRow()
-
Get the width of the area the table can be placed in via builder.getPageSetup().getPageWidth() - builder.getPageSetup().getRightMargin()
.
-
Get the width of the table via
for (Cell cell : table.getFirstRow().getCells()) {
tableWidth += cell.getCellFormat().getWidth();
}
-
Compare table width > width of area the table can be placed in
- if this is false, the table width fits ok
-
Else: if the table width is greater than the area, the table is removed
-
Go back to #1 with the font size being: original font size - (how many times has the table been removed)
Is there a more efficient way to get be placing a table within the current margins of the document? If the table being resized starts as being very large (wide), this process is taking quite some time.
Thank you.
@EthanEttema,
Please compress the following resources into ZIP format and attach the .zip file here for testing:
- A simplified source Word document
- Aspose.Words generated output document showing the undesired behavior
- Your expected Word file showing the desired output. You can create this file manually by using MS Word. It would be great if you please also list the complete steps that you performed in MS Word to create the expected file
- Please also create a standalone simplified Java Application (source code without compilation errors) that helps us to reproduce this problem on our end and attach it here for testing. Please do not include Aspose.Words JAR files in it to reduce the file size.
As soon as you get these pieces of information ready, we will then start investigation into your particular scenario and provide you code to achieve the same output by using Aspose.Words for Java.
Hi @awais.hafeez,
The final document does not have any issues, it is the amount of time Aspose is taking to get the result which is the issue.
Please find attached two word documents. One with “BEFORE”, which contains a table which runs off the page, and the other with “AFTER” which has recreated the table but with smaller font size in order to fit within the margins. Both of these were generated via Aspose.Words for Java.
To get from the “BEFORE” to “AFTER”, the code follows the flow mentioned in the first post.
Thanks.Aspose.zip (2.0 MB)
@EthanEttema,
We are checking this scenario and will get back to you soon.
Thank you.
On our side, we’ve profiled the longest running bits of code and found that insertHtml()
is taking some time.
AsposeInsertHtml.png (420.7 KB)
@EthanEttema,
The following code keeps reducing the font size of Table content until the Table fits within the Page bounds. The entire process took just under 9 seconds on my end when running with 21.6 version of Aspose.Words for Java.
Document doc = new Document("C:\\Temp\\Aspose\\BEFORE large data not sized Aspose.docx");
Table table = doc.getSections().get(2).getBody().getTables().get(0);
Section tableSection = (Section) table.getAncestor(NodeType.SECTION);
double pageWidth = tableSection.getPageSetup().getPageWidth();
while (getTableWidth(table) >= pageWidth) {
for (Run run : (Iterable<Run>) table.getChildNodes(NodeType.RUN, true))
run.getFont().setSize(run.getFont().getSize() - 1);
doc.updatePageLayout();
}
doc.save("C:\\Temp\\Aspose\\awjava-21.6.docx");
public static double getTableWidth(Table table) throws Exception {
LayoutCollector collector = new LayoutCollector((Document) table.getDocument());
LayoutEnumerator enumerator = new LayoutEnumerator((Document) table.getDocument());
double maxWidth = 0;
for (Row row : (Iterable<Row>) table.getRows()) {
enumerator.setCurrent(collector.getEntity(row.getLastCell().getFirstParagraph()));
while (enumerator.moveParent())
if (enumerator.getType() == LayoutEntityType.ROW)
break;
// Get the width of Row
double rowWidth = enumerator.getRectangle().getX() + enumerator.getRectangle().getWidth();
if ((rowWidth > maxWidth))
maxWidth = rowWidth;
}
return maxWidth;
}
Thanks for your response. We are also using 21.6 version.
We’ve taken this back and incorporated some of these changes locally, and have seen some significant performance gains - particularly around reducing the font size as opposed to generating the entire table.
In the awjava-21.6.docx that is attached to the response, if a table cell is empty, it’s still retaining the original font size even after reducing the font size via the Run
. In this case it is still at 12 which makes the row height larger than expected. Is there a way to address this?
@EthanEttema,
The following Java code should fix the issue with empty cells by reducing the font sizes of paragraph break characters:
Document doc = new Document("C:\\Temp\\Aspose\\BEFORE large data not sized Aspose.docx");
Table table = doc.getSections().get(2).getBody().getTables().get(0);
Section tableSection = (Section) table.getAncestor(NodeType.SECTION);
double pageWidth = tableSection.getPageSetup().getPageWidth();
while (getTableWidth(table) > pageWidth) {
for (Paragraph paragraph : (Iterable<Paragraph>) table.getChildNodes(NodeType.PARAGRAPH, true)) {
paragraph.getParagraphBreakFont().setSize(paragraph.getParagraphBreakFont().getSize() - 1);
for (Run run : (Iterable<Run>) paragraph.getChildNodes(NodeType.RUN, true))
run.getFont().setSize(run.getFont().getSize() - 1);
}
doc.updatePageLayout();
}
doc.save("C:\\Temp\\Aspose\\awjava-21.6.docx");
Thank you for your response. We have taken these suggestions and applied them with noticeable improvements.
1 Like