Implement IReplacingCallback and write custom method for find and replace operation

I have a document with blank spaces, that is to be filled with information automatically. Normally I use doc.Range.Replace(Regex, String, FindAndReplaceOptions()) for simple replacing operations, but I faced an unusual blank space: an empty paragraph with a lower border. In order to fill it, I tried to make use of IReplacingCallback, but space remains unfilled. The code is listed below(&insert is a marker for activation of this callback):

    private class InsertOnMatch : IReplacingCallback
    {
        private readonly string _replacement;
        
        public InsertOnMatch(string replacement)
        {
            _replacement = replacement;
        }
        ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
        {
            if (_replacement.Contains("&insert"))
            {
                var builder = new DocumentBuilder((Document)e.MatchNode.Document);
                e.Replacement = _replacement.Remove(_replacement.IndexOf("&insert"));
                Paragraph targetParagraph = (Paragraph)((Run)e.MatchNode).ParentParagraph.NextSibling;
                builder.MoveTo(targetParagraph);
                builder.Write(e.Replacement);
                return ReplaceAction.Stop;
            }

            e.Replacement = _replacement;

            return ReplaceAction.Replace;
        }
    }

How to do it the right way?

@gregarshinov,

Thanks for your inquiry. Please ZIP and attach your input, output and expected output Word documents here for our reference. We will then provide you more information about your query along with code.

Archive.zip (392.5 KB)
Here you are!

@gregarshinov,

Thanks for sharing the documents. We have not found the “&insert” in your input document. The difference between output and expected output document is following text.

"Общество с ограниченной ответственностью “СиСофт Нижний Новогород”

Could you please share some more detail about your issue that you are facing (the unusual blank space)? Please also share the simplified code example that is calling InsertOnMatch callback. We will investigate the issue and provide you more information on it. Thanks for your cooperation.

The full listing is like this:

    private Document FillBid(Document doc)
    {
        var masks = new List<ValueTuple<Regex, string>>
        {
            (new Regex(@"_+ \[указывается сайт, на котором опубликована закупка\],"), "<WWW>"),
            (new Regex(@"(?<=Извещение №\u00A0)(_+)"), "31704930675"),
            (new Regex(@"(?<=запроса предложений №\u00A0)(_+)"), "0080/17/2.2/0006493/Гипрогазцент/ЗП/ГОС/Э/24.03.2017"),
            (new Regex(@"мы&p"), "Общество с ограниченной ответсвенностью \"СиСофт Нижний Новогород\"&insert"),
            (new Regex(@"(?<=на поставку )_+"), "САПР 2D/3D"),
            (new Regex(@"(?<=действует до )«_____»__________"), "«01» августа 2017")
            
        };
        var options = new FindReplaceOptions
        {
            PreserveMetaCharacters = true
        };
        foreach (var mask in masks)
        {
            doc.Range.Replace(mask.Item1, new InsertOnMatch(mask.Item2), false);
        }
        return doc;
    }
    
    private class InsertOnMatch : IReplacingCallback
    {
        private readonly string _replacement;
        
        public InsertOnMatch(string replacement)
        {
            _replacement = replacement;
        }
        ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
        {
            if (_replacement.Contains("&insert"))
            {
                var builder = new DocumentBuilder((Document)e.MatchNode.Document);
                e.Replacement = _replacement.Remove(_replacement.IndexOf("&insert"));
                Paragraph targetParagraph = (Paragraph)((Run)e.MatchNode).ParentParagraph.NextSibling;
                builder.MoveTo(targetParagraph.NextSibling);
                builder.Write(e.Replacement);
                return ReplaceAction.Stop;
            }

            e.Replacement = _replacement;

            return ReplaceAction.Replace;
        }
    }

@gregarshinov,

Thanks for sharing the detail. In your code, please replace the following line of code

Paragraph targetParagraph = (Paragraph)((Run)e.MatchNode).ParentParagraph.NextSibling;
with
Paragraph targetParagraph = (Paragraph)((Run)e.MatchNode).ParentParagraph;

Please check the following modified code. Hope this helps you.

Document doc = new Document(MyDir + "input.docx");
                 
var options = new FindReplaceOptions
{
    PreserveMetaCharacters = true,
    ReplacingCallback = new InsertOnMatch("Общество с ограниченной ответсвенностью \"СиСофт Нижний Новогород\"&insert")
};

doc.Range.Replace(@"мы&p", "", options);
doc.Save(MyDir + "18.4.docx");

private class InsertOnMatch : IReplacingCallback
{
    private readonly string _replacement;

    public InsertOnMatch(string replacement)
    {
        _replacement = replacement;
    }
    ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
    {
        if (_replacement.Contains("&insert"))
        {
            var builder = new DocumentBuilder((Document)e.MatchNode.Document);
            e.Replacement = _replacement.Remove(_replacement.IndexOf("&insert"));
            Paragraph targetParagraph = (Paragraph)((Run)e.MatchNode).ParentParagraph;//.NextSibling;
            builder.MoveTo(targetParagraph.NextSibling);
            builder.Write(e.Replacement);
            return ReplaceAction.Stop;
        }

        e.Replacement = _replacement;

        return ReplaceAction.Replace;
    }
}

Thank you very much, @tahir.manzoor !