Fix/Calculate Header Footer Height while Replacing Footer Content in Word DOCX ODT Documents Dynamically using C# .NET

@RCAtWork,

Sure, please let us know if you have any troubles and we will be glad to look into this further for you.

1 Like

Thanks - working through it now. Its working out sometimes. I’m now trying to fix it for all pages. There are documents with different footer sections. Its working out for “footer section 1”, but doesn’t replace “footer section 2” onwards. Any ideas where I can change your code to fix this?

I reckon its got something to do with your comment “lets not process other footers at the moment”

@RCAtWork,

We are working on your query and will get back to you soon.

1 Like

Thanks Awais, I really appreciate it.

@RCAtWork,

Please check if the following code is acceptable for you?

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

LayoutEnumerator enumerator = new LayoutEnumerator(doc);

for (int pageIndex = 0; pageIndex < doc.PageCount; pageIndex++)
{
    MarkHeaderFooterBoundaries(enumerator);
    enumerator.MoveNext();
}

doc.UpdatePageLayout();

Node[] lines = doc.GetChildNodes(NodeType.Shape, true).ToArray();
foreach (Shape line in lines)
{
    if (line.AlternativeText.Equals("RemoveMe"))
    {
        PageSetup pageSetup = line.ParentParagraph.ParentSection.PageSetup;
        Console.WriteLine("Footer's Top: " + line.Top + " and Height: " + (pageSetup.PageHeight - line.Top) + " points");

        HeaderFooter footer = (HeaderFooter)line.GetAncestor(NodeType.HeaderFooter);
        foreach (Run run in footer.GetChildNodes(NodeType.Run, true))
        {
            run.Remove();
        }

        Shape textBox = new Shape(doc, ShapeType.TextBox);
        textBox.Width = pageSetup.PageWidth - pageSetup.LeftMargin - pageSetup.RightMargin;
        textBox.Height = pageSetup.PageHeight - line.Top;
        // just to visualize our working area
        textBox.StrokeColor = Color.Green;
        textBox.StrokeWeight = 1;
        textBox.AppendChild(new Paragraph(doc));
        footer.FirstParagraph.AppendChild(textBox);
    }
    line.Remove();
}

doc.Save("E:\\Temp\\19.11.docx"); 

public static void MarkHeaderFooterBoundaries(LayoutEnumerator enumerator)
{
    do
    {
        if (enumerator.MoveLastChild())
        {
            MarkHeaderFooterBoundaries(enumerator);
            enumerator.MoveParent();
        }

        if (enumerator.Type == LayoutEntityType.HeaderFooter)
        {
            AddLine(enumerator);
        }

        // Stop after all elements on the page have been procesed.
        if (enumerator.Type == LayoutEntityType.Page)
            return;

    } while (enumerator.MovePrevious());
}

public static void AddLine(LayoutEnumerator enumerator)
{
    double top = 0;

    DocumentBuilder builder = new DocumentBuilder(enumerator.Document);
    if (enumerator.Kind.Equals("FIRSTPAGEFOOTER"))
    {
        builder.MoveToHeaderFooter(HeaderFooterType.FooterFirst);
        top = enumerator.Rectangle.Top;
    }
    else if (enumerator.Kind.Equals("PRIMARYFOOTER"))
    {
        builder.MoveToHeaderFooter(HeaderFooterType.FooterPrimary);
        top = enumerator.Rectangle.Top;
    }
    else if (enumerator.Kind.Equals("EVENPAGESFOOTER"))
    {
        builder.MoveToHeaderFooter(HeaderFooterType.FooterEven);
        top = enumerator.Rectangle.Top;
    }
    else
    {
        return;
    }

    HeaderFooter hf = (HeaderFooter)builder.CurrentStory;
    bool shapeAlreadyExists = false;
    foreach (Shape obj in hf.GetChildNodes(NodeType.Shape, true))
    {
        if (obj.AlternativeText.Equals("RemoveMe"))
        {
            shapeAlreadyExists = true;
            break;
        }
    }

    if (!shapeAlreadyExists)
    {
        Shape line = new Shape(enumerator.Document, ShapeType.Line);
        line.StrokeColor = Color.Red;
        line.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
        line.RelativeVerticalPosition = RelativeVerticalPosition.Page;
        line.WrapType = WrapType.None;
        line.AlternativeText = "RemoveMe";

        builder.InsertNode(line);

        line.Width = enumerator.Rectangle.Width;
        line.Left = 0;
        line.Top = top;
    }
}

Hi Awais,
The above changes don’t have the expected output. See attached simplified input. Note your code output only affects the first footer section.
Input and Output.zip (48.4 KB)

@RCAtWork,

The code is not able to process this document correctly because not all Sections have their own headers/footers. Some Sections have their ‘Link to Previous’ setting enabled. I think, you can modify/edit the source Word document i.e. disable ‘Link to Previous’ option and copy real headers/footers into those Sections. The code should then work fine. Please let me know if we can be of any further assistance.

Oh that’s unfortunate because it seems so close to being doable. I say this because If I remove the IF (!shapeAlreadyExists) I can see the output of every footer’s top and height on every page. Could I add this to a list with the top and height and page and then loop through every page and modify every footer. I know its not the best approach but it would help. Unfortunately I can’t remove the link to previous as these are controlled documents and we are only allowed to replace the footers.

@RCAtWork,

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

1 Like

Thanks Awais, I’m getting no where fast and this is a big issue for us. The reason I need the footer heights exactly is because the documents are large and have a lot of pictures in them. If I clear and set the footers and keep them to the same size what end up happening is that some pictures are clipped by the footer insead of going to the next page.

If you have any other alternatives I’d be delighted to try them.

@RCAtWork,

Please spare us some time for the investigation of this scenario. We will get back to you with our findings soon.

1 Like

Hi just wondering how you are getting on with this issue. It would be fantastic for us to get a solution.

If it makes things simpler I only need to replace the footer with text. Just as long as the footer height on each page doesn’t change.

@RCAtWork,

Thanks for the details. We will get back to you with our findings soon within a couple of days.

1 Like

@RCAtWork,

Thanks for being patient. But unfortunately, it is still not clear to us what is the ultimate goal of this usecase. MS Word documents are not fixed page documents. You normally provide content and MS Word will flow it to the pages on the fly. If you need to change footer content, then there is no point in fixing size of the footer. If you need fixed size then use section properties to specify that size. Use footer story of the section to specify content. If you really need to work in width + height + location on a page terms - you can use fixed page format - XPS or PDF. Just use the right tools for the job e.g. Aspose.PDF can be used to work with PDF files. MS Word document format is not designed for geometrical layout tasks like this. Please let us know if you need more information; we are always glad to help you.

Hi Awais,

We have 1000’s of documents which have been approved by an admin. When a non admin opens the document we want to be able to add text saying it was opened by X on Y date; somewhere (preferably on the footer). The problem is is that if I remove the footer and re-add our content the documents change, a line might go onto the next page or worse an image may become clipped.

@RCAtWork,

Thanks for the additional information. We have logged your requirement in our issue tracking system. Your ticket number is WORDSNET-19656. We will further look into the details of this requirement and will keep you updated on the status of the linked issue. We apologize for any inconvenience.

1 Like

In the mean time we have resorted to pre-pending a small bit of text on each footer. Its not ideal but it means we can move forward with the total solution.

@RCAtWork,

Thanks for being patient. Regarding WORDSNET-19656, we will also keep you posted on any further updates on this issue.

1 Like

@RCAtWork,

Regarding WORDSNET-19656, it is to update you that we have now closed this issue. A simple solution would be to just add a floating text box above existing text in the footer with the text. This will neither affect content nor size of the footer.

This approach does not require footer height calculation or removing the original document contents. I have attached 19656TextBox.zip (33.1 KB) demonstrating a transparent floating text box added to the footer.

MS Word document format is not designed to support the approach you are trying to implement. In general case, it is very difficult to replace some arbitrary content in the middle of the document without disturbing the layout of subsequent parts.

For example, there may be a wrapped floating object in the footer (shape, table, frame) positioned so that it overlaps the main story text. Main text will be wrapped around that floating object. Replacing the footer contents, even preserving the footer height most precisely, will still remove the floating object and main text will flow in a different way as a result. Even without floaters, the task is not trivial unless all your documents have a similar layout. We have decided to close this ticket without implementing the requested approach.

In case you have further inquiries or may need any help in future, please let us know.