diff --git a/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj b/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj index 7ee3db4..2248b07 100644 --- a/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj +++ b/ClosedXML/ClosedXML/ClosedXML/ClosedXML.csproj @@ -130,6 +130,10 @@ + + + + diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/EnumConverter.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/EnumConverter.cs index 4f1b858..6f8e332 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/EnumConverter.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/EnumConverter.cs @@ -398,6 +398,42 @@ #endregion } } + public static PhoneticAlignmentValues ToOpenXml(this XLPhoneticAlignment value) + { + switch (value) + { + case XLPhoneticAlignment.Center : + return PhoneticAlignmentValues.Center; + case XLPhoneticAlignment.Distributed: + return PhoneticAlignmentValues.Distributed; + case XLPhoneticAlignment.Left: + return PhoneticAlignmentValues.Left; + case XLPhoneticAlignment.NoControl: + return PhoneticAlignmentValues.NoControl; + #region default + default: + throw new ApplicationException("Not implemented value!"); + #endregion + } + } + public static PhoneticValues ToOpenXml(this XLPhoneticType value) + { + switch (value) + { + case XLPhoneticType.FullWidthKatakana: + return PhoneticValues.FullWidthKatakana; + case XLPhoneticType.HalfWidthKatakana: + return PhoneticValues.HalfWidthKatakana; + case XLPhoneticType.Hiragana: + return PhoneticValues.Hiragana; + case XLPhoneticType.NoConversion: + return PhoneticValues.NoConversion; + #region default + default: + throw new ApplicationException("Not implemented value!"); + #endregion + } + } #endregion #region To ClosedXml public static XLFontUnderlineValues ToClosedXml(this UnderlineValues value) @@ -792,6 +828,42 @@ #endregion } } + public static XLPhoneticAlignment ToClosedXml(this PhoneticAlignmentValues value) + { + switch (value) + { + case PhoneticAlignmentValues.Center: + return XLPhoneticAlignment.Center; + case PhoneticAlignmentValues.Distributed: + return XLPhoneticAlignment.Distributed; + case PhoneticAlignmentValues.Left: + return XLPhoneticAlignment.Left; + case PhoneticAlignmentValues.NoControl: + return XLPhoneticAlignment.NoControl; + #region default + default: + throw new ApplicationException("Not implemented value!"); + #endregion + } + } + public static XLPhoneticType ToClosedXml(this PhoneticValues value) + { + switch (value) + { + case PhoneticValues.FullWidthKatakana: + return XLPhoneticType.FullWidthKatakana; + case PhoneticValues.HalfWidthKatakana: + return XLPhoneticType.HalfWidthKatakana; + case PhoneticValues.Hiragana: + return XLPhoneticType.Hiragana; + case PhoneticValues.NoConversion: + return XLPhoneticType.NoConversion; + #region default + default: + throw new ApplicationException("Not implemented value!"); + #endregion + } + } #endregion } } \ No newline at end of file diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLPhonetic.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLPhonetic.cs new file mode 100644 index 0000000..a38a5c1 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLPhonetic.cs @@ -0,0 +1,11 @@ +using System; + +namespace ClosedXML.Excel +{ + public interface IXLPhonetic: IEquatable + { + String Text { get; set; } + Int32 Start { get; set; } + Int32 End { get; set; } + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLPhonetics.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLPhonetics.cs new file mode 100644 index 0000000..31022b3 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLPhonetics.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace ClosedXML.Excel +{ + public enum XLPhoneticAlignment { Center, Distributed, Left, NoControl } + public enum XLPhoneticType { FullWidthKatakana, HalfWidthKatakana, Hiragana, NoConversion } + public interface IXLPhonetics : IXLFontBase, IEnumerable, IEquatable + { + IXLPhonetics SetBold(); IXLPhonetics SetBold(Boolean value); + IXLPhonetics SetItalic(); IXLPhonetics SetItalic(Boolean value); + IXLPhonetics SetUnderline(); IXLPhonetics SetUnderline(XLFontUnderlineValues value); + IXLPhonetics SetStrikethrough(); IXLPhonetics SetStrikethrough(Boolean value); + IXLPhonetics SetVerticalAlignment(XLFontVerticalTextAlignmentValues value); + IXLPhonetics SetShadow(); IXLPhonetics SetShadow(Boolean value); + IXLPhonetics SetFontSize(Double value); + IXLPhonetics SetFontColor(IXLColor value); + IXLPhonetics SetFontName(String value); + IXLPhonetics SetFontFamilyNumbering(XLFontFamilyNumberingValues value); + + IXLPhonetics Add(String text, Int32 start, Int32 end); + IXLPhonetics ClearText(); + IXLPhonetics ClearFont(); + Int32 Count { get; } + + XLPhoneticAlignment Alignment { get; set; } + XLPhoneticType Type { get; set; } + + IXLPhonetics SetAlignment(XLPhoneticAlignment phoneticAlignment); + IXLPhonetics SetType(XLPhoneticType phoneticType); + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichText.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichText.cs index 8a0ab6b..9832a7e 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichText.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichText.cs @@ -3,7 +3,7 @@ namespace ClosedXML.Excel { - public interface IXLRichText : IEnumerable + public interface IXLRichText : IEnumerable, IEquatable { Boolean Bold { set; } Boolean Italic { set; } @@ -29,12 +29,15 @@ IXLRichString AddText(String text); IXLRichString AddText(String text, IXLFontBase font); - IXLRichText Clear(); + IXLRichText ClearText(); + IXLRichText ClearFont(); IXLRichText Substring(Int32 index); IXLRichText Substring(Int32 index, Int32 length); Int32 Count { get; } Int32 Length { get; } - + String Text { get; } + IXLPhonetics Phonetics { get; } + Boolean HasPhonetics { get; } } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLPhonetic.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLPhonetic.cs new file mode 100644 index 0000000..73118c4 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLPhonetic.cs @@ -0,0 +1,25 @@ +using System; + +namespace ClosedXML.Excel +{ + internal class XLPhonetic: IXLPhonetic + { + public XLPhonetic(String text, Int32 start, Int32 end) + { + Text = text; + Start = start; + End = end; + } + public String Text { get; set; } + public Int32 Start { get; set; } + public Int32 End { get; set; } + + public bool Equals(IXLPhonetic other) + { + if (other == null) + return false; + + return Text == other.Text && Start == other.Start && End == other.End; + } + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLPhonetics.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLPhonetics.cs new file mode 100644 index 0000000..b120bb8 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLPhonetics.cs @@ -0,0 +1,110 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +namespace ClosedXML.Excel +{ + internal class XLPhonetics : IXLPhonetics + { + private List phonetics = new List(); + + IXLFontBase m_defaultFont; + public XLPhonetics(IXLFontBase defaultFont) + { + m_defaultFont = defaultFont; + Type = XLPhoneticType.FullWidthKatakana; + Alignment = XLPhoneticAlignment.Left; + ClearFont(); + } + + public Boolean Bold { get; set; } + public Boolean Italic { get; set; } + public XLFontUnderlineValues Underline { get; set; } + public Boolean Strikethrough { get; set; } + public XLFontVerticalTextAlignmentValues VerticalAlignment { get; set; } + public Boolean Shadow { get; set; } + public Double FontSize { get; set; } + public IXLColor FontColor { get; set; } + public String FontName { get; set; } + public XLFontFamilyNumberingValues FontFamilyNumbering { get; set; } + + public IXLPhonetics SetBold() { Bold = true; return this; } public IXLPhonetics SetBold(Boolean value) { Bold = value; return this; } + public IXLPhonetics SetItalic() { Italic = true; return this; } public IXLPhonetics SetItalic(Boolean value) { Italic = value; return this; } + public IXLPhonetics SetUnderline() { Underline = XLFontUnderlineValues.Single; return this; } public IXLPhonetics SetUnderline(XLFontUnderlineValues value) { Underline = value; return this; } + public IXLPhonetics SetStrikethrough() { Strikethrough = true; return this; } public IXLPhonetics SetStrikethrough(Boolean value) { Strikethrough = value; return this; } + public IXLPhonetics SetVerticalAlignment(XLFontVerticalTextAlignmentValues value) { VerticalAlignment = value; return this; } + public IXLPhonetics SetShadow() { Shadow = true; return this; } public IXLPhonetics SetShadow(Boolean value) { Shadow = value; return this; } + public IXLPhonetics SetFontSize(Double value) { FontSize = value; return this; } + public IXLPhonetics SetFontColor(IXLColor value) { FontColor = value; return this; } + public IXLPhonetics SetFontName(String value) { FontName = value; return this; } + public IXLPhonetics SetFontFamilyNumbering(XLFontFamilyNumberingValues value) { FontFamilyNumbering = value; return this; } + + public IXLPhonetics Add(String text, Int32 start, Int32 end) + { + phonetics.Add(new XLPhonetic(text, start, end)); + return this; + } + public IXLPhonetics ClearText() + { + phonetics.Clear(); + return this; + } + public IXLPhonetics ClearFont() + { + Bold = m_defaultFont.Bold; + Italic = m_defaultFont.Italic; + Underline = m_defaultFont.Underline; + Strikethrough = m_defaultFont.Strikethrough; + VerticalAlignment = m_defaultFont.VerticalAlignment; + Shadow = m_defaultFont.Shadow; + FontSize = m_defaultFont.FontSize; + FontColor = new XLColor(m_defaultFont.FontColor); + FontName = m_defaultFont.FontName; + FontFamilyNumbering = m_defaultFont.FontFamilyNumbering; + return this; + } + public Int32 Count { get { return phonetics.Count; } } + + public XLPhoneticAlignment Alignment { get; set; } + public XLPhoneticType Type { get; set; } + + public IXLPhonetics SetAlignment(XLPhoneticAlignment phoneticAlignment) { Alignment = phoneticAlignment; return this; } + public IXLPhonetics SetType(XLPhoneticType phoneticType) { Type = phoneticType; return this; } + + public IEnumerator GetEnumerator() + { + return phonetics.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public bool Equals(IXLPhonetics other) + { + if (other == null) + return false; + + Int32 phoneticsCount = phonetics.Count; + for (Int32 i = 0; i < phoneticsCount; i++) + { + if (!phonetics[i].Equals(other.ElementAt(i))) + return false; + } + + return + Bold == other.Bold + && Italic == other.Italic + && Underline == other.Underline + && Strikethrough == other.Strikethrough + && VerticalAlignment == other.VerticalAlignment + && Shadow == other.Shadow + && FontSize == other.FontSize + && FontColor.Equals(other.FontColor) + && FontName == other.FontName + && FontFamilyNumbering == other.FontFamilyNumbering + ; + } + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichText.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichText.cs index f834a47..ecb7c0b 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichText.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichText.cs @@ -5,7 +5,7 @@ namespace ClosedXML.Excel { - internal class XLRichText: IXLRichText, IEquatable + internal class XLRichText: IXLRichText { List richTexts = new List(); @@ -46,12 +46,19 @@ m_length += richText.Text.Length; return richText; } - public IXLRichText Clear() + public IXLRichText ClearText() { richTexts.Clear(); m_length = 0; return this; } + public IXLRichText ClearFont() + { + String text = Text; + ClearText(); + AddText(text); + return this; + } public override string ToString() { @@ -153,7 +160,26 @@ return false; } - return true; + if (phonetics == null) + return true; + else + return Phonetics.Equals(other.Phonetics); } + + public String Text { get { return ToString(); } } + + private IXLPhonetics phonetics; + public IXLPhonetics Phonetics + { + get + { + if (phonetics == null) + phonetics = new XLPhonetics(m_defaultFont); + + return phonetics; + } + } + + public Boolean HasPhonetics { get { return phonetics != null; } } } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs index 99f9ff4..1fe7564 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs @@ -13,7 +13,7 @@ { } - public XLFont(IXLStylized container, IXLFont defaultFont) + public XLFont(IXLStylized container, IXLFontBase defaultFont) { this.container = container; if (defaultFont != null) diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWSContentManager.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWSContentManager.cs index ae9cc29..d2e8bc7 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWSContentManager.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWSContentManager.cs @@ -55,46 +55,46 @@ public XLWSContentManager(Worksheet opWorksheet) { - contents.Add(XLWSContents.SheetProperties, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SheetDimension, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SheetViews, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SheetFormatProperties, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.Columns, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SheetData, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SheetCalculationProperties, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SheetProtection, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.ProtectedRanges, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.Scenarios, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.AutoFilter, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SortState, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.DataConsolidate, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.CustomSheetViews, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.MergeCells, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.PhoneticProperties, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.ConditionalFormatting, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.DataValidations, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.Hyperlinks, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.PrintOptions, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.PageMargins, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.PageSetup, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.HeaderFooter, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.RowBreaks, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.ColumnBreaks, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.CustomProperties, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.CellWatches, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.IgnoredErrors, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.SmartTags, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.Drawing, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.LegacyDrawing, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.LegacyDrawingHeaderFooter, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.DrawingHeaderFooter, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.Picture, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.OleObjects, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.Controls, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.AlternateContent, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.WebPublishItems, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.TableParts, opWorksheet.Elements().FirstOrDefault()); - contents.Add(XLWSContents.WorksheetExtensionList, opWorksheet.Elements().FirstOrDefault()); + contents.Add(XLWSContents.SheetProperties, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SheetDimension, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SheetViews, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SheetFormatProperties, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.Columns, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SheetData, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SheetCalculationProperties, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SheetProtection, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.ProtectedRanges, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.Scenarios, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.AutoFilter, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SortState, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.DataConsolidate, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.CustomSheetViews, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.MergeCells, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.PhoneticProperties, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.ConditionalFormatting, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.DataValidations, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.Hyperlinks, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.PrintOptions, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.PageMargins, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.PageSetup, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.HeaderFooter, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.RowBreaks, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.ColumnBreaks, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.CustomProperties, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.CellWatches, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.IgnoredErrors, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.SmartTags, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.Drawing, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.LegacyDrawing, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.LegacyDrawingHeaderFooter, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.DrawingHeaderFooter, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.Picture, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.OleObjects, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.Controls, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.AlternateContent, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.WebPublishItems, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.TableParts, opWorksheet.Elements().LastOrDefault()); + contents.Add(XLWSContents.WorksheetExtensionList, opWorksheet.Elements().LastOrDefault()); } public void SetElement(XLWSContents content, OpenXmlElement element) diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Load.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Load.cs index ca23648..ed1b163 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Load.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Load.cs @@ -368,10 +368,14 @@ if (!StringExtensions.IsNullOrWhiteSpace(dCell.CellValue.Text)) { SharedStringItem sharedString = sharedStrings[Int32.Parse(dCell.CellValue.Text)]; - var runElements = sharedString.Elements(); - if (runElements.Any()) + + var runs = sharedString.Elements(); + var phoneticRuns = sharedString.Elements(); + var phoneticProperties = sharedString.Elements(); + if (runs.Any()) { - foreach (var run in runElements) + #region Load Runs + foreach (var run in runs) { var runProperties = run.RunProperties; String text = run.Text.InnerText.Replace("\n", Environment.NewLine); @@ -383,52 +387,34 @@ else { var rt = xlCell.RichText.AddText(text); - rt.Bold = GetBoolean(runProperties.Elements().FirstOrDefault()); - var fontColor = GetColor(runProperties.Elements().FirstOrDefault()); - if (fontColor.HasValue) - rt.FontColor = fontColor; - - var fontFamilyNumbering = runProperties.Elements().FirstOrDefault(); - if (fontFamilyNumbering != null && fontFamilyNumbering.Val != null) - rt.FontFamilyNumbering = (XLFontFamilyNumberingValues)Int32.Parse(fontFamilyNumbering.Val.ToString()); - var runFont = runProperties.Elements().FirstOrDefault(); - if (runFont != null) - { - if (runFont.Val != null) - rt.FontName = runFont.Val; - } - var fontSize = runProperties.Elements().FirstOrDefault(); - if (fontSize != null) - { - if (((FontSize)fontSize).Val != null) - rt.FontSize = ((FontSize)fontSize).Val; - } - - rt.Italic = GetBoolean(runProperties.Elements().FirstOrDefault()); - rt.Shadow = GetBoolean(runProperties.Elements().FirstOrDefault()); - rt.Strikethrough = GetBoolean(runProperties.Elements().FirstOrDefault()); - - var underline = runProperties.Elements().FirstOrDefault(); - if (underline != null) - if (underline.Val != null) - rt.Underline = underline.Val.Value.ToClosedXml(); - else - rt.Underline = XLFontUnderlineValues.Single; - - var verticalTextAlignment = runProperties.Elements().FirstOrDefault(); - if (verticalTextAlignment != null) - - if (verticalTextAlignment.Val != null) - rt.VerticalAlignment = verticalTextAlignment.Val.Value.ToClosedXml(); - else - rt.VerticalAlignment = XLFontVerticalTextAlignmentValues.Baseline; + LoadFont(runProperties, rt); } } + #endregion } else { - xlCell.m_cellValue = sharedString.InnerText; + xlCell.m_cellValue = sharedString.Text.InnerText; } + + #region Load PhoneticProperties + if (phoneticProperties.Any()) + { + var pp = phoneticProperties.First(); + if (pp.Alignment != null) + xlCell.RichText.Phonetics.Alignment = pp.Alignment.Value.ToClosedXml(); + if (pp.Type != null) + xlCell.RichText.Phonetics.Type = pp.Type.Value.ToClosedXml(); + + LoadFont(pp, xlCell.RichText.Phonetics); + } + #endregion + #region Load Phonetic Runs + foreach (var pr in phoneticRuns) + { + xlCell.RichText.Phonetics.Add(pr.Text.InnerText, (Int32)pr.BaseTextStartIndex.Value, (Int32)pr.EndingBaseIndex.Value); + } + #endregion } else xlCell.m_cellValue = dCell.CellValue.Text; @@ -483,6 +469,49 @@ } } + private void LoadFont(OpenXmlElement fontSource, IXLFontBase fontBase) + { + fontBase.Bold = GetBoolean(fontSource.Elements().FirstOrDefault()); + var fontColor = GetColor(fontSource.Elements().FirstOrDefault()); + if (fontColor.HasValue) + fontBase.FontColor = fontColor; + + var fontFamilyNumbering = fontSource.Elements().FirstOrDefault(); + if (fontFamilyNumbering != null && fontFamilyNumbering.Val != null) + fontBase.FontFamilyNumbering = (XLFontFamilyNumberingValues)Int32.Parse(fontFamilyNumbering.Val.ToString()); + var runFont = fontSource.Elements().FirstOrDefault(); + if (runFont != null) + { + if (runFont.Val != null) + fontBase.FontName = runFont.Val; + } + var fontSize = fontSource.Elements().FirstOrDefault(); + if (fontSize != null) + { + if (((FontSize)fontSize).Val != null) + fontBase.FontSize = ((FontSize)fontSize).Val; + } + + fontBase.Italic = GetBoolean(fontSource.Elements().FirstOrDefault()); + fontBase.Shadow = GetBoolean(fontSource.Elements().FirstOrDefault()); + fontBase.Strikethrough = GetBoolean(fontSource.Elements().FirstOrDefault()); + + var underline = fontSource.Elements().FirstOrDefault(); + if (underline != null) + if (underline.Val != null) + fontBase.Underline = underline.Val.Value.ToClosedXml(); + else + fontBase.Underline = XLFontUnderlineValues.Single; + + var verticalTextAlignment = fontSource.Elements().FirstOrDefault(); + if (verticalTextAlignment != null) + + if (verticalTextAlignment.Val != null) + fontBase.VerticalAlignment = verticalTextAlignment.Val.Value.ToClosedXml(); + else + fontBase.VerticalAlignment = XLFontVerticalTextAlignmentValues.Baseline; + } + private void LoadRows(Stylesheet s, NumberingFormats numberingFormats, Fills fills, Borders borders, Fonts fonts, XLWorksheet ws, SharedStringItem[] sharedStrings, Dictionary sharedFormulasR1C1, Dictionary styleList, Row row) { var xlRow = (XLRow)ws.Row((Int32)row.RowIndex.Value, false); diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs index aad77cc..fc40876 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs @@ -19,6 +19,8 @@ [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Dictionary m_sharedStyles; [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private readonly Dictionary m_sharedFonts; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly HashSet m_tableNames; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private uint m_tableId; @@ -28,6 +30,7 @@ { m_relIdGenerator = new RelIdGenerator(); m_sharedStyles = new Dictionary(); + m_sharedFonts = new Dictionary(); m_tableNames = new HashSet(); m_tableId = 0; } @@ -43,6 +46,11 @@ [DebuggerStepThrough] get { return m_sharedStyles; } } + public Dictionary SharedFonts + { + [DebuggerStepThrough] + get { return m_sharedFonts; } + } public HashSet TableNames { [DebuggerStepThrough] diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs index 0fd6ca1..5c946d0 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs @@ -148,7 +148,7 @@ workbookPart.AddNewPart( context.RelIdGenerator.GetNext(RelType.Workbook)); - GenerateSharedStringTablePartContent(sharedStringTablePart); + GenerateSharedStringTablePartContent(sharedStringTablePart, context); WorkbookStylesPart workbookStylesPart = workbookPart.WorkbookStylesPart ?? workbookPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); @@ -683,7 +683,7 @@ } } - private void GenerateSharedStringTablePartContent(SharedStringTablePart sharedStringTablePart) + private void GenerateSharedStringTablePartContent(SharedStringTablePart sharedStringTablePart, SaveContext context) { sharedStringTablePart.SharedStringTable = new SharedStringTable() { Count = 0, UniqueCount = 0 }; @@ -751,6 +751,35 @@ sharedStringItem.Append(run); } + if (c.RichText.HasPhonetics) + { + foreach (var p in c.RichText.Phonetics) + { + PhoneticRun phoneticRun = new PhoneticRun() + { + BaseTextStartIndex = (UInt32)p.Start, + EndingBaseIndex = (UInt32)p.End + }; + + Text text = new Text(); + text.Text = p.Text; + + phoneticRun.Append(text); + sharedStringItem.Append(phoneticRun); + } + var f = new XLFont(null, c.RichText.Phonetics); + context.SharedFonts.Add(f, new FontInfo() { Font = f }); + + PhoneticProperties phoneticProperties = new PhoneticProperties() { + FontId = context.SharedFonts[new XLFont(null, c.RichText.Phonetics)].FontId + }; + if (c.RichText.Phonetics.Alignment != XLPhoneticAlignment.Left) + phoneticProperties.Alignment = c.RichText.Phonetics.Alignment.ToOpenXml(); + if (c.RichText.Phonetics.Type != XLPhoneticType.FullWidthKatakana) + phoneticProperties.Type = c.RichText.Phonetics.Type.ToOpenXml(); + + sharedStringItem.Append(phoneticProperties); + } sharedStringTablePart.SharedStringTable.Append(sharedStringItem); sharedStringTablePart.SharedStringTable.Count += 1; @@ -785,7 +814,6 @@ c.SharedStringId = stringId; stringId++; - } } } @@ -796,8 +824,8 @@ private void GenerateWorkbookStylesPartContent(WorkbookStylesPart workbookStylesPart, SaveContext context) { var defaultStyle = new XLStyle(null, DefaultStyle); - Dictionary sharedFonts = new Dictionary(); - sharedFonts.Add(defaultStyle.Font, new FontInfo {FontId = 0, Font = defaultStyle.Font}); + if (!context.SharedFonts.ContainsKey(defaultStyle.Font)) + context.SharedFonts.Add(defaultStyle.Font, new FontInfo { FontId = 0, Font = defaultStyle.Font }); Dictionary sharedFills = new Dictionary(); sharedFills.Add(defaultStyle.Fill, new FillInfo {FillId = 2, Fill = defaultStyle.Fill}); @@ -889,9 +917,9 @@ foreach (var xlStyle in xlStyles) { - if (!sharedFonts.ContainsKey(xlStyle.Font)) + if (!context.SharedFonts.ContainsKey(xlStyle.Font)) { - sharedFonts.Add(xlStyle.Font, new FontInfo {FontId = fontCount++, Font = xlStyle.Font}); + context.SharedFonts.Add(xlStyle.Font, new FontInfo { FontId = fontCount++, Font = xlStyle.Font }); } if (!sharedFills.ContainsKey(xlStyle.Fill)) @@ -913,7 +941,7 @@ } var allSharedNumberFormats = ResolveNumberFormats(workbookStylesPart, sharedNumberFormats); - var allSharedFonts = ResolveFonts(workbookStylesPart, sharedFonts); + ResolveFonts(workbookStylesPart, context); var allSharedFills = ResolveFills(workbookStylesPart, sharedFills); var allSharedBorders = ResolveBorders(workbookStylesPart, sharedBorders); @@ -936,7 +964,7 @@ { StyleId = styleCount++, Style = xlStyle, - FontId = allSharedFonts[xlStyle.Font].FontId, + FontId = context.SharedFonts[xlStyle.Font].FontId, FillId = allSharedFills[xlStyle.Fill].FillId, BorderId = allSharedBorders[xlStyle.Border].BorderId, NumberFormatId = numberFormatId @@ -1464,15 +1492,15 @@ return nF.Equals(xlFill); } - private Dictionary ResolveFonts(WorkbookStylesPart workbookStylesPart, Dictionary sharedFonts) + private void ResolveFonts(WorkbookStylesPart workbookStylesPart, SaveContext context) { if (workbookStylesPart.Stylesheet.Fonts == null) { workbookStylesPart.Stylesheet.Fonts = new Fonts(); } - var allSharedFonts = new Dictionary(); - foreach (var fontInfo in sharedFonts.Values) + var newFonts = new Dictionary(); + foreach (var fontInfo in context.SharedFonts.Values) { Int32 fontId = 0; Boolean foundOne = false; @@ -1490,10 +1518,13 @@ Font font = GetNewFont(fontInfo); workbookStylesPart.Stylesheet.Fonts.AppendChild(font); } - allSharedFonts.Add(fontInfo.Font, new FontInfo {Font = fontInfo.Font, FontId = (UInt32) fontId}); + newFonts.Add(fontInfo.Font, new FontInfo { Font = fontInfo.Font, FontId = (UInt32)fontId }); } + context.SharedFonts.Clear(); + foreach (var kp in newFonts) + context.SharedFonts.Add(kp.Key, kp.Value); + workbookStylesPart.Stylesheet.Fonts.Count = (UInt32) workbookStylesPart.Stylesheet.Fonts.Count(); - return allSharedFonts; } private Font GetNewFont(FontInfo fontInfo) diff --git a/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj b/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj index acaeccc..488d995 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj +++ b/ClosedXML/ClosedXML/ClosedXML_Net3.5/ClosedXML_Net3.5.csproj @@ -358,12 +358,24 @@ Excel\Ranges\XLRanges.cs + + Excel\RichText\IXLPhonetic.cs + + + Excel\RichText\IXLPhonetics.cs + Excel\RichText\IXLRichString.cs Excel\RichText\IXLRichText.cs + + Excel\RichText\XLPhonetic.cs + + + Excel\RichText\XLPhonetics.cs + Excel\RichText\XLRichString.cs diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/RichText/XLRichStringTest.cs b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/RichText/XLRichStringTest.cs index efa7e23..80adfea 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/RichText/XLRichStringTest.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/RichText/XLRichStringTest.cs @@ -86,7 +86,7 @@ actual = richString.ToString(); Assert.AreEqual(expected, actual); - richString.Clear(); + richString.ClearText(); expected = String.Empty; actual = richString.ToString(); Assert.AreEqual(expected, actual); @@ -710,7 +710,7 @@ richString.AddText(" "); richString.AddText("World!"); - richString.Clear(); + richString.ClearText(); String expected = String.Empty; String actual = richString.ToString(); Assert.AreEqual(expected, actual);