Hello Team,
We are currently in process of upgrading our ASPOSE.Words library from 21.7 to 24.1 and doing so we ran into the below issue for one of our test cases using a Text content with all border.
Issue - When converting the HTML content to EMF image using the below logic, the EMF output has missing bottom border while in the earlier version it worked fine. Not sure what is the issue.
Sample Code:
public void getRenderedDocument() {
try {
byte[] htmlBytes = Files.readAllBytes("Sample Text.html");
// Define HTML loadoptions to load the HTML bytes into Word Document
HtmlLoadOptions options = new HtmlLoadOptions();
// To avoid converting Metafile images to PNG image.
options.setConvertMetafilesToPng(false);
// Initialize Word Document with HTML bytes.
Document doc = new Document(htmlBytes, options);
// Get DocumentBuilder instance to update document properties
// such as Size, Alignment, Format, etc.
DocumentBuilder builder = new DocumentBuilder(doc);
PageSetup pageSetup = builder.getPageSetup();
Section section = doc.getFirstSection();
Body body = section.getBody();
// update the Page Properties such as Margin and Size
updatePageProperties(pageSetup, contentLayout);
// The source HTML passed within {@code Document} will have atleast
// 1 <table> element present when it is a Text/Note/Grid object.
TableCollection tables = body.getTables();
if (tables.getCount() == 1) {
Table table = tables.get(0);
updateTableProperties(table);
}
// reset document last paragraph formatting properties
resetLastParagraphProperties(body);
//Save docx as EMF image
ImageSaveOptions emfOptions = new ImageSaveOptions(SaveFormat.EMF);
emfOptions.setPageSet(new PageSet(0));
doc.save("Aspose Output - 24.1.emf", emfOptions);
} catch (Exception ex) {
throw new IllegalStateException(ex.getMessage(), ex);
}
}
private void updatePageProperties(PageSetup pageSetup) {
double imgHeight = ConvertUtil.pixelToPoint(243.0);
double imgWidth = ConvertUtil.pixelToPoint(490.0);
double margin = 0;
// reset page margin
pageSetup.setLeftMargin(margin);
pageSetup.setRightMargin(margin);
pageSetup.setTopMargin(margin);
pageSetup.setBottomMargin(margin);
// Set header and footer distance to default 0. Required to ensure no
// extra spacing is coming from header or footer.
pageSetup.setFooterDistance(0);
pageSetup.setHeaderDistance(0);
// Default paper type is LETTER so change to CUSTOM when setting new
// size.
pageSetup.setPaperSize(PaperSize.CUSTOM);
pageSetup.setPageWidth(imgWidth);
pageSetup.setPageHeight(imgHeight);
}
private void updateTableProperties(Table table) throws Exception{
// Reset left/right indent since table might be shifted left
table.setLeftIndent(0);
// Set Table {@code AutoFitBehavior} value
table.autoFit(AutoFitBehavior.FIXED_COLUMN_WIDTHS);
double rowHeight = ConvertUtil.pixelToPoint(243.0);
double cellWidth = ConvertUtil.pixelToPoint(490.0);
for (Row row : table.getRows()) {
RowFormat rowFmt = row.getRowFormat();
rowFmt.setAllowBreakAcrossPages(false);
rowFmt.setHeight(rowHeight);
rowFmt.setHeightRule(HeightRule.EXACTLY);
for(Cell cell : row.getCells()) {
CellFormat cellFmt = cell.getCellFormat();
cellFmt.setWidth(cellWidth);
cellFmt.setTopPadding(0);
cellFmt.setBottomPadding(0);
}
}
Node node = table.getLastRow().getLastChild();
if (node != null && node.getNodeType() == NodeType.PARAGRAPH &&
"\uFEFF \r".equals(node.getText())) {
node.remove();
}
}
private void resetLastParagraphProperties(Body body) {
Paragraph lastPara = body.getLastParagraph();
String paratext = lastPara.getText();
if (StringUtils.isNullOrBlank(paratext)) {
ParagraphFormat paraFmt = lastPara.getParagraphFormat();
paraFmt.setPageBreakBefore(true);
}
}
Could you check and let us know what changed that caused this issue? What should we need to do from our side to ensure the behavior remains same?
Attachment: HtmlToEMFUsingWords241IncorrectImage.zip (26.7 KB)
Issue marked in red line:
Aspose Words 24.1 paragraph spacing issue
@oraspose Your code does not take table border width into account. If it is required to render the table to image, you should calculate actual bounds of the table. You can achieve this using LayoutCollector
and LayoutEnumerator
:
HtmlLoadOptions options = new HtmlLoadOptions();
// To avoid converting Metafile images to PNG image.
options.setConvertMetafilesToPng(false);
// Initialize Word Document with HTML bytes.
Document doc = new Document("C:\\Temp\\in.html", options);
// The source HTML passed within {@code Document} will have atleast
// 1 <table> element present when it is a Text/Note/Grid object.
TableCollection tables = doc.getFirstSection().getBody().getTables();
if (tables.getCount() == 1)
{
Table table = tables.get(0);
updateTableProperties(table);
}
renderTablePart(doc);
//Save docx as EMF image
ImageSaveOptions emfOptions = new ImageSaveOptions(SaveFormat.EMF);
emfOptions.setPageSet(new PageSet(0));
doc.save("C:\\Temp\\out.docx");
doc.save("C:\\Temp\\out.emf", emfOptions);
private static void renderTablePart(Document oneTableDoc) throws Exception
{
// Set maximum allowed page height
oneTableDoc.getFirstSection().getPageSetup().setPageHeight(1584);
LayoutCollector collector = new LayoutCollector(oneTableDoc);
LayoutEnumerator enumerator = new LayoutEnumerator(oneTableDoc);
Table table = oneTableDoc.getFirstSection().getBody().getTables().get(0);
// Calculate table size.
// For demonstration purposes the example purposes the while table is on the same page.
enumerator.setCurrent(collector.getEntity(table.getFirstRow().getFirstCell().getFirstParagraph()));
int startPageIndex = enumerator.getPageIndex();
// Move enumerator to a row.
while (enumerator.getType()!= LayoutEntityType.ROW)
enumerator.moveParent();
double top = enumerator.getRectangle().y;
double left = enumerator.getRectangle().x;
// Move enumerator to the last row.
enumerator.setCurrent(collector.getEntity(table.getLastRow().getFirstCell().getFirstParagraph()));
int endPageIndex = enumerator.getPageIndex();
// Move enumerator to a row.
while (enumerator.getType()!= LayoutEntityType.ROW)
enumerator.moveParent();
double bottom = enumerator.getRectangle().y + enumerator.getRectangle().height;
double right = enumerator.getRectangle().x + enumerator.getRectangle().width;
// Reset margins
PageSetup ps = oneTableDoc.getFirstSection().getPageSetup();
ps.setPageWidth(ps.getPageWidth()-ps.getLeftMargin()-ps.getRightMargin());
ps.setLeftMargin(0);
ps.setRightMargin(0);
ps.setPageHeight(ps.getPageHeight()-ps.getTopMargin()-ps.getBottomMargin());
ps.setTopMargin(0);
ps.setBottomMargin(0);
// Set calculated width
ps.setPageWidth(right - left);
// Do not set page height if table spans several pages.
if(startPageIndex == endPageIndex)
ps.setPageHeight(bottom - top);
oneTableDoc.updatePageLayout();
}
I do not see any issue with the code I have provided above because it worked fine when using Aspose.Words v21.7 and we did not have to write any additional logic to show bottom border specifically.
Was there any rendering change with Aspose.Words v24.1 for HTML input?
@oraspose Most likely, the problem occurs because current Aspose.Words table layout algorithm has been improved to make it closer to MS Word. If you save the output document as DOCX and open it in MS Word, you will see the same result as Aspose.Words rendering result. Aspose.Words goal is to make rendering as close to MS Word as possible.
Thank you for the information. Let me try the logic you have suggested and see if it works for all our use-cases.
1 Like
Hi @alexey.noskov I tried the logic as per your suggestion and this time the right border is missing in both the generated Word Document and the EMF image as well.
I am expecting the EMF image to be of size 490(W)x243(H) pixels.
Attachment: out.zip (17.9 KB)
@oraspose Please try setting table alignment to center:
private static void updateTableProperties(Table table) throws Exception
{
// Reset left/right indent since table might be shifted left
table.setLeftIndent(0);
table.setAlignment(TableAlignment.CENTER);
// Set Table {@code AutoFitBehavior} value
table.autoFit(AutoFitBehavior.FIXED_COLUMN_WIDTHS);
double rowHeight = ConvertUtil.pixelToPoint(243.0);
double cellWidth = ConvertUtil.pixelToPoint(490.0);
for (Row row : table.getRows()) {
RowFormat rowFmt = row.getRowFormat();
rowFmt.setAllowBreakAcrossPages(false);
rowFmt.setHeight(rowHeight);
rowFmt.setHeightRule(HeightRule.EXACTLY);
for (Cell cell : row.getCells())
{
CellFormat cellFmt = cell.getCellFormat();
cellFmt.setWidth(cellWidth);
cellFmt.setTopPadding(0);
cellFmt.setBottomPadding(0);
}
}
Node node = table.getLastRow().getLastChild();
if (node != null && node.getNodeType() == NodeType.PARAGRAPH &&
"\uFEFF \r".equals(node.getText())) {
node.remove();
}
}
In this case however, left and right borders are thinner than top and bottom.
out.zip (11.9 KB)
@alexey.noskov I noticed that the 1st paragraph spacing within the EMF image generated using 21.7 vs 24.1 looks different. The paragraph spacing in v24.1 is more than v21.7 and probably pushing the text below and assuming it causing the bottom border to be missing.
Could you check why paragraph spacing got changed? Is that intentional with Aspose Words v24.1?
@oraspose You should compare EMF output with MS Word document. The current Aspose.Words output looks closer to what is shown in MS Word. So the current rendering result is more accurate then old one.