Hello!
We are going to refactor HTML import module by the end of this year. Most likely table centering attributes will be also taken in consideration and roundtripped via HTML. To be absolutely sure what case is interesting for you please attach an example here.
Of course you cannot change files manually if they come from some editor and should be processed programmatically. When you are importing an HTML document you can find the tables with right or center alignment in HTML and their counterparts in the document model. The easiest approach is just counting tables starting from the beginning. If some table appears to be right- or center-aligned you just change the alignment of the table rows in the model. This property should be changed:
https://reference.aspose.com/words/net/aspose.words.tables/table/alignment/
Regards,
Hi,
Sorry to hear about the timeline.
My use case is somewhat convoluted. The system is phrase-based, which means that I replace “text-macros” in the word-document with html-phrases. I do this with a DocumentVisitor where I in VisitRun checks whether the Run contains the text-macro currently being searched. If it does I use a DocumentBuilder to insert the html:
var builder = new DocumentBuilder(run.Document);
builder.MoveTo(run);
builder.InsertHtml(htmlText);
run.ParentNode.RemoveChild(run);
(I am actually wondering whether I could simply use Document.Range.Replace instead?)
If my process where sequential I could simply count the number of tables in the document and in the html and go from there. But it’s not And it will be impossible to make sequential, since the word-document with the text-macros may change at any time.
If I could somehow get the list of tables inserted into the document by the DocumentBuilder it would be fairly simple to examine the html for table-align attributes and change the document tables accordingly.
So what I really would like to have is something to mimic this:
NodeCollection tablesInserted = builder.GetChildNodes(NodeType.Table, true);
or this:
NodeCollection tablesInserted = run.GetChildNodes(NodeType.Table, true);
I can see that run.ParentNode has a GetChildNodes method. Would that work??
Thanks,
Torben
Hi
Thanks for your inquiry. Yes, of course, you can simply use Range.Replace in this case. You should use ReplaceEvaluator. Please see the following link for more information:
https://reference.aspose.com/words/net/aspose.words/range/replace/
However, the example provided in this article will work only in simple cases, when text macros are at the beginning of the matched run. To make it work in all cases, you should split matched run. You can use the same technique as described in the following article:
https://docs.aspose.com/words/net/find-and-replace/
Regarding finding inserted nodes, I think, you can use NodeInserted event handler in this case:
https://reference.aspose.com/words/net/aspose.words/documentbase/nodechangingcallback/
Please let me know if you need more assistance, I will be glad to help you.
Best regards.
Hi Alexey,
I have seen a few times that the run didn’t match because the text somehow where split across multiple runs, but have not figured out the right solution for that yet.
Your second link points to the same place as the first - I guess that is wrong? Any pointers would be nice, I don’t want to invent the wheel again, if I can avoid it
Thanks
Hi
I am sorry, this is my mistake. Here is correct link:
https://docs.aspose.com/words/net/find-and-replace/
Best regards.
Great,
Thanks for the right link.
My first trial (without the solution in your link) is as follows:
I have some code that finds the tables in the html and what their alignment is. This is stored for future reference. I then call Range.Replace:
htmlTableAlignments = findTableAlignments(htmlText);
currentTable = -1;
document.NodeInserted += NodeInserted;
document.Range.Replace(new Regex(searchText, RegexOptions.ExplicitCapture), HtmlReplaceEvaluator, true);
document.NodeInserted -= NodeInserted;
// The HtmlReplaceEvaluator:
private ReplaceAction HtmlReplaceEvaluator(object sender, ReplaceEvaluatorArgs e)
{
DocumentBuilder builder = new DocumentBuilder(e.MatchNode.Document);
builder.MoveTo(e.MatchNode);
builder.InsertHtml(htmlText);
e.Replacement = "";
return ReplaceAction.Replace;
}
// NodeInserted:
private void NodeInserted(object sender, NodeChangedEventArgs e)
{
if (e.Node.NodeType == NodeType.Table)
{
currentTable++;
return;
}
if (e.Node.NodeType == NodeType.Row)
{
var htmlTableAlignment = htmlTableAlignments[currentTable];
setDocumentTableRowAlignment(e.Node as Row, htmlTableAlignment.tableAlignment);
}
}
// setDocumentTableRowAlignment
private void setDocumentTableRowAlignment(Row row, TableAlignment htmlAlignment)
{
switch (htmlAlignment)
{
case TableAlignment.taLeft:
row.RowFormat.Alignment = RowAlignment.Left;
break;
case TableAlignment.taCenter:
row.RowFormat.Alignment = RowAlignment.Center;
break;
case TableAlignment.taRight:
row.RowFormat.Alignment = RowAlignment.Right;
break;
}
}
TableAlignment is my own enum. I guess you can see how it goes. The only problem is that it does not work. The table is not centered or right-aligned in word
When debugging I see the Alignment property being set correctly on each row. What puzzles me, though, is why you don’t have an Alignment property on the Table itself. Wouldn’t that make much more sense?
I am a bit at a loss for why this does not work. Any ideas?
Thanks!
Hi
Thanks for your inquiry. I think, in your case, you can try collecting tables inserted into the document, and then setting its alignment. For example, see the following code:
// Create document and DocumentBuilder.
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// Create instanse of the class, which will help uyse to get collection of inserted tables.
InsertedNodesCollector collector = new InsertedNodesCollector();
// Add NodeInserted event handler
doc.NodeInserted += collector.NodeInserted;
// Insert some HTML.
// For example there are 3 tables, and we would like that 1st will be left aligned, the 2nd centered and the 3rd right aligned.
builder.InsertHtml("<table><tr><td>test</td><td>test</td><td>test</td></tr><tr><td>test</td><td>test</td><td>test</td></tr></table>"
+
"<table><tr><td>test</td><td>test</td><td>test</td></tr><tr><td>test</td><td>test</td><td>test</td></tr></table>"
+
"<table><tr><td>test</td><td>test</td><td>test</td></tr><tr><td>test</td><td>test</td><td>test</td></tr></table>");
for (int tabIdx = 0; tabIdx < collector.InsertedTables.Count; tabIdx++)
{
// Get table
Table currentTable = (Table) collector.InsertedTables[tabIdx];
// Loop trough all rows in the table
foreach (Row row in currentTable.Rows)
{
switch (tabIdx)
{
case 0:
row.RowFormat.Alignment = RowAlignment.Left;
break;
case 1:
row.RowFormat.Alignment = RowAlignment.Center;
break;
case 2:
row.RowFormat.Alignment = RowAlignment.Right;
break;
default:
row.RowFormat.Alignment = RowAlignment.Left;
break;
}
}
}
// Save output document.
doc.Save(@"Test001\out.doc");
==================================================================
class InsertedNodesCollector
{
// Collect tables inserted in the document.
public void NodeInserted(object sender, NodeChangedEventArgs e)
{
if (e.Node.NodeType == NodeType.Table)
mInsertedTables.Add(e.Node);
}
/// <summary>
/// Returns collection of inserted tables.
/// </summary>
public List<Node> InsertedTables
{
get { return mInsertedTables; }
}
private readonly List<Node> mInsertedTables = new List<Node>();
}
Hope this helps.
Best regards.
Great!
That method works! Wonder what’s the difference, though
Thanks for your quick and thorough support. This just makes me recommend the product even more!
Regards,
Torben