-
Notifications
You must be signed in to change notification settings - Fork 0
fix: Add x: namespace prefix to sheetData elements for Excel compatib… #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…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.
There was a problem hiding this 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 generatedsheetData,row,c(cell),f(formula), andv(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)); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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)); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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)); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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)); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
| 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>"); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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:
- Unprefixed (in the default namespace), OR
- 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:'.
| } | ||
| else | ||
| { | ||
| CreateNode("d:cols"); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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. |
| 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 |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| return "<x:v>" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + "</x:v>"; //Fixes issue 15071 | |
| return "<v>" + ConvertUtil.ExcelEscapeString(GetValueForXml(v)) + "</v>"; //Fixes issue 15071 |
| 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); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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())); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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())); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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())); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
| 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())); |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
…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.