That’s helpful thanks, however still a couple of issues.
Firstly, just FYI your code deleted the search text, which I tried to fix in the code below but oddly it didn’t work as expected.
Secondly, your code writes to the content control text prompt rather than entering the text in it as you would do manually (demonstrated by the fact the text is greyed out). Again I tried to fix this but it didn’t work as expected.
I’m not sure if that has anything to do with the fact it looks like my client has given me an evaluation license rather than a full license, though I would assume not?
Thirdly, I have made a few other changes to the code. though it’s not yet working, please see below…
//
WriteFieldAfter(@“c:\temp\sample doc.docx”,“KEEPERS”,“resident vet”,“success”);
//
//
private static void WriteFieldAfter(string filenameAndPath, string bookmarkName, string searchText, string insertionText)
{
Document doc = new Document(filenameAndPath);
FindReplaceOptions options = new FindReplaceOptions();
FindAndReplace findAndReplace = new FindAndReplace
{
BookmarkName = bookmarkName,
InsertionText = insertionText
};
options.ReplacingCallback = findAndReplace;
doc.Range.Replace(new Regex(searchText), searchText, options);
doc.Save(filenameAndPath);
}
//
//
private class FindAndReplace : IReplacingCallback
{
public object BookmarkName { get; internal set; }
public string InsertionText { get; internal 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
Paragraph start = ((Run)runs[0]).ParentParagraph;
StructuredDocumentTag targetSdt = null;
Paragraph para = start;
bool flag = true;
while (para != null && flag)
{
foreach (StructuredDocumentTag sdt in para.GetChildNodes(NodeType.StructuredDocumentTag, true))
{
if (sdt.Tag.Equals(BookmarkName))
{
targetSdt = sdt;
flag = false;
break;
}
}
para = (Paragraph)para.NextSibling;
}
if (targetSdt != null)
{
Run clone = (Run)targetSdt.FirstChild;
clone.Font.Name = "Arial";
clone.Font.Size = 10;
targetSdt.RemoveAllChildren();
clone.Text = InsertionText;
targetSdt.AppendChild(clone);
if (targetSdt.Level == MarkupLevel.Inline)
{
targetSdt.AppendChild(clone);
}
if (targetSdt.Level == MarkupLevel.Block)
{
para.ParagraphFormat.Alignment = ParagraphAlignment.Left;
para.AppendChild(clone);
targetSdt.AppendChild(para);
}
}
foreach (Run run in runs)
run.Remove();
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;
}
}
//
Fourthly, I’m attaching a new document to work on and another document showing the expected output (i.e. entering the name Sarah Jones in the appropriate content control).
Sample.zip (56.8 KB)
Many thanks!