<!--- Store the XML Excel data. We are storing it first so that we can clean up the data afterwards and then stream it as a binary object to the browser. ---> <cfsavecontent variable="strXmlData"> <cfoutput> <!--- Define this document as both an XML doucment and a Microsoft Excel document. ---> <?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <!--- This is the Workbook root element. This element stores characteristics and properties of the workbook, such as the namespaces used in SpreadsheetML. ---> <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"> <!--- The first child element of the WorkBook element is DocumentProperties. Office documents store metadata related to the document—for example, the author name, company, creation date, and more in the DocumentProperties element. ---> <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"> <Author>Ben Nadel</Author> <Company>Kinky Solutions</Company> </DocumentProperties> <!--- The Styles node represents information related to individual styles that can be used to format components of the workbook. ---> <Styles> <!--- Basic format used by all cells. ---> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Top"/> <Borders/> <Font/> <Interior/> <NumberFormat/> <Protection/> </Style> <!--- This is the movie rating style. We are going to format the number so that it goes to one decimal place. ---> <Style ss:ID="Rating"> <NumberFormat ss:Format="0.0" /> </Style> <!--- This is the date of the movie viewing. It is going to be a short date in the format of d-mmm-yyyy (ex. 15-Mar-2007). ---> <Style ss:ID="ShortDate"> <NumberFormat ss:Format="[ENG][$-409]d\-mmm\-yyyy;@" /> </Style> <!--- This is the boolean format of the has fighting and has boobies columns. We are going to display these values in Yes / No format. ---> <Style ss:ID="YesNo"> <NumberFormat ss:Format="Yes/No" /> </Style> </Styles> <!--- This defines the first worksheeet and it's name. We are only using one worksheet in this example, but you could add more Worksheet nodes after this one for multiple tabs. The "Name" attribute here is the name that shows up in the tab. ---> <Worksheet ss:Name="Movie Data"> <Table <!--- We need a column for each column of the query. This attribute is required to be correct. If the value here does NOT match the data in Excel file, the document will not render properly. ---> ss:ExpandedColumnCount="#ListLen( qMovie.ColumnList )#" <!--- We need a row for every query record plus one for the header row. Again, if this value does not match what is in the document, the excel file will not render properly. ---> ss:ExpandedRowCount="#(qMovie.RecordCount + 1)#" x:FullColumns="1" x:FullRows="1"> <!--- Here, we can define general properties regarding each column in the data output. ---> <Column ss:Index="1" ss:Width="30" /> <Column ss:Index="2" ss:Width="100" /> <Column ss:Index="3" ss:Width="42" /> <Column ss:Index="4" ss:Width="84" /> <Column ss:Index="5" ss:Width="66" /> <Column ss:Index="6" ss:Width="70" /> <!--- This is our header row. All cells in the header row will be of type string. ---> <Row> <Cell> <Data ss:Type="String">ID</Data> </Cell> <Cell> <Data ss:Type="String">Name</Data> </Cell> <Cell> <Data ss:Type="String">Rating</Data> </Cell> <Cell> <Data ss:Type="String">Date Watched</Data> </Cell> <Cell> <Data ss:Type="String">Has Fighting</Data> </Cell> <Cell> <Data ss:Type="String">Has Boobies</Data> </Cell> </Row> <!--- Loop over the query. ---> <cfloop query="qMovie"> <!--- When we output the excel XML row / cell data, we can put the format the tabbing / returning of the Cell and data cells in relation to each other; however, we cannot freely move around the values within the Data cells as it may change the ability to convert the data type. For instance, we cannot put any white space in front of a numeric value or it will not be parsed as a number and will error out. ---> <Row> <Cell> <Data ss:Type="Number">#qMovie.id#</Data> </Cell> <Cell> <Data ss:Type="String">#qMovie.name#</Data> </Cell> <Cell ss:StyleID="Rating"> <Data ss:Type="Number">#qMovie.rating#</Data> </Cell> <Cell ss:StyleID="ShortDate"> <Data ss:Type="DateTime">#DateFormat( qMovie.date_watched, "yyyy-mm-dd" )#T#TimeFormat( qMovie.date_watched, "HH:mm:ss.l" )#</Data> </Cell> <Cell ss:StyleID="YesNo"> <Data ss:Type="Number">#qMovie.has_fighting#</Data> </Cell> <Cell ss:StyleID="YesNo"> <Data ss:Type="Number">#qMovie.has_boobies#</Data> </Cell> </Row> </cfloop> </Table> </Worksheet> </Workbook> </cfoutput> </cfsavecontent> <!--- Define the way in which the browser should interpret the content that we are about to stream. ---> <cfheader name="content-disposition" value="attachment; filename=basic.xml" /> <!--- When streaming the Excel XML data, trim the data and replace all the inter-tag white space. No need to stream any more content than we have to. ---> <cfcontent type="application/msexcel" variable="#ToBinary( ToBase64( strXmlData.Trim().ReplaceAll( '>\s+', '>' ).ReplaceAll( '\s+<', '<' ) ) )#" />