diff --git a/ClosedXML/Excel/PageSetup/XLHFItem.cs b/ClosedXML/Excel/PageSetup/XLHFItem.cs index 7e3ccda..1f03c36 100644 --- a/ClosedXML/Excel/PageSetup/XLHFItem.cs +++ b/ClosedXML/Excel/PageSetup/XLHFItem.cs @@ -6,13 +6,13 @@ { internal class XLHFItem : IXLHFItem { - private readonly XLWorksheet _worksheet; - public XLHFItem(XLWorksheet worksheet) + internal readonly XLHeaderFooter HeaderFooter; + public XLHFItem(XLHeaderFooter headerFooter) { - _worksheet = worksheet; + HeaderFooter = headerFooter; } - public XLHFItem(XLHFItem defaultHFItem, XLWorksheet worksheet) - :this(worksheet) + public XLHFItem(XLHFItem defaultHFItem, XLHeaderFooter headerFooter) + :this(headerFooter) { defaultHFItem.texts.ForEach(kp => texts.Add(kp.Key, kp.Value)); } @@ -42,7 +42,7 @@ { XLRichString richText = new XLRichString(text, XLWorkbook.DefaultStyle.Font, this); - var hfText = new XLHFText(richText, _worksheet); + var hfText = new XLHFText(richText, this); if (occurrence == XLHFOccurrence.AllPages) { AddTextToOccurrence(hfText, XLHFOccurrence.EvenPages); @@ -73,6 +73,8 @@ texts[occurrence].Add(hfText); else texts.Add(occurrence, new List { hfText }); + + this.HeaderFooter.Changed = true; } public IXLRichString AddText(XLHFPredefinedText predefinedText, XLHFOccurrence occurrence) diff --git a/ClosedXML/Excel/PageSetup/XLHFText.cs b/ClosedXML/Excel/PageSetup/XLHFText.cs index ed921ea..ea9d5a8 100644 --- a/ClosedXML/Excel/PageSetup/XLHFText.cs +++ b/ClosedXML/Excel/PageSetup/XLHFText.cs @@ -5,18 +5,31 @@ { internal class XLHFText { - private readonly XLWorksheet _worksheet; - public XLHFText(XLRichString richText, XLWorksheet worksheet) + private readonly XLHFItem _hfItem; + public XLHFText(XLRichString richText, XLHFItem hfItem) { RichText = richText; - _worksheet = worksheet; + _hfItem = hfItem; } public XLRichString RichText { get; private set; } public String GetHFText(String prevText) { + var wsFont = _hfItem.HeaderFooter.Worksheet.Style.Font; + + var isRichText = RichText.FontName != null && RichText.FontName != wsFont.FontName + || RichText.Bold != wsFont.Bold + || RichText.Italic != wsFont.Italic + || RichText.Strikethrough != wsFont.Strikethrough + || RichText.FontSize > 0 && Math.Abs(RichText.FontSize - wsFont.FontSize) > XLHelper.Epsilon + || RichText.VerticalAlignment != wsFont.VerticalAlignment + || RichText.Underline != wsFont.Underline + || !RichText.FontColor.Equals(wsFont.FontColor); + + if (!isRichText) + return RichText.Text; + StringBuilder sb = new StringBuilder(); - var wsFont = _worksheet.Style.Font; if (RichText.FontName != null && RichText.FontName != wsFont.FontName) sb.Append("&\"" + RichText.FontName); diff --git a/ClosedXML/Excel/PageSetup/XLHeaderFooter.cs b/ClosedXML/Excel/PageSetup/XLHeaderFooter.cs index 1da5789..18fe407 100644 --- a/ClosedXML/Excel/PageSetup/XLHeaderFooter.cs +++ b/ClosedXML/Excel/PageSetup/XLHeaderFooter.cs @@ -7,30 +7,35 @@ internal class XLHeaderFooter: IXLHeaderFooter { + public XLHeaderFooter(XLWorksheet worksheet) { - Left = new XLHFItem(worksheet); - Right = new XLHFItem(worksheet); - Center = new XLHFItem(worksheet); + this.Worksheet = worksheet; + Left = new XLHFItem(this); + Right = new XLHFItem(this); + Center = new XLHFItem(this); SetAsInitial(); } public XLHeaderFooter(XLHeaderFooter defaultHF, XLWorksheet worksheet) { + this.Worksheet = worksheet; defaultHF.innerTexts.ForEach(kp => innerTexts.Add(kp.Key, kp.Value)); - Left = new XLHFItem(defaultHF.Left as XLHFItem, worksheet); - Center = new XLHFItem(defaultHF.Center as XLHFItem, worksheet); - Right = new XLHFItem(defaultHF.Right as XLHFItem, worksheet); + Left = new XLHFItem(defaultHF.Left as XLHFItem, this); + Center = new XLHFItem(defaultHF.Center as XLHFItem, this); + Right = new XLHFItem(defaultHF.Right as XLHFItem, this); SetAsInitial(); } + internal readonly IXLWorksheet Worksheet; + public IXLHFItem Left { get; private set; } public IXLHFItem Center { get; private set; } public IXLHFItem Right { get; private set; } public String GetText(XLHFOccurrence occurrence) { - if (innerTexts.ContainsKey(occurrence)) return innerTexts[occurrence]; + //if (innerTexts.ContainsKey(occurrence)) return innerTexts[occurrence]; var retVal = String.Empty; var leftText = Left.GetText(occurrence); @@ -46,7 +51,19 @@ private Dictionary innerTexts = new Dictionary(); internal String SetInnerText(XLHFOccurrence occurrence, String text) - { + { + var parsedElements = ParseFormattedHeaderFooterText(text); + + if (parsedElements.Any(e => e.Position == 'L')) + this.Left.AddText(string.Join("\r\n", parsedElements.Where(e => e.Position == 'L').Select(e => e.Text).ToArray()), occurrence); + + if (parsedElements.Any(e => e.Position == 'C')) + this.Center.AddText(string.Join("\r\n", parsedElements.Where(e => e.Position == 'C').Select(e => e.Text).ToArray()), occurrence); + + if (parsedElements.Any(e => e.Position == 'R')) + this.Right.AddText(string.Join("\r\n", parsedElements.Where(e => e.Position == 'R').Select(e => e.Text).ToArray()), occurrence); + + if (innerTexts.ContainsKey(occurrence)) innerTexts[occurrence] = text; else @@ -55,6 +72,45 @@ return innerTexts[occurrence]; } + private struct ParsedHeaderFooterElement + { + public char Position; + public string Text; + } + + private static IEnumerable ParseFormattedHeaderFooterText(string text) + { + var parsedElements = new List(); + var currentPosition = 'L'; // default is LEFT + var hfElement = ""; + + for (int i = 0; i < text.Length; i++) + { + if (i < text.Length - 1 && text[i] == '&' && (new char[] { 'L', 'C', 'R' }.Contains(text[i + 1]))) + { + if ("" != hfElement) parsedElements.Add(new ParsedHeaderFooterElement() + { + Position = currentPosition, + Text = hfElement + }); + + currentPosition = text[i + 1]; + i += 2; + hfElement = ""; + } + + hfElement += text[i]; + } + + if ("" != hfElement) + parsedElements.Add(new ParsedHeaderFooterElement() + { + Position = currentPosition, + Text = hfElement + }); + return parsedElements; + } + private Dictionary _initialTexts; private Boolean _changed; diff --git a/ClosedXML_Tests/ClosedXML_Tests.csproj b/ClosedXML_Tests/ClosedXML_Tests.csproj index e822189..0d280d1 100644 --- a/ClosedXML_Tests/ClosedXML_Tests.csproj +++ b/ClosedXML_Tests/ClosedXML_Tests.csproj @@ -75,6 +75,7 @@ + diff --git a/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs b/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs new file mode 100644 index 0000000..d1748a9 --- /dev/null +++ b/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs @@ -0,0 +1,37 @@ +using ClosedXML.Excel; +using NUnit.Framework; +using System.IO; +using System.Linq; + +namespace ClosedXML_Tests.Excel +{ + [TestFixture] + public class HeaderFooterTests + { + [Test] + public void CanChangeWorksheetHeader() + { + var wb = new XLWorkbook(); + IXLWorksheet ws = wb.AddWorksheet("Sheet1"); + + ws.PageSetup.Header.Center.AddText("Initial page header", XLHFOccurrence.EvenPages); + + var ms = new MemoryStream(); + wb.SaveAs(ms); + + wb = new XLWorkbook(ms); + ws = wb.Worksheets.First(); + + ws.PageSetup.Header.Center.Clear(); + ws.PageSetup.Header.Center.AddText("Changed header", XLHFOccurrence.EvenPages); + + wb.SaveAs(ms); + + wb = new XLWorkbook(ms); + ws = wb.Worksheets.First(); + + var newHeader = ws.PageSetup.Header.Center.GetText(XLHFOccurrence.EvenPages); + Assert.AreEqual("Changed header", newHeader); + } + } +} \ No newline at end of file diff --git a/ClosedXML_Tests/Resource/Examples/PageSetup/HeaderFooters.xlsx b/ClosedXML_Tests/Resource/Examples/PageSetup/HeaderFooters.xlsx index 58263e9..3363190 100644 --- a/ClosedXML_Tests/Resource/Examples/PageSetup/HeaderFooters.xlsx +++ b/ClosedXML_Tests/Resource/Examples/PageSetup/HeaderFooters.xlsx Binary files differ