Incorrect Table Layout when saving HTML Table to DOCX and EMF

Hi Team,

I am facing issue when converting the HTML Table to DOCX or EMF output. Based on the logic acquired from this post which provides solution to the similar table layout issue but that solution does not work for the below expected use-case.

Expected Output:
Expected Output.jpg (47.3 KB)

Sample Code for updating Page and Table settings:

private void convertToImage() {
    try {
        byte[] htmlBytes = Files.readAllBytes("Sample Table.html");	
        HtmlLoadOptions options = new HtmlLoadOptions();
    		
    	Document doc = new Document(htmlBytes, options);
    	DocumentBuilder builder = new DocumentBuilder(doc);
    	PageSetup pageSetup = builder.getPageSetup();
    		
    	//update page properties like size and margin
    	updatePageSettings(pageSetup);
    		
    	// For Last Paragraph within Document, set font size to 0 if no text
    	// so that it won't occupy the space after the table.
    	// Also, do page break between Table and Paragraph so that while
    	// saving 1st Document Page only Table is saved.
    	Section section = doc.getFirstSection();
    	Body body = section.getBody();
    	Paragraph lastPara = body.getLastParagraph();
    	String paratext = lastPara.getText();
    	if(StringUtils.isNullOrBlank(paratext)) {
    		ParagraphFormat paraFmt = lastPara.getParagraphFormat();
    		paraFmt.getStyle().getFont().setSize(0);
    		paraFmt.setPageBreakBefore(true);
    	}
    		
    	// Update Table Layout properties such as Margin, Padding and Size
    	TableCollection tables = body.getTables();
    	Table table = tables.get(0);
    	if (table != null) {
    		// Reset left indent. since table might be shifted left.
    		table.setLeftIndent(0);
    		// Need to ensure table has fixed column widths
    		table.autoFit(AutoFitBehavior.FIXED_COLUMN_WIDTHS);
    		//update table ROW and CELL Layout
    		updateTableRowSettings(table);
    		//update Document Page height based on Table Height
    		renderTablePart(doc);
    	}
    		
    	// Save as different formats
    	doc.save("Sample Table.html", SaveFormat.HTML);
    	doc.save("Sample Table.docx", SaveFormat.DOCX);
    	doc.save("Sample Table.emf", SaveFormat.EMF);
    		
    } catch(Exception ex) {
    	System.out.println(ex.getMessage());
    }
}

private void updatePageSettings(PageSetup pageSetup) {
    double margin = 0;
    pageSetup.setLeftMargin(margin);
    pageSetup.setRightMargin(margin);
    pageSetup.setTopMargin(margin);
    pageSetup.setBottomMargin(margin);
    	
    double widthpx = 586.08;
    double widthpt = ConvertUtil.pixelToPoint(widthpx);
    pageSetup.setPageWidth(widthpt);
}

private void updateTableRowSettings(Table table) throws Exception{
    			
    List<Double> rowHeights = new ArrayList<>();
    rowHeights.add(52.9000);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    rowHeights.add(25.0);
    	
    List<Double> colWidths = new ArrayList<>();
    colWidths.add(228.48);
    colWidths.add(8.0);
    colWidths.add(90.88);
    colWidths.add(25.0);
    colWidths.add(49.92);
    colWidths.add(8.0);
    colWidths.add(90.88);
    colWidths.add(25.0);
    colWidths.add(49.92);
    	
    for (Row row : table.getRows()) {
    	RowFormat rowFmt = row.getRowFormat();
    	int rowIndex = table.indexOf(row);
    	double rowHeight = ConvertUtil.pixelToPoint(rowHeights.get(rowIndex));
    		
    	rowFmt.setAllowBreakAcrossPages(false);		
    	rowFmt.setHeight(rowHeight);
    	rowFmt.setHeightRule(HeightRule.EXACTLY);   
    		
    	for(Cell cell : row.getCells()) {
    		int colIndex = row.indexOf(cell);
    		double cellWidth = ConvertUtil.pixelToPoint(colWidths.get(colIndex));
    			
    		CellFormat cellFmt = cell.getCellFormat();
    		cellFmt.setWidth(cellWidth);
    		cellFmt.setTopPadding(0);
    		cellFmt.setBottomPadding(0);
    	}
    }
}

private void renderTablePart(Document oneTableDoc) throws Exception
{
    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()));
    // 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()));
    // 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);
    ps.setPageHeight(bottom - top);

    oneTableDoc.updatePageLayout();
}

Expected Output:
Expected Output.jpg (47.3 KB)

Could you suggest what is incorrect about the logic above? How do I fix the Table layout before saving the document?

Sample Test Files: Sample Table.zip (15.7 KB)

@oraspose I’m getting the expected result without making any change. This is the code that I use:

LoadOptions opt = new LoadOptions();
opt.setLoadFormat(LoadFormat.HTML);
Document doc = new Document("C:\\Temp\\input.html", opt);

doc.save("C:\\Temp\\output.docx");

output.docx (14.9 KB)

After read your code I assume that you want something else, can you please attach your expected output in docx format.

Hi. I am actually providing custom page size due to which the output does match. Take a look at the logic above which has a series of steps in customizing the DOCX page. The end output after customizing the page should match the expected output.

@oraspose I noticed that and for that reason I ask for an example docx file as expected output, you can use MS Word app to create the document.

Hi. I have attached the expected output in DOCX format for your reference.

Expected DOCX output: expected output.docx (14.5 KB)

I would like to achieve the same output using the logic provided above.

1 Like

@oraspose you can achieve what you want using the following code:

Document doc = new Document("C:\\Temp\\input.html", new Aspose.Words.Loading.LoadOptions
{
    LoadFormat = LoadFormat.Html,
    WarningCallback = new ConversionIssueCallBack()
});

doc.FirstSection.PageSetup.BottomMargin = 0;
doc.FirstSection.PageSetup.RightMargin = 6;
doc.FirstSection.PageSetup.LeftMargin = 6;
doc.FirstSection.PageSetup.TopMargin = 0;
doc.FirstSection.PageSetup.FooterDistance = 0;
doc.FirstSection.PageSetup.HeaderDistance = 0;

var table = (Table)doc.FirstSection.Body.GetChild(NodeType.Table, 0, true);
table.BottomPadding = 0;
var paraBefore = doc.FirstSection.Body.InsertBefore(new Paragraph(doc), table);
var paraAfter = (Paragraph)doc.FirstSection.Body.InsertAfter(new Paragraph(doc), table);
paraAfter.ParagraphFormat.SpaceBefore = 0;

doc.UpdatePageLayout();

LayoutCollector collector = new LayoutCollector(doc);
LayoutEnumerator enumerator = new LayoutEnumerator(doc);

enumerator.Current = collector.GetEntity(paraBefore);
var paraBeforeSize = enumerator.Rectangle;
enumerator.Current = collector.GetEntity(paraAfter);
var paraAfterSize = enumerator.Rectangle;

var paraFirst = (Paragraph)table.FirstRow.FirstCell.InsertBefore(new Paragraph(doc), table.FirstRow.FirstCell.FirstParagraph);
paraFirst.ParagraphFormat.Alignment = ParagraphAlignment.Left;
paraFirst.ParagraphFormat.LeftIndent = 0;

var paraLast = (Paragraph)table.FirstRow.LastCell.InsertBefore(new Paragraph(doc), table.FirstRow.LastCell.LastParagraph);
paraLast.ParagraphFormat.Alignment = ParagraphAlignment.Right;
paraLast.ParagraphFormat.RightIndent = 0;

doc.UpdatePageLayout();
enumerator.Current = collector.GetEntity(paraFirst);
var paraFirstSize = enumerator.Rectangle;

enumerator.Current = collector.GetEntity(paraLast);
var paraLastSize = enumerator.Rectangle;

doc.FirstSection.PageSetup.PageHeight = paraAfterSize.Top - paraBeforeSize.Bottom;
// Add right and left margins and an extra point for each one, is the real minimun distance in between the paragraph an the border
doc.FirstSection.PageSetup.PageWidth = paraLastSize.Right - paraFirstSize.Left + 14;
paraBefore.Remove();
paraAfter.Remove();
paraFirst.Remove();
paraLast.Remove();

doc.UpdatePageLayout();

doc.Save("C:\\Temp\\output.docx");

@oraspose this is the code in Java:

Document doc = new Document("C:\Temp\input.html", new LoadOptions(LoadFormat.HTML));
doc.getFirstSection().getPageSetup().setBottomMargin(0);
doc.getFirstSection().getPageSetup().setRightMargin(6);
doc.getFirstSection().getPageSetup().setLeftMargin(6);
doc.getFirstSection().getPageSetup().setTopMargin(0);
doc.getFirstSection().getPageSetup().setFooterDistance(0);
doc.getFirstSection().getPageSetup().setHeaderDistance(0);

Table table = (Table) doc.getFirstSection().getBody().getChild(NodeType.TABLE, 0, true);
table.setBottomPadding(0);
Paragraph paraBefore = (Paragraph) doc.getFirstSection().getBody().insertBefore(new Paragraph(doc), table);
Paragraph paraAfter = (Paragraph) doc.getFirstSection().getBody().insertAfter(new Paragraph(doc), table);
paraAfter.getParagraphFormat().setSpaceBefore(0);

doc.updatePageLayout();
LayoutCollector collector = new LayoutCollector(doc);
LayoutEnumerator enumerator = new LayoutEnumerator(doc);

enumerator.setCurrent(collector.getEntity(paraBefore));
Rectangle2D.Float paraBeforeSize = enumerator.getRectangle();
enumerator.setCurrent(collector.getEntity(paraAfter));
Rectangle2D.Float paraAfterSize = enumerator.getRectangle();

Paragraph paraFirst = (Paragraph) table.getFirstRow().getFirstCell().insertBefore(new Paragraph(doc), table.getFirstRow().getFirstCell().getFirstParagraph());
paraFirst.getParagraphFormat().setAlignment(ParagraphAlignment.LEFT);
paraFirst.getParagraphFormat().setLeftIndent(0);

Paragraph paraLast = (Paragraph) table.getFirstRow().getLastCell().insertBefore(new Paragraph(doc), table.getFirstRow().getLastCell().getLastParagraph());
paraLast.getParagraphFormat().setAlignment(ParagraphAlignment.RIGHT);
paraLast.getParagraphFormat().setRightIndent(0);
doc.updatePageLayout();
enumerator.setCurrent(collector.getEntity(paraFirst));
Rectangle2D.Float paraFirstSize = enumerator.getRectangle();

enumerator.setCurrent(collector.getEntity(paraLast));
Rectangle2D.Float paraLastSize = enumerator.getRectangle();
doc.getFirstSection().getPageSetup().setPageHeight(paraAfterSize.getY() - paraBeforeSize.getY() - paraBeforeSize.getHeight());
// Add right and left margins and an extra point for each one, is the real minimum distance in between the paragraph and the border
doc.getFirstSection().getPageSetup().setPageWidth(paraLastSize.getX() + paraLastSize.getWidth() - paraFirstSize.getX() + 14);
paraBefore.remove();
paraAfter.remove();
paraFirst.remove();
paraLast.remove();

doc.updatePageLayout();
doc.save("C:\\Temp\\output.docx");
1 Like

Hi.

The solution you have provided works for that specific use-case. I was kind of looking for a more generic solution where in I can feed the values just like you did and generate the DOCX with correct Table size.

I have few queries over the solution you have provided.

  1. How did you decide on the value 6pt or 8px for Page Left and Right Margin?
  2. Does setting Header and Footer Distance to 0 makes a difference in the final output?
  3. What is your intention on adding new Paragraph Before and After within the Document?
  4. What is the importance of adding “14pt” while setting Page Width? How did you arrive at this value? Will this value change if the Table has more rows and columns?

@oraspose

  1. How did you decide on the value 6pt or 8px for Page Left and Right Margin?

Due to the way I calculate the table width, horizontal table borders are not included. As a result, I need to reserve that space in the page margins. If you don’t set horizontal page margins, the lateral table borders will be truncated.

  1. Does setting Header and Footer Distance to 0 makes a difference in the final output?

In this particular scenario don’t make any difference.

  1. What is your intention on adding new Paragraph Before and After within the Document?

Tables are complex objects, and depending on how they are configured, dealing with them using the LayoutEnumerator class can be challenging. For this reason, I used four paragraphs - two before and after the table to calculate the table height, and the other two placed in the leftmost and rightmost cells of the table to calculate the table width. These paragraphs are deleted after use, so they do not affect the final page layout.

  1. What is the importance of adding “14pt” while setting Page Width? How did you arrive at this value? Will this value change if the Table has more rows and columns?

I used two paragraphs to calculate the table width, but the table borders are not included in that value, so I reserve space for them in the page margins. The number 14 comes from adding the right page margin, left page margin, and an extra point for each side because it’s the default separation between a paragraph and the table border when you set the indent of the paragraph to 0. So, this value should not change unless you change the table borders. This particular code will work as long as the table fits into a single page, regardless of the number of rows and columns it has.

Developing a generic solution using flow documents can be complex due to various factors such as table sizing, page width, and shape placement. It is often recommended to begin by addressing a specific use case and then gradually expanding the code to accommodate other scenarios. Careful consideration of these factors is necessary to ensure accurate rendering and layout of flow documents with tables. So is up to you to determine how to deal with each use case and you always can post here if you have any doubt.

1 Like

Hello Eduardo,

Really appreciate you time and effort in replying to my queries. Once again thanks for helping out. Have a good day.

1 Like

Hello,

Just a follow-up question on the way “6 pt” for left and right margin is calculated. The table border width in the HTML specified is “5 px” on each side, so sum of horizontal table borders width is “10 px” or “7.5 pt”.

Why “6 pt” instead of “7.5 pt” for the left and right table margin? Suppose, If I have different table border width say “3 px” on all sides then how will I calculated the exact Left and Right margin required to calculate table width.

@oraspose I’m revisiting the full thread, I’ll back with you in some minutes.

@oraspose thanks for your patience, I reviewed the whole solution, the fixed number that I use were calculated on the fly, I’m posting a more accurate solution for you, so you don’t need to deal with this:

Document doc = new Document("C:\\Temp\\Sample Table.html", new Aspose.Words.Loading.LoadOptions
{
    LoadFormat = LoadFormat.Html,
    WarningCallback = new ConversionIssueCallBack()
});

doc.FirstSection.PageSetup.BottomMargin = 0;
doc.FirstSection.PageSetup.TopMargin = 0;
doc.FirstSection.PageSetup.FooterDistance = 0;
doc.FirstSection.PageSetup.HeaderDistance = 0;

var table = (Table)doc.FirstSection.Body.GetChild(NodeType.Table, 0, true);
table.BottomPadding = 0;
var paraBefore = doc.FirstSection.Body.InsertBefore(new Paragraph(doc), table);
var paraAfter = (Paragraph)doc.FirstSection.Body.InsertAfter(new Paragraph(doc), table);
paraAfter.ParagraphFormat.SpaceBefore = 0;

doc.UpdatePageLayout();

LayoutCollector collector = new LayoutCollector(doc);
LayoutEnumerator enumerator = new LayoutEnumerator(doc);

enumerator.Current = collector.GetEntity(paraBefore);
var paraBeforeSize = enumerator.Rectangle;
enumerator.Current = collector.GetEntity(paraAfter);
var paraAfterSize = enumerator.Rectangle;

var paraFirst = (Paragraph)table.FirstRow.FirstCell.InsertBefore(new Paragraph(doc), table.FirstRow.FirstCell.FirstParagraph);
paraFirst.ParagraphFormat.Alignment = ParagraphAlignment.Left;
paraFirst.ParagraphFormat.LeftIndent = 0;
var leftMargin = table.FirstRow.FirstCell.CellFormat.Borders.Left.LineWidth * 2;
doc.FirstSection.PageSetup.LeftMargin = leftMargin;

var paraLast = (Paragraph)table.FirstRow.LastCell.InsertBefore(new Paragraph(doc), table.FirstRow.LastCell.LastParagraph);
paraLast.ParagraphFormat.Alignment = ParagraphAlignment.Right;
paraLast.ParagraphFormat.RightIndent = 0;
var rightMargin = table.FirstRow.LastCell.CellFormat.Borders.Right.LineWidth * 2;
doc.FirstSection.PageSetup.RightMargin = rightMargin;

doc.UpdatePageLayout();
enumerator.Current = collector.GetEntity(paraFirst);
var paraFirstSize = enumerator.Rectangle;

enumerator.Current = collector.GetEntity(paraLast);
var paraLastSize = enumerator.Rectangle;

doc.FirstSection.PageSetup.PageHeight = paraAfterSize.Top - paraBeforeSize.Bottom;
// Add right and left margins and an extra point for each one, is the real minimun distance in between the paragraph an the border
doc.FirstSection.PageSetup.PageWidth = paraLastSize.Right - paraFirstSize.Left + rightMargin + leftMargin;
paraBefore.Remove();
paraAfter.Remove();
paraFirst.Remove();
paraLast.Remove();

doc.UpdatePageLayout();

doc.Save("C:\\Temp\\output.docx");
1 Like

Hello Eduardo,

First of all, really appreciate your help and support in figuring out an accurate solution which resolved the issue which I was struggling to find a generic solution for. Upon running a bunch of test cases with different table size and border size, this solution passed them all after doing a visual comparison one by one.

But, when I tried saving the document as “EMF” image and upon opening them it seems to be empty. I have attached a sample of one of the test case for your reference which includes the actual HTML, saved document and converted EMF image. Let me know if you need anything else.

Sample EMF conversion code used along with your generic solution:

ImageSaveOptions emfOptions = new ImageSaveOptions(SaveFormat.EMF);
emfOptions.setPageSet(new PageSet(0));
doc.save("TestCase1.emf", emfOptions);

EMF conversion failed test case: Sample Test Case 1.zip (18.9 KB)

@oraspose let me check it and I’ll be with you soon.

@oraspose sorry I cannot reproduce your issue, I’m getting the proper EMF file.
output.zip (18.2 KB)

Let me check and get back to you.

2 Likes

Hello,

I was able to generate the EMF image correctly for most of the test cases but it is not generating it correctly for the attached test case. I generated both “docx” and “emf” format but unfortunately both did not produce the correct output.

Sample Code used for generating DOCX and EMF output:

private void convertGridToImage() {
    try {
        byte[] htmlBytes = Files.readAllBytes("TestCase2Input.html");
        HtmlLoadOptions options = new HtmlLoadOptions();
            
        Document doc = AsposeWordUtility.createDocument(htmlBytes, options);
        DocumentBuilder builder = AsposeWordUtility.createDocumentBuilder(doc);
            
        double heightpx = 168.0;
        double widthpx = 516.33333;
        PageSetup pageSetup = builder.getPageSetup();
        updatePageSettings(pageSetup, heightpx, widthpx);
            
        Section section = doc.getFirstSection();
        Body body = section.getBody();
            
        Paragraph lastPara = body.getLastParagraph();
        String paratext = lastPara.getText();
        if(StringUtils.isNullOrBlank(paratext)) {
            ParagraphFormat paraFmt = lastPara.getParagraphFormat();
            paraFmt.getStyle().getFont().setSize(0);
            paraFmt.setPageBreakBefore(true);
        }
            
        TableCollection tables = body.getTables();
        Table table = tables.get(0);
        if(table != null) {
            table.setLeftIndent(0);
                                
            List<Double> cellWidths = Arrays.asList(166.33333,70.0,70.0,70.0,70.0,70.0);
            List<Double> rowHeights = Arrays.asList(25.0,25.0,25.0,25.0,25.0,25.0,25.0);
            updateTableRowSettings(table, rowHeights, cellWidths);
                
            Node node = table.getLastRow().getLastChild();
            if (node != null && node.getNodeType() == NodeType.PARAGRAPH &&
                "\uFEFF \r".equals(node.getText())) {
                node.remove();
            }
        }

        renderTablePart(doc);
            
        doc.save("TestCase2.docx");
        doc.save("TestCase2.emf");
    } catch(Exception ex) {
        System.out.println(ex);
    }
}

private void updatePageSettings(PageSetup pageSetup, double heightpx, double widthpx) {
    double margin = 0;
    pageSetup.setTopMargin(margin);
    pageSetup.setBottomMargin(margin);
    pageSetup.setLeftMargin(margin);
    pageSetup.setRightMargin(margin);
        
    double widthpt = ConvertUtil.pixelToPoint(widthpx);
    double heightpt = ConvertUtil.pixelToPoint(heightpx);
    pageSetup.setPageHeight(heightpt);
    pageSetup.setPageWidth(widthpt);
}

private void updateTableRowSettings(Table table, List<Double> rowHeights, List<Double> cellWidths) throws Exception {            
    for (Row row : table.getRows()) {
        int rowIndex = table.indexOf(row);
        double rowHeight = ConvertUtil.pixelToPoint(rowHeights.get(rowIndex));
            
        RowFormat rowFmt = row.getRowFormat();
        rowFmt.setAllowBreakAcrossPages(false);
        rowFmt.setHeightRule(HeightRule.EXACTLY);
        rowFmt.setHeight(rowHeight);
            
        for(Cell cell : row.getCells()) {
            int colIndex = row.indexOf(cell);
            double cellWidth = ConvertUtil.pixelToPoint(cellWidths.get(colIndex));
                
            CellFormat cellFmt = cell.getCellFormat();
            cellFmt.setWidth(cellWidth);
            cellFmt.setTopPadding(0);
            cellFmt.setBottomPadding(0);                
        }
    }
}
    
private void renderTablePart(Document doc) throws Exception {
    Section firstSection = doc.getFirstSection();
    Body body = firstSection.getBody();
        
    PageSetup pageSetup = firstSection.getPageSetup();
    pageSetup.setBottomMargin(0);
    pageSetup.setTopMargin(0);
    pageSetup.setFooterDistance(0);
    pageSetup.setHeaderDistance(0);
        
    Table table = (Table) body.getChild(NodeType.TABLE, 0, true);
    table.setBottomPadding(0);
        
    Paragraph paraBefore = (Paragraph) body.insertBefore(new Paragraph(doc), table);
    Paragraph paraAfter = (Paragraph) body.insertAfter(new Paragraph(doc), table);
    paraAfter.getParagraphFormat().setSpaceBefore(0);

    doc.updatePageLayout();
        
    LayoutCollector collector = new LayoutCollector(doc);
    LayoutEnumerator enumerator = new LayoutEnumerator(doc);

    enumerator.setCurrent(collector.getEntity(paraBefore));
    Rectangle2D.Float paraBeforeSize = enumerator.getRectangle();
    enumerator.setCurrent(collector.getEntity(paraAfter));
    Rectangle2D.Float paraAfterSize = enumerator.getRectangle();

    Paragraph paraFirst = (Paragraph) table.getFirstRow().getFirstCell().insertBefore(new Paragraph(doc), table.getFirstRow().getFirstCell().getFirstParagraph());
    paraFirst.getParagraphFormat().setAlignment(ParagraphAlignment.LEFT);
    paraFirst.getParagraphFormat().setLeftIndent(0);
    double leftMargin = table.getFirstRow().getFirstCell().getCellFormat().getBorders().getLeft().getLineWidth() * 2.0;
    pageSetup.setLeftMargin(leftMargin);

    Paragraph paraLast = (Paragraph) table.getFirstRow().getLastCell().insertBefore(new Paragraph(doc), table.getFirstRow().getLastCell().getLastParagraph());
    paraLast.getParagraphFormat().setAlignment(ParagraphAlignment.RIGHT);
    paraLast.getParagraphFormat().setRightIndent(0);
    double rightMargin = table.getFirstRow().getFirstCell().getCellFormat().getBorders().getRight().getLineWidth() * 2.0;
    pageSetup.setRightMargin(rightMargin);
        
    doc.updatePageLayout();
        
    enumerator.setCurrent(collector.getEntity(paraFirst));
    Rectangle2D.Float paraFirstSize = enumerator.getRectangle();
        
    enumerator.setCurrent(collector.getEntity(paraLast));
    Rectangle2D.Float paraLastSize = enumerator.getRectangle();
        
    //pageSetup.setPageHeight(paraAfterSize.getY() - paraBeforeSize.getY() - paraBeforeSize.getHeight());
    //paraAfterSize.TOP - paraBeforeSize.BOTTOM
    pageSetup.setPageHeight(paraAfterSize.getY() - paraBeforeSize.getHeight());
        
    // Add right and left margins and an extra point for each one, is the real minimum distance in between the paragraph and the border
    //paraLastSize.Right - paraFirstSize.Left + rightMargin + leftMargin
    pageSetup.setPageWidth((paraLastSize.getX() + paraLastSize.getWidth()) - paraFirstSize.getX() + (rightMargin + leftMargin));
                
    paraBefore.remove();
    paraAfter.remove();
    paraFirst.remove();
    paraLast.remove();

    doc.updatePageLayout();
}

Test Case: Test Case 2.zip (17.6 KB)

@oraspose sorry using the code that I provided I get the following EMF response:
output.zip (1.9 KB)

Can you please point if I’m missing something. I’m using the latest version of the Aspose.Words package (v23.5).

We are using ASPOSE Words for JAVA v21.7.0. Does this make a difference in generating EMF?