From e1935c77c79eae429b4caa793bb6d18baee6415a Mon Sep 17 00:00:00 2001 From: Thomas Herrmann Date: Tue, 2 Dec 2025 14:54:57 +0100 Subject: [PATCH 1/2] fix: Add x: namespace prefix to sheetData elements for Excel compatibility Dynamically generated sheetData content was missing namespace prefixes, causing XML inconsistency when worksheet root uses 'x:' prefix. Symptoms: Excel opens the file with correct file size but displays an empty worksheet - data is silently ignored due to malformed XML. --- EPPlus/ExcelWorksheet.cs | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/EPPlus/ExcelWorksheet.cs b/EPPlus/ExcelWorksheet.cs index 12b29eb1..581a8b20 100644 --- a/EPPlus/ExcelWorksheet.cs +++ b/EPPlus/ExcelWorksheet.cs @@ -1460,12 +1460,12 @@ private void LoadMergeCells(XmlReader xr) /// The writer private void UpdateMergedCells(StreamWriter sw) { - sw.Write(""); + sw.Write(""); foreach (string address in _mergedCells) { - sw.Write("", address); + sw.Write("", address); } - sw.Write(""); + sw.Write(""); } /// /// Reads a row from the XML reader @@ -3442,7 +3442,7 @@ private void SaveXml(Stream stream) else { CreateNode("d:cols"); - CreateNode("d:sheetData"); + //CreateNode("d:sheetData"); CreateNode("d:mergeCells"); CreateNode("d:hyperlinks"); CreateNode("d:rowBreaks"); @@ -3533,13 +3533,13 @@ private void UpdateColBreaks(StreamWriter sw) var col=cse.Value._value as ExcelColumn; if (col != null && col.PageBreak) { - breaks.AppendFormat("", cse.Column); + breaks.AppendFormat("", cse.Column); count++; } } if (count > 0) { - sw.Write(string.Format("{1}", count, breaks.ToString())); + sw.Write(string.Format("{1}", count, breaks.ToString())); } } @@ -3554,13 +3554,13 @@ private void UpdateRowBreaks(StreamWriter sw) var row=cse.Value._value as RowInternal; if (row != null && row.PageBreak) { - breaks.AppendFormat("", cse.Row); + breaks.AppendFormat("", cse.Row); count++; } } if (count>0) { - sw.Write(string.Format("{1}", count, breaks.ToString())); + sw.Write(string.Format("{1}", count, breaks.ToString())); } } /// @@ -3574,13 +3574,13 @@ private void UpdateColumnData(StreamWriter sw) { if (first) { - sw.Write(""); + sw.Write(""); first = false; } var col = cse.Value._value as ExcelColumn; ExcelStyleCollection cellXfs = _package.Workbook.Styles.CellXfs; - sw.Write(""); + sw.Write(""); } } /// @@ -3636,7 +3636,7 @@ private void UpdateRowCellData(StreamWriter sw) var ss = _package.Workbook._sharedStrings; var styles = _package.Workbook.Styles; var cache = new StringBuilder(); - cache.Append(""); + cache.Append(""); FixSharedFormulas(); //Fixes Issue #32 @@ -3668,21 +3668,21 @@ private void UpdateRowCellData(StreamWriter sw) { if (f.IsArray) { - cache.AppendFormat("{3}{4}", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); + cache.AppendFormat("{3}{4}", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); } else { - cache.AppendFormat("{4}{5}", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, sfId, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); + cache.AppendFormat("{4}{5}", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, sfId, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); } } else if (f.IsArray) { - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); + cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); } else { - cache.AppendFormat("{3}", cse.CellAddress, styleID < 0 ? 0 : styleID, sfId, GetFormulaValue(v), GetCellType(v, true)); + cache.AppendFormat("{3}", cse.CellAddress, styleID < 0 ? 0 : styleID, sfId, GetFormulaValue(v), GetCellType(v, true)); } } else @@ -3690,25 +3690,25 @@ private void UpdateRowCellData(StreamWriter sw) // We can also have a single cell array formula if (f.IsArray) { - cache.AppendFormat("{3}{4}", cse.CellAddress, styleID < 0 ? 0 : styleID, string.Format("{0}:{1}", f.Address, f.Address), ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); + cache.AppendFormat("{3}{4}", cse.CellAddress, styleID < 0 ? 0 : styleID, string.Format("{0}:{1}", f.Address, f.Address), ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); } else { - cache.AppendFormat("", f.Address, styleID < 0 ? 0 : styleID, GetCellType(v, true)); - cache.AppendFormat("{0}{1}", ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v)); + cache.AppendFormat("", f.Address, styleID < 0 ? 0 : styleID, GetCellType(v, true)); + cache.AppendFormat("{0}{1}", ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v)); } } } else if (formula != null && formula.ToString() != "") { - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID, GetCellType(v, true)); - cache.AppendFormat("{0}{1}", ConvertUtil.ExcelEscapeString(formula.ToString()), GetFormulaValue(v)); + cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID, GetCellType(v, true)); + cache.AppendFormat("{0}{1}", ConvertUtil.ExcelEscapeString(formula.ToString()), GetFormulaValue(v)); } else { if (v == null && styleID > 0) { - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); + cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); } else if (v != null) { @@ -3725,8 +3725,8 @@ private void UpdateRowCellData(StreamWriter sw) if ((TypeCompat.IsPrimitive(v) || v is double || v is decimal || v is DateTime || v is TimeSpan)) { //string sv = GetValueForXml(v); - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID, GetCellType(v)); - cache.AppendFormat("{0}", GetFormulaValue(v)); + cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID, GetCellType(v)); + cache.AppendFormat("{0}", GetFormulaValue(v)); } else { @@ -3741,8 +3741,8 @@ private void UpdateRowCellData(StreamWriter sw) { ix = ss[vString].pos; } - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); - cache.AppendFormat("{0}", ix); + cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); + cache.AppendFormat("{0}", ix); } } } @@ -3767,8 +3767,8 @@ private void UpdateRowCellData(StreamWriter sw) } columnStyles = null; - if (row != -1) cache.Append(""); - cache.Append(""); + if (row != -1) cache.Append(""); + cache.Append(""); sw.Write(cache.ToString()); sw.Flush(); } @@ -3856,7 +3856,7 @@ private object GetFormulaValue(object v) //{ if (v != null && v.ToString()!="") { - return "" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + ""; //Fixes issue 15071 + return "" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + ""; //Fixes issue 15071 } else { @@ -3933,9 +3933,9 @@ private string GetValueForXml(object v) } private void WriteRow(StringBuilder cache, ExcelStyleCollection cellXfs, int prevRow, int row) { - if (prevRow != -1) cache.Append(""); + if (prevRow != -1) cache.Append(""); //ulong rowID = ExcelRow.GetRowID(SheetID, row); - cache.AppendFormat(" cellXf } private void WriteRow(StreamWriter sw, ExcelStyleCollection cellXfs, int prevRow, int row) { - if (prevRow != -1) sw.Write(""); + if (prevRow != -1) sw.Write(""); //ulong rowID = ExcelRow.GetRowID(SheetID, row); - sw.Write(""); + sw.Write(""); first = false; } @@ -4056,7 +4056,7 @@ private void UpdateHyperLinks(StreamWriter sw) if (uri is ExcelHyperLink && !string.IsNullOrEmpty((uri as ExcelHyperLink).ReferenceAddress)) { ExcelHyperLink hl = uri as ExcelHyperLink; - sw.Write("", + sw.Write("", Cells[cse.Row, cse.Column, cse.Row + hl.RowSpann, cse.Column + hl.ColSpann].Address, ExcelCellBase.GetFullAddress(SecurityElement.Escape(Name), SecurityElement.Escape(hl.ReferenceAddress)), string.IsNullOrEmpty(hl.Display) ? "" : " display=\"" + SecurityElement.Escape(hl.Display) + "\"", @@ -4084,13 +4084,13 @@ private void UpdateHyperLinks(StreamWriter sw) if (uri is ExcelHyperLink) { ExcelHyperLink hl = uri as ExcelHyperLink; - sw.Write("", ExcelCellBase.GetAddress(cse.Row, cse.Column), relationship.Id, + sw.Write("", ExcelCellBase.GetAddress(cse.Row, cse.Column), relationship.Id, string.IsNullOrEmpty(hl.Display) ? "" : " display=\"" + SecurityElement.Escape(hl.Display) + "\"", string.IsNullOrEmpty(hl.ToolTip) ? "" : " tooltip=\"" + SecurityElement.Escape(hl.ToolTip) + "\""); } else { - sw.Write("", ExcelCellBase.GetAddress(cse.Row, cse.Column), relationship.Id); + sw.Write("", ExcelCellBase.GetAddress(cse.Row, cse.Column), relationship.Id); } id = relationship.Id; } @@ -4099,7 +4099,7 @@ private void UpdateHyperLinks(StreamWriter sw) } if (!first) { - sw.Write(""); + sw.Write(""); } } /// From 5a745df44b3efb3b9ff06abb89834497c8e88f7b Mon Sep 17 00:00:00 2001 From: Thomas Herrmann Date: Fri, 19 Dec 2025 16:34:53 +0100 Subject: [PATCH 2/2] fix: Dynamic XML namespace prefixes for consistent Excel files When saving, inconsistent namespace prefixes were used, resulting in invalid XML documents. The prefix is now dynamically determined from the document and used consistently across all elements. - Extract _nsPrefix from WorksheetXml. DocumentElement - Replace all hardcoded "x:" prefixes with _nsPrefix - Add using alias RegexMatch to resolve naming conflict - Fix $"" combined with AppendFormat/string.Format calls --- EPPlus/ExcelWorksheet.cs | 156 ++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 74 deletions(-) diff --git a/EPPlus/ExcelWorksheet.cs b/EPPlus/ExcelWorksheet.cs index 581a8b20..aaad5ad2 100644 --- a/EPPlus/ExcelWorksheet.cs +++ b/EPPlus/ExcelWorksheet.cs @@ -30,31 +30,32 @@ * Jan Källman Total rewrite 2010-03-01 * Jan Källman License changed GPL-->LGPL 2011-12-27 *******************************************************************************/ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Drawing; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Text.RegularExpressions; -using System.Xml; +using OfficeOpenXml.Compatibility; using OfficeOpenXml.ConditionalFormatting; using OfficeOpenXml.DataValidation; using OfficeOpenXml.Drawing; using OfficeOpenXml.Drawing.Chart; using OfficeOpenXml.Drawing.Vml; +using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup; using OfficeOpenXml.FormulaParsing.LexicalAnalysis; using OfficeOpenXml.Packaging.Ionic.Zip; +using OfficeOpenXml.Sparkline; using OfficeOpenXml.Style.XmlAccess; using OfficeOpenXml.Table; using OfficeOpenXml.Table.PivotTable; using OfficeOpenXml.Utils; - +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Globalization; +using System.IO; using System.Linq; -using OfficeOpenXml.Compatibility; -using OfficeOpenXml.Sparkline; +using System.Security; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using RegexMatch = System.Text.RegularExpressions.Match; namespace OfficeOpenXml { @@ -371,6 +372,7 @@ internal void Clear(ExcelAddressBase Destination) private XmlDocument _worksheetXml; internal ExcelWorksheetView _sheetView; internal ExcelHeaderFooter _headerFooter; + private string _nsPrefix = ""; #endregion #region ExcelWorksheet Constructor /// @@ -1018,7 +1020,7 @@ private string GetWorkSheetXml(Stream stream, long start, long end, out Encoding char[] block; int pos; StringBuilder sb = new StringBuilder(); - Match startmMatch, endMatch; + RegexMatch startmMatch, endMatch; do { int size = stream.Length < BLOCKSIZE ? (int)stream.Length : BLOCKSIZE; @@ -1081,7 +1083,7 @@ private string GetWorkSheetXml(Stream stream, long start, long end, out Encoding } private void GetBlockPos(string xml, string tag, ref int start, ref int end) { - Match startmMatch, endMatch; + RegexMatch startmMatch, endMatch; startmMatch = Regex.Match(xml.Substring(start), string.Format("(<[^>]*{0}[^>]*>)", tag)); //"<[a-zA-Z:]*" + tag + "[?]*>"); if (!startmMatch.Success) //Not found @@ -1460,12 +1462,14 @@ private void LoadMergeCells(XmlReader xr) /// The writer private void UpdateMergedCells(StreamWriter sw) { - sw.Write(""); + sw.Write($"<{_nsPrefix}mergeCells>"); foreach (string address in _mergedCells) { - sw.Write("", address); + sw.Write($"<{_nsPrefix}mergeCell ref=\"{address}\" />"); + } - sw.Write(""); + sw.Write($""); + } /// /// Reads a row from the XML reader @@ -3433,6 +3437,16 @@ private static string GetTotalFunction(ExcelTableColumn col, string FunctionNum) private void SaveXml(Stream stream) { + // Ermittle den Namespace-Prefix aus dem Dokument + var worksheetNode = _worksheetXml.DocumentElement; + if (worksheetNode != null && !string.IsNullOrEmpty(worksheetNode.Prefix)) + { + _nsPrefix = worksheetNode.Prefix + ":"; + } + else + { + _nsPrefix = ""; + } //Create the nodes if they do not exist. StreamWriter sw = new StreamWriter(stream, System.Text.Encoding.UTF8, 65536); if (this is ExcelChartsheet) @@ -3533,13 +3547,13 @@ private void UpdateColBreaks(StreamWriter sw) var col=cse.Value._value as ExcelColumn; if (col != null && col.PageBreak) { - breaks.AppendFormat("", cse.Column); + breaks.Append($"<{_nsPrefix}brk id=\"{cse.Column}\" max=\"16383\" man=\"1\"/>"); count++; } } if (count > 0) { - sw.Write(string.Format("{1}", count, breaks.ToString())); + sw.Write($"<{_nsPrefix}colBreaks count=\"{count}\" manualBreakCount=\"{count}\">{breaks}"); } } @@ -3554,13 +3568,13 @@ private void UpdateRowBreaks(StreamWriter sw) var row=cse.Value._value as RowInternal; if (row != null && row.PageBreak) { - breaks.AppendFormat("", cse.Row); + breaks.Append($"<{_nsPrefix}brk id=\"{cse.Row}\" max=\"1048575\" man=\"1\"/>"); count++; } } if (count>0) { - sw.Write(string.Format("{1}", count, breaks.ToString())); + sw.Write($"<{_nsPrefix}rowBreaks count=\"{count}\" manualBreakCount=\"{count}\">{breaks}"); } } /// @@ -3574,13 +3588,13 @@ private void UpdateColumnData(StreamWriter sw) { if (first) { - sw.Write(""); + sw.Write($"<{_nsPrefix}cols>"); first = false; } var col = cse.Value._value as ExcelColumn; ExcelStyleCollection cellXfs = _package.Workbook.Styles.CellXfs; - sw.Write(""); + sw.Write($""); } } /// @@ -3636,7 +3650,7 @@ private void UpdateRowCellData(StreamWriter sw) var ss = _package.Workbook._sharedStrings; var styles = _package.Workbook.Styles; var cache = new StringBuilder(); - cache.Append(""); + cache.Append($"<{_nsPrefix}sheetData>"); FixSharedFormulas(); //Fixes Issue #32 @@ -3668,21 +3682,21 @@ private void UpdateRowCellData(StreamWriter sw) { if (f.IsArray) { - cache.AppendFormat("{3}{4}", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"{GetCellType(v, true)}><{_nsPrefix}f ref=\"{f.Address}\" t=\"array\">{ConvertUtil.ExcelEscapeString(f.Formula)}{GetFormulaValue(v)}"); } else { - cache.AppendFormat("{4}{5}", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, sfId, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"{GetCellType(v, true)}><{_nsPrefix}f ref=\"{f.Address}\" t=\"shared\" si=\"{sfId}\">{ConvertUtil.ExcelEscapeString(f.Formula)}{GetFormulaValue(v)}"); } } else if (f.IsArray) { - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"/>"); } else { - cache.AppendFormat("{3}", cse.CellAddress, styleID < 0 ? 0 : styleID, sfId, GetFormulaValue(v), GetCellType(v, true)); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"{GetCellType(v, true)}><{_nsPrefix}f t=\"shared\" si=\"{sfId}\"/>{GetFormulaValue(v)}"); } } else @@ -3690,25 +3704,25 @@ private void UpdateRowCellData(StreamWriter sw) // We can also have a single cell array formula if (f.IsArray) { - cache.AppendFormat("{3}{4}", cse.CellAddress, styleID < 0 ? 0 : styleID, string.Format("{0}:{1}", f.Address, f.Address), ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true)); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"{GetCellType(v, true)}><{_nsPrefix}f ref=\"{f.Address}:{f.Address}\" t=\"array\">{ConvertUtil.ExcelEscapeString(f.Formula)}{GetFormulaValue(v)}"); } else { - cache.AppendFormat("", f.Address, styleID < 0 ? 0 : styleID, GetCellType(v, true)); - cache.AppendFormat("{0}{1}", ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v)); + cache.Append($"<{_nsPrefix}c r=\"{f.Address}\" s=\"{(styleID < 0 ? 0 : styleID)}\"{GetCellType(v, true)}>"); + cache.Append($"<{_nsPrefix}f>{ConvertUtil.ExcelEscapeString(f.Formula)}{GetFormulaValue(v)}"); } } } else if (formula != null && formula.ToString() != "") { - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID, GetCellType(v, true)); - cache.AppendFormat("{0}{1}", ConvertUtil.ExcelEscapeString(formula.ToString()), GetFormulaValue(v)); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"{GetCellType(v, true)}>"); + cache.Append($"<{_nsPrefix}f>{ConvertUtil.ExcelEscapeString(formula.ToString())}{GetFormulaValue(v)}"); } else { if (v == null && styleID > 0) { - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"/>"); } else if (v != null) { @@ -3725,8 +3739,8 @@ private void UpdateRowCellData(StreamWriter sw) if ((TypeCompat.IsPrimitive(v) || v is double || v is decimal || v is DateTime || v is TimeSpan)) { //string sv = GetValueForXml(v); - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID, GetCellType(v)); - cache.AppendFormat("{0}", GetFormulaValue(v)); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\"{GetCellType(v)}>"); + cache.Append($"{GetFormulaValue(v)}"); } else { @@ -3741,8 +3755,8 @@ private void UpdateRowCellData(StreamWriter sw) { ix = ss[vString].pos; } - cache.AppendFormat("", cse.CellAddress, styleID < 0 ? 0 : styleID); - cache.AppendFormat("{0}", ix); + cache.Append($"<{_nsPrefix}c r=\"{cse.CellAddress}\" s=\"{(styleID < 0 ? 0 : styleID)}\" t=\"s\">"); + cache.Append($"<{_nsPrefix}v>{ix}"); } } } @@ -3767,8 +3781,8 @@ private void UpdateRowCellData(StreamWriter sw) } columnStyles = null; - if (row != -1) cache.Append(""); - cache.Append(""); + if (row != -1) cache.Append($""); + cache.Append($""); sw.Write(cache.ToString()); sw.Flush(); } @@ -3856,7 +3870,7 @@ private object GetFormulaValue(object v) //{ if (v != null && v.ToString()!="") { - return "" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + ""; //Fixes issue 15071 + return $"<{_nsPrefix}v>" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + $""; //Fixes issue 15071 } else { @@ -3933,9 +3947,9 @@ private string GetValueForXml(object v) } private void WriteRow(StringBuilder cache, ExcelStyleCollection cellXfs, int prevRow, int row) { - if (prevRow != -1) cache.Append(""); + if (prevRow != -1) cache.Append($""); //ulong rowID = ExcelRow.GetRowID(SheetID, row); - cache.AppendFormat(" cellXf } if (currRow.Height >= 0) { - cache.AppendFormat(string.Format(CultureInfo.InvariantCulture, " ht=\"{0}\"", currRow.Height)); + cache.Append(string.Format(CultureInfo.InvariantCulture, " ht=\"{0}\"", currRow.Height)); if (currRow.CustomHeight) { cache.Append(" customHeight=\"1\""); @@ -3956,7 +3970,7 @@ private void WriteRow(StringBuilder cache, ExcelStyleCollection cellXf if (currRow.OutlineLevel > 0) { - cache.AppendFormat(" outlineLevel =\"{0}\"", currRow.OutlineLevel); + cache.Append($" outlineLevel=\"{currRow.OutlineLevel}\""); if (currRow.Collapsed) { if (currRow.Hidden) @@ -3977,15 +3991,15 @@ private void WriteRow(StringBuilder cache, ExcelStyleCollection cellXf var s = GetStyleInner(row, 0); if (s > 0) { - cache.AppendFormat(" s=\"{0}\" customFormat=\"1\"", cellXfs[s].newID); + cache.Append($" s=\"{cellXfs[s].newID}\" customFormat=\"1\""); } cache.Append(">"); } private void WriteRow(StreamWriter sw, ExcelStyleCollection cellXfs, int prevRow, int row) { - if (prevRow != -1) sw.Write(""); + if (prevRow != -1) sw.Write($""); //ulong rowID = ExcelRow.GetRowID(SheetID, row); - sw.Write(" cellXfs, i if (currRow.OutlineLevel > 0) { - sw.Write(" outlineLevel =\"{0}\"", currRow.OutlineLevel); + sw.Write($" outlineLevel=\"{currRow.OutlineLevel}\""); if (currRow.Collapsed) { if (currRow.Hidden) @@ -4027,7 +4041,7 @@ private void WriteRow(StreamWriter sw, ExcelStyleCollection cellXfs, i var s = GetStyleInner(row, 0); if (s > 0) { - sw.Write(" s=\"{0}\" customFormat=\"1\"", cellXfs[s].newID); + sw.Write($" s=\"{cellXfs[s].newID}\" customFormat=\"1\""); } sw.Write(">"); } @@ -4047,7 +4061,7 @@ private void UpdateHyperLinks(StreamWriter sw) var uri = _hyperLinks.GetValue(cse.Row, cse.Column); if (first && uri != null) { - sw.Write(""); + sw.Write($"<{_nsPrefix}hyperlinks>"); first = false; } @@ -4056,12 +4070,8 @@ private void UpdateHyperLinks(StreamWriter sw) if (uri is ExcelHyperLink && !string.IsNullOrEmpty((uri as ExcelHyperLink).ReferenceAddress)) { ExcelHyperLink hl = uri as ExcelHyperLink; - sw.Write("", - Cells[cse.Row, cse.Column, cse.Row + hl.RowSpann, cse.Column + hl.ColSpann].Address, - ExcelCellBase.GetFullAddress(SecurityElement.Escape(Name), SecurityElement.Escape(hl.ReferenceAddress)), - string.IsNullOrEmpty(hl.Display) ? "" : " display=\"" + SecurityElement.Escape(hl.Display) + "\"", - string.IsNullOrEmpty(hl.ToolTip) ? "" : " tooltip=\"" + SecurityElement.Escape(hl.ToolTip) + "\""); - } + sw.Write($"<{_nsPrefix}hyperlink ref=\"{Cells[cse.Row, cse.Column, cse.Row + hl.RowSpann, cse.Column + hl.ColSpann].Address}\" location=\"{ExcelCellBase.GetFullAddress(SecurityElement.Escape(Name), SecurityElement.Escape(hl.ReferenceAddress))}\"{(string.IsNullOrEmpty(hl.Display) ? "" : $" display=\"{SecurityElement.Escape(hl.Display)}\"")}{(string.IsNullOrEmpty(hl.ToolTip) ? "" : $" tooltip=\"{SecurityElement.Escape(hl.ToolTip)}\"")}/>"); + } else if( uri!=null) { string id; @@ -4081,17 +4091,15 @@ private void UpdateHyperLinks(StreamWriter sw) else { var relationship = Part.CreateRelationship(hyp, Packaging.TargetMode.External, ExcelPackage.schemaHyperlink); - if (uri is ExcelHyperLink) - { - ExcelHyperLink hl = uri as ExcelHyperLink; - sw.Write("", ExcelCellBase.GetAddress(cse.Row, cse.Column), relationship.Id, - string.IsNullOrEmpty(hl.Display) ? "" : " display=\"" + SecurityElement.Escape(hl.Display) + "\"", - string.IsNullOrEmpty(hl.ToolTip) ? "" : " tooltip=\"" + SecurityElement.Escape(hl.ToolTip) + "\""); - } - else - { - sw.Write("", ExcelCellBase.GetAddress(cse.Row, cse.Column), relationship.Id); - } + if (uri is ExcelHyperLink) + { + ExcelHyperLink hl = uri as ExcelHyperLink; + sw.Write($"<{_nsPrefix}hyperlink ref=\"{ExcelCellBase.GetAddress(cse.Row, cse.Column)}\"{(string.IsNullOrEmpty(hl.Display) ? "" : $" display=\"{SecurityElement.Escape(hl.Display)}\"")}{(string.IsNullOrEmpty(hl.ToolTip) ? "" : $" tooltip=\"{SecurityElement.Escape(hl.ToolTip)}\"")}" + $" r:id=\"{relationship.Id}\"/>"); + } + else + { + sw.Write($"<{_nsPrefix}hyperlink ref=\"{ExcelCellBase.GetAddress(cse.Row, cse.Column)}\" r:id=\"{relationship.Id}\"/>"); + } id = relationship.Id; } //cell.HyperLinkRId = id; @@ -4099,7 +4107,7 @@ private void UpdateHyperLinks(StreamWriter sw) } if (!first) { - sw.Write(""); + sw.Write($""); } } ///