EvotecIT / OfficeIMO

Fast and easy to use cross-platform .NET library that creates or modifies Microsoft Word (DocX) and later also Excel (XLSX) files without installing any software. Library is based on Open XML SDK
MIT License
263 stars 47 forks source link

Color applied to first paragraph in header/footer ignored #168

Closed hisuwh closed 8 months ago

hisuwh commented 8 months ago

Summary

We are trying to apply some colours to text in headers and footers. Though we are doing something slightly weird potentially in that we're adding a table to the header then. For some reason it's not applying the color to the first paragraph

Code

This is roughly what we're doing though I have simplified it to just show the sequence of calls to office IMO methods:

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

var header1 = headerTable.Rows[0].Cells[1].AddParagraph();
header.ParagraphAlignment = JustificationValues.Center;
var text1 = header1.AddText("Header 1");
text.ColorHex = "0000FF";

var header2 = headerTable.Rows[0].Cells[1].AddParagraph();
header.ParagraphAlignment = JustificationValues.Center;
var text2 = header2.AddText("Header 2");
text.ColorHex = "FF0000";

Screenshots

Header 1 should be blue Header 2 should be red

It seems to only be applying the style to the second paragraph.

Header: image

Footer: image

PrzemyslawKlys commented 8 months ago
string filePath = System.IO.Path.Combine(folderPath, "Basic Document with Headers and Footers Default.docx");
using (WordDocument document = WordDocument.Create(filePath)) {
    document.AddHeadersAndFooters();
    document.DifferentOddAndEvenPages = false;
    document.DifferentFirstPage = false;

    var headerTable = document.Header.Default.AddTable(1, 3, WordTableStyle.TableNormal);
    headerTable.WidthType = TableWidthUnitValues.Pct;
    headerTable.Style = WordTableStyle.GridTable1Light;

    var header1 = headerTable.Rows[0].Cells[1].AddParagraph();
    header1.ParagraphAlignment = JustificationValues.Center;
    var text1 = header1.AddText("Should be blue?");
    text1.ColorHex = "0000FF";

    var header2 = headerTable.Rows[0].Cells[1].AddParagraph();
    header2.ParagraphAlignment = JustificationValues.Center;
    var text2 = header2.AddText("Should be red?");
    text2.ColorHex = "FF0000";
    document.Save();
}

Gets me this:

image

Looks ok to me.

hisuwh commented 8 months ago

Am I loosing my mind, or are these two blocks of code identical: image

Looking at whats in the document at the breakpoint. There a lot of empty paragraphs, but the key one doesn't have a colour set:

: 
:
Should be blue? : 021766
:
Should be red? : f64c36
:
Header 1 : 
:
:
Header 2 : f64c36

Except one works and one doesn't: image

hisuwh commented 8 months ago

Ah I've solved it. "Header 1" was actually "Header 1\n" So I'm guessing AddText does some splitting and returns the last text block? If I trim the trailing \n then it gets the correct colour

hisuwh commented 8 months ago

Is there a way to style all the text regardless of the linebreaks within it though? As I can foresee that still being a requirement.

hisuwh commented 8 months ago

So this fails:

string filePath = System.IO.Path.Combine("C:\\temp", "Basic Document with Headers and Footers Default.docx");
using (WordDocument document = WordDocument.Create(filePath)) {
    document.AddHeadersAndFooters();
    document.DifferentOddAndEvenPages = false;
    document.DifferentFirstPage = false;

    var headerTable = document.Header.Default.AddTable(1, 3, WordTableStyle.TableNormal);
    headerTable.WidthType = TableWidthUnitValues.Pct;
    headerTable.Width = 5000;

    var headers = new List<(string, string)>
    {
        ("Should be blue?\n", "#0000FF"), // this is the problem
        ("Should be red?", "#FF0000")
    };

    foreach (var header in headers)
    {
        var headerRow = headerTable.Rows[0].Cells[1].AddParagraph();
        headerRow.ParagraphAlignment = JustificationValues.Center;
        var text = headerRow.AddText(header.Item1);
        text.ColorHex = header.Item2;
    }
    document.Save();
}
PrzemyslawKlys commented 8 months ago

Ye, as part of this PR:

I've added conversion of those \n and similar. It solved:

What you are seeing in your example is - there is already empty paragraph added in each cell. That means after you add 2 more there are 3.

image

So not only in your code \n adds another Run within Paragraph with break in it, but also you already have some more at each cell. Each run has it's own style.

So while the break doesn't do anything really, you have to be aware that it exists. In your case it's mostly that empty paragraph (paragraph 0) doing the hiding.

string filePath = System.IO.Path.Combine(folderPath, "Basic Document with Headers and Footers Default2.docx");
using (WordDocument document = WordDocument.Create(filePath)) {
    document.AddHeadersAndFooters();
    document.DifferentOddAndEvenPages = false;
    document.DifferentFirstPage = false;

    var headerTable = document.Header.Default.AddTable(1, 3, WordTableStyle.TableNormal);
    headerTable.WidthType = TableWidthUnitValues.Pct;
    headerTable.Width = 5000;

    var headers = new List<(string, string)>
    {
        ("Should be blue?\n", "#0000FF"), // this is the problem
        ("Should be red?", "#FF0000")
    };
    var count = 0;
    foreach (var header in headers) {
        var headerRow = headerTable.Rows[0].Cells[1].Paragraphs[count].SetText(header.Item1).SetColorHex(header.Item2);
        headerRow.ParagraphAlignment = JustificationValues.Center;
        headerRow.AddParagraph(); // probably some code to not add it if it's last in line
        count++;
    }
    document.Save();
}
hisuwh commented 8 months ago

Thanks @PrzemyslawKlys as always for being so responsive and helpful 🙇