Hi,
How can I create If Field with a Table node as one of its results?
Thanks,
Łukasz
Hi,
How can I create If Field with a Table node as one of its results?
Thanks,
Łukasz
Please check following template and output Word documents where I placed a Table inside True part of IF field. The following C# code will show the Table while specifying false to merge field will hide it.
Document doc = new Document("C:\\temp\\Table inside true part of IF field\\Table inside true part of IF field.docx");
doc.MailMerge.Execute(new string[] { "show" }, new object[] { "true" });
doc.Save("C:\\Temp\\Table inside true part of IF field\\21.3.docx");
Hi, thank you.
Is there any way I can do it purely programmatically?
I mean construct such IF with table from scratch in code without using template.
Thanks,
Łukasz
You can build logic on the following code to programmatically insert such IF field with merge field and Table:
Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// { IF "{ MERGEFIELD show }" = "<<Table>>" "False Part" }
Field field = builder.InsertField("IF \"", null);
builder.MoveTo(field.Start.NextSibling.NextSibling);
// Insert merge field and expression
FieldMergeField mergeField = (FieldMergeField)builder.InsertField(FieldType.FieldMergeField, false);
mergeField.FieldName = "show";
builder.Write("\" = \"true\" \"");
// Write True part of IF Field
// In our case, its a Table
builder.StartTable();
builder.InsertCell();
builder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
builder.Write("This is row 1 cell 1");
builder.InsertCell();
builder.Write("This is row 1 cell 2");
builder.EndRow();
builder.InsertCell();
builder.Writeln("This is row 2 cell 1");
builder.InsertCell();
builder.Writeln("This is row 2 cell 2");
builder.EndRow();
builder.EndTable();
// Write False part of IF Field
builder.Write("\" \"Don't show\"");
// perform Mail Merge
doc.MailMerge.Execute(new string[] { "show" }, new object[] { "true" });
doc.Save("C:\\Temp\\21.3.docx");
Hi,
thank you for the example.
Could you please let me know if this is possible when I have already existing document with If field and I want to replace true result, which is a bookmark, with a table?
How can I easily insert a table in its true result?
thanks,
Łukasz
You can first place a keyword or marker inside the true part of the target IF field and then using Find and Replace functionality of Aspose.Words, replace that keyword marker with Table or other content:
Document doc = new Document("C:\\temp\\Table inside true part of IF field.docx");
foreach (Field field in doc.Range.Fields)
{
if (field.Type == FieldType.FieldIf)
{
FieldIf ifField = (FieldIf)field;
ifField.TrueText = "TrueText"; // use a keyword/marker here
ifField.Update();
break;
}
}
FindReplaceOptions options = new FindReplaceOptions();
// options.ReplacingCallback = ...
doc.Range.Replace("TrueText", "", options); // find that keyword and replace with Table etc
doc.Save("C:\\Temp\\21.3.docx");
Hi,
thanks. I can see that Replace method takes string as a second parameter.
How can I use it to place a table object there?
Thanks,
Łukasz
You can implement IReplacingCallback interface if you want to insert custom content during a find and replace operation:
Document doc = new Document("C:\\temp\\Table inside true part of IF field.docx");
foreach (Field field in doc.Range.Fields)
{
if (field.Type == FieldType.FieldIf)
{
FieldIf ifField = (FieldIf)field;
ifField.TrueText = "TrueText"; // use a keyword/marker here
ifField.Update();
break;
}
}
FindReplaceOptions options = new FindReplaceOptions();
options.ReplacingCallback = new ReplaceEvaluator();
doc.Range.Replace("TrueText", "", options); // find that keyword and replace with Table etc
doc.MailMerge.Execute(new string[] { "show" }, new object[] { "true" });
doc.Save("C:\\Temp\\21.3.docx");
private class ReplaceEvaluator : IReplacingCallback
{
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
{
// This is a Run node that contains either the beginning or the complete match.
Node currentNode = e.MatchNode;
// The first (and may be the only) run can contain text before the match,
// in this case it is necessary to split the run.
if (e.MatchOffset > 0)
currentNode = SplitRun((Run)currentNode, e.MatchOffset);
// This array is used to store all nodes of the match for further removing.
ArrayList runs = new ArrayList();
// Find all runs that contain parts of the match string.
int remainingLength = e.Match.Value.Length;
while (
(remainingLength > 0) &&
(currentNode != null) &&
(currentNode.GetText().Length <= remainingLength))
{
runs.Add(currentNode);
remainingLength = remainingLength - currentNode.GetText().Length;
// Select the next Run node.
// Have to loop because there could be other nodes such as BookmarkStart etc.
do
{
currentNode = currentNode.NextSibling;
}
while ((currentNode != null) && (currentNode.NodeType != NodeType.Run));
}
// Split the last run that contains the match if there is any text left.
if ((currentNode != null) && (remainingLength > 0))
{
SplitRun((Run)currentNode, remainingLength);
runs.Add(currentNode);
}
//// to insert Table
DocumentBuilder builder = new
DocumentBuilder((Document)e.MatchNode.Document);
builder.MoveTo((Run)runs[runs.Count - 1]);
Table table = builder.StartTable();
builder.InsertCell();
builder.Write("This is row 1 cell 1");
builder.InsertCell();
builder.Write("This is row 1 cell 2");
builder.EndRow();
builder.EndTable();
foreach (Run run in runs)
run.Remove();
return ReplaceAction.Skip;
}
public static Run SplitRun(Run run, int position)
{
Run afterRun = (Run)run.Clone(true);
afterRun.Text = run.Text.Substring(position);
run.Text = run.Text.Substring((0), (0) + (position));
run.ParentNode.InsertAfter(afterRun, run);
return afterRun;
}
}
Hi,
Thanks for all your help.
I am still struggling as I want to import an existing table to true result from another document.
I get an error that I cannot Insert node of this type at this lcoation
Do you have any advice?
Thanks,
Łukasz
You first need to import a Table node from another document to the current document and then insert it at desired position inside IF field. Please check the following methods:
Hi,
thank you. This is what I have tried and I still get the error that I cannot Insert node of this type at this location. I have tried using either NodeImporter or DocumentBase to ImportNodes, but I still get the error.
Please see the documents attached that I am using.
I want to replace EXT_0STAT bookmark in Aspose.dotx with content from Aspose.docx.
Could you please advise how to do it?
Aspose.zip (36.0 KB)
Thanks,
Łukasz
The following code should insert Table inside the false part of IF field:
Document docx = new Document("C:\\Temp\\Aspose\\Aspose.docx");
Table table = docx.FirstSection.Body.Tables[0];
Document doc = new Document("C:\\Temp\\Aspose\\Aspose.dotx");
Table importedTable = (Table)doc.ImportNode(table, true);
foreach (Field field in doc.Range.Fields)
{
if (field.Type == FieldType.FieldIf)
{
FieldIf ifField = (FieldIf)field;
ifField.FalseText = "FalseText"; // use a keyword/marker here
ifField.Update();
break;
}
}
FindReplaceOptions options = new FindReplaceOptions();
options.ReplacingCallback = new ReplaceEvaluator(importedTable);
doc.Range.Replace("FalseText", "", options); // find that keyword and replace with Table etc
//doc.MailMerge.Execute(new string[] { "show" }, new object[] { "true" });
doc.Save("C:\\Temp\\Aspose\\21.3.docx");
private class ReplaceEvaluator : IReplacingCallback
{
Table _table = null;
public ReplaceEvaluator(Table table)
{
_table = table;
}
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
{
// This is a Run node that contains either the beginning or the complete match.
Node currentNode = e.MatchNode;
// The first (and may be the only) run can contain text before the match,
// in this case it is necessary to split the run.
if (e.MatchOffset > 0)
currentNode = SplitRun((Run)currentNode, e.MatchOffset);
// This array is used to store all nodes of the match for further removing.
ArrayList runs = new ArrayList();
// Find all runs that contain parts of the match string.
int remainingLength = e.Match.Value.Length;
while (
(remainingLength > 0) &&
(currentNode != null) &&
(currentNode.GetText().Length <= remainingLength))
{
runs.Add(currentNode);
remainingLength = remainingLength - currentNode.GetText().Length;
// Select the next Run node.
// Have to loop because there could be other nodes such as BookmarkStart etc.
do
{
currentNode = currentNode.NextSibling;
}
while ((currentNode != null) && (currentNode.NodeType != NodeType.Run));
}
// Split the last run that contains the match if there is any text left.
if ((currentNode != null) && (remainingLength > 0))
{
SplitRun((Run)currentNode, remainingLength);
runs.Add(currentNode);
}
//// to insert Table
DocumentBuilder builder = new DocumentBuilder((Document)e.MatchNode.Document);
builder.MoveTo((Run)runs[runs.Count - 1]);
builder.Writeln();
Paragraph para = (Paragraph)builder.CurrentParagraph.PreviousSibling;
para.ParentNode.InsertAfter(_table, para);
foreach (Run run in runs)
run.Remove();
return ReplaceAction.Skip;
}
public static Run SplitRun(Run run, int position)
{
Run afterRun = (Run)run.Clone(true);
afterRun.Text = run.Text.Substring(position);
run.Text = run.Text.Substring((0), (0) + (position));
run.ParentNode.InsertAfter(afterRun, run);
return afterRun;
}
}