@ilvarol you can use the following code to add the required line breaks in your document:
Document doc = new Document("C:\\Temp\\input.docx");
FindReplaceOptions options = new FindReplaceOptions();
options.ReplacingCallback = new AddLinebreakAtEndOfLineHandler();
options.UseSubstitutions = true;
options.IgnoreDeleted = true;
options.MatchCase = false;
var findText = "[RetailerLongName]";
var replaceWithText = "Retailer Long Name";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[RetailerAddress]";
replaceWithText = "Retailer Address Will Be Here";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[RetailerTelephone]";
replaceWithText = "+90123456789";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[RetailerEmail]";
replaceWithText = "test@testandtest.com";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[RetailerVatNumber]";
replaceWithText = "123456789";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[RentalContractNumber]";
replaceWithText = "123456789";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[CurrentDate]";
replaceWithText = DateTime.Now.ToShortDateString();
doc.Range.Replace(findText, replaceWithText, options);
findText = "[CompanyName]";
replaceWithText = "Company Name";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[CustomerName]";
replaceWithText = "Customer Name";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[CustomerPostcode]";
replaceWithText = "+12345";
doc.Range.Replace(findText, replaceWithText, options);
findText = "[CustomerTown]";
replaceWithText = "Customer Town";
doc.Range.Replace(findText, replaceWithText, options);
doc.Save("C:\\Temp\\output.docx");
public class AddLinebreakAtEndOfLineHandler : IReplacingCallback
{
private bool _addLineBreak;
public bool AddLineBreak
{
get => _addLineBreak;
set
{
_addLineBreak = value;
}
}
public AddLinebreakAtEndOfLineHandler(bool addLineBreak = true)
{
_addLineBreak = addLineBreak;
}
ReplaceAction IReplacingCallback.Replacing(ReplacingArgs args)
{
Run run = (Run)args.MatchNode;
var nextNode = run.NextSibling;
if (_addLineBreak && nextNode != null && nextNode.NodeType == NodeType.Run)
{
RemoveUnnecessaryRuns(args.Match.Length, run, args.MatchOffset);
var nameMatch = Guid.NewGuid().ToString();
var bookmarkStartMatch = new BookmarkStart(run.Document, nameMatch);
var bookmarkEndMatch = new BookmarkEnd(run.Document, nameMatch);
var nameAfterMatch = Guid.NewGuid().ToString();
var bookmarkStartAfterMatch = new BookmarkStart(run.Document, nameAfterMatch);
var bookmarkEndAfterMatch = new BookmarkEnd(run.Document, nameAfterMatch);
Dictionary<string, Run> runsInBookmark = new Dictionary<string, Run>();
run.ParentParagraph.InsertBefore(bookmarkStartMatch, run);
run.ParentParagraph.InsertAfter(bookmarkEndMatch, run);
runsInBookmark[nameMatch] = run;
run.ParentParagraph.InsertBefore(bookmarkStartAfterMatch, nextNode);
run.ParentParagraph.InsertAfter(bookmarkEndAfterMatch, nextNode);
runsInBookmark[nameAfterMatch] = (Run)nextNode;
LayoutCollector collector = new LayoutCollector((Document)run.Document);
LayoutEnumerator enumerator = new LayoutEnumerator((Document)run.Document);
var bcMatch = run.Document.Range.Bookmarks.FirstOrDefault(b => b.Name == nameMatch);
enumerator.Current = collector.GetEntity(bcMatch.BookmarkStart);
var startMatchRect = enumerator.Rectangle;
var bcAfterMatch = run.Document.Range.Bookmarks.FirstOrDefault(b => b.Name == nameAfterMatch);
enumerator.Current = collector.GetEntity(bcAfterMatch.BookmarkStart);
var startAfterMatchRect = enumerator.Rectangle;
// It is the last element in the line
if (startMatchRect.Y != startAfterMatchRect.Y)
{
run.Text = args.Replacement + ControlChar.LineBreak;
runsInBookmark[nameAfterMatch].Text = runsInBookmark[nameAfterMatch].Text.TrimStart();
}
else
{
run.Text = args.Replacement;
}
bcMatch.Remove();
bcAfterMatch.Remove();
return ReplaceAction.Skip;
}
return ReplaceAction.Replace;
}
private static void RemoveUnnecessaryRuns(int matchTextLength, Run startMatchNode, int matchOffset)
{
var remainingLength = matchTextLength;
if(matchOffset > 0)
{
var prevText = startMatchNode.Text.Substring(0, matchOffset);
Run newRun = (Run)startMatchNode.Clone(true);
newRun.Text = prevText;
startMatchNode.ParentParagraph.InsertBefore(newRun, startMatchNode);
startMatchNode.Text = startMatchNode.Text.Substring(matchOffset);
}
remainingLength -= startMatchNode.Text.Length;
//First node check
if (remainingLength <= 0)
{
var nextText = startMatchNode.Text.Substring(matchTextLength);
Run newRun = (Run)startMatchNode.Clone(true);
newRun.Text = nextText;
startMatchNode.ParentParagraph.InsertAfter(newRun, startMatchNode);
startMatchNode.Text = startMatchNode.Text.Substring(0, matchTextLength);
return;
}
var currentNode = startMatchNode.NextSibling;
while (remainingLength > 0 && currentNode != null && currentNode.NodeType == NodeType.Run)
{
var currentRun = (Run)currentNode;
startMatchNode.Text += currentRun.Text;
remainingLength -= currentRun.Text.Length;
if (remainingLength < 0)
{
var spltTextIndex = currentRun.Text.Length + remainingLength;
var nextText = currentRun.Text.Substring(spltTextIndex);
Run newRun = (Run)currentRun.Clone(true);
newRun.Text = nextText;
currentRun.ParentParagraph.InsertAfter(newRun, currentRun);
}
currentNode = currentNode.NextSibling;
currentRun.Remove();
}
}
}
output.docx (15.8 KB)