Calculate image and table width

Hi!

I’m generating word document’s containing images and tables inserted from unknown (customer) html snippets.
So the tables or images could be too wide. This is not under our control.

Using the AutoFit function is no option because tables which are not to wide would be fitted also. (Additionaly we have strange bugs with it which I am not able to reproduce with an example, otherwise I had created an Aspose issue long ago).

My question:
What is the best way to find out if the image or table is out of the document border?
Calculating page width and image/table width should be no problem but an indent could be set so this would not work.
And as second step what property should I set when the table is to wide? The preferred width? I should not change the style of the customers tables.

Has anyone a solution for that?

Thank you in advance!

1 Like

Hi Petra,


Thanks for your inquiry. I think you should implement INodeChangingCallback interface and use INodeChangingCallback.NodeInserted or INodeChangingCallback.NodeInserting methods to keep track of what new Tables/Images have been inserted from HTML. You can estimate Table width by summing up widths of all cells in a particular row (see Cell.CellFormat.Width property). Images are represented by Shape and you can use Shape.Width property to measure it.

Hope, this helps.

Best regards,

Hi!

Thank you for your fast help! Unfortunately this is not what I need.
I can also iterate over document.getChildNodes(NodeType.TABLE, true); to get all tables and images. But with this way and with your proposal I have still the problem: How can I know that this was inserted by HTML and not from another source?

My bigger problem is still: How can I reliable calculate if the table/image fit into the page when an indent is set? It is not assumed that the table/image always starts from the outer left margin. Do you know what I mean?
And again: What is than the best way to set the width without autofit?

Best regards
Petra

Hi Petra,


Thanks for your inquiry. I think, you can meet this requirement using LayoutCollector and LayoutEnumerator classes. Please see attached sample document and try running the following code:

Document doc = new Document(getMyDir() + “inp.docx”);

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

Table table = doc.getFirstSection().getBody().getTables().get(0);
Row row = table.getFirstRow();
Cell firstCell = row.getFirstCell();
Cell lastCell = row.getLastCell();

enumerator.setCurrent(collector.getEntity(firstCell.getFirstParagraph()));
enumerator.moveParent(LayoutEntityType.CELL);

System.out.print("Table starts at: " + enumerator.getRectangle().getX() + " and ends at: ");

enumerator.setCurrent(collector.getEntity(lastCell.getLastParagraph()));
enumerator.moveParent(LayoutEntityType.CELL);

System.out.println(enumerator.getRectangle().getX() + enumerator.getRectangle().getWidth());

Hope, this helps.

Best regards,

Hi again!
As a start this is helpful, thanks :slight_smile:
Now I am able to find out if the table is to wide but there is still the open question what is the alternativ to .autoFit(AutoFitBehavior.AUTO_FIT_TO_WINDOW); ?
This method seems not always working but I am not able to create a reproducible example with it.

I tried to set the AutoFitBehavior as test on the current inserted node.
But builder.insertHtml(descriptionHTML); has unfortunately no return value! :frowning:

So I tried it with different variant of this:

Section currentSection = builder.getCurrentSection();
NodeCollection childNodes = currentSection.getChildNodes();
HashSet<com.aspose.words.Table> tableNodes = getTableNode(childNodes, new HashSet<>());
for (com.aspose.words.Table tableNode : tableNodes)
{
if(tableNode.getCount() > 0)
{
tableNode.autoFit(AutoFitBehavior.AUTO_FIT_TO_WINDOW);
}
}

private static HashSet<com.aspose.words.Table> getTableNode(NodeCollection nodeCollection, HashSet<com.aspose.words.Table> tables)
{
for (Object node : nodeCollection) {
if(node instanceof com.aspose.words.Table)
{
tables.add((com.aspose.words.Table)node);
}
else
{
if(node instanceof CompositeNode)
{
CompositeNode compositeNode = (CompositeNode)node;
NodeCollection childNodes = compositeNode.getChildNodes();
return getTableNode(childNodes, tables);
}
}
}

return tables;
}

But .autoFit(AutoFitBehavior.AUTO_FIT_TO_WINDOW); has than no effect. Does this make any sense?


Best regards
Petra

Hi Petra,


Thanks for your inquiry. You can get what Tables are inserted by insertHtml method using following code:
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);

HandleNodeChanging handler = new HandleNodeChanging();
doc.setNodeChangingCallback(handler);
builder.insertHtml(
Hello World
);

for (Table table : (Iterable
) handler.getInsertedTables()){
// do something here
}

static class HandleNodeChanging implements INodeChangingCallback {
private ArrayList mInsertedTables = new ArrayList();

public ArrayList getInsertedTables()
{
return mInsertedTables;
}

public void nodeInserted(NodeChangingArgs args) throws Exception {
if (args.getNode().getNodeType() == NodeType.TABLE)
mInsertedTables.add(args.getNode());
}

public void nodeInserting(NodeChangingArgs args) throws Exception {
// Do Nothing
}

public void nodeRemoved(NodeChangingArgs args) throws Exception {
// Do Nothing
}

public void nodeRemoving(NodeChangingArgs args) throws Exception {
// Do Nothing
}
}

Secondly, please provide resources such as input Word document/html/code etc to be able to reproduce autoFit method related issue on our end. Thanks for your cooperation.

Best regards,

Hi again!

Your proposed solution to use INodeChangingCallback to get only the inserted HTML tables is suitable for me. Thanks!

Unfortunately the previous proposal with the LayoutCollector is not good. The performance of

collector.getEntity(firstCell.getFirstParagraph()

is very, very bad. I generate a document with 600 tables. At the end each call of getEntity needs 3-4 seconds. This is not usable.
So I have to still call the buggy autofit function instead. I try to prepare an example for you to show when the autofit does not work. Unfortunately this is not so easy.

Best regards,
Petra

Hi Petra,


Thanks for your inquiry. Please make sure that you always use the latest version of Aspose.Words for Java (16.1.0). In case the problems still remain, please provide two test cases corresponding to performance and autofit method related issues. Please also provide required resources (documents) to be able to test these scenarios on our end. Thanks for your cooperation.

Best regards,