String replacing

Hi,

I have the following returned as a run type and I what to replace what to make what is between /BS/ /BE/ bold any ideas how to do this please.

Mortgage Arrangement and Valuation /BS/Fee./BE/Payable at the start of the mortgage. Not refundable after the valuation has been carried out. This /BS/fee/BE/ includes an amount not greater than �250 payable to /BS/us/BE/ as part of the cost to /BS/us/BE/ of financing this mortgage with the remainder payable to undertake a valuation.

Regards

Tim

Hi Timothy,

Thanks for your inquiry. In your case, I suggest you please implementing IReplacingCallback
interface to find all instances of particular word in the document.
Please use the following code example to achieve your requirements. This
code example does the followings:

  • Find all instances of particular word in the document
  • Insert bookmark to each resulting match found
  • Bold the Run nodes between inserted bookmarks

Please read following documentation link for your kind reference.
https://docs.aspose.com/words/net/find-and-replace/

Hope this helps you. Please let us know if you have any more queries.

Document doc = new Document(MyDir + "Test01.docx");
string startTag = "/BS/";
string endTag = "/BE/";
doc.Range.Replace(new Regex(startTag), new FindAndInsertBookMarks(startTag.Replace("/", "")), false);
doc.Range.Replace(new Regex(endTag), new FindAndInsertBookMarks(endTag.Replace("/", "")), false);
ArrayList bookmarks = new ArrayList();
foreach (Bookmark bm in doc.Range.Bookmarks)
{
    if (bm.Name.StartsWith("BM_"))
        bookmarks.Add(bm);
}
for (int i = 0; i < bookmarks.Count - 1; i += 2)
{
    BookmarkStart bmStart = ((Bookmark)bookmarks[i]).BookmarkStart;
    BookmarkEnd bmEnd = ((Bookmark)bookmarks[i + 1]).BookmarkEnd;
    Node currentNode = bmStart;
    while (currentNode != bmEnd && currentNode != null)
    {
        if (currentNode.NodeType == NodeType.Run)
        {
            ((Run)currentNode).Font.Bold = true;
        }
        currentNode = currentNode.NextPreOrder(doc);
    }
}
doc.Range.Replace(startTag, "", false, false);
doc.Range.Replace(endTag, "", false, false);
doc.Range.Bookmarks.Clear();
doc.Save(MyDir + "Out.docx");
public class FindAndInsertBookMarks : IReplacingCallback
{
    int i = 0;
    string bookmark = "";
    public FindAndInsertBookMarks(string bm)
    {
        bookmark = bm;
    }

    ///
    /// This method is called by the Aspose.Words find and insert bookmark
    ///
    ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
    {
        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);
        }
        // Create Document Builder
        DocumentBuilder builder = new DocumentBuilder(e.MatchNode.Document as Document);
        builder.MoveTo((Run)runs[runs.Count - 1]);
        builder.StartBookmark("BM_" + bookmark + i);
        builder.EndBookmark("BM_" + bookmark + i);
        i++;
        // Signal to the replace engine to do nothing because we have already done all what we wanted.
        return ReplaceAction.Skip;
    }
}

Program doesn’t like SplitRun and get the following message

Error 2 The name ‘SplitRun’
does not exist in the current context C: \ASPOSETEST\ ASPOSETEST\ Program.cs 83 35 ASPOSETEST

Any ideas please

Hi Timothy,

Please accept my apologies for your inconvenience. Please add the following SplitRun method in your code and let us know if you face any issue.

///
/// Splits text of the specified run into two runs.
/// Inserts the new run just after the specified run.
///
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, position);
    run.ParentNode.InsertAfter(afterRun, run);
    return afterRun;
}

Hi,
Many thanks , the code is working as required.
Is there a command/method that would allowing to loop around formulas after the merge to validate the output.
Regards
Tim

Hi Timothy,

Thanks for your inquiry. It would be great if you please share some more detail about your query along with following detail for investigation purposes.

  • Please attach your input Word document.
  • Please
    attach your target Word document showing the desired behavior.

Please note that OfficeMath Represents an Office Math object such as function, equation, matrix or alike. Can contain child elements including runs of mathematical text, bookmarks, comments, other OfficeMath instances and some other nodes. In the latest version of Aspose.Words, OfficeMath nodes do not provide public methods and properties to create or modify a OfficeMath object.

Morning Tahir,
Back ground details which I think will explain where I am comming from:
We currently have a .Net window service which reads an XML files and merges it with a MS Word template by making calls to Microsoft Word routines (MERGE etc). Once the merged has completed the document is then passed to my program to do the following using MS Word functions:
Change to carriage return
Change /BS/vvvvv/BE/ to bold characters
Delete empty rows in tables.
Insert banding details into headers and footers
Return the document back to the service for archiving and printing/email/FTP etc
Our development team (which I am not part of) have developed a new version of the service using ASPOSE.NET and my job is to write a new DLL to perform the same functions above. Now I have good working knowledge of MS Word but not of ASPOSE.WORD
With the MS Word templates the users user formulas, IF statement, merge fields etc. With some of the formulas they are merge fields whcih contain a strinf numeric value (ie leading spaces)
example: { = 200.00 + ’ 125.55’ + 250.00}
With Word, the MERGE functiona handles this and returns a valid formula from the MERGE. With ASPOSE.WORD it would appear it doesn’t and as a result we get Field Error (Sorry but I was not and so I need to update the formula so that it does work. Now if the formula is in a Table cell it is very easy to do but if it is the text of the document I have difficulties. With limited knowledge I have used NodeCollection (GetChildNodes(NodeType.Run, true);
to loop around the document and handle them that way, but this doesn’t return the complete formula and I am having to write code to build up the formula and then replace the string field and it works I feel there must be a better way of doing this.
The other issues I have is that with word MERGE the IF staement is evaluated and the result is returned in the merged document and not the IF statement. With ASPOSE it seems to return the IF statement witth the values (which you can see via the alt F9 function)
{ IF 0>0 "true" }
This means that if a table cell has an IF statement in it I have to evalute it in order to determine if the row is blank and I can delete it. Again I hhave written code to handles this and it works but is there a way whereby the merge functions reaults just the result and not the evaluated IF statement
Many thanks for your help
Tim

Hi Timothy,

Thanks for your inquiry.

First
of all, please note that Aspose.Words is quite different from the
Microsoft Word’s Object Model in that it represents the document as a tree of objects
more like an XML DOM tree. If you worked with any XML DOM library you
will find it is easy to understand and work with Aspose.Words. When you
load a Word document into Aspose.Words, it builds its DOM and all
document elements and formatting are simply loaded into memory. Please
read the following articles for more information on DOM:
https://docs.aspose.com/words/net/aspose-words-document-object-model/

@talba:

Change to carriage return
Change /BS/vvvvv/BE/ to bold characters

You can achieve this by using the same approach shared here:
https://forum.aspose.com/t/66922

@talba:

Delete empty rows in tables.

Please use the following code snippet to delete empty rows.

Document srcDoc = new Document(MyDir + "in.docx");
foreach (Table table in srcDoc.GetChildNodes(NodeType.Table, true))
{
    Node[] rows = table.GetChildNodes(NodeType.Row, true).ToArray();
    for (int i = 0; i < rows.Length; i++)
    {
        if (rows[i].ToString(SaveFormat.Text).Trim().Equals(""))
            rows[i].Remove();
    }
}
srcDoc.Save(MyDir + "out.docx");

@talba:

Insert banding details into headers and footers

Please use DocumentBuilder.MoveToHeaderFooter method to move the cursor to the beginning of a header or footer in the current section and insert the contents according to your requirements. Following code example shows how to insert a watermark image into a document using DocumentBuilder.

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
// The best place for the watermark image is in the header or footer so it is shown on every page.
builder.MoveToHeaderFooter(HeaderFooterType.HeaderPrimary);
Image image = Image.FromFile(MyDir + "Watermark.png");
// Insert a floating picture.
Shape shape = builder.InsertImage(image);
shape.WrapType = WrapType.None;
shape.BehindText = true;
shape.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
shape.RelativeVerticalPosition = RelativeVerticalPosition.Page;
// Calculate image left and top position so it appears in the centre of the page.
shape.Left = (builder.PageSetup.PageWidth - shape.Width) / 2;
shape.Top = (builder.PageSetup.PageHeight - shape.Height) / 2;
doc.Save(MyDir + "DocumentBuilder.InsertWatermark Out.doc");

@talba:

example: { = 200.00 + ’ 125.55’ + 250.00}

With Word, the MERGE functiona handles this and returns a valid formula from the MERGE. With ASPOSE.WORD it would appear it doesn’t and as a result we get Field Error (Sorry but I was not and so I need to update the formula so that it does work. Now if the formula is in a Table cell it is very easy to do but if it is the text of the document I have difficulties.

Please attach your input and expected output MS Word document here for investigation purpose.

@talba:

The other issues I have is that with word MERGE the IF staement is evaluated and the result is returned in the merged document and not the IF statement. With ASPOSE it seems to return the IF statement witth the values (which you can see via the alt F9 function)

{IF 0 > 0 “true”}

This means that if a table cell has an IF statement in it I have to evalute it in order to determine if the row is blank and I can delete it. Again I hhave written code to handles this and it works but is there a way whereby the merge functions reaults just the result and not the evaluated IF statement

Please attach your input and expected output MS Word document here for investigation purpose. We will then provide you more information on this along with code.

HI,
Sorry in delay getting back, but been very buy. The command cell.ToString(SaveFormat.Text).Trim(); has solved the table/IF issues. I was using cell.GetText() which returns everything whereas cell.ToString(SaveFormat.Text).Trim(); returns the true value of the cell so thank you very much for your help. Is there a book I can purchase on programming with ASPOSE Word

Hi Timothy,

Thanks for your inquiry.

*talba:

I was using cell.GetText() which returns everything whereas cell.ToString(SaveFormat.Text).Trim(); returns the true value of the cell so thank you very much for your help.*

It is nice to hear from you that your problem has been solved. Please feel free to ask if you have any question about Aspose.Words, we will be happy to help you.

*talba:

Is there a book I can purchase on programming with ASPOSE Word*

Please check the documentation of Aspose.Words for .NET from here:
https://docs.aspose.com/words/net/

I have attached the Aspose.Words for .NET API Reference in chm format with this post for your kind reference. This CHM file can be located in Help folder where you installed Aspose.Words for example C:\Program Files (x86)\Aspose\Aspose.Words for .NET\Help. Hope this helps you.

I currently have this code

doc.Range.Replace(new Regex(startTag), new FindAndInsertBookMarks(startTag.Replace("/", ""));

implemented in a dll solution and since installing Aspose 21.5 and .net framework 4.8, error messages are returned relating to converting from a string on the rebuild e.g.
Error CS1503 - Argument 1: cannot convert from ‘System.Text.RegularExpressions.Regex’ to ‘string’

Does this code need to be reworked with the new Aspose version?

@JJordanUni You should use FindReplaceOptions.ReplacingCallback and Range.Replace overload that accepts Regex and FindReplaceOptions as parameters.

Thank you @alexey.noskov, I think that has got me back on the right track. Do you think the following looks ok (without seeing the full code for FindAndInsertBookMarks)?

FindReplaceOptions options = new FindReplaceOptions();
FindAndInsertBookMarks replacestart = new FindAndInsertBookMarks(startTag.Replace("/", ""));
options.ReplacingCallback = replacestart;
asposeDocument.Range.Replace(new Regex(startTag),"", options);

@JJordanUni Yes, your code is correct.

1 Like