@SCDGLC,
Please see the following sample input/output Word documents:
Docs.zip (76.6 KB)
In the “ERROR_Table1.docx” document, I have inserted a couple more Tables with title “Strawberry Delight” under “Bookmark2” and a “Search Text” in between them.
The following code appends Row to the first Table under specified Bookmark after “Search Text”.
InsertTableRow(@"E:\temp\ERROR_RowTest\Error_row.docx",
@"E:\temp\ERROR_RowTest\\Error_table1.docx",
@"E:\temp\ERROR_RowTest\\19.10.docx",
"Bookmark2",
"Strawberry Delight",
"Search Text");
private class FindAndReplace : IReplacingCallback
{
public object BookmarkName { get; internal set; }
public string TableTitle { get; internal set; }
public string SearchText { get; internal set; }
public Table TheTable { get; set; }
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 do
Document doc = ((Document)e.MatchNode.Document);
Bookmark bm = doc.Range.Bookmarks[BookmarkName.ToString()];
Paragraph bmPara = (Paragraph)bm.BookmarkStart.GetAncestor(NodeType.Paragraph);
if (bmPara != null)
{
int bmParaIndex = doc.GetChildNodes(NodeType.Paragraph, true).IndexOf(bmPara);
Paragraph start = ((Run)runs[0]).ParentParagraph;
int searchTextParaIndex = doc.GetChildNodes(NodeType.Paragraph, true).IndexOf(start);
if (searchTextParaIndex > bmParaIndex)
{
Table targetTable = null;
CompositeNode node = (CompositeNode)start;
bool flag = true;
while (node != null && flag)
{
if (node.NodeType == NodeType.Table)
{
Table table = (Table)node;
if (table.Title == TableTitle)
{
targetTable = table;
flag = false;
break;
}
}
node = (CompositeNode)node.NextSibling;
}
if (targetTable != null)
{
TheTable = targetTable;
}
}
}
return ReplaceAction.Skip;
}
private 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;
}
}
private static void InsertTableRow(string rowFilenameAndPath,
string tableFilenameAndPath,
string outputFilenameAndPath,
string bookmarkName,
string tableTitle,
string searchText)
{
Document tableDoc = new Document(tableFilenameAndPath);
Document rowDoc = new Document(rowFilenameAndPath);
// Get the row to be appended
// index is hard coded here because there will always be only one row
NodeImporter imp = new NodeImporter(rowDoc, tableDoc, ImportFormatMode.KeepSourceFormatting);
Node impNode = imp.ImportNode(rowDoc.FirstSection.Body.Tables[0].Rows[0], true);
FindReplaceOptions options = new FindReplaceOptions();
FindAndReplace findAndReplace = new FindAndReplace
{
BookmarkName = bookmarkName,
TableTitle = tableTitle,
SearchText = searchText
};
options.ReplacingCallback = findAndReplace;
tableDoc.Range.Replace(new Regex(searchText), "", options);
Table targetTable = findAndReplace.TheTable;
if (targetTable != null)
{
targetTable.Rows.Add(impNode);
}
tableDoc.Save(outputFilenameAndPath);
}
Hope, this helps in achieving what you are looking for.