diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/IXLCell.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/IXLCell.cs index 14d713d..e5a162c 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/IXLCell.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/IXLCell.cs @@ -85,6 +85,8 @@ /// TimeSpan GetTimeSpan(); + IXLRichString GetRichText(); + /// /// Clears the contents of this cell (including styles). /// diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs index ec16788..90c8638 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Cells/XLCell.cs @@ -50,7 +50,15 @@ public XLAddress Address { get; internal set; } public String InnerText { - get { return StringExtensions.IsNullOrWhiteSpace(m_cellValue) ? FormulaA1 : m_cellValue; } + get + { + if (HasRichText) + return m_richText.ToString(); + else if (StringExtensions.IsNullOrWhiteSpace(m_cellValue)) + return FormulaA1; + else + return m_cellValue; + } } public IXLRange AsRange() { @@ -125,18 +133,16 @@ public T GetValue() { if (!StringExtensions.IsNullOrWhiteSpace(FormulaA1)) - { - return (T) Convert.ChangeType(String.Empty, typeof (T)); - } - if (Value is TimeSpan) - { - if (typeof (T) == typeof (String)) - { - return (T) Convert.ChangeType(Value.ToString(), typeof (T)); - } - return (T) Value; - } - return (T) Convert.ChangeType(Value, typeof (T)); + return (T)Convert.ChangeType(String.Empty, typeof(T)); + else if (Value is TimeSpan) + if (typeof(T) == typeof(String)) + return (T)Convert.ChangeType(Value.ToString(), typeof(T)); + else + return (T)Value; + else if (Value is IXLRichString) + return (T)RichText; + else + return (T)Convert.ChangeType(Value, typeof(T)); } public String GetString() { @@ -158,6 +164,10 @@ { return GetValue(); } + public IXLRichString GetRichText() + { + return RichText; + } public String GetFormattedString() { String cValue; @@ -1853,15 +1863,17 @@ m_richText = new XLRichString(m_style.Font); } else - { m_richText = new XLRichString(GetFormattedString(), m_style.Font); - } + m_dataType = XLCellValues.Text; + if (!Style.Alignment.WrapText) + Style.Alignment.WrapText = true; } return m_richText; } } + public Int32 SharedStringId; public Boolean HasRichText { get { return m_richText != null; } @@ -1876,4 +1888,4 @@ }; #endregion } -} \ No newline at end of file +} diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs index 15f94e3..9f763d1 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Columns/XLColumn.cs @@ -326,7 +326,7 @@ { Boolean isMerged = false; var cellAsRange = c.AsRange(); - foreach (var m in (Worksheet).Internals.MergedRanges) + foreach (var m in (Worksheet as XLWorksheet).Internals.MergedRanges) { if (cellAsRange.Intersects(m)) { @@ -337,46 +337,138 @@ if (!isMerged) { Int32 textRotation = c.Style.Alignment.TextRotation; - var f = (XLFont) c.Style.Font; - Double thisWidth; - if (textRotation == 0) + List> kpList = new List>(); + + if (c.HasRichText) { - thisWidth = f.GetWidth(c.GetFormattedString()); + foreach (var rt in c.RichText) + { + String formattedString = rt.Text; + var arr = formattedString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); + Int32 arrCount = arr.Count(); + for (Int32 i = 0; i < arrCount; i++) + { + String s = arr[i]; + if (i < arrCount - 1) + s += Environment.NewLine; + kpList.Add(new KeyValuePair(c.Style.Font, s)); + } + } } else { - if (textRotation == 255) + String formattedString = c.GetFormattedString(); + var arr = formattedString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); + Int32 arrCount = arr.Count(); + for (Int32 i = 0; i < arrCount; i++) { - thisWidth = f.GetWidth("X"); + String s = arr[i]; + if (i < arrCount - 1) + s += Environment.NewLine; + kpList.Add(new KeyValuePair(c.Style.Font, s)); } - else + } + + Double thisWidthMax = 0; + Double runningWidth = 0; + Boolean rotated = false; + Double rotationAdd = 0; + Double rotationMod = 0; + Double rotationIncrement = 0; + foreach (var kp in kpList) + { + IXLFontBase f = kp.Key; + String formattedString = kp.Value; + + Int32 newLinePosition = formattedString.IndexOf(Environment.NewLine); + if (textRotation == 0) { - Int32 rotation; - if (textRotation == 90 || textRotation == 180 || textRotation == 255) + if (newLinePosition >= 0) { - rotation = 90; + if (newLinePosition > 0) + runningWidth += f.GetWidth(formattedString.Substring(0, newLinePosition)); + + if (runningWidth > thisWidthMax) + thisWidthMax = runningWidth; + + if (newLinePosition < formattedString.Length - 2) + runningWidth = f.GetWidth(formattedString.Substring(newLinePosition + 2)); + else + runningWidth = 0; } else { - rotation = textRotation%90; + runningWidth += f.GetWidth(formattedString); } + } + else + { + if (textRotation == 255) + { + if (runningWidth == 0) + runningWidth = f.GetWidth("X"); - Double r = DegreeToRadian(rotation); - thisWidth = f.GetWidth(c.GetFormattedString())*Math.Cos(r) + Math.Sin(r)*f.GetWidth("X"); + if (newLinePosition >= 0) + runningWidth += f.GetWidth("X"); + } + else + { + rotated = true; + Double vWidth = f.GetWidth("X"); + if (vWidth > rotationAdd) + rotationAdd = vWidth; + + if (newLinePosition >= 0) + { + rotationIncrement += 0.5; + rotationMod += 2 + rotationIncrement; + + if (newLinePosition > 0) + runningWidth += f.GetWidth(formattedString.Substring(0, newLinePosition)); + + if (runningWidth > thisWidthMax) + thisWidthMax = runningWidth; + + if (newLinePosition < formattedString.Length - 2) + runningWidth = f.GetWidth(formattedString.Substring(newLinePosition + 2)); + else + runningWidth = 0; + + } + else + { + runningWidth += f.GetWidth(formattedString); + } + } } } - if (thisWidth > colMaxWidth) + if (runningWidth > thisWidthMax) + thisWidthMax = runningWidth; + + if (rotated) { - colMaxWidth = thisWidth; + Int32 rotation; + if (textRotation == 90 || textRotation == 180 || textRotation == 255) + rotation = 90; + else + rotation = textRotation % 90; + + Double r = DegreeToRadian(rotation); + if (rotationMod == 0) + rotationMod = 1; + thisWidthMax = (thisWidthMax * Math.Cos(r) + (Math.Sin(r) * rotationAdd * rotationMod)) + 1; } + + + + if (thisWidthMax > colMaxWidth) + colMaxWidth = thisWidthMax + 1; } } if (colMaxWidth == 0) - { colMaxWidth = Worksheet.ColumnWidth; - } Width = colMaxWidth; @@ -385,7 +477,7 @@ private double DegreeToRadian(double angle) { - return Math.PI*angle/180.0; + return Math.PI * angle / 180.0; } public IXLColumn AdjustToContents(Double minWidth, Double maxWidth) diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichString.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichString.cs index 71c7b93..2aae75e 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichString.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/IXLRichString.cs @@ -5,9 +5,36 @@ { public interface IXLRichString : IEnumerable { + Boolean Bold { set; } + Boolean Italic { set; } + XLFontUnderlineValues Underline { set; } + Boolean Strikethrough { set; } + XLFontVerticalTextAlignmentValues VerticalAlignment { set; } + Boolean Shadow { set; } + Double FontSize { set; } + IXLColor FontColor { set; } + String FontName { set; } + XLFontFamilyNumberingValues FontFamilyNumbering { set; } + + IXLRichString SetBold(); IXLRichString SetBold(Boolean value); + IXLRichString SetItalic(); IXLRichString SetItalic(Boolean value); + IXLRichString SetUnderline(); IXLRichString SetUnderline(XLFontUnderlineValues value); + IXLRichString SetStrikethrough(); IXLRichString SetStrikethrough(Boolean value); + IXLRichString SetVerticalAlignment(XLFontVerticalTextAlignmentValues value); + IXLRichString SetShadow(); IXLRichString SetShadow(Boolean value); + IXLRichString SetFontSize(Double value); + IXLRichString SetFontColor(IXLColor value); + IXLRichString SetFontName(String value); + IXLRichString SetFontFamilyNumbering(XLFontFamilyNumberingValues value); + IXLRichText AddText(String text); + IXLRichText AddText(String text, IXLFontBase font); IXLRichString Clear(); - IXLRichText Characters(Int32 index, Int32 length); + IXLRichString Substring(Int32 index); + IXLRichString Substring(Int32 index, Int32 length); Int32 Count { get; } + Int32 Length { get; } + + } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichString.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichString.cs index cf46eae..6524a0f 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichString.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/RichText/XLRichString.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; using System.Text; +using System.Linq; namespace ClosedXML.Excel { - internal class XLRichString: IXLRichString + internal class XLRichString: IXLRichString, IEquatable { List richTexts = new List(); @@ -21,15 +22,34 @@ } public Int32 Count { get { return richTexts.Count; } } + private Int32 m_length = 0; + public Int32 Length + { + get + { + return m_length; + } + } public IXLRichText AddText(String text) { - var richText = new XLRichText(text, m_defaultFont); + return AddText(text, m_defaultFont); + } + public IXLRichText AddText(String text, IXLFontBase font) + { + var richText = new XLRichText(text, font); + return AddText(richText); + } + + public IXLRichText AddText(IXLRichText richText) + { richTexts.Add(richText); + m_length += richText.Text.Length; return richText; } public IXLRichString Clear() { richTexts.Clear(); + m_length = 0; return this; } @@ -40,42 +60,53 @@ return sb.ToString(); } - public IXLRichText Characters(Int32 index, Int32 length) + public IXLRichString Substring(Int32 index) { + return Substring(index, m_length - index); + } + public IXLRichString Substring(Int32 index, Int32 length) + { + if (index + 1 > m_length || (m_length - index + 1) < length || length <= 0) + throw new IndexOutOfRangeException("Index and length must refer to a location within the string."); + List newRichTexts = new List(); - Int32 runningLength = 0; + XLRichString retVal = new XLRichString(m_defaultFont); + + Int32 lastPosition = 0; foreach (var rt in richTexts) { - if (runningLength + rt.Text.Length > index + 1) - { - Int32 startIndex = index - runningLength + 1; - if (startIndex > 0) - { - var newRT = new XLRichText(rt.Text.Substring(0, startIndex + 1), rt); - newRichTexts.Add(newRT); - } - - if (rt.Text.Length - startIndex + 1 >= length) - { - var newRT = new XLRichText(rt.Text.Substring(startIndex, length), rt); - newRichTexts.Add(newRT); - - if (rt.Text.Length > startIndex + length + 1) - { - newRichTexts.Add(new XLRichText(rt.Text.Substring(startIndex + length), rt)); - } - } - - - } - else + if (lastPosition >= index + 1 + length) // We already have what we need { newRichTexts.Add(rt); - runningLength += rt.Text.Length; } + else if (lastPosition + rt.Text.Length >= index + 1) // Eureka! + { + Int32 startIndex = index - lastPosition; + + if (startIndex > 0) + newRichTexts.Add(new XLRichText(rt.Text.Substring(0, startIndex), rt)); + else if (startIndex < 0) + startIndex = 0; + + Int32 leftToTake = length - retVal.Length; + if (leftToTake > rt.Text.Length - startIndex) + leftToTake = rt.Text.Length - startIndex; + + XLRichText newRT = new XLRichText(rt.Text.Substring(startIndex, leftToTake), rt); + newRichTexts.Add(newRT); + retVal.AddText(newRT); + + if (startIndex + leftToTake < rt.Text.Length) + newRichTexts.Add(new XLRichText(rt.Text.Substring(startIndex + leftToTake), rt)); + } + else // We haven't reached the desired position yet + { + newRichTexts.Add(rt); + } + lastPosition += rt.Text.Length; } richTexts = newRichTexts; - throw new NotImplementedException(); + return retVal; } public IEnumerator GetEnumerator() @@ -87,5 +118,42 @@ { return GetEnumerator(); } + + public Boolean Bold { set { richTexts.ForEach(rt => rt.Bold = value); } } + public Boolean Italic { set { richTexts.ForEach(rt => rt.Italic = value); } } + public XLFontUnderlineValues Underline { set { richTexts.ForEach(rt => rt.Underline = value); } } + public Boolean Strikethrough { set { richTexts.ForEach(rt => rt.Strikethrough = value); } } + public XLFontVerticalTextAlignmentValues VerticalAlignment { set { richTexts.ForEach(rt => rt.VerticalAlignment = value); } } + public Boolean Shadow { set { richTexts.ForEach(rt => rt.Shadow = value); } } + public Double FontSize { set { richTexts.ForEach(rt => rt.FontSize = value); } } + public IXLColor FontColor { set { richTexts.ForEach(rt => rt.FontColor = value); } } + public String FontName { set { richTexts.ForEach(rt => rt.FontName = value); } } + public XLFontFamilyNumberingValues FontFamilyNumbering { set { richTexts.ForEach(rt => rt.FontFamilyNumbering = value); } } + + public IXLRichString SetBold() { Bold = true; return this; } public IXLRichString SetBold(Boolean value) { Bold = value; return this; } + public IXLRichString SetItalic() { Italic = true; return this; } public IXLRichString SetItalic(Boolean value) { Italic = value; return this; } + public IXLRichString SetUnderline() { Underline = XLFontUnderlineValues.Single; return this; } public IXLRichString SetUnderline(XLFontUnderlineValues value) { Underline = value; return this; } + public IXLRichString SetStrikethrough() { Strikethrough = true; return this; } public IXLRichString SetStrikethrough(Boolean value) { Strikethrough = value; return this; } + public IXLRichString SetVerticalAlignment(XLFontVerticalTextAlignmentValues value) { VerticalAlignment = value; return this; } + public IXLRichString SetShadow() { Shadow = true; return this; } public IXLRichString SetShadow(Boolean value) { Shadow = value; return this; } + public IXLRichString SetFontSize(Double value) { FontSize = value; return this; } + public IXLRichString SetFontColor(IXLColor value) { FontColor = value; return this; } + public IXLRichString SetFontName(String value) { FontName = value; return this; } + public IXLRichString SetFontFamilyNumbering(XLFontFamilyNumberingValues value) { FontFamilyNumbering = value; return this; } + + public bool Equals(IXLRichString other) + { + Int32 count = Count; + if (count != other.Count) + return false; + + for (Int32 i = 0; i < count; i++) + { + if (richTexts.ElementAt(i) != other.ElementAt(i)) + return false; + } + + return true; + } } } diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs index 7de6c40..99f9ff4 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/Style/XLFont.cs @@ -232,38 +232,6 @@ #endregion - public Double GetWidth(String text) - { - if (StringExtensions.IsNullOrWhiteSpace(text)) - return 0; - - System.Drawing.Font stringFont = new System.Drawing.Font(fontName, (float)fontSize); - return GetWidth(stringFont, text); - } - private Double GetWidth(System.Drawing.Font stringFont, string text) - { - //String textToUse = new String('X', text.Length); - Size textSize = TextRenderer.MeasureText(text, stringFont); - double width = (double)(((textSize.Width / (double)7) * 256) - (128 / 7)) / 256; - width = (double)decimal.Round((decimal)width + 0.2M, 2); - - return width + 1; - } - - public Double GetHeight() - { - System.Drawing.Font stringFont = new System.Drawing.Font(fontName, (float)fontSize); - return GetHeight(stringFont); - } - - private Double GetHeight(System.Drawing.Font stringFont) - { - Size textSize = TextRenderer.MeasureText("X", stringFont); - var val = (double)textSize.Height * 0.85; - return val; - } - - public Boolean Equals(IXLFont other) { var otherF = other as XLFont; diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs index fd04cbc..e750fef 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook.cs @@ -408,27 +408,6 @@ return WorksheetsInternal.Worksheet(position); } - public HashSet GetSharedStrings() - { - HashSet modifiedStrings = new HashSet(); - foreach (var w in WorksheetsInternal) - { - foreach (var c in w.Internals.CellsCollection.Values) - { - if ( - c.DataType == XLCellValues.Text - && !StringExtensions.IsNullOrWhiteSpace(c.InnerText) - && c.ShareString - && !modifiedStrings.Contains(c.Value.ToString()) - ) - { - modifiedStrings.Add(c.Value.ToString()); - } - } - } - return modifiedStrings; - } - public IXLCustomProperty CustomProperty(String name) { return CustomProperties.CustomProperty(name); diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs index c11730f..aad77cc 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.NestedTypes.cs @@ -17,8 +17,6 @@ [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly RelIdGenerator m_relIdGenerator; [DebuggerBrowsable(DebuggerBrowsableState.Never)] - private readonly Dictionary m_sharedStrings; - [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly Dictionary m_sharedStyles; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly HashSet m_tableNames; @@ -29,7 +27,6 @@ public SaveContext() { m_relIdGenerator = new RelIdGenerator(); - m_sharedStrings = new Dictionary(); m_sharedStyles = new Dictionary(); m_tableNames = new HashSet(); m_tableId = 0; @@ -41,11 +38,6 @@ [DebuggerStepThrough] get { return m_relIdGenerator; } } - public Dictionary SharedStrings - { - [DebuggerStepThrough] - get { return m_sharedStrings; } - } public Dictionary SharedStyles { [DebuggerStepThrough] diff --git a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs index 047909c..fd99c28 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Excel/XLWorkbook_Save.cs @@ -115,11 +115,6 @@ { var context = new SaveContext(); - //sharedStrings = new Dictionary(); - //context.SharedStyles = new Dictionary(); - //tableNames = new HashSet(); - //tableId = 0; - WorkbookPart workbookPart = document.WorkbookPart ?? document.AddWorkbookPart(); var worksheets = WorksheetsInternal; @@ -153,7 +148,7 @@ workbookPart.AddNewPart( context.RelIdGenerator.GetNext(RelType.Workbook)); - GenerateSharedStringTablePartContent(sharedStringTablePart, context); + GenerateSharedStringTablePartContent(sharedStringTablePart); WorkbookStylesPart workbookStylesPart = workbookPart.WorkbookStylesPart ?? workbookPart.AddNewPart(context.RelIdGenerator.GetNext(RelType.Workbook)); @@ -688,31 +683,111 @@ } } - private void GenerateSharedStringTablePartContent(SharedStringTablePart sharedStringTablePart, SaveContext context) + private void GenerateSharedStringTablePartContent(SharedStringTablePart sharedStringTablePart) { - HashSet modifiedStrings = GetSharedStrings(); - - sharedStringTablePart.SharedStringTable = new SharedStringTable {Count = 0, UniqueCount = 0}; - - UInt32 stringCount = (UInt32) modifiedStrings.Count(); + sharedStringTablePart.SharedStringTable = new SharedStringTable() { Count = 0, UniqueCount = 0 }; Int32 stringId = 0; - foreach (var s in modifiedStrings) - { - SharedStringItem sharedStringItem = new SharedStringItem(); - Text text = new Text(); - text.Text = s; - if (s.StartsWith(" ") || s.EndsWith(" ")) - { - text.Space = SpaceProcessingModeValues.Preserve; - } - sharedStringItem.AppendChild(text); - sharedStringTablePart.SharedStringTable.AppendChild(sharedStringItem); - sharedStringTablePart.SharedStringTable.Count += 1; - sharedStringTablePart.SharedStringTable.UniqueCount += 1; - context.SharedStrings.Add(s, (UInt32) stringId); - stringId++; + Dictionary newStrings = new Dictionary(); + Dictionary newRichStrings = new Dictionary(); + foreach (var w in Worksheets.Cast()) + { + foreach (var c in w.Internals.CellsCollection.Values) + { + if ( + c.DataType == XLCellValues.Text + && c.ShareString + && !StringExtensions.IsNullOrWhiteSpace(c.InnerText)) + { + if (c.HasRichText) + { + if (newRichStrings.ContainsKey(c.RichText)) + { + c.SharedStringId = newRichStrings[c.RichText]; + } + else + { + + SharedStringItem sharedStringItem = new SharedStringItem(); + foreach (var rt in c.RichText) + { + var run = new A.Run(); + + var runProperties = new A.RunProperties(); + + Bold bold = rt.Bold ? new Bold() : null; + Italic italic = rt.Italic ? new Italic() : null; + Underline underline = rt.Underline != XLFontUnderlineValues.None ? new Underline() { Val = rt.Underline.ToOpenXml() } : null; + Strike strike = rt.Strikethrough ? new Strike() : null; + VerticalTextAlignment verticalAlignment = new VerticalTextAlignment() { Val = rt.VerticalAlignment.ToOpenXml() }; + Shadow shadow = rt.Shadow ? new Shadow() : null; + FontSize fontSize = new FontSize() { Val = rt.FontSize }; + Color color = GetNewColor(rt.FontColor); + FontName fontName = new FontName() { Val = rt.FontName }; + FontFamilyNumbering fontFamilyNumbering = new FontFamilyNumbering() { Val = (Int32)rt.FontFamilyNumbering }; + + if (bold != null) runProperties.Append(bold); + if (italic != null) runProperties.Append(italic); + if (underline != null) runProperties.Append(underline); + if (strike != null) runProperties.Append(strike); + runProperties.Append(verticalAlignment); + if (shadow != null) runProperties.Append(shadow); + runProperties.Append(fontSize); + runProperties.Append(color); + runProperties.Append(fontName); + runProperties.Append(fontFamilyNumbering); + + Text text = new Text(); + text.Text = rt.Text; + if (rt.Text.StartsWith(" ") || rt.Text.EndsWith(" ") || rt.Text.Contains(Environment.NewLine)) + text.Space = SpaceProcessingModeValues.Preserve; + + run.Append(runProperties); + run.Append(text); + + sharedStringItem.Append(run); + } + + + sharedStringTablePart.SharedStringTable.Append(sharedStringItem); + sharedStringTablePart.SharedStringTable.Count += 1; + sharedStringTablePart.SharedStringTable.UniqueCount += 1; + + newRichStrings.Add(c.RichText, stringId); + c.SharedStringId = stringId; + + stringId++; + } + } + else + { + if (newStrings.ContainsKey(c.Value.ToString())) + { + c.SharedStringId = newStrings[c.Value.ToString()]; + } + else + { + String s = c.Value.ToString(); + SharedStringItem sharedStringItem = new SharedStringItem(); + Text text = new Text(); + text.Text = s; + if (s.StartsWith(" ") || s.EndsWith(" ")) + text.Space = SpaceProcessingModeValues.Preserve; + sharedStringItem.Append(text); + sharedStringTablePart.SharedStringTable.Append(sharedStringItem); + sharedStringTablePart.SharedStringTable.Count += 1; + sharedStringTablePart.SharedStringTable.UniqueCount += 1; + + newStrings.Add(c.Value.ToString(), stringId); + c.SharedStringId = stringId; + + stringId++; + + } + } + } + } } } #region GenerateWorkbookStylesPartContent @@ -2223,7 +2298,7 @@ { if (opCell.ShareString) { - cellValue.Text = context.SharedStrings[opCell.InnerText].ToString(); + cellValue.Text = opCell.SharedStringId.ToString(); cell.CellValue = cellValue; } else diff --git a/ClosedXML/ClosedXML/ClosedXML/Extensions.cs b/ClosedXML/ClosedXML/ClosedXML/Extensions.cs index 2c327b6..dcaae48 100644 --- a/ClosedXML/ClosedXML/ClosedXML/Extensions.cs +++ b/ClosedXML/ClosedXML/ClosedXML/Extensions.cs @@ -4,9 +4,10 @@ using System.Globalization; using System.Linq; using System.Text; +using System.Windows.Forms; [assembly: CLSCompliantAttribute(true)] -namespace ClosedXML +namespace ClosedXML.Excel { public static class Extensions { @@ -138,5 +139,30 @@ return intToString[value]; } } + + public static class FontBaseExtensions + { + public static Double GetWidth(this IXLFontBase font, String text) + { + if (StringExtensions.IsNullOrWhiteSpace(text)) + return 0; + + System.Drawing.Font stringFont = new System.Drawing.Font(font.FontName, (float)font.FontSize); + + Size textSize = TextRenderer.MeasureText(text, stringFont); + double width = (double)(((textSize.Width / (double)7) * 256) - (128 / 7)) / 256; + width = (double)decimal.Round((decimal)width + 0.2M, 2); + + return width ; + } + + public static Double GetHeight(this IXLFontBase font) + { + System.Drawing.Font stringFont = new System.Drawing.Font(font.FontName, (float)font.FontSize); + Size textSize = TextRenderer.MeasureText("X", stringFont); + return (double)textSize.Height * 0.85; + } + + } } diff --git a/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/AdjustToContents.cs b/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/AdjustToContents.cs index 2b6dff3..bae56f4 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/AdjustToContents.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/AdjustToContents.cs @@ -89,6 +89,23 @@ ws2.Columns().AdjustToContents(); + var ws4 = wb.Worksheets.Add("Adjust Widths 2"); + ws4.Cell(1, 1).SetValue("Text to adjust - 255").Style.Alignment.TextRotation = 255; + for (Int32 co = 0; co < 90; co += 5) + { + var c = ws4.Cell(1, (co / 5) + 2); + + c.RichText.AddText("Text to adjust - " + co).SetBold(); + c.RichText.AddText(Environment.NewLine); + c.RichText.AddText("World!").SetBold().SetFontColor(XLColor.Blue).SetFontSize(10); + c.RichText.AddText(Environment.NewLine); + c.RichText.AddText("Hello Cruel and unsusual world").SetBold().SetFontSize(15); + c.RichText.AddText(Environment.NewLine); + c.RichText.AddText("Hello").SetBold(); + c.Style.Alignment.SetTextRotation(co); + } + ws4.Columns().AdjustToContents(); + var ws3 = wb.Worksheets.Add("Adjust Heights"); ws3.Cell(1, 1).SetValue("Text to adjust - 255").Style.Alignment.TextRotation = 255; for (Int32 ro = 0; ro < 90; ro += 5) @@ -98,6 +115,23 @@ ws3.Rows().AdjustToContents(); + var ws5 = wb.Worksheets.Add("Adjust Heights 2"); + ws5.Cell(1, 1).SetValue("Text to adjust - 255").Style.Alignment.TextRotation = 255; + for (Int32 ro = 0; ro < 90; ro += 5) + { + var c = ws5.Cell((ro / 5) + 2, 1); + c.RichText.AddText("Text to adjust - " + ro).SetBold(); + c.RichText.AddText(Environment.NewLine); + c.RichText.AddText("World!").SetBold().SetFontColor(XLColor.Blue).SetFontSize(10); + c.RichText.AddText(Environment.NewLine); + c.RichText.AddText("Hello Cruel and unsusual world").SetBold().SetFontSize(15); + c.RichText.AddText(Environment.NewLine); + c.RichText.AddText("Hello").SetBold(); + c.Style.Alignment.SetTextRotation(ro); + } + + ws5.Rows().AdjustToContents(); + wb.SaveAs(filePath); } diff --git a/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/ShowCase.cs b/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/ShowCase.cs index 3b9ba95..8281a6e 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/ShowCase.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Examples/Misc/ShowCase.cs @@ -86,14 +86,8 @@ // Put a label on the totals cell of the field "DOB" excelTable.Field("DOB").TotalsRowLabel = "Average:"; - //Add thick borders - // This range will contain the entire contents of our spreadsheet: - var firstCell = ws.FirstCellUsed(); - var lastCell = ws.LastCellUsed(); - var contents = ws.Range(firstCell.Address, lastCell.Address); - - //Add thick borders - contents.Style.Border.OutsideBorder = XLBorderStyleValues.Thick; + //Add thick borders to the contents of our spreadsheet + ws.RangeUsed().Style.Border.OutsideBorder = XLBorderStyleValues.Thick; // You can also specify the border for each side with: // contents.FirstColumn().Style.Border.LeftBorder = XLBorderStyleValues.Thick; diff --git a/ClosedXML/ClosedXML/ClosedXML_Examples/ModifyFiles.cs b/ClosedXML/ClosedXML/ClosedXML_Examples/ModifyFiles.cs index 83167c1..0e3983d 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Examples/ModifyFiles.cs +++ b/ClosedXML/ClosedXML/ClosedXML_Examples/ModifyFiles.cs @@ -6,7 +6,7 @@ { public static void Run() { - new DeleteRows().Create(@"C:\Excel Files\Modify\DeleteRows.xlsx"); + new DeleteRows().Create(@"C:\Excel Files\Modified\DeleteRows.xlsx"); } } } diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj b/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj index f0a28cb..f312bf5 100644 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/ClosedXML_Tests.csproj @@ -60,7 +60,7 @@ - + diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/RichText/XLRichStringTest.cs b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/RichText/XLRichStringTest.cs new file mode 100644 index 0000000..efa7e23 --- /dev/null +++ b/ClosedXML/ClosedXML/ClosedXML_Tests/Excel/RichText/XLRichStringTest.cs @@ -0,0 +1,735 @@ +using ClosedXML.Excel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Linq; +using System; + +namespace ClosedXML_Tests +{ + + + /// + ///This is a test class for XLRichStringTest and is intended + ///to contain all XLRichStringTest Unit Tests + /// + [TestClass()] + public class XLRichStringTest + { + + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //Use ClassCleanup to run code after all tests in a class have run + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //Use TestCleanup to run code after each test has run + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///A test for ToString + /// + [TestMethod()] + public void ToStringTest() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + richString.AddText(" "); + richString.AddText("World"); + string expected = "Hello World"; + string actual = richString.ToString(); + Assert.AreEqual(expected, actual); + + richString.AddText("!"); + expected = "Hello World!"; + actual = richString.ToString(); + Assert.AreEqual(expected, actual); + + richString.Clear(); + expected = String.Empty; + actual = richString.ToString(); + Assert.AreEqual(expected, actual); + } + + /// + ///A test for AddText + /// + [TestMethod()] + public void AddTextTest1() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var cell = ws.Cell(1, 1); + var richString = cell.RichText; + + string text = "Hello"; + richString.AddText(text).SetBold().SetFontColor(XLColor.Red); + + Assert.AreEqual(cell.GetString(), text); + Assert.AreEqual(cell.RichText.First().Bold, true); + Assert.AreEqual(cell.RichText.First().FontColor, XLColor.Red); + + Assert.AreEqual(1, richString.Count); + + richString.AddText("World"); + Assert.AreEqual(richString.First().Text, text, "Item in collection is not the same as the one returned"); + } + + [TestMethod()] + public void AddTextTest2() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var cell = ws.Cell(1, 1); + Int32 number = 123; + + cell.SetValue(number).Style + .Font.SetBold() + .Font.SetFontColor(XLColor.Red); + + string text = number.ToString(); + + Assert.AreEqual(cell.RichText.ToString(), text); + Assert.AreEqual(cell.RichText.First().Bold, true); + Assert.AreEqual(cell.RichText.First().FontColor, XLColor.Red); + + Assert.AreEqual(1, cell.RichText.Count); + + cell.RichText.AddText("World"); + Assert.AreEqual(cell.RichText.First().Text, text, "Item in collection is not the same as the one returned"); + } + + [TestMethod()] + public void AddTextTest3() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var cell = ws.Cell(1, 1); + Int32 number = 123; + cell.Value = number; + cell.Style + .Font.SetBold() + .Font.SetFontColor(XLColor.Red); + + string text = number.ToString(); + + Assert.AreEqual(cell.RichText.ToString(), text); + Assert.AreEqual(cell.RichText.First().Bold, true); + Assert.AreEqual(cell.RichText.First().FontColor, XLColor.Red); + + Assert.AreEqual(1, cell.RichText.Count); + + cell.RichText.AddText("World"); + Assert.AreEqual(cell.RichText.First().Text, text, "Item in collection is not the same as the one returned"); + } + + [TestMethod()] + public void HasRichTextTest1() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var cell = ws.Cell(1, 1); + cell.RichText.AddText("123"); + + Assert.AreEqual(true, cell.HasRichText); + + cell.DataType = XLCellValues.Text; + + Assert.AreEqual(true, cell.HasRichText); + + cell.DataType = XLCellValues.Number; + + Assert.AreEqual(false, cell.HasRichText); + + cell.RichText.AddText("123"); + + Assert.AreEqual(true, cell.HasRichText); + + cell.Value = 123; + + Assert.AreEqual(false, cell.HasRichText); + + cell.RichText.AddText("123"); + + Assert.AreEqual(true, cell.HasRichText); + + cell.SetValue("123"); + + Assert.AreEqual(false, cell.HasRichText); + + } + + [TestMethod()] + public void AccessRichTextTest1() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var cell = ws.Cell(1, 1); + cell.RichText.AddText("12"); + cell.DataType = XLCellValues.Number; + + Assert.AreEqual(12.0, cell.GetDouble()); + + var richText = cell.RichText; + + Assert.AreEqual("12", richText.ToString()); + + richText.AddText("34"); + + Assert.AreEqual("1234", cell.GetString()); + + Assert.AreEqual(XLCellValues.Text, cell.DataType); + + cell.DataType = XLCellValues.Number; + + Assert.AreEqual(1234.0, cell.GetDouble()); + + } + + /// + ///A test for Characters + /// + [TestMethod()] + public void Substring_All_From_OneString() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + + var actual = richString.Substring(0); + + Assert.AreEqual(richString.First(), actual.First()); + + Assert.AreEqual(1, actual.Count); + + actual.First().SetBold(); + + Assert.AreEqual(true, ws.Cell(1, 1).RichText.First().Bold); + } + + [TestMethod()] + public void Substring_From_OneString_Start() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + + var actual = richString.Substring(0, 2); + + Assert.AreEqual(1, actual.Count); // substring was in one piece + + Assert.AreEqual(2, richString.Count); // The text was split because of the substring + + Assert.AreEqual("He", actual.First().Text); + + Assert.AreEqual("He", richString.First().Text); + Assert.AreEqual("llo", richString.Last().Text); + + actual.First().SetBold(); + + Assert.AreEqual(true, ws.Cell(1, 1).RichText.First().Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.Last().Bold); + + richString.Last().SetItalic(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.First().Italic); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.Last().Italic); + + Assert.AreEqual(false, actual.First().Italic); + + richString.SetFontSize(20); + + Assert.AreEqual(20, ws.Cell(1, 1).RichText.First().FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.Last().FontSize); + + Assert.AreEqual(20, actual.First().FontSize); + } + + [TestMethod()] + public void Substring_From_OneString_End() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + + var actual = richString.Substring(2); + + Assert.AreEqual(1, actual.Count); // substring was in one piece + + Assert.AreEqual(2, richString.Count); // The text was split because of the substring + + Assert.AreEqual("llo", actual.First().Text); + + Assert.AreEqual("He", richString.First().Text); + Assert.AreEqual("llo", richString.Last().Text); + + actual.First().SetBold(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.First().Bold); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.Last().Bold); + + richString.Last().SetItalic(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.First().Italic); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.Last().Italic); + + Assert.AreEqual(true, actual.First().Italic); + + richString.SetFontSize(20); + + Assert.AreEqual(20, ws.Cell(1, 1).RichText.First().FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.Last().FontSize); + + Assert.AreEqual(20, actual.First().FontSize); + } + + [TestMethod()] + public void Substring_From_OneString_Middle() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + + var actual = richString.Substring(2, 2); + + Assert.AreEqual(1, actual.Count); // substring was in one piece + + Assert.AreEqual(3, richString.Count); // The text was split because of the substring + + Assert.AreEqual("ll", actual.First().Text); + + Assert.AreEqual("He", richString.First().Text); + Assert.AreEqual("ll", richString.ElementAt(1).Text); + Assert.AreEqual("o", richString.Last().Text); + + actual.First().SetBold(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.First().Bold); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(1).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.Last().Bold); + + richString.Last().SetItalic(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.First().Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Italic); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.Last().Italic); + + Assert.AreEqual(false, actual.First().Italic); + + richString.SetFontSize(20); + + Assert.AreEqual(20, ws.Cell(1, 1).RichText.First().FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(1).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.Last().FontSize); + + Assert.AreEqual(20, actual.First().FontSize); + } + + [TestMethod()] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void Substring_IndexOutsideRange1() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + + var richText = richString.Substring(50); + } + + [TestMethod()] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void Substring_IndexOutsideRange2() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + richString.AddText("World"); + + var richText = richString.Substring(50); + } + + [TestMethod()] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void Substring_IndexOutsideRange3() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + + var richText = richString.Substring(1, 10); + } + + [TestMethod()] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void Substring_IndexOutsideRange4() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + richString.AddText("World"); + + var richText = richString.Substring(5, 20); + } + + [TestMethod()] + public void Substring_All_From_ThreeStrings() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Good Morning"); + richString.AddText(" my "); + richString.AddText("neighbors!"); + + var actual = richString.Substring(0); + + Assert.AreEqual(richString.ElementAt(0), actual.ElementAt(0)); + Assert.AreEqual(richString.ElementAt(1), actual.ElementAt(1)); + Assert.AreEqual(richString.ElementAt(2), actual.ElementAt(2)); + + Assert.AreEqual(3, actual.Count); + Assert.AreEqual(3, richString.Count); + + actual.First().SetBold(); + + Assert.AreEqual(true, ws.Cell(1, 1).RichText.First().Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.Last().Bold); + } + + [TestMethod()] + public void Substring_From_ThreeStrings_Start1() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Good Morning"); + richString.AddText(" my "); + richString.AddText("neighbors!"); + + var actual = richString.Substring(0, 4); + + Assert.AreEqual(1, actual.Count); // substring was in one piece + + Assert.AreEqual(4, richString.Count); // The text was split because of the substring + + Assert.AreEqual("Good", actual.First().Text); + + Assert.AreEqual("Good", richString.ElementAt(0).Text); + Assert.AreEqual(" Morning", richString.ElementAt(1).Text); + Assert.AreEqual(" my ", richString.ElementAt(2).Text); + Assert.AreEqual("neighbors!", richString.ElementAt(3).Text); + + actual.First().SetBold(); + + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(0).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(3).Bold); + + richString.First().SetItalic(); + + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(0).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(3).Italic); + + Assert.AreEqual(true, actual.First().Italic); + + richString.SetFontSize(20); + + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(0).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(1).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(2).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(3).FontSize); + + Assert.AreEqual(20, actual.First().FontSize); + } + + [TestMethod()] + public void Substring_From_ThreeStrings_Start2() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Good Morning"); + richString.AddText(" my "); + richString.AddText("neighbors!"); + + var actual = richString.Substring(0, 15); + + Assert.AreEqual(2, actual.Count); + + Assert.AreEqual(4, richString.Count); // The text was split because of the substring + + Assert.AreEqual("Good Morning", actual.ElementAt(0).Text); + Assert.AreEqual(" my", actual.ElementAt(1).Text); + + Assert.AreEqual("Good Morning", richString.ElementAt(0).Text); + Assert.AreEqual(" my", richString.ElementAt(1).Text); + Assert.AreEqual(" ", richString.ElementAt(2).Text); + Assert.AreEqual("neighbors!", richString.ElementAt(3).Text); + + actual.ElementAt(1).SetBold(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(0).Bold); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(1).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(3).Bold); + + richString.First().SetItalic(); + + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(0).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(3).Italic); + + Assert.AreEqual(true, actual.ElementAt(0).Italic); + Assert.AreEqual(false, actual.ElementAt(1).Italic); + + richString.SetFontSize(20); + + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(0).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(1).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(2).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(3).FontSize); + + Assert.AreEqual(20, actual.ElementAt(0).FontSize); + Assert.AreEqual(20, actual.ElementAt(1).FontSize); + } + + [TestMethod()] + public void Substring_From_ThreeStrings_End1() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Good Morning"); + richString.AddText(" my "); + richString.AddText("neighbors!"); + + var actual = richString.Substring(21); + + Assert.AreEqual(1, actual.Count); // substring was in one piece + + Assert.AreEqual(4, richString.Count); // The text was split because of the substring + + Assert.AreEqual("bors!", actual.First().Text); + + Assert.AreEqual("Good Morning", richString.ElementAt(0).Text); + Assert.AreEqual(" my ", richString.ElementAt(1).Text); + Assert.AreEqual("neigh", richString.ElementAt(2).Text); + Assert.AreEqual("bors!", richString.ElementAt(3).Text); + + actual.First().SetBold(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(0).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Bold); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(3).Bold); + + richString.Last().SetItalic(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(0).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Italic); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(3).Italic); + + Assert.AreEqual(true, actual.First().Italic); + + richString.SetFontSize(20); + + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(0).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(1).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(2).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(3).FontSize); + + Assert.AreEqual(20, actual.First().FontSize); + } + + [TestMethod()] + public void Substring_From_ThreeStrings_End2() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Good Morning"); + richString.AddText(" my "); + richString.AddText("neighbors!"); + + var actual = richString.Substring(13); + + Assert.AreEqual(2, actual.Count); + + Assert.AreEqual(4, richString.Count); // The text was split because of the substring + + Assert.AreEqual("my ", actual.ElementAt(0).Text); + Assert.AreEqual("neighbors!", actual.ElementAt(1).Text); + + Assert.AreEqual("Good Morning", richString.ElementAt(0).Text); + Assert.AreEqual(" ", richString.ElementAt(1).Text); + Assert.AreEqual("my ", richString.ElementAt(2).Text); + Assert.AreEqual("neighbors!", richString.ElementAt(3).Text); + + actual.ElementAt(1).SetBold(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(0).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Bold); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Bold); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(3).Bold); + + richString.Last().SetItalic(); + + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(0).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(1).Italic); + Assert.AreEqual(false, ws.Cell(1, 1).RichText.ElementAt(2).Italic); + Assert.AreEqual(true, ws.Cell(1, 1).RichText.ElementAt(3).Italic); + + Assert.AreEqual(false, actual.ElementAt(0).Italic); + Assert.AreEqual(true, actual.ElementAt(1).Italic); + + richString.SetFontSize(20); + + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(0).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(1).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(2).FontSize); + Assert.AreEqual(20, ws.Cell(1, 1).RichText.ElementAt(3).FontSize); + + Assert.AreEqual(20, actual.ElementAt(0).FontSize); + Assert.AreEqual(20, actual.ElementAt(1).FontSize); + } + + [TestMethod()] + public void Substring_From_ThreeStrings_Mid1() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Good Morning"); + richString.AddText(" my "); + richString.AddText("neighbors!"); + + var actual = richString.Substring(5, 10); + + Assert.AreEqual(2, actual.Count); + + Assert.AreEqual(5, richString.Count); // The text was split because of the substring + + Assert.AreEqual("Morning", actual.ElementAt(0).Text); + Assert.AreEqual(" my", actual.ElementAt(1).Text); + + Assert.AreEqual("Good ", richString.ElementAt(0).Text); + Assert.AreEqual("Morning", richString.ElementAt(1).Text); + Assert.AreEqual(" my", richString.ElementAt(2).Text); + Assert.AreEqual(" ", richString.ElementAt(3).Text); + Assert.AreEqual("neighbors!", richString.ElementAt(4).Text); + } + + [TestMethod()] + public void Substring_From_ThreeStrings_Mid2() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Good Morning"); + richString.AddText(" my "); + richString.AddText("neighbors!"); + + var actual = richString.Substring(5, 15); + + Assert.AreEqual(3, actual.Count); + + Assert.AreEqual(5, richString.Count); // The text was split because of the substring + + Assert.AreEqual("Morning", actual.ElementAt(0).Text); + Assert.AreEqual(" my ", actual.ElementAt(1).Text); + Assert.AreEqual("neig", actual.ElementAt(2).Text); + + Assert.AreEqual("Good ", richString.ElementAt(0).Text); + Assert.AreEqual("Morning", richString.ElementAt(1).Text); + Assert.AreEqual(" my ", richString.ElementAt(2).Text); + Assert.AreEqual("neig", richString.ElementAt(3).Text); + Assert.AreEqual("hbors!", richString.ElementAt(4).Text); + } + + + /// + ///A test for Clear + /// + [TestMethod()] + public void ClearTest() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + richString.AddText(" "); + richString.AddText("World!"); + + richString.Clear(); + String expected = String.Empty; + String actual = richString.ToString(); + Assert.AreEqual(expected, actual); + + Assert.AreEqual(0, richString.Count); + } + + [TestMethod()] + public void CountTest() + { + var ws = new XLWorkbook().Worksheets.Add("Sheet1"); + var richString = ws.Cell(1, 1).RichText; + + richString.AddText("Hello"); + richString.AddText(" "); + richString.AddText("World!"); + + Assert.AreEqual(3, richString.Count); + } + + } +} diff --git a/ClosedXML/ClosedXML/ClosedXML_Tests/XLRichStringTest.cs b/ClosedXML/ClosedXML/ClosedXML_Tests/XLRichStringTest.cs deleted file mode 100644 index b46ab32..0000000 --- a/ClosedXML/ClosedXML/ClosedXML_Tests/XLRichStringTest.cs +++ /dev/null @@ -1,262 +0,0 @@ -using System; -using System.Linq; -using ClosedXML.Excel; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace ClosedXML_Tests -{ - /// - /// This is a test class for XLRichStringTest and is intended - /// to contain all XLRichStringTest Unit Tests - /// - [TestClass] - public class XLRichStringTest - { - private TestContext testContextInstance; - - /// - /// Gets or sets the test context which provides - /// information about and functionality for the current test run. - /// - public TestContext TestContext - { - get { return testContextInstance; } - set { testContextInstance = value; } - } - #region Additional test attributes - // - //You can use the following additional attributes as you write your tests: - // - //Use ClassInitialize to run code before running the first test in the class - //[ClassInitialize()] - //public static void MyClassInitialize(TestContext testContext) - //{ - //} - // - //Use ClassCleanup to run code after all tests in a class have run - //[ClassCleanup()] - //public static void MyClassCleanup() - //{ - //} - // - //Use TestInitialize to run code before running each test - //[TestInitialize()] - //public void MyTestInitialize() - //{ - //} - // - //Use TestCleanup to run code after each test has run - //[TestCleanup()] - //public void MyTestCleanup() - //{ - //} - // - #endregion - /// - /// A test for ToString - /// - [TestMethod] - public void ToStringTest() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var richString = ws.Cell(1, 1).RichText; - - richString.AddText("Hello"); - richString.AddText(" "); - richString.AddText("World"); - string expected = "Hello World"; - string actual = richString.ToString(); - Assert.AreEqual(expected, actual); - - richString.AddText("!"); - expected = "Hello World!"; - actual = richString.ToString(); - Assert.AreEqual(expected, actual); - - richString.Clear(); - expected = String.Empty; - actual = richString.ToString(); - Assert.AreEqual(expected, actual); - } - - /// - /// A test for AddText - /// - [TestMethod] - public void AddTextTest1() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var cell = ws.Cell(1, 1); - var richString = cell.RichText; - - string text = "Hello"; - richString.AddText(text).SetBold().SetFontColor(XLColor.Red); - - Assert.AreEqual(cell.GetString(), text); - Assert.AreEqual(cell.RichText.First().Bold, true); - Assert.AreEqual(cell.RichText.First().FontColor, XLColor.Red); - - Assert.AreEqual(1, richString.Count); - - richString.AddText("World"); - Assert.AreEqual(richString.First().Text, text, "Item in collection is not the same as the one returned"); - } - - [TestMethod] - public void AddTextTest2() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var cell = ws.Cell(1, 1); - Int32 number = 123; - - cell.SetValue(number).Style - .Font.SetBold() - .Font.SetFontColor(XLColor.Red); - - string text = number.ToString(); - - Assert.AreEqual(cell.RichText.ToString(), text); - Assert.AreEqual(cell.RichText.First().Bold, true); - Assert.AreEqual(cell.RichText.First().FontColor, XLColor.Red); - - Assert.AreEqual(1, cell.RichText.Count); - - cell.RichText.AddText("World"); - Assert.AreEqual(cell.RichText.First().Text, text, "Item in collection is not the same as the one returned"); - } - - [TestMethod] - public void AddTextTest3() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var cell = ws.Cell(1, 1); - Int32 number = 123; - cell.Value = number; - cell.Style - .Font.SetBold() - .Font.SetFontColor(XLColor.Red); - - string text = number.ToString(); - - Assert.AreEqual(cell.RichText.ToString(), text); - Assert.AreEqual(cell.RichText.First().Bold, true); - Assert.AreEqual(cell.RichText.First().FontColor, XLColor.Red); - - Assert.AreEqual(1, cell.RichText.Count); - - cell.RichText.AddText("World"); - Assert.AreEqual(cell.RichText.First().Text, text, "Item in collection is not the same as the one returned"); - } - - [TestMethod] - public void HasRichTextTest1() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var cell = ws.Cell(1, 1); - cell.RichText.AddText("123"); - - Assert.AreEqual(true, cell.HasRichText); - - cell.DataType = XLCellValues.Text; - - Assert.AreEqual(true, cell.HasRichText); - - cell.DataType = XLCellValues.Number; - - Assert.AreEqual(false, cell.HasRichText); - - cell.RichText.AddText("123"); - - Assert.AreEqual(true, cell.HasRichText); - - cell.Value = 123; - - Assert.AreEqual(false, cell.HasRichText); - - cell.RichText.AddText("123"); - - Assert.AreEqual(true, cell.HasRichText); - - cell.SetValue("123"); - - Assert.AreEqual(false, cell.HasRichText); - } - - [TestMethod] - public void AccessRichTextTest1() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var cell = ws.Cell(1, 1); - cell.RichText.AddText("12"); - cell.DataType = XLCellValues.Number; - - Assert.AreEqual(12.0, cell.GetDouble()); - - var richText = cell.RichText; - - Assert.AreEqual("12", richText.ToString()); - - richText.AddText("34"); - - Assert.AreEqual("1234", cell.GetString()); - - Assert.AreEqual(XLCellValues.Text, cell.DataType); - - cell.DataType = XLCellValues.Number; - - Assert.AreEqual(1234.0, cell.GetDouble()); - } - - /// - /// A test for Characters - /// - [TestMethod] - public void CharactersTest() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var richString = ws.Cell(1, 1).RichText; - - int index = 0; // TODO: Initialize to an appropriate value - int length = 0; // TODO: Initialize to an appropriate value - IXLRichText expected = null; // TODO: Initialize to an appropriate value - IXLRichText actual; - actual = richString.Characters(index, length); - Assert.AreEqual(expected, actual); - Assert.Inconclusive("Verify the correctness of this test method."); - } - - /// - /// A test for Clear - /// - [TestMethod] - public void ClearTest() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var richString = ws.Cell(1, 1).RichText; - - richString.AddText("Hello"); - richString.AddText(" "); - richString.AddText("World!"); - - richString.Clear(); - String expected = String.Empty; - String actual = richString.ToString(); - Assert.AreEqual(expected, actual); - - Assert.AreEqual(0, richString.Count); - } - - [TestMethod] - public void CountTest() - { - var ws = new XLWorkbook().Worksheets.Add("Sheet1"); - var richString = ws.Cell(1, 1).RichText; - - richString.AddText("Hello"); - richString.AddText(" "); - richString.AddText("World!"); - - Assert.AreEqual(3, richString.Count); - } - } -} \ No newline at end of file