I want to populate all content controls matching the passed in criteria. However it is only populating the first content control, even though there are other content controls matching same passed in criteria.
I had this working previously but since adding further parameters it no longer works.
Attached is the Main Doc that I’m using for testing, along with the Desired Results and the Actual Results. Test Docs.zip (44.4 KB)
This is the code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using Aspose.Words;
using Aspose.Words.Markup;
using OutSystems.HubEdition.RuntimePlatform;
using OutSystems.HubEdition.RuntimePlatform.Log;
using System.Diagnostics;
using Aspose.Words.Saving;
using Aspose.Words.Replacing;
using System.Text.RegularExpressions;
using System.Collections;
namespace OutSystems.NssEXT_AsposeWordIntegration
{
public class CssEXT_AsposeWordIntegration : IssEXT_AsposeWordIntegration
{
static void Main(string[] args)
{
CssEXT_AsposeWordIntegration asposeExt = new CssEXT_AsposeWordIntegration();
asposeExt.MssWriteSingleFieldValue(@"D:\sdavids\Test Data\Working\Main Doc.docx", "B1", "Name", "Category 1", "Ben");
asposeExt.MssWriteSingleFieldValue(@"D:\sdavids\Test Data\Working\Main Doc.docx", "B1", "Name", "Category 2", "Adam");
}
/// <summary>
/// Populates a single Content Control.
/// </summary>
/// <param name="ssFilenameAndPath"></param>
/// <param name="ssBookmarkName"></param>
/// <param name="ssContentControlTag"></param>
/// <param name="ssSearchText">Text to be searched for and if found, the first Content Control with the Tag passed following the specified search text is populated. If an empty string is passed (the default), then no search text is used and the first empty Content Control with the passed Tag that's found following the specified Bookmark Name is populated. A Content Control is considered empty if populated/prompt text is an empty string, or the Tag, or Tag_Title.</param>
/// <param name="ssInsertionText">The text to write to the Content Control.</param>
public void MssWriteSingleFieldValue(string ssFilenameAndPath, string ssBookmarkName, string ssContentControlTag, string ssSearchText, string ssInsertionText) {
LoadLicense();
if (ssSearchText == "")
{
// Populates the first empty instance of Content Control
// with the Tag passed under the specified Bookmark.
WriteSingleFieldValue_NoSearch(ssFilenameAndPath, ssBookmarkName, ssContentControlTag, ssInsertionText);
}
else
{
// Populates the Content Control with the specified Tag that is
// found under the Bookmark and after the specified search text.
WriteSingleFieldValue_WithSearch(ssFilenameAndPath, ssBookmarkName, ssSearchText, ssContentControlTag, ssInsertionText);
}
} // MssWriteSingleFieldValue
private static void WriteSingleFieldValue_WithSearch(string filenameAndPath, string bookmarkName, string searchText, string contentControlTag, string insertionText)
{
// Populate the Content Control with the specified Tag that is
// found under the Bookmark and after the specified search text.
Document doc = new Document(filenameAndPath);
FindReplaceOptions options = new FindReplaceOptions();
FindAndReplace findAndReplace = new FindAndReplace
{
BookmarkName = bookmarkName,
InsertionText = insertionText,
ContentControlTag = contentControlTag,
TableTitle = ""
};
options.ReplacingCallback = findAndReplace;
doc.Range.Replace(new Regex(searchText), searchText, options);
doc.Save(filenameAndPath);
}
private static void WriteSingleFieldValue_NoSearch(string filenameAndPath, string bookmarkName, string contentControlTag, string insertionText)
{
// Populates the first empty instance of Content Control
// with the Tag passed under the specified Bookmark.
Document doc = new Document(filenameAndPath);
Bookmark bm = doc.Range.Bookmarks[bookmarkName];
Paragraph start = (Paragraph)bm.BookmarkStart.GetAncestor(NodeType.Paragraph);
StructuredDocumentTag targetSdt = null;
CompositeNode node = (CompositeNode)start;
bool flag = true;
while (node != null && flag)
{
foreach (StructuredDocumentTag sdt in node.GetChildNodes(NodeType.StructuredDocumentTag, true))
{
if ((sdt.Tag.Equals(contentControlTag))
&& ((sdt.ToString(SaveFormat.Text).Trim().Equals("Click or tap here to enter text."))
|| (sdt.ToString(SaveFormat.Text).Trim().Equals(""))
|| (sdt.ToString(SaveFormat.Text).Trim().Equals(contentControlTag))
|| sdt.ToString(SaveFormat.Text).Trim().Equals(contentControlTag + "_" + contentControlTag)))
{
targetSdt = sdt;
flag = false;
break;
}
}
node = (CompositeNode)node.NextSibling;
}
if (targetSdt != null)
{
if (targetSdt.Level == MarkupLevel.Cell && targetSdt.FirstChild.NodeType == NodeType.Cell)
{
Paragraph paragraph = ((Aspose.Words.Tables.Cell)targetSdt.FirstChild).FirstParagraph;
targetSdt.IsShowingPlaceholderText = false;
paragraph.RemoveAllChildren();
Run newTextRun = new Run(start.Document, insertionText);
newTextRun.Font.Name = "Arial";
newTextRun.Font.Size = 10;
paragraph.AppendChild(newTextRun);
}
}
doc.Save(filenameAndPath);
}
private class FindAndReplace : IReplacingCallback
{
public object BookmarkName { get; internal set; }
public string TableTitle { get; internal set; }
public string SearchText { get; internal set; }
public string InsertionText { get; internal set; }
public string ContentControlTag { get; internal set; }
public Aspose.Words.Tables.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);
}
Document doc = ((Document)e.MatchNode.Document);
Bookmark bm = doc.Range.Bookmarks[BookmarkName.ToString()];
Paragraph bmPara = (Paragraph)bm.BookmarkStart.GetAncestor(NodeType.Paragraph);
if (TableTitle != "")
{
//We're adding a row to a table
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)
{
Aspose.Words.Tables.Table targetTable = null;
CompositeNode node = (CompositeNode)start;
bool flag = true;
while (node != null && flag)
{
if (node.NodeType == NodeType.Table)
{
Aspose.Words.Tables.Table table = (Aspose.Words.Tables.Table)node;
if (table.Title == TableTitle)
{
targetTable = table;
flag = false;
break;
}
}
node = (CompositeNode)node.NextSibling;
}
if (targetTable != null)
{
TheTable = targetTable;
}
}
}
return ReplaceAction.Skip;
}
else
{
// We're populating a content control
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)
{
StructuredDocumentTag targetSdt = null;
CompositeNode node = (CompositeNode)start;
bool flag = true;
while (node != null && flag)
{
foreach (StructuredDocumentTag sdt in node.GetChildNodes(NodeType.StructuredDocumentTag, true))
{
if (sdt.Tag.Equals(ContentControlTag))
{
targetSdt = sdt;
flag = false;
if (targetSdt != null)
{
targetSdt.IsShowingPlaceholderText = false;
Run newTextRun = new Run(start.Document, InsertionText);
newTextRun.Font.Name = "Arial";
newTextRun.Font.Size = 10;
if (targetSdt.Level == MarkupLevel.Inline)
{
targetSdt.RemoveAllChildren();
targetSdt.AppendChild(newTextRun);
}
if (targetSdt.Level == MarkupLevel.Block)
{
targetSdt.RemoveAllChildren();
Paragraph paraInsert = new Paragraph(doc);
paraInsert.ParagraphFormat.Alignment = ParagraphAlignment.Left;
paraInsert.AppendChild(newTextRun);
targetSdt.AppendChild(paraInsert);
}
if (targetSdt.Level == MarkupLevel.Cell)
{
Paragraph paragraph = ((Aspose.Words.Tables.Cell)targetSdt.FirstChild).FirstParagraph;
targetSdt.IsShowingPlaceholderText = false;
paragraph.RemoveAllChildren();
paragraph.AppendChild(newTextRun);
}
//return ReplaceAction.Stop;
}
}
}
node = (CompositeNode)node.NextSibling;
}
}
}
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 ParagraphAlignment GetAlignment(RCAsposeAlignmentRecord alignment)
{
if (alignment.ssSTAsposeAlignment.ssLeft == true)
{
return ParagraphAlignment.Left;
}
else
{
if (alignment.ssSTAsposeAlignment.ssCentre == true)
{
return ParagraphAlignment.Center;
}
else
{
if (alignment.ssSTAsposeAlignment.ssRight == true)
{
return ParagraphAlignment.Right;
}
else
{
return ParagraphAlignment.Left;
}
}
}
}
private void LoadLicense()
{
////GenericExtendedActions.LogMessage(AppInfo.GetAppInfo().OsContext, "Inside LoadLicense", "LoadLicense"); //DEBUGGING - DELETE THIS LINE
// Loads the embedded Aspose license
Assembly assembly = Assembly.GetExecutingAssembly();
string resourceName = assembly.GetName().Name + ".Aspose.Words.lic";
using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
{
Aspose.Words.License license = new Aspose.Words.License();
license.SetLicense(resourceStream);
}
//GenericExtendedActions.LogMessage(AppInfo.GetAppInfo().OsContext, "End", "Load License"); // DEBUGGING - DELETE ME
}
} // CssEXT_AsposeWordIntegration
} // OutSystems.NssEXT_AsposeWordIntegration