Generating Template back from output document

Hi,

We have the following use case

  1. Template with aspose keywords and syntax are created. Contains both static text & dynamic content
  2. Document is generated by replacing aspose keywords and syntax with runtime values retrieved from third party system
  3. Document generated in step#2 is reviewed and reviewer will look into static text in the context of entire generated content.
  4. There are chances for changes in third party system which means the step #2 has to be repeated. On doing that we would lose all the changes done by reviewer in step #3.

We are looking out a way where the template can be regenerated from generated content. This way we would regenerate the template from step #3 after review is completed. From there on the updated template would be used for generating the content.

@manikandanid Probably you can use StructuredDocumentTags or form fields for dynamic text. In this case you will be able to update the dynamic text values after generating the report.

Aspose_afterReview.docx (12.7 KB)
Aspose_beforeReview.docx (12.6 KB)
Aspose_afterReplacingAsposeSyntax.docx (12.7 KB)

Not sure i explained it rightly. Will try to explain with sample.
Attached sample template Aspose_beforeReview.docx contains aspose syntax. This is the content of the file at the start of review cycle
In the c# code, we programmatically replace the aspose placeholder with actual values resulting in doc Aspose_afterReplacingAsposeSyntax.docx
Now doc Aspose_afterReplacingAsposeSyntax.docx is sent for review . After review the content is modifed to as shown in doc Aspose_afterReview.docx.

What we are looking out for is to apply the changes to static content in Aspose_afterReview.docx to
Aspose_beforeReview.docx.

Hope i am able to explain it better.

@manikandanid Thank you for additional information. You can try using document comparison feature. But you should create logic to identify dynamic values. For example you can wrap them into SDT or bookmark. Then you can accept revisions applied to the static content. For example in your document changed has been made in the first paragraph. So you can use the following code:

Document doc1 = new Document(@"C:\Temp\Aspose_beforeReview.docx");
Document doc2 = new Document(@"C:\Temp\Aspose_afterReplacingAsposeSyntax.docx");
 
doc1.Compare(doc2, "AW", DateTime.Now);

// Suppose we know that chnages has been made in the first paragraph.
doc1.FirstSection.Body.FirstParagraph.Range.Revisions.AcceptAll();

// Regect other revisions.
doc1.Revisions.RejectAll();

doc1.Save(@"C:\Temp\out.docx");

out.docx (10.1 KB)

There are many assumption in this approach which might be difficult in real time. Is there any way where i can tell aspose not to consider for the document comparison. Say for e.g: any section of document with in tag <<[NOCOMPARESTART]>> & <<[NOCOMPAREEND]>>
should not be considered for the comparison. This will leave only the static portion of the text to be compared. This way i can replace all the static text from doc Aspose_afterReview.docx into Aspose_beforeReview.docx

Aspose_afterReplacingAsposeSyntax.docx (13.0 KB)

Aspose_afterReview.docx (12.6 KB)

Aspose_beforeReview.docx (12.8 KB)

Can something like this be done ?

@manikandanid I am afraid, there is no way to ignore parts of the document upon comparing. I do not see any simple solution for your requirements. the only way is somehow mark the placeholders as I suggested earlier and then replace dynamic text with placeholders.

@manikandanid The user can use standard MS Word features to insert bookmarks into the document while creating it manually in MS Word. There is no need in addition Aspose syntax for this.

Apologies for late reply. The bookmark approach solved my problem. What i did is all the static text content is bookmarked in the template (assume version V1). Now after applying the aspose syntax values, the document is generated and reviewed(assume version V2). Now the bookmark content from version V1 in the template will be replaced by the same bookmark content from version V2. This solves the use case i needed.

One overahead in this approach is that the user who creates the template have to put all static text in doc into bookmark and name it uniquely. From aspose library, is there any way to find the text in doc automatically and create a bookmark for it. The bookmark content should have only text and not any of the aspose syntax. This will result in large number of bookmarks but that should nt matter if creation of bookmark and replace is done programatically.

@manikandanid If you need to find and wrap some particular text into a bookmark, you can achieve this using IReplacingCallback.
For example see the following code:

Document doc = new Document(@"C:\Temp\in.docx");

ReplacingCallbackWrapWithBookmark callback = new ReplacingCallbackWrapWithBookmark();
FindReplaceOptions opt = new FindReplaceOptions(FindReplaceDirection.Backward);
opt.ReplacingCallback = callback;
doc.Range.Replace("test", "", opt);

doc.Save(@"C:\Temp\out.docx");
public class ReplacingCallbackWrapWithBookmark : ReplacingCallabackBase, IReplacingCallback
{
    public ReplaceAction Replacing(ReplacingArgs args)
    {
        Document doc = (Document)args.MatchNode.Document;
        List<Run> matchedRuns = GetMatchedRuns(args);

        // Generate an unique bookmakr name. Another approach can be used.
        // If bookmark starts with undescore it is hidden in MS Word. 
        string bookmarkName = "_" + Guid.NewGuid().ToString();
        while (doc.Range.Bookmarks[bookmarkName] != null)
            bookmarkName += "_" + Guid.NewGuid().ToString();

        // Insert a bookmark around the matched text
        matchedRuns.First().ParentNode.InsertBefore(new BookmarkStart(doc, bookmarkName), matchedRuns[0]);
        matchedRuns.Last().ParentNode.InsertAfter(new BookmarkEnd(doc, bookmarkName), matchedRuns.Last());

        Bookmarks.Add(bookmarkName);

        // Signal to the replace engine to do nothing because we have already done all what we wanted.
        return ReplaceAction.Skip;
    }

    protected static List<Run> GetMatchedRuns(ReplacingArgs args)
    {
        // This is a Run node that contains either the beginning or the complete match.
        Node currentNode = args.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 (args.MatchOffset > 0)
            currentNode = SplitRun((Run)currentNode, args.MatchOffset);

        // This array is used to store all nodes of the match for further deleting.
        List<Run> runs = new List<Run>();

        // Find all runs that contain parts of the match string.
        int remainingLength = args.Match.Value.Length;
        while (
            remainingLength > 0 &&
            currentNode != null &&
            currentNode.GetText().Length <= remainingLength)
        {
            runs.Add((Run)currentNode);
            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((Run)currentNode);
        }

        return runs;
    }

    private static Run SplitRun(Run run, int position)
    {
        Run afterRun = (Run)run.Clone(true);
        run.ParentNode.InsertAfter(afterRun, run);
        afterRun.Text = run.Text.Substring(position);
        run.Text = run.Text.Substring((0), (0) + (position));
        return afterRun;
    }

    public List<string> Bookmarks
    {
        get { return mBookmarks; }
    }

    private List<string> mBookmarks = new List<string>();
}
1 Like

Thanks for the detailed explanation. Great support Aspose team. I really appreciate.
Will check this out and will update you back.

1 Like