Home » excel » asp.net – How do I specify merged cells in SpreadsheetML

asp.net – How do I specify merged cells in SpreadsheetML

Posted by: admin May 14, 2020 Leave a comment

Questions:

I am attempting to user SpreadsheetML to generate an Excel report server side and download the report via the browser. I have everything working and am getting the files I need downloaded. However, I run into a problem when I attempt to merge cells in one of the sheets I am creating. I have found two different syntaxes online and tried them both without success. I save the files as .xml files and the will open fine and show the expected data but the cells are not merged.

The first syntax uses the “mergeAcross” qualifier on the element and is supposed to merge the number of cells specified into the current cell. The second syntax using the element. I have pasted the actual xml code below for both attempts. If I can figure out what the XML should be then I can create it programatically easily.

Version 1

<?xml version='1.0'?>
<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<ss:Worksheet ss:Name='Distribution List Overview'>
<ss:Table>
    <ss:Row>
        <ss:Cell mergeAcross="2"><ss:Data ss:Type="String">First Cell Entry</ss:Data></ss:Cell>
        <ss:Cell><ss:Data ss:Type="String">Third Cell</ss:Data></ss:Cell>
    </ss:Row>
</ss:Table>
</ss:Worksheet>
</ss:Workbook>

Version 1

<?xml version='1.0'?>
<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<ss:Worksheet ss:Name='Distribution List Overview'>
<ss:Table>
    <ss:Row>
        <ss:Cell><ss:Data ss:Type="String">First Cell Entry</ss:Data></ss:Cell>
        <ss:Cell><ss:Data ss:Type="String">Third Cell</ss:Data></ss:Cell>
    </ss:Row>
</ss:Table>
<mergeCells count="2">
    <mergeCell ref="A1:B1"/>
</mergeCells>
</ss:Worksheet>
</ss:Workbook>

Both approaches above fail to create a merged cell. I am expecting to get “First Cell Entry” filling cells A1 and B1 with “Third Cell” in cell C1. Instead I get “First Cell Entry” in cell A1 and “Third Cell” in cell B1. Any help or suggestions would be greatly appreciated. This is the only remaining item I need to get some legacy code working and I do not want to convert the entire report over to OpenXML SDK code.

How to&Answers:

Try replacing mergeAcross with ss:MergeAcross. In other words, use:

<ss:Cell ss:MergeAcross="2"><ss:Data ss:Type="String">First Cell Entry</ss:Data></ss:Cell>

Also, you may notice that to get “A1:B1” merged cell you need to set ss:MergeAcross value to 1, not 2.

Answer:

Mario’s answer remains the correct answer to this question.

However, since there is decent traffic hitting this question I thought I would add some sample code for a few additional operations that I had to dig up when working on this report.

Here is an example of how to add styling information to a file. Add a block like the one below into your file immediately after the workbook element

<?xml version='1.0'?><ss:Workbook xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet'>
<ss:Styles>
  <ss:Style ss:ID='1'>
    <ss:Font ss:Bold='1'/>
    <ss:Alignment ss:Horizontal='Center'/>
  </ss:Style>
</ss:Styles>
<ss:Worksheet ss:Name='Distribution List Overview'>

The defines a style to set the font-weight bold and to horizontally center the text in each cell. You seem to be able to add an arbitrary number of style parameters to the block and should be able to specify pretty much anything supported by Excel. You’ll have to do some research to find out what the correct element names are but they seem to closely parallel Excel commands so guessing is not as hard as it sounds.

You can add this to a Cell or Row by appending the style descriptor the the target element as shown below

<ss:Cell ss:StyleID='1'>

To specify horizontal alignment and wrapped text declare another style block in between the ‘ss:Styles’ and ‘/ss:Styles’ elements and give it a unique identifier

<ss:Style ss:ID='3'>
    <ss:Alignment ss:Vertical='Bottom' ss:WrapText='1'/>    
</ss:Style>

Borders can be created using the following style structure

<ss:Style ss:ID='4'>
<ss:Font ss:Bold='1'/>
<ss:Borders>
    <ss:Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>
    <ss:Border ss:Position='Left' ss:LineStyle='Continuous' ss:Weight='1'/>
    <ss:Border ss:Position='Right' ss:LineStyle='Continuous' ss:Weight='1'/>
    <ss:Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='1'/>
</ss:Borders>

When assigned to a Cell this will set the text font to bold and apply borders on all sides with a normal weight. Adjust the Weight parameter to make the borders bolder.

Finally, I spent quite a while investigating how to add multiple records to a single cell. As far as I can tell you cannot nest Tables inside a cell so I had to figure out how to encode an alt-enter to cause line feeds inside the cell. This requires a custom style as well as some special text to be inserted inline. You need to enable line wrap as I showed above and then use the ‘&#10’ string to separate your lines. The block below will display two names in the specified cell on two lines using the example style specified above

<ss:Cell ss:StyleID='3'>
  <ss:Data ss:Type='String'>Jane Doe&#10Janet Doe</ss:Data>
</ss:Cell>

I have not managed to figure out a way to apply multiple styles to a single element so I have had to create several styles, some with very minor differences, and assign each cell the specific style ID it requires to format everything correctly. For example, I had to create a style with normal text and normal weight borders, one with bold text and normal borders and one with bold text and bold borders since I could not figure out a way to apply the font weight and the border weight separately.