TechSpoken
"Any ideas?" is the most frequently-asked question in technical forums. My answer is: yes.

Changing the Sheet names in SQL Server RS Excel: QnD XSLT

October 3, 2007 14:07 by LSN

I had a nice note from Gilda Tramontana this week, asking for more information about something I'd posted about revising the Excel output you get from SQL Server Reporting Services. 

Someone had noted, in the forum thread that Gilda referenced, that the way that documentation acknowledges the limitations of the default Excel output is "amusing". Apparently the term they use in the docs is "unique attributes" and, believe me, they're not talking about primary keys here. 

In another dev universe, long ago and far away, we used to refer to these "unique attributes" as "infelicities" or "devolutions". They're not bugs, they just... are.

Whatever. In the thread, I responded that the Excel default output is not the only Excel output available to you from SQL Server RS:

What I mean: you can use the data-xml export from RS and associate an XSLT stylesheet with it.  That means you can take the data and make presentation in Excel you want, just go out to SSML.  SSML is Excel 2003's XML dialect.  It's pretty straightforward, although Excel's debugging abilities are minimal -- .it's hard to see what you did wrong, so get used to reading an XSD!

 ... and you can read the rest of the thread if you want... but Gilda wrote asking for more information and I said I would do my best.  I'll now provide a walkthrough here of how you apply the XSLT and how you create it. 

I hope this walkthrough will not only show you that you can do it, but also why it is hard to do it generically. My example will be complete, and will provide you with some generic bits to start you off.  But you will have to adapt a bit.  Ready?

First, realize that I said the data-xml export option.  Not the Excel export option. 

Second, realize  that you can take any Excel export document that you get from a Reporting Services report and Save it As SSML (Excel 2003 Spreadsheet XML dialect), to give you a reasonable starting point.  IOW, you really don't have to figure out how to do this from scratch.

So here is what you do:

  1. Export your report as Excel and, from Excel, Save a copy of the sample output As SSML.  Like I said.  This is your example of your almost-perfect target result.
  2. Also, from Reporting Services or the preview, Export your report as Data XML, so you know what the underlying data you are going to have to work with at runtime looks like. Now you have an example of your source, from which you are going to derive your perfect target result.
  3. Now you need to create an XSLT style sheet that will reproduce what you have in the SSML, with one simple change (in this case: the name of each worksheet), and plugging in your source Data XML into the Excel rows instead of the literals you see in your SSML sample.
    Try not to faint.  The samples you just saved give you almost everything you need.  I'll provide an illustration, and walk you through this part, below.
  4. Now attach your XSLT document to the report by putting its name in the Data Output tab of the Report Properties dialog.
  5. You can test your results at this point by choosing Export to XML file with report data from Report Preview.  If you've done this right, the result is SSML.
  6. Deploy your XSLT document to your report server. 
    You can do this by rightclicking on the XSLT within your Visual Studio project, the same way you deploy the report , or you can do it by uploading the XSLT as a file in the Report Manager (which of course you can also do with the RDL).
  7. Re-deploy your report to the Report Server, too, because you've adjusted its properties to include the XSLT reference.
  8. When you Export this report to Data XML, your result is now Excel in your preferred format !

 

Here's the zoom-in instructions for step #3 above, the part you're scared about doing.

In my example, the report is Recipients grouped by Locale, so Locale is the group-break value for which I would like to change the worksheet names. 

Remember: Excel creates different sheets in response to your explicit data page breaks, usually on a group within a data region.  

When I examine my report data sample, I might see something that looks like this: 

<Report Name="Recipients" xmlns="Recipients">
   <table1>
      <table1_Locale_Collection>
         <table1_Locale Locale="AZ">
            <Detail_Collection>
               <Detail textbox3="0" Recipient_AppPreferredDeliveryType="EMAIL-ATTACH"
                          Recipient=
"XXX" email="XXX@XXX.XXX" />
               <Detail textbox3="0" Recipient_AppPreferredDeliveryType="FAX"
                          Recipient=
"YYY" email="YYY@YYY.COM" fax="999-999-9999"/>
               <Detail textbox3="0" Recipient_AppPreferredDeliveryType="EMAIL-ATTACH"
                          Recipient=
"ZZZ" email="ZZZ@ZZZ.ZZZ" />
            </Detail_Collection>
         </table1_Locale>
         <table1_Locale Locale="CA">
            <Detail_Collection>
               <Detail textbox3="0" Recipient_AppPreferredDeliveryType="EMAIL-LINK"
                           Recipient=
"AAA" email="AAA@AAA.AAA" />
               <Detail textbox3="0" Recipient_AppPreferredDeliveryType="POSTAL"
                           Recipient=
"BBB" email="" mail_line_1="BBB" etc="ETC"/>
            </Detail_Collection>
         </table1_Locale>
         <!-- more here -->
      </table1_Locale_Collection>
   </table1>
</Report>

 

It's a pretty straightforward structure. You can see where the label for locale that corresponds to my group break with the paging instructions is located (there is a table1_Locale element for each, with a Detail_Collection underneath). You can see where the elements for each detail row are going to come from (there are Detail nodes in each Detail_Collection).

When I examine my sample SSML export, I see something that looks superficially much more complicated, but actually has a very logical structure . It has a Workbook root, under which are three first-level children with global information (DocumentProperties, ExcelWorkbook, and Styles) followed by a succession of Worksheet nodes. 

Your XSLT is going to preserve much of this sample intact.  It's going to repeat the three first-level "prolog" children pretty much verbatim (actually, I recommend that you strip out much of the ExcelWorkbook node -- you'll see why when you check out its contents -- and you can remove as much of DocumentProperties as you want). After the "prolog", it will provide a template for the Worksheets, as you'll see below.

Start your XSLT document with something that declares all the necessary namespaces from Excel's point of view, and create a template that matches any root element ( "/*").  This is just an easy way to avoid specifying the namespace of the Report root node for the match.  You can use the skeleton you see here, verbatim (just add the Styles from your sample):

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
     xmlns:xsl=
"http://www.w3.org/1999/XSL/Transform"
     xmlns=
"urn:schemas-microsoft-com:office:spreadsheet"
     xmlns:o=
"urn:schemas-microsoft-com:office:office"
     xmlns:x=
"urn:schemas-microsoft-com:office:excel"
     xmlns:ss=
"urn:schemas-microsoft-com:office:spreadsheet"
     xmlns:html=
"http://www.w3.org/TR/REC-html40">

   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" omit-xml-declaration="no"/>

   <xsl:template match="/*">

      <?mso-application progid="Excel.Sheet"?>
      <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
                xmlns:o=
"urn:schemas-microsoft-com:office:office"
                xmlns:x=
"urn:schemas-microsoft-com:office:excel"
                xmlns:ss=
"urn:schemas-microsoft-com:office:spreadsheet"
                xmlns:html=
"http://www.w3.org/TR/REC-html40">

         <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
            <!-- etc -->
         </DocumentProperties>

         <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
            <ProtectStructure>False</ProtectStructure>
            <ProtectWindows>False</ProtectWindows>
         </ExcelWorkbook>

         <Styles>
            <!-- your samples' styles go here, verbatim-->
         </Styles>

         <!-- see below for your Worksheet template-->

      </Workbook>
   </xsl:template>
</xsl:stylesheet>

 

Now you need to add some information in where I've indicated the Worksheet template goes, into the skeleton I've provided above.  This is the part that is quite difficult to do generically, because, depending on how you've nested and named your data regions, I can't tell you exactly what element you want to drill down to, to match what appears as the "page element" in your report's XML data. 

In mine, it's an element named table1_Locale, a couple of layers deep.  I'm going to iterate through all of these nodes in the data XML, and create a Worksheet node for each in the output.  As before, I'm going to use * instead of literal names for the nodes, to avoid bothering with namespace discussions.

As you can see in this skeleton, I'm going to create my sheet names as an expression (the word "Locale-" plus the value of the Locale attribute that holds the value for this group in the source data XML. That's the one significant change we're making from the original content provided by the default Excel renderer; the original sample you saved would have had an attribute that said something like ss:Name="Sheet1".

<xsl:for-each select="./*/*/*"> <!-- Report/table1/table1_Locale_collection/table1_Locale -->
  <Worksheet ss:Name="{concat('Locale-',@Locale)}">
 <Names/>
  <Table >
  <!-- see below for what goes in here -->
  </Table>
 </Worksheet>
</xsl:for-each>

 

The curly braces you see are a shorthand way to insert the result of an expression in an attribute. You may never have seen that syntax before.  If you prefer, you can use xsl:attribute instruction to supply the sheet name as an expression. 

Inside the Worksheet's Table node, I return to my SSML saved sample for more content that I can plop in verbatim: first, a set of Column definitions, followed by some Row nodes that hold the header rows for each sheet.  You can just paste this in from your saved sample.

Anything that isn't the same throughout the report, such as the name of the Locale for each "page" in my case, can be replaced by an appropriate expression.  Here's a header row from mine; you can see the xsl:value-of construct supplying the name of the Locale for this worksheet:

    <Row ss:Height="25.5">
    <Cell ss:MergeAcross="1" ss:StyleID="s28">
          <
Data ss:Type="String"><xsl:value-of select="@Locale"/></Data></Cell>
    <Cell ss:StyleID="s28"/>
    <Cell ss:StyleID="s28"/>
    <Cell ss:MergeAcross="2" ss:StyleID="s28"/>
    <Cell ss:MergeAcross="1" ss:StyleID="s28"/>
    <Cell ss:StyleID="s28"/>
    <Cell ss:StyleID="s28"/>
   </Row>

 

Finally, below your header rows, it's time to iterate through your details. Put another xsl:for-each construct in place at this point in the template and point it at your Detail nodes. Paste a sample row into the xsl:for-each, right out of your SSML sample content, and adjust the content of each cell to point at the appropriate data element.  Mine looks like this:

<xsl:for-each select="./*/*"> <!-- DetailCollection/Detail -->

   <Row ss:Height="38.25">
    <Cell ss:MergeAcross="1" ss:StyleID="s29"/>
    <Cell ss:StyleID="s29"><Data ss:Type="String">
            <
xsl:value-of
            
select="@Recipient_AppPreferredDeliveryType"/></Data></Cell>
    <Cell ss:StyleID="s29"><Data ss:Type="String">
            <
xsl:value-of select="@Recipient"/></Data></Cell>
    <Cell ss:MergeAcross="2" ss:StyleID="s29">
            <
Data ss:Type="String"><xsl:value-of select="@Title"/></Data></Cell>
    <Cell ss:MergeAcross="1" ss:StyleID="s29">
           <
Data ss:Type="String"><xsl:value-of select="@email"/></Data></Cell>
    <Cell ss:MergeAcross="1" ss:StyleID="s29">
           <Data ss:Type="String"><xsl:value-of select="@mail_line_1"/></Data></Cell>
    <Cell ss:StyleID="s29">
           <
Data ss:Type="String"><xsl:value-of select="@last_edit"/></Data></Cell>
   </Row>
   </xsl:for-each>
<!—Your Table close tag is here -->

 

  ... and that's pretty much all she wrote.  Get the idea?

Now, as I said, you can start thinking about how many other forms of Excel you might support from the same data.

You don't have to design the formatting in an RDL at all, if you don't want to.  Design it in Excel exactly the way you want it, save out the SSML, and then plug your data elements into it from the original report...

"Unique attributes", indeed. Hmph.


Currently rated 4.7 by 3 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Related posts

Comments

November 15. 2007 02:09

Gravatar


Hi lisa,

the article which u have posted has help me bulit up the XSLT file. But the probelm is when i try to export my data as XML from RS ,it throws and unusual error : Problems came up during load i.e. worksheet setting error.

I would highly appreciate if u can help me trace this error.

Thank,
Darshan

Darshan

November 15. 2007 02:41

Gravatar

Hi Darshan,

Unfortunately that's NOT an unusual error. It's the only error Excel ever throws and it is extremely hard to debug. There is supposed to be a log of what this error represents -- but often the location of the log that is supposed to be created doesn't exist. I have looked in vain for where it might be going instead. FWIW, I have found that it shows up more often if I try to open the file in Excel 2007.

In any case, I have learned not to rely on the log being available, but if you can find it, that's the first place to go.

The second place to go is wherever the error told you the problem is! Excel's message is usually able to tell you whether it can load the workbook at all and is finding a problem with the worksheet definition(s) or contents, so you can look wherever it points and figure out what you munged when you did your editing or excerpting.

If Excel doesn't tell me where to look, I often comment out various portions of my stylesheet, for example eliminating the contents of the data tables, to see if that eliminates the issue. If it doesn't, I know it's something in my globals, or column definitions, etc. If it does, I know I need to fix the data representations that I used.

It's tedious, but it is easier if you don't rely on RS to give you the result; IOW, take your example data XML and apply the XSLT explicitly to it, outside the RS context. This makes it faster to test and try to re-load in Excel with each change you make. You can apply the XSLT using Visual Studio, or any XML tool that you prefer -- or look at this post http://spacefold.com/lisa/post/After-you-learn-to-walk%2c-you-can-run-a-postscript-to-the-QnD-XSLT-walkthrough.aspx for some more information on using quick and dirty VBS scripts to do it.

One of the things I've learned to watch out for is the case-sensitive names of styles. Another thing would be the datatypes of content you put in cells. If you get really stuck, you can post me your Excel result and I'll try to see what's wrong with it -- no guarantees, though. I'll just be doing it by trial and error or possibly attempting to validate your result against the Excel schema (SOMETIMES that works).

L

November 17. 2007 14:57

Gravatar

Hi Lisa,

How do i save a excel export file from RS to ssml file format? Also you have one snapshot for the nodes. when i try to save an xls file to .ssml i cant find that nodes. Any help is appreciated

Mitul

mitul

November 17. 2007 16:35

Gravatar

Mitul, when your Excel Export file is open in Excel, there is a Save As XML Spreadsheet. That's the SSML !

What are the nodes you can't find?

L

November 17. 2007 19:20

Gravatar

hey lisa, thanks for the help...but when i tried to read my .xslt file from rs , it threw and error : cannot load the specified XSLT file. Expected end of expression.

Mitul

mitul

November 17. 2007 19:38

Gravatar

Well, if you make a mistake in XSLT and load it to RS without testing it you have to expect that <s>.

XSLT doesn't need to be loaded to RS without testing, Mitul! I don't know what toolset you're using so it is difficult for me to recommend, but if you're in Visual Studio you can load an XML file (in this case your source RS data file) and give it a stylesheet reference so you can see what happens when you apply the stylesheet.

If you want other ways to do it, you can read this post

http://spacefold.com/lisa/post/After-you-learn-to-walk%2c-you-can-run-a-postscript-to-the-QnD-XSLT-walkthrough.aspx. It discusses run-time application of an XSLT without RS doing it for you, but you can certainly use the script approach I threw in there for testing if you don't have a better tool to do it with.

HTH...

L

November 18. 2007 13:42

Gravatar

Your article is superb. I just have one problem. My .xsl file works. conversion to SSML is perfect. The only problem is it can't give the following xml tag in the final SSML file.

<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="Excel.Sheet"?>

I have to manually open the final SSML file and place these tags at the top and open it in EXCEL. Please advise

Praveen

November 18. 2007 14:11

Gravatar

Hey, thanks for the strokes, Praveen.

FWIW Excel doesn't need the encoding specified in the xml declaration, although it does need the declaration.

You should be getting the declaration because of this line in the XSLT:

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" omit-xml-declaration="no"/>

... and if you'll notice I did specify UTF-8 as part of this output instruction, so if it were required you would still be okay.

FWIW UTF-8 is probably the default encoding when you *don't* specify one, so you would be okay in any case.

Excel also does not need the prog-id specified to open the XML correctly as SSML, because it gets that information from the namespaces defined on the Workbook element tag.

It's possible to force that line into the output, but honestly it works fine without it <s>.

>L<

L

November 19. 2007 15:00

Gravatar

I understand what you are point to.
But with out those two tag in place for the SSML the file wouldnt open directly in EXCEL when you double click on that.

I even tried all possibilities with <xsl:output />

some how xsl:output attributes are not used what I mentioned in my XSLT file. not sure why? I made lot of changes to my Reporting Services installations like Security Extensions and other extensions. Not sure if this is causing this problem.

The work around I used is

<xsl:value-of disable-output-escaping="yes" select="concat('&lt;?xml version=&quot;1.0&quot;','?&gt;')"/>
<xsl:value-of disable-output-escaping="yes" select="concat('&lt;?mso-application progid=&quot;Excel.Sheet&quot;','?&gt;')"/>


I manually tried to emit these tags in to output XML


Praveen

November 19. 2007 15:52

Gravatar

>>But with out those two tag in place for the SSML the file wouldnt open directly in EXCEL when you double click on that.

Sure it will, Praveen, you just need to write the file with an XLS extension.

I can't remember if you told me whether you are requesting the output programmatically or not -- but assuming you are there should be no problem changing the name of the output file. If you are not, tell me more about your scenario and remember that I did follow up this post with a recommendation to handle the application of XSLT yourself, rather than using the "automagic" RS version -- which allows you greater flexibility. Since you are already using custom extensions to RS, you might be able to embed this right into the process without anything external.

FYI: I don't think that your RS changes are the reason why the xsl:output tags are not being used. I think this is some limitation of the classes or methods they are using to apply the xslt. Not sure.

Re your workaround:

This is not the right way, ordinarily, to add processing instructions into your output. There is a right way, without cheating, and it will be something like this (forgive me if it doesn't post correctly, or if I make a mistake -- we're packing to move and I don't have any references to consult):

&lt;xsl:processing-instruction name="mso-application" &gt;
progid="Excel.Sheet"&lt;/xsl:processing-instruction&gt;

Re the xml declaration, though: even though I don't think this has anything to do with your custom extensions, it may have something to do with the versions of .NET components on your system, because that's coming across just fine for me, even with no xsl:output instruction at all.

L

November 19. 2007 15:53

Gravatar

PS Praveen -- those encoded less than and greater than signs should not be encoded, this is a real xslt instruction we are trying to include in the stylesheet. I can't make it come out right when I post a comment... just look up xsl:processing-instruction and you'll see what I'm talking about...

L

February 8. 2008 17:01

Gravatar

Please cud you make a video of how to do this entire process..i am not able to get the 3rd part. When i create the ssml it doesnt show me the workbook, worksheet xml code. Also how to create XSLT?

sheetal

March 8. 2008 07:00

Gravatar

When i try to export to Export to XML file with report data, it only shows one line when i open it in Excel. The output file when opened in a browser looks OK. Any idea on this? Thanks.

cgracias

March 8. 2008 22:15

Gravatar

Hi CGracias,

The output file looks okay in the browser, but does it look like your XSLT was correctly applied? Or is it still the original report data?

Also, what version of Excel are you opening it in? I think what you are describing would happen if it was Excel 2000. Even though 2000 had some limited XML support, SSML, the dialect we are using here, really got started with 2003.

L

March 9. 2008 01:40

Gravatar

Hi again. I got it to work after applying the workaround used by Praveen. I can now open it in Excel. The only problem now that i have is the formatting (font sizes, colors, etc). It would be good if i can also insert images on the file. I'm just new in XSLT so i'm not really sure what i'm doing here :). Anyway, thanks again. Any notes on the formatting will be highly appreciated.

CGracias

March 9. 2008 05:36

Gravatar

Good news! I got the formatting working using the Style. I'm not sure yet about the images or logo i should say.

CGracias

March 9. 2008 06:52

Gravatar

Hi CGracias,

You should be able to do most things with SSML that you can do in Excel. The only exception I know of is charts or other embedded ole objects. That being said, pictures might certainly fall into that category.

I do a lot of very fancy Excel work. But when I turn data into Excel it is because I am looking to do something that Excel does very well, better than other reporting formats. Since showing pictures isn't one of the... I admit I haven't used Excel for that particular purpose. I don't know if this comment will help or not.

L

March 9. 2008 18:22

Gravatar

Hi, That's OK. I got a workaround on the logo. Luckily, the logo is only plain text and in plain color. The style will do for this. Thanks. CGracias

CGracias

March 18. 2008 19:17

Gravatar

Hi Lisa,

I m trying to apply this to an .rdl which has a matrix tool to group the records in the dataset so that each group appears in a different worksheet, but unable to do the renaming in this case. please help.

Sheetal

March 19. 2008 02:50

Gravatar

Hi Sheetal,

Are you saying that the original/standard Excel has the correct grouping and each group already does appear in a different worksheet, but you can't apply the renaming technique? Or is the problem that you also need to move the groups into separate worksheets?

If the former (you don't see how to apply renaming), remember that this was only a very simple example of what you can do. I used the following for my simple rename (I am going to substitute square brackets here for angle brackets in the XML):

[Worksheet ss:Name="{concat('Locale-',@Locale)}"]

... but I could have said:

[Worksheet]
[xsl:attribute name="ss:Name"]
*****
[/xsl:attribute]
[/Worksheet]

... and where you see **** there can be a considerable amount of code, depending on how you want to set the rule for naming each sheet.

Another thing you have to remember is that I deliberately picked a value (Locale name) that happened to provide legal sheet name values for Excel. In some cases, your group values wouldn't be legal for a sheet name. For example suppose you had dates in your groups; the slash character might not be legal in the Excel tab name. Is this what you are running into?

Provide an example, and I'll try to help.

L

March 26. 2008 13:19

Gravatar

Hi Lisa,

Here is my requirement:

I have an report which when exported to excel sheet will have a summary data (all data ) in the first worksheet and later the subsequent worksheets will have data related to a particular group. For example we have a report called sales by industry, so first worksheet will contain all the industries and their sales ...later worksheets will have detialed information regarding a particular industry...so i have in my report two matrix one for the first summary worksheet.

And the 2nd matrix is placed inside a list item whoes grouping is based upon the industry and has page break after facility checked, so that each time the industry changes the data is placed in another worksheet.

cud you provide me with a similar example of using matrix and list which groups the report data and creating an XSLT for it.

Please let me know if you need any code from my side.


Thnx,
Sheetal.

Sheetal

March 26. 2008 15:54

Gravatar

Sheetal, have you tried to follow the steps that I outlined and found that for some reason it doesn't work for a matrix or for a matrix inside a list?

What does the original export look like when you export this report using RS in-the-box Excel export output? As far as I can remember, when you export a matrix it looks pretty much the same as a table in the resulting Excel.

Is the problem that the page breaks don't come out automatically, or what?

From my point of view, the original in-the-box Excel formatting does not matter very much. It is nice if it is pretty close to what you want, because you can use it as your "target" with a few tweaks. But if it is not, then create an Excel example that *is* your goal, save that as SSML and work from there as your target.

As long as the data export (XML) has the values you need you can do what you want. In fact I just posted a followup on this subject (http://spacefold.com/lisa/post/Another-postscript-to-QnD-Excel-in-RS-post.aspx) to say that, at least in my experience, the data export from RS-RDLs is extremely clean and easy to understand.

The only exception is OLE containers such as charts; you can't translate those into SSML as far as I know. But if the problem is just that you want it to be a pivot table structure in Excel from the matrix, that should be possible to do.

In fact, as I said in my followup post, RDL data export is so clean, compared to some other environments in which I've done this, it's a joy to handle the matrix output. You can easily see what the full set of contents is, what your column headers need to look like, you don't have to figure it out using keys or grouping.

Is this the kind of thing that is bothering you (how to figure out the row headers? If so I could post about this.

No, I don't want any code "from your side". If you want me or somebody on my team to do this *for* you, you'll have to pay the company that I work for ;-).

L

April 19. 2008 08:53

Gravatar

I am having trouble with my style sheet. Once in reporting Services when I export to xml with report data, I don't get the line: <?mso-application progid="Excel.Sheet"?> in my xml output. When I look at the excel version of the xml the few lines are as follows:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40";>
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
When I look at the Reporting Services xml data the first few lines are as follows:
<?xml version="1.0" encoding="utf-8"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40";>
<DocumentProperties xmlns="urn:schemas-microsoft-
com:office:office">
I can't figure out what I'm doing wrong. I used the style sheet example provided here, but I can't get the output correct. The first few lines of the style sheet are as follows:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40";>

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" omit-xml-declaration="no"/>

<xsl:template match="/*">

<?mso-application progid="Excel.Sheet"?>

<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40"" rel="nofollow">http://www.w3.org/TR/REC-html40";>

<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">

Could you please help.

Barbara

April 20. 2008 18:16

Gravatar

First I am having trouble following your request for help with all that extra XML stuff in there <g>.

Second, to get the processing instruction you need to use the following line (as I told somebody else, either in response to this entry or a different one in this "group" of entries):

<xsl:processing-instruction name="mso-application">progid="Excel.Sheet"</xsl:processing-instruction>

[if this doesn't work I will follow up with an escaped version]

Third, when you add the processing instruction, RS may strip out the xml declaration, so you may need to add it back in like this (try doing without it first!):

<xsl:value-of disable-output-escaping="yes" select="concat('&lt;?xml version=&quot;1.0&quot;','?&gt;')"/>
<!-- this is a kludge needed if you're going to export directly from the
the Report Manager interface instead of using URL Access; the Report Manager
takes off the XML declaration and Excel doesn't like that. -->

Hope this helps...

L

April 27. 2008 01:31

Gravatar

I tried this logic -renaming sheets - mentioned above to apply to my report generated on SSRS but when i finally export my excel the sheets names are not renamed, however when i export to xml i see the new sheetnames..what could be the problem? Any ideas

sa

April 27. 2008 10:47

Gravatar

There's no problem, sa. That's exactly what you should expect! You are getting the default Excel from RS's default Excel renderer. You're getting the Excel you want from XML + XSLT.

If you'll notice, I actually said:

>> When you Export this report to Data XML, your result is now Excel in your preferred format !




L

May 20. 2008 09:45

Gravatar

Hi Lisa

Thanks for your excellent posting, after a little fiddling with the various outputs I was able to produce what I wanted. I appreciate the clarity of your examples, much better than others I read.

I only wish Excel XML wasn't such a "fat" format uncompressed though, the file size jumped from +4MB to +17MB!

Still, you can't have everything, almost perfect is OK :)

Cheers!

Domo

May 20. 2008 14:20

Gravatar

Hi Domo, You're very welcome, thanks for writing. And you're right: you can't have everything -- in Excel 2007 you can have a smaller file size at the cost of much greater complexity in creating the XML <s>.

L

June 2. 2008 06:30

Gravatar

Hi
I am new to Prolog, I seek a Prolog predicate that runs an Excel file ( like this: predicate .... c:\book1.xls).
If you know help me and please write the predicate.

senvy

June 2. 2008 10:39

Gravatar

Hi Senvy. The "Prolog" that I mentioned in my post has nothing to do with the Prolog programming language. It is just a way of saying the "beginning constructs in the spreadsheet definition" -- prolog or prologue is an English word. In my XSLT files I happen to use the word "Prolog" as the name of the template that performs this service. I could have said "Preface" instead, or "FirstSteps", or anything like that.

Having said that I am not sure what you think a "Prolog predicate that runs an Excel file" would do. Run the macros in the file? display the spreadsheet? What is your goal here?

L

July 18. 2008 01:31

Gravatar

Hi,

I'd like to thank you for this entire thread. I went from knowing absolutely nothing about xml, xsl, SSML, etc. to being able to produce a report from RS and render it into the Excel format I want including meaningful tab names. :)

Now here's the situation that I find myself in. Like I said, I've gotten my report to work directly from RS. However, I'm not able to get it to render directly from SharePoint Services. The errors I get are either "Strict Parsing Error" or "Worksheet Setting" depending on which escaped version of code I use.

Can you help?

Thanks,

Michele

July 18. 2008 03:57

Gravatar

Hi Michele,

Try the version I posted above on April 19th (half unescaped and half Praveen's workaround escaped version), here it is again:

<xsl:processing-instruction name="mso-application">progid="Excel.Sheet"</xsl:processing-instruction>


<xsl:value-of disable-output-escaping="yes" select="concat('&lt;?xml version=&quot;1.0&quot;','?&gt;')"/>
<!-- this is a kludge needed if you're going to export directly from the
the Report Manager interface instead of using URL Access; the Report Manager
takes off the XML declaration and Excel doesn't like that. -->


... and try including some specific xsl:output instructions, which I may not have mentioned before and usually help:

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" omit-xml-declaration="yes"/>


... if this does not work for you, no I can't help, unfortunately. I run screaming away from RS and SharePoint integration, there are many people who understand that stuff much better than I do.

Part of the reason I have avoided it is that it seemed like it might be totally different in RS 2008 (see section on Moving right along to the Next Great Thing in http://spacefold.com/lisa/post/Configuring-Reporting-Services-is-a-bear-Will-this-bear-sh~t-or-emerge-from-the-woods-in-Katmai.aspx).

There might be something else in your Sharepoint-RS integration that is causing this. There might not.

Here are some ideas:

* -- test displaying some other XML document within Sharepoint that is *not* Excel-oriented. If you can get one to display properly, then tweak the xsl:output instructions above to match.

* -- try displaying your Excel Saved as SSML as a document within Sharepoint (without any programmatic manipulation, and not created by RS). Can you get it to display properly? If so, what is different about it?

Best I can do...

L

July 23. 2008 20:02

Gravatar

Hi,

I apologize for not getting back to you sooner but some other things took priority over this project.

In any case, I tried running the report out of Sharepoint again and it magically worked. Guess it's one of those glitches.

Thanks again.

Michele

July 23. 2008 20:27

Gravatar

Thanks for letting me know, Michele, I am glad to hear it. Maybe something was cached. Don't you hate it when that happens!?!

L

August 6. 2008 19:43

Gravatar

Hi again!

I'm sorry if I'm keeping this thread alive well past its perceived life, but I haven't found a better or more comprehensive source for Reporting Services & Excel (Lisa, you totally ROCK!!!). Anyway, onto my questions....

First, I was wondering if there was a way of using this method to have the grouping that occurs when you render a report directly to Excel. They seem to get "dropped" when you save your SSML file. All you get are rows that are either visible or hidden. I keep getting an error when I use &ltxsl:for-each-group&gt - apparently this can't be used as a child of a table. And the &ltfor-each&gt element doesn't allow group-by as an attibute.

Second, I'm not exactly sure how to conditionally apply the styles. For example, I have columns that are mostly numeric, but for cases where there are no records that meet the criteria, I have "No Records Found". I could just as easily make these "0" so that everything is numeric, but I'm trying to alleviate as much confusion as possible (e.g. one column is an average cost). I've tried using &ltxsl:choose&gt & &ltxsl:otherwise&gt, but can't quite get it to work right.

Finally, I know that someone else stated that they were able to add their company logo using a style. I was able to add the URL into the spreadsheet, but not display it as an image. Any help with this would be greatly appreciated.

Thanks in advance.

Michele

August 7. 2008 09:54

Gravatar

Hi again Michele,

I don't think the logo situation is what you think it is -- CGracias would have used text with a style to emulate the picture/image, not include it. SSML doesn't include support for OLE objects, so you can't embed the graphic in the "normal" way.

You can definitely apply for-each inside a table, but you have to do it right <g>. I'm not going to guess at what you are doing wrong, because there are two many possibilities.

On the other hand, yes those groupings get "dropped" when you save your SSML file, and I'm not sure there is a way to put them in exactly as provided in the direct-to-Excel method from RS, which is a little hokey. There might be a decent replacement for it; I'll try to think of one and post something. I'll include an example of conditional style application. I think what you are probably missing is the ability to use <xsl:attribute>, although there are a couple of different ways to do this.

Don't expect a quick post -- but I will try this weekend.

Thanks for the "strokes" !

L

August 7. 2008 10:07

Gravatar

Oh -- Michele -- one more thing. There is actually a "group by" attribute in XSLT standard 2.0, which MS doesn't support <shrug>.

The alternative is something called Muenchian grouping, which works fine in standard 1.x, You will also find gives you something more tools and more to think about, in terms of performance benefits, in XSLT in general. I'll try to post about that too but you can google for it.

L

August 7. 2008 11:10

Gravatar

Hey Lisa!

Thanks for the response. I'll do more reasearch on the grouping thing - thanks for providing another route to try. It was the for-each-group that was giving me the error saying it couldn't be a child of a table, not for-each (I've been using that like crazy thanks to you :)

Thanks, also, for setting me straight on the logo thing. Fortunately, this is a "nice to have" and not a "must have".

You still rock!!

Michele

August 7. 2008 11:32

Gravatar

>>It was the for-each-group that was giving me the error saying it couldn't be a child of a table, not for-each

OK (?)... provide an example of what you're trying to do that isn't working -- e-mail -- and I'll try to straighten this out.

L

August 8. 2008 06:07

Gravatar

Hi!

I've been able to conditionally apply the styles that I want so I'm good there. I have someone else in the office today that's trying to help me with the grouping problem. He doesn't think that the for-each-group will help resolve the issue so I don't think I'm going to pursue that path anymore for the time being. I'll post by Monday and let you know where we're at & post the solution (if we've arrived at one by then). I'm still trying to plug away at getting the logo to display & might be able to enlist the help our resident guru with that.

Thanks again!

Michele

August 12. 2008 19:48

Gravatar

Hi!

I give up. I can't seem to figure out how to get the grouping to work. And just to clarify - my data is sorted correctly in Excel; it just doesn't have the nice little +/- off to the left to expand & collapse the groups beneath the main group. If/when I do figure this out, I'll be sure to post.

Thanks again.

Michele

August 12. 2008 21:10

Gravatar

I totally understand what your question is about. And just to clarify on *this* side, I did spend *some* time on the weekend trying to figure out a good way to emulate the expand/collapse feature of binary Excel in SSML.

I don't have a good solution for you, and didn't have time to post my thoughts about this yet. I didn't rush because I don't think the conclusion will be immediately helpful to you; I'm looking for a substitute approach, not a way to make this work. Thanks for checking back in!

L

Add comment


(Will show your Gravatar icon)  

  Country flag




Live preview

September 6. 2008 00:22

Gravatar