Page break MetaCharacter is not working properly inside a table cell (#10647)

Hey,

when I use the Replace method of the Aspose.Words.Document.Range class to replace a string with the MetaCharacter “&m”, that is mentioned here, the PageBreak is not applied when the replacement was executed within a table cell.

I used the following code with Aspose.Words 19.4:

Dim document As New Aspose.Words.Document(“10647_1.docx”)
document.Range.Replace(“{PAGEBREAK}”, “&m”, New Aspose.Words.Replacing.FindReplaceOptions())
document.Save(“10647_1_TestResult.docx”)

I attached the source and result document here: 10647.zip (18.3 KB)

When doing a PageBreak in Microsoft Word itself (Ctrl + Return), the PageBreak will be applied properly. At least for Microsoft Office Word 2019.

Can you confirm this? Is there another way to achieve my goal?

Regards

Mark

@bruegmann

You want to replace the text {PAGEBREAK} with page break. In this case, you need to use ControlChar.PageBreak instead of &m. If you want to find page break in the document, you can use &m.

In your document {PAGEBREAK} is in the table’s cell. If you insert page break in the table using MS Word, the table is split into two tables. To achieve the same output, you need to implement IReplacingCallback interface and split the table in IReplacingCallback.Replacing method. Following method splits the table using row index. Hope this helps you.

public static void SplitTable(Table table, int rowindex)
{
    Table newTable = (Table)table.Clone(true);
    table.ParentNode.InsertAfter(newTable, table);
    int rowcount = table.Rows.Count;

    for (int i = 0; i < rowindex; i++)
    {
        newTable.Rows[i].Remove();
    }

    for (int i = rowindex; i < rowcount; i++)
    {
        table.Rows[i].Remove();
    }

    Paragraph separator = new Paragraph(table.Document);
    table.ParentNode.InsertAfter(separator, table);
}

I am not sure if it helps me.

The “&m” character is working when used inside the replacement parameter. It is only not working when the “&m” is inside a table cell.

Also the documentation says, that the “&m” MetadataCharacter can be used in both search pattern and replacement string.

So I do not know if the the “&m” should not work inside the replacement parameter in generally or the work around, you posted above, should be used automatically inside of the (Aspose)Replacement method.

Either way, I would love to get some clarification about it because the behavior is a bit inconsistent.

Kindly regards

Mark

Yes, you can use “&m” in pattern and replacement string.

Yes, in this case, the replacement will not work. As shared in my previous post, this case is related to insertion of page break inside table’s cell. To achieve the desired output, please implement IReplacingCallback interface as shown in following code example.

Document doc = new Document(MyDir + "10647_1.docx");
FindReplaceOptions options = new FindReplaceOptions();
options.ReplacingCallback = new FindandSplitTable();
doc.Range.Replace("{PAGEBREAK}", "&m", options);
doc.Save(MyDir + "19.4.docx");

class FindandSplitTable : IReplacingCallback
{
    ReplaceAction IReplacingCallback.Replacing(ReplacingArgs e)
    {
        Node currentNode = e.MatchNode;
        if (currentNode.GetAncestor(NodeType.Row) != null)
        {
            Row row = (Row)currentNode.GetAncestor(NodeType.Row);
            int index = row.ParentTable.Rows.IndexOf(row);
            SplitTable(row.ParentTable, index);
        }
                
        e.Replacement = "";
        return ReplaceAction.Replace;
    }
}

I have implemented your snippets but they do not deliver the desired output.

The table is separated correctly but inserting a Paragraph is not adding a page break. But this helped me out. Or is there a better way meanwhile?

That being solved, the “{PAGEBREAK}” content is not replaced with String.Empty but remains.

Can you confirm that?

Regards Mark

@bruegmann,

We are checking this scenario and will get back to you soon.

@bruegmann,

Please use the following line of code before saving the document to get the desired output.

doc.Range.Replace("{PAGEBREAK}", "", new FindReplaceOptions());

Ok. So you say that I need to call the Replace() method twice? One time for finding the word and split the Table and a second time to find the word and actually replace it?

@bruegmann,

The code example shared in this thread splits the table into two tables by cloning Table node. So, yes you need to call Range.Replace method twice. Moreover, you may call Range.Replace method in SplitTable method for table node.

Ok.

I cannot call it from within the IReplacingCallback.Replacing or SplitTable method because I do not have the information about the used pattern parameter.

Sure for a simple string pattern I could use the Aspose.Words.Replacing.ReplacingArgs.Match.Value property but for a RegEx pattern this value is wrong.

It would be nice if you could provide these informations within the Aspose.Words.Replacing.ReplacingArgs class like this (or in an extra class “ReplacementPattern” that contains these properties):

/// <summary>
/// Return the pattern for the replacement operation.
/// </summary>
public string Pattern { get; }
/// <summary>
/// Returns whether the <see cref="Pattern"/> was used within a 
/// regular expression or not.
/// </summary>
public bool IsRegularExpression { get; }

In the meantime I will implement such properties in my project on my own.

@bruegmann,

You can simply add these properties in the class that implements IReplacingCallback interface. You can set the values of these properties for your class before using FindReplaceOptions.ReplacingCallback property.

That is what I tried to say with “In the meantime I will implement such properties in my project on my own.”.

I was just suggesting, that these properties would be important to other users, too. Because now everyone has to add these properties on their own.

Anyways. It is working now. I appreciate your help. Thank you!

Unfortunately I run into an error (NullReferenceException) while applying the workaround on the attached word document. I also tested it with Aspose.Words 19.5 but the result stays the same.

This line causes the error:

int index = row.ParentTable.Rows.IndexOf(row);

The ParentTable property is null when the Replacing(ReplacingArgs e) is called for the second time. The text inside of the cell is “|>SV<|24.05.2013”. Please not that the {PAGEBRAK} pattern changed to |>SV<|.

Can you confirm that?

10647_2.zip (6.1 KB)

@bruegmann,

Please call Document.UpdatePageLayout method before calling Range.Replace second time.

If you still face problem, please create a standalone console application ( source code without compilation errors ) that helps us to reproduce your problem on our end and attach it here for testing. Please also share your input document for which you are facing this issue.

I already shared the document that causes the error here.

The UpdatePageLayout call has no effect. I attached an example console project. The command line arguments are:

"PATH_TO_FILE" "|>SV<|" "&m"

Test.Console.Aspose.zip (6.6 KB)

@bruegmann,

In this case, we suggest you please find the desired text and insert bookmarks. Iterate over the inserted bookmarks and split the table. We have modified the code example and attach it with this post for your kind reference.
Test.Console.Aspose.zip (6.9 KB)