Skip to content

Conversation

@jogibear9988
Copy link
Member

…ility

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.

Copilot AI review requested due to automatic review settings December 2, 2025 14:26
…ility

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.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes XML namespace prefix inconsistency in dynamically generated Excel worksheet data. When the worksheet root element uses the 'x:' namespace prefix, all child elements within sheetData must also use this prefix to maintain XML validity.

Key Changes:

  • Added x: namespace prefix to dynamically generated sheetData, row, c (cell), f (formula), and v (value) elements
  • Commented out static CreateNode("d:sheetData") call since sheetData is now dynamically generated with the correct namespace
  • Updated both StringBuilder and StreamWriter-based WriteRow methods for consistency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (f.IsArray)
{
cache.AppendFormat("<c r=\"{0}\" s=\"{1}\"{5}><f ref=\"{2}\" t=\"array\">{3}</f>{4}</c>", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true));
cache.AppendFormat("<x:c r=\"{0}\" s=\"{1}\"{5}><x:f ref=\"{2}\" t=\"array\">{3}</x:f>{4}</x:c>", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opening <f> tag is missing the x: namespace prefix while the closing tag has it (</x:f>). This creates an XML mismatch. Change <f ref= to <x:f ref= for consistency.

Copilot uses AI. Check for mistakes.
else
{
cache.AppendFormat("<c r=\"{0}\" s=\"{1}\"{6}><f ref=\"{2}\" t=\"shared\" si=\"{3}\">{4}</f>{5}</c>", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, sfId, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true));
cache.AppendFormat("<x:c r=\"{0}\" s=\"{1}\"{6}><x:f ref=\"{2}\" t=\"shared\" si=\"{3}\">{4}</x:f>{5}</x:c>", cse.CellAddress, styleID < 0 ? 0 : styleID, f.Address, sfId, ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opening <f> tag is missing the x: namespace prefix while the closing tag has it (</x:f>). This creates an XML mismatch. Change <f ref= to <x:f ref= for consistency.

Copilot uses AI. Check for mistakes.
else
{
cache.AppendFormat("<c r=\"{0}\" s=\"{1}\"{4}><f t=\"shared\" si=\"{2}\"/>{3}</c>", cse.CellAddress, styleID < 0 ? 0 : styleID, sfId, GetFormulaValue(v), GetCellType(v, true));
cache.AppendFormat("<x:c r=\"{0}\" s=\"{1}\"{4}><x:f t=\"shared\" si=\"{2}\"/>{3}</x:c>", cse.CellAddress, styleID < 0 ? 0 : styleID, sfId, GetFormulaValue(v), GetCellType(v, true));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opening <f> tag is missing the x: namespace prefix. Change <f t= to <x:f t= for consistency with other formula elements.

Copilot uses AI. Check for mistakes.
if (f.IsArray)
{
cache.AppendFormat("<c r=\"{0}\" s=\"{1}\"{5}><f ref=\"{2}\" t=\"array\">{3}</f>{4}</c>", 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("<x:c r=\"{0}\" s=\"{1}\"{5}><x:f ref=\"{2}\" t=\"array\">{3}</x:f>{4}</x:c>", cse.CellAddress, styleID < 0 ? 0 : styleID, string.Format("{0}:{1}", f.Address, f.Address), ConvertUtil.ExcelEscapeString(f.Formula), GetFormulaValue(v), GetCellType(v, true));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opening <f> tag is missing the x: namespace prefix while the closing tag has it (</x:f>). This creates an XML mismatch. Change <f ref= to <x:f ref= for consistency.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 12 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1463 to +1468
sw.Write("<x:mergeCells>");
foreach (string address in _mergedCells)
{
sw.Write("<mergeCell ref=\"{0}\" />", address);
sw.Write("<x:mergeCell ref=\"{0}\" />", address);
}
sw.Write("</mergeCells>");
sw.Write("</x:mergeCells>");
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'x:' namespace prefix is incorrect for main spreadsheet elements. The 'x:' prefix is registered for schemaMicrosoftExcel (urn:schemas-microsoft-com:office:excel) which is used for VML drawings, not for main spreadsheet elements like mergeCells, mergeCell, etc.

Main spreadsheet elements should either be:

  1. Unprefixed (in the default namespace), OR
  2. Match the prefix used in the original worksheet XML document

Hardcoding 'x:' prefix will break standard Excel files where these elements are unprefixed. Consider dynamically detecting and using the appropriate prefix from the worksheet root element instead of hardcoding 'x:'.

Copilot uses AI. Check for mistakes.
}
else
{
CreateNode("d:cols");
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commenting out CreateNode("d:sheetData") while adding 'x:' prefixes to dynamically generated sheetData content creates an inconsistency. If this line is commented out because sheetData will be dynamically generated, there should be an explanation comment. Additionally, this change coupled with the hardcoded 'x:' prefixes suggests a fundamental issue with namespace handling that needs a more comprehensive solution rather than piecemeal changes.

Suggested change
CreateNode("d:cols");
CreateNode("d:cols");
// The sheetData node is generated dynamically below, so we do not create it here.
// WARNING: Ensure that dynamically generated sheetData content uses consistent XML namespaces.

Copilot uses AI. Check for mistakes.
if (v != null && v.ToString()!="")
{
return "<v>" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + "</v>"; //Fixes issue 15071
return "<x:v>" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + "</x:v>"; //Fixes issue 15071
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'x:' namespace prefix is incorrect for the 'v' (value) element. This is a main spreadsheet schema element that should be unprefixed or match the worksheet's namespace prefix. Using 'x:' (which is for VML elements) will cause XML validation errors.

Suggested change
return "<x:v>" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + "</x:v>"; //Fixes issue 15071
return "<v>" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + "</v>"; //Fixes issue 15071

Copilot uses AI. Check for mistakes.
Comment on lines +3986 to +3988
if (prevRow != -1) sw.Write("</x:row>");
//ulong rowID = ExcelRow.GetRowID(SheetID, row);
sw.Write("<row r=\"{0}\"", row);
sw.Write("<x:row r=\"{0}\"", row);
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'x:' namespace prefix is incorrect for 'row' elements in the StreamWriter version. Row elements are part of the main spreadsheet schema and should either be unprefixed (default namespace) or match the prefix used in the original worksheet XML. The 'x:' prefix is reserved for VML drawing elements. This will break standard Excel files.

Copilot uses AI. Check for mistakes.
Comment on lines +3536 to +3542
breaks.AppendFormat("<x:brk id=\"{0}\" max=\"16383\" man=\"1\"/>", cse.Column);
count++;
}
}
if (count > 0)
{
sw.Write(string.Format("<colBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</colBreaks>", count, breaks.ToString()));
sw.Write(string.Format("<x:colBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</x:colBreaks>", count, breaks.ToString()));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'x:' namespace prefix is incorrect for colBreaks and brk elements. These are main spreadsheet schema elements that should either be unprefixed (default namespace) or match the prefix used in the original worksheet XML. The 'x:' prefix is reserved for VML drawing elements (schemaMicrosoftExcel), not for these elements. This will cause XML validation errors and break compatibility with standard Excel files.

Copilot uses AI. Check for mistakes.
Comment on lines +3557 to +3563
breaks.AppendFormat("<x:brk id=\"{0}\" max=\"1048575\" man=\"1\"/>", cse.Row);
count++;
}
}
if (count>0)
{
sw.Write(string.Format("<rowBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</rowBreaks>", count, breaks.ToString()));
sw.Write(string.Format("<x:rowBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</x:rowBreaks>", count, breaks.ToString()));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'x:' namespace prefix is incorrect for rowBreaks and brk elements. These are main spreadsheet schema elements that should either be unprefixed (default namespace) or match the prefix used in the original worksheet XML. The 'x:' prefix is reserved for VML drawing elements (schemaMicrosoftExcel), not for these elements. This will cause XML validation errors and break compatibility with standard Excel files.

Copilot uses AI. Check for mistakes.
Comment on lines +3936 to +3938
if (prevRow != -1) cache.Append("</x:row>");
//ulong rowID = ExcelRow.GetRowID(SheetID, row);
cache.AppendFormat("<row r=\"{0}\"", row);
cache.AppendFormat("<x:row r=\"{0}\"", row);
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'x:' namespace prefix is incorrect for 'row' elements. Row elements are part of the main spreadsheet schema and should either be unprefixed (default namespace) or match the prefix used in the original worksheet XML. The 'x:' prefix is reserved for VML drawing elements. This will break standard Excel files.

Copilot uses AI. Check for mistakes.
if (count > 0)
{
sw.Write(string.Format("<colBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</colBreaks>", count, breaks.ToString()));
sw.Write(string.Format("<x:colBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</x:colBreaks>", count, breaks.ToString()));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant call to 'ToString' on a String object.

Copilot uses AI. Check for mistakes.
if (count>0)
{
sw.Write(string.Format("<rowBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</rowBreaks>", count, breaks.ToString()));
sw.Write(string.Format("<x:rowBreaks count=\"{0}\" manualBreakCount=\"{0}\">{1}</x:rowBreaks>", count, breaks.ToString()));
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant call to 'ToString' on a String object.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant