OfficeIMO icon indicating copy to clipboard operation
OfficeIMO copied to clipboard

How to align page number in Footer

Open hisuwh opened this issue 1 year ago • 7 comments

I have seen how you can add page numbers to the footer using .AddPageNumber() but how can I position this with other content I have in the footer.

We have done this in the header by using a table (I'm not sure if there is a better way):

wordDocument.AddHeadersAndFooters();
var headerTable = wordDocument.Header.Default.AddTable(1, 3, WordTableStyle.TableNormal);
headerTable.WidthType = TableWidthUnitValues.Pct;
headerTable.Width = WordTableGenerator.OneHundredPercentWidth;

var para = headerTable.Rows[0].Cells[0].AddParagraph();
para.AddImage(headerLogo, "logo.png", targetWidth, targetHeight);
para.ParagraphAlignment = JustificationValues.Left;

var header = headerTable.Rows[0].Cells[1].AddParagraph(headerText);
header.ParagraphAlignment = JustificationValues.Center;

I can't do this in the Footer as the AddPageNumber method is only available on the WordFooter type. So I have to do this:

var footer = wordDocument.Footer.Default.AddParagraph(footerText);
footer.ParagraphAlignment = JustificationValues.Center;

var pageNumber = wordDocument.Footer.Default.AddPageNumber(WordPageNumberStyle.PageNumberXofY);
pageNumber.ParagraphAlignment = JustificationValues.Right;

Meaning I end up with my footer text on one line and the Page Number on another - rather than side by side in one Row as I would prefer.

image

hisuwh avatar Jul 13 '23 18:07 hisuwh

Well, the way to do it is to expand AddPageNumber to work on Paragraphs, rather then on Documents directly, and use same method as you use for header with a table. I guess poor implementation on my side, that would require fixing. Or you can use Fields, as after all it's all field codes

image

There's no direct way now. So you either have to fix my implementation that will work with both document and paragraph or build your own Paragraph with fields

namespace OfficeIMO.Examples.Word {
    internal static partial class Fields {
        internal static void Example_DocumentWithFields02(string folderPath, bool openWord) {
            Console.WriteLine("[*] Creating standard document with tables");
            string filePath = System.IO.Path.Combine(folderPath, "Document with Fields02.docx");
            using (WordDocument document = WordDocument.Create(filePath)) {
                var paragraph = document.AddParagraph("Basic paragraph");
                paragraph.ParagraphAlignment = JustificationValues.Center;

                document.AddParagraph();

                document.AddHeadersAndFooters();

                // added page number using fields which triggers fields refresh
                document.AddField(WordFieldType.NumPages);

                document.AddField(WordFieldType.Author);

                document.AddField(WordFieldType.GreetingLine);

                // added page number using dedicated way
                var pageNumber = document.Header.Default.AddPageNumber(WordPageNumberStyle.Roman);

                document.Save(openWord);
            }
        }
    }
}

for example:

namespace OfficeIMO.Examples.Word {
    internal static partial class Fields {
        internal static void Example_DocumentWithFields02(string folderPath, bool openWord) {
            Console.WriteLine("[*] Creating standard document with tables");
            string filePath = System.IO.Path.Combine(folderPath, "Document with Fields02.docx");
            using (WordDocument document = WordDocument.Create(filePath)) {
                var paragraph = document.AddParagraph("Basic paragraph");
                paragraph.ParagraphAlignment = JustificationValues.Center;

                document.AddParagraph();

                document.AddHeadersAndFooters();

                // added page number using fields which triggers fields refresh
                document.AddField(WordFieldType.Page).AddText(" of ").AddField(WordFieldType.NumPages);

                document.AddField(WordFieldType.Author);

                document.AddField(WordFieldType.GreetingLine);

                // added page number using dedicated way
                var pageNumber = document.Header.Default.AddPageNumber(WordPageNumberStyle.Roman);

                document.Save(openWord);
            }
        }
    }
}

image

And you can use fields anywhere

PrzemyslawKlys avatar Jul 13 '23 19:07 PrzemyslawKlys

Thanks for your prompt and thorough response.

I have tried doing it like this:

var footerTable = wordDocument.Footer.Default.AddTable(1, 3, WordTableStyle.TableNormal);
footerTable.WidthType = TableWidthUnitValues.Pct;
footerTable.Width = WordTableGenerator.OneHundredPercentWidth;

var footer = footerTable.Rows[0].Cells[1].AddParagraph(footerText);
footer.ParagraphAlignment = JustificationValues.Center;

var pageNumber = footerTable.Rows[0].Cells[2].AddParagraph();
pageNumber.ParagraphAlignment = JustificationValues.Right;

pageNumber
    .AddText("Page ")
    .AddField(WordFieldType.Page)
    .AddText(" of ")
    .AddField(WordFieldType.NumPages);

Which works: image

Except I get this pop up when I open the document: image

hisuwh avatar Jul 14 '23 08:07 hisuwh

Those are fields, which I guess need to be updated on open to be able to tell which page are those. I would guess this is by design. But if the same doesn't happen with the other way, there must be some difference for that.

PrzemyslawKlys avatar Jul 14 '23 08:07 PrzemyslawKlys

Yh with the standard .AddPageNumber method I didn't get that popup.

hisuwh avatar Jul 14 '23 08:07 hisuwh

Well then that needs investigation what is different and why one triggers and the other one doesn't. Probably better to fix 1st method to add to paragraph, but that requires some work.

PrzemyslawKlys avatar Jul 14 '23 08:07 PrzemyslawKlys

Do you know what's needed to achieve that - is it just a lot of refactoring? I would offer to help but I likely won't have much time - though with some guidance on what's needed it might be more possible.

hisuwh avatar Jul 14 '23 08:07 hisuwh

The code starts here:

https://github.com/EvotecIT/OfficeIMO/blob/470cef22a54c3d736e88c91bffc955b515e635c7/OfficeIMO.Word/WordFooter.cs#L57-L60

When you use it, it does this:

                document.AddHeadersAndFooters();
                document.Footer.Default.AddPageNumber(WordPageNumberStyle.PageNumberXofY);

image

Then if you add paragraphs there:

                document.AddHeadersAndFooters();
                document.Footer.Default.AddParagraph("Test1");
                document.Footer.Default.AddParagraph("Test2");
                document.Footer.Default.AddPageNumber(WordPageNumberStyle.PageNumberXofY);

image

That means we are basically applying it to last element in footer. Looking at how it behaves I would say you need to modify this line, and instead of appending it to footer directly, you would need to allow assigning it to last paragraph wherever you want..

https://github.com/EvotecIT/OfficeIMO/blob/470cef22a54c3d736e88c91bffc955b515e635c7/OfficeIMO.Word/WordPageNumber.cs#L101C47-L101C47

At least that's my guess, not tested.

PrzemyslawKlys avatar Jul 14 '23 08:07 PrzemyslawKlys