How can I change orientation to landscape only in the pages of a word document that have tables?

ectD759.docx (95.7 KB)

Hi team. Please assist me with the following: I have a word document with some tables. It would be helpful if I could change the orientation of the pages that have tables. How can I change orientation only in the pages that have tables? I’ve seen your documentation on how to find tables in a Word document and change their orientation. I attach my input word document ectD759.docx

@panCognity MS Word documents are flow by their nature, so there is no “page” concept. Page orientation in MS Word document is specified per section. So in your case it is required to put the table into the separate section and then change it’s orientation. For example you ca use code like the following to achieve this:

Document doc = new Document(@"C:\Temp\in.docx");
            
// Loop through the tables in the document.
foreach(Table t in doc.GetChildNodes(NodeType.Table, true))
{
    // process only tables, which are direct children of body.
    if (t.ParentNode.NodeType != NodeType.Body)
        continue;

    Section currentSection = (Section)t.GetAncestor(NodeType.Section);
    // Clone the section where the table is located.
    // The table will be placed in this section.
    Section tableSection= (Section)currentSection.Clone(true);
    tableSection.Body.RemoveAllChildren();
    // Clone the section one more tyme to place content after the table.
    Section remainingContentSection = (Section)currentSection.Clone(true);
    remainingContentSection.Body.RemoveAllChildren();

    // Move content after the tale into a separate section.
    while (currentSection.Body.LastChild != t)
        remainingContentSection.Body.PrependChild(currentSection.Body.LastChild);

    // Move the table into the separate section.
    tableSection.Body.PrependChild(t);
    // Change the table section orientation.
    tableSection.PageSetup.Orientation = Aspose.Words.Orientation.Landscape;

    // Put the sections after the current section.
    currentSection.ParentNode.InsertAfter(remainingContentSection, currentSection);
    currentSection.ParentNode.InsertAfter(tableSection, currentSection);
}

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

I’ve read about sections, but the tables in my input .docx file were not in sections. I searched for ways to do that and then asked for your help. Thank you! I appreciate it! How can I remove a blank section (remove page with no text)? In the code you provided, it inserts a section after the table.
Also, I would like to change orientation in sections where placeholder contains the word kinhsh, e.g. [4040068980_Kinhsh]. How should I do that when I have this kind of placeholder?

@panCognity An empty page is produced y a page break, which is there after the table in your original document. The approach for placeholder is the same as for table. I have modified the code to handle placeholders and remove a redundant page breaks:

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

// Loop through the tables in the document.
foreach (Node n in doc.GetChildNodes(NodeType.Any, true))
{
    // process only nodes, which are direct children of body.
    if (n.ParentNode.NodeType != NodeType.Body)
        continue;

    if (n.NodeType == NodeType.Table ||
        (n.NodeType == NodeType.Paragraph && Regex.IsMatch(n.ToString(SaveFormat.Text).Trim(), @"\[\d+_Kinhsh\]", RegexOptions.IgnoreCase)))
    {
        Section currentSection = (Section)n.GetAncestor(NodeType.Section);
        // Clone the section where the table is located.
        // The table will be placed in this section.
        Section tableSection = (Section)currentSection.Clone(true);
        tableSection.Body.RemoveAllChildren();
        // Clone the section one more tyme to place content after the table.
        Section remainingContentSection = (Section)currentSection.Clone(true);
        remainingContentSection.Body.RemoveAllChildren();

        // Move content after the tale into a separate section.
        while (currentSection.Body.LastChild != n)
            remainingContentSection.Body.PrependChild(currentSection.Body.LastChild);

        // Move the table into the separate section.
        tableSection.Body.PrependChild(n);
        // Change the table section orientation.
        tableSection.PageSetup.Orientation = Aspose.Words.Orientation.Landscape;

        // Remove page break at the begining of the section.
        Run firstRun = (Run)remainingContentSection.Body.GetChild(NodeType.Run, 0, true);
        while (firstRun != null && firstRun.Text == ControlChar.PageBreak)
        {
            firstRun.Remove();
            firstRun = (Run)remainingContentSection.Body.GetChild(NodeType.Run, 0, true);
        }

        // Put the sections after the current section.
        currentSection.ParentNode.InsertAfter(remainingContentSection, currentSection);
        currentSection.ParentNode.InsertAfter(tableSection, currentSection);
    }
}

doc.Save(@"C:\Temp\out.docx");
1 Like

Thank you so much! :smile:

1 Like

I changed the regex to @"\[(\d+_Kinhsh)\]", but still cannot evaluate to true for the pattern of the placeholder. What is wrong with that? I tested the regular expression outside my application, in a tool and it seems right.

@panCognity Both regular expression works fine on my side and page orientation is changed to landscape.

I made this change with bold letters on purpose, just to check the regular expression. I now see it is evaluated
output_modified.docx (516.4 KB)

, but still cannot change page orientation. I attach the resulted output docx. Can you see anything strange in my code?

public static bool RotateSectionWithTableAndPlaceholder(Aspose.Words.Document tempDoc, string tempDirectory, ref bool error)
{
    try
    {
        // Loop through the tables in the document.
        foreach (Node n in tempEcrionDoc.GetChildNodes(NodeType.Any, true))
        {
            // process only nodes, which are direct children of body.
            if (n.ParentNode.NodeType != NodeType.Body)
                continue;
                string nString = n.ToString(SaveFormat.Text).Trim();
                bool regMatch = Regex.IsMatch(nString, @"\[\d+_Kinhsh\]", RegexOptions.IgnoreCase);

            if (n.NodeType == NodeType.Table ||
                (n.NodeType == NodeType.Paragraph && regMatch))
            {
                Section currentSection = (Section)n.GetAncestor(NodeType.Section);
                // Clone the section where the table is located.
                // The table will be placed in this section.
                Section tableSection = (Section)currentSection.Clone(true);
                tableSection.Body.RemoveAllChildren();
                // Clone the section one more tyme to place content after the table.
                Section remainingContentSection = (Section)currentSection.Clone(true);
                remainingContentSection.Body.RemoveAllChildren();

                // Move content after the tale into a separate section.
                while (currentSection.Body.LastChild != n)
                    remainingContentSection.Body.PrependChild(currentSection.Body.LastChild);

                // Move the table into the separate section.
                tableSection.Body.PrependChild(n);
                // Change the table section orientation.
                tableSection.PageSetup.Orientation = Aspose.Words.Orientation.Landscape;

                // Remove page break at the begining of the section.
                Run firstRun = (Run)remainingContentSection.Body.GetChild(NodeType.Run, 0, true);
                while (firstRun != null && firstRun.Text == ControlChar.PageBreak)
                {
                    firstRun.Remove();
                    firstRun = (Run)remainingContentSection.Body.GetChild(NodeType.Run, 0, true);
                }

                // Put the sections after the current section.
                currentSection.ParentNode.InsertAfter(remainingContentSection, currentSection);
                currentSection.ParentNode.InsertAfter(tableSection, currentSection);
            }
        }

        string tempFile = Path.GetFileNameWithoutExtension(tempDoc.OriginalFileName);

        tempEcrionDoc.Save(Path.Combine(tempDirectory, $"{tempFile}_modified.docx"));

        return false;
    }
    catch (Exception ex)
    {
        Log.Error($"Rotation error in file {tempDoc.OriginalFileName}|Reason: {ex.Message}");
        error = true;
        return true;
    }

}

@panCognity As I can see orientation of the page with placeholder is changed in your attached output:

Do you need to change page orientation for all pages with placeholders like [123455_abcde]? If so you can change the regular expression like this:

@"\[\d+_\w+\]"

In the output_modified.docx I have attached earlier, there are no pages with Landscape orientation in all placeholders containing word Kinhsh. I attach a screenshot. Where do you see this result?

@panCognity No, I do not see this. I see the result as shown on the screenshot attached earlier.

I see portrait in the section with placeholders containing Kinhsh. I send you my code. Can you please share again your code?

try
{
    // Loop through the tables in the document.
    foreach (Node n in tempEcrionDoc.GetChildNodes(NodeType.Any, true))
    {
        // process only nodes, which are direct children of body.
        if (n.ParentNode.NodeType != NodeType.Body)
            continue;
        string nString = n.ToString(SaveFormat.Text).Trim();
        bool regMatch = Regex.IsMatch(nString, @"\[\d+_Kinhsh\]", RegexOptions.IgnoreCase);

        if (n.NodeType == NodeType.Table ||
            (n.NodeType == NodeType.Paragraph && regMatch))
        {
            Section currentSection = (Section)n.GetAncestor(NodeType.Section);
            // Clone the section where the table is located.
            // The table will be placed in this section.
            Section tableSection = (Section)currentSection.Clone(true);
            tableSection.Body.RemoveAllChildren();
            // Clone the section one more tyme to place content after the table.
            Section remainingContentSection = (Section)currentSection.Clone(true);
            remainingContentSection.Body.RemoveAllChildren();

            // Move content after the tale into a separate section.
            while (currentSection.Body.LastChild != n)
                remainingContentSection.Body.PrependChild(currentSection.Body.LastChild);

            // Move the table into the separate section.
            tableSection.Body.PrependChild(n);
            // Change the table section orientation.
            tableSection.PageSetup.Orientation = Aspose.Words.Orientation.Landscape;
            if (n.NodeType == NodeType.Table)
            {
                tableSection.Body.Tables[0].AllowAutoFit = true;
                tableSection.Body.Tables[0].AutoFit(AutoFitBehavior.AutoFitToWindow);
            }
            // Remove page break at the begining of the section.
            Run firstRun = (Run)remainingContentSection.Body.GetChild(NodeType.Run, 0, true);
            while (firstRun != null && firstRun.Text == ControlChar.PageBreak)
            {
                firstRun.Remove();
                firstRun = (Run)remainingContentSection.Body.GetChild(NodeType.Run, 0, true);
            }

            // Put the sections after the current section.
            currentSection.ParentNode.InsertAfter(remainingContentSection, currentSection);
            currentSection.ParentNode.InsertAfter(tableSection, currentSection);
        }

    }

    string tempFile = Path.GetFileNameWithoutExtension(tempDoc.OriginalFileName);

    tempDoc.Save(Path.Combine(tempDirectory, $"{tempFile}_modified.docx"));

@panCognity I have used the code I posted earlier in this post.
The provided screenshot was made from the document you have shared in this post.

We don’t see the same result. I have Aspose.Words (23.10.0). I still see portrait in placeholders containing word Kinhsh. I attach the document again of my input and my output after my last run, in which i change also the width on the sections containing tables. What is wrong? I am wondering. I gave that piece of code to a collegue of mine to test it along with the input docx file and she doesn’t see any portrait in the sections with Placeholders Kinhsh also.
output_modified.docx (513.2 KB)
input.docx (256.1 KB)

I just saw. In the sections with placeholders containing the word Kinhsh, you will not find any landscape if you remove the paragraph mark. Can you see that?

@panCognity

Since the section with placeholder contains only one paragraph, where you remove paragraph break, the section break is also removed. The remaining content is added into the next section, which is portrait orientated. So this is expected.

In the attached document, I see proper landscape orientation of the page where Kinhsh placeholder is located.

Where is this?

Do you mean this part? This is where paragraph is removed?

@panCognity No, I mean removing paragraph break from the document manually in MS Word.

I cannot reproduce your problem on my side. Also, the output you have attached looks correct on my side as shown on the screenshots.

What can I say? My output differs from yours.

@panCognity Now I see the problem. It occurs because there are hidden paragraphs in your document. So the document view is different when view with shown hidden marks and without them. I view the document with show all hidden marks enabled.
Please try adding the following code before saving the document:

// Unhide hidden paragraphs.
doc.GetChildNodes(NodeType.Paragraph, true).Cast<Paragraph>().ToList()
    .ForEach(p => p.ParagraphBreakFont.Hidden = false);
1 Like