I'm attempting to read a spreadsheet that has predefined charts on multiple tabs using cfspreadsheet, but when it comes to processing the data, I get variable is undefined.
I've used the example from Adobe - http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec17cba-7f87.html
I've also looked at other examples, but those examples use a combination of cfspreadsheet and poi or java and I would prefer to only use cfspreadsheet if possible. Any idea looking at my code below where the problem is coming from? Thanks.
<cfcontent type="application/vnd.ms-excel" reset="Yes">
<cfquery name="GetData" datasource="#request.dsn#">
SELECT *
FROM v_Occurrences
</cfquery>
<cfset strFileName = "OccurrenceData" & "#now().getTime()#" & "#UserID#">
<!---
<cfdump var="#GetData#">
--->
<cfset filepath = "file:///...OccurenceData.xls">
<!--- Write the two sheets to a single file --->
<cfspreadsheet
action ="read"
columnnames = "Occurence_Date,Full_Name_Client"
columns = "2"
excludeHeaderRow = "false"
headerrow = "1"
query="GetData"
rows = "2"
src ="#filepath#">
<cfscript>
OccurrenceData = SpreadsheetNew("Data");
Month = SpreadsheetNew("Month");
Person = SpreadsheetNew("Person");
SpreadsheetAddRows(occurrencedata,getdata);
</cfscript>
<!--- Write the two sheets to a single file --->
<cfspreadsheet
action="write"
filename="#filepath#"
name="OccurrenceData"
overwrite="true"
sheetname="Data" >
<cfspreadsheet
action="Update"
filename="#filepath#"
name="Month"
sheetname="Month">
<cfspreadsheet
action="Update"
filename="#filepath#"
name="Person"
sheetname="Person" >
<cfspreadsheet
action="read"
src="#filepath#"
sheetname="occurrencedata"
query="GetData">
Here's where the error occurs: variable Occurrence_Data is undefined
<cfscript>
SpreadsheetAddRow(OccurrenceData,"Date,Name",1,1);
SpreadsheetAddRow(OccurrenceData,
"#Dateformat(Occurrence_Date,'mm/dd/yyyy')#,#Full_Name_Client#",
2,1,true);
</cfscript>
<cfspreadsheet
action="write"
autosize="true"
filename="#strFileName#.xls"
overwrite="true"
password="password"
query="GetData"
sheetname="Data" >
Problem number 1. This is probably doing more harm than good.
<cfcontent type="application/vnd.ms-excel" reset="Yes">
Problem number 2. If you want to write two sheets to a single file, you don't do this:
OccurrenceData = SpreadsheetNew("Data");
Month = SpreadsheetNew("Month");
You do something like this:
OccurrenceData = SpreadsheetNew("Data");
// do stuff with this sheet
SpreadsheetCreateSheet(OccurrenceData, "Month");
SpreadSheetSetActiveSheetNumber(OccurrenceData, 2);
// do stuff with this sheet
SpreadSheetWrite(OccurrenceData, whateverYourFileNameIs);
I also suggest that you do one thing at a time. Write a bit of code, run it, and look at the results. Then add a bit more code, run it, and look at the results. This will help you isolate the code that causes the error.
I have a request from a client to generate an Excel spreadsheet from a query. I have the query kicking out the fields and I can generate the Excel file without a hitch. The problem comes when the client takes that Excel file and then tries to manipulate it.
The majority of the trouble comes from fields that should be marked as currency or dates. I am, with some struggle, able to generate a "real" date field. Before this Excel was not sorting the dates properly. I was able to call an Excel formula by using the code below. DateValue forces Excel to acknowledge this as a real date field. However, this fails when this file is manipulated through Excel.
<cfset SpreadsheetSetCellFormula(s
,"DATEVALUE(#Chr(34)##Replacement_ETD##Chr(34)#)"
, therow
, 9)>
The next problem is the currency field. I can't get Excel to acknowledge the values as a currency. It always comes up custom. When this is set, the SUM function won't work in Excel. You can add the fields individually like A1+B1+C1 = TOTAL. However, this won't be helpful when there are 200 rows.
I was able to get a suggestion from another CF programmer who had a similar situation. He generated the Excel file first with the proper headings and set the columns to their proper fields such as date and currency, etc.
The next step would be to fill in the fields row by row and they should be properly formatted.
Code:
<cfset filename = expandPath("./reports/arrivals.xlsx")>
<cfspreadsheet action="read" src = "#filename#" name = "s" >
<cfset therow = 0>
<cfoutput query="myExcel" startrow="1">
<cfset therow = myExcel.currentrow + 1>
<cfset SpreadsheetSetCellValue(s, Incumbent, therow, 1)>
<cfset SpreadsheetSetCellValue(s, Section, therow, 2)>
<cfset SpreadsheetSetCellValue(s, Position_Number, therow, 3)>
<cfset SpreadsheetSetCellValue(s, Position_Title, therow, 4)>
<cfset SpreadsheetSetCellValue(s, Incumbent_Emplyment_Type, therow, 5)>
<cfset SpreadsheetSetCellValue(s, Incumbent_ETD, therow, 6)>
<cfset SpreadsheetSetCellValue(s, Tour_Comments, therow, 7)>
<cfset SpreadsheetSetCellValue(s, Replacement, therow, 8)>
<cfset SpreadsheetSetCellValue(s, Replacement_ETA, therow, 9)>
</cfoutput>
<cfheader name="content-disposition" value="attachment; filename=Departures_(#DateFormat(now(),'mmddyy')#).xls">
<cfcontent type="application/msexcel" variable="#spreadsheetReadBinary(s)#" reset="true">
The data in the cells has already been properly formatted. When this file is generated and streamed to the user the columns are not formatted as expected.
Does anyone else know if this method will work or have a better suggestion on getting CF to generate a proper date and currency field for Excel to acknowledge?
Adobe ColdFusion v10 running on RHEL 5.
Per request here is some code using queryNew that will generate code dates and currency.
Step one: I created an Excel file with the first row frozen and it has the column header. Column one has been designated as the date the format is long date - mm/dd/yyy; Column two is Dollar which as been set to currency.
I read that file then fill in the rows and stream the file to the user for download.
<cfset filename = expandPath("./reports/Test.xlsx")>
<cfspreadsheet action="read" src = "#filename#" name = "s" >
<cfset myQuery = QueryNew("MyDate, Dollar", "Date, Decimal")>
<cfset newRow = QueryAddRow(MyQuery, 5)>
<cfset temp = QuerySetCell(myQuery, "MyDate", "03-11-2000", 1)>
<cfset temp = QuerySetCell(myQuery, "Dollar", "403.45", 1)>
<cfset temp = QuerySetCell(myQuery, "MyDate", "01-01-2009", 2)>
<cfset temp = QuerySetCell(myQuery, "Dollar", "603.22", 2)>
<cfset temp = QuerySetCell(myQuery, "MyDate", "09-21-2013", 3)>
<cfset temp = QuerySetCell(myQuery, "Dollar", "103.55", 3)>
<cfset temp = QuerySetCell(myQuery, "MyDate", "01-15-2005", 4)>
<cfset temp = QuerySetCell(myQuery, "Dollar", "3.33", 4)>
<cfset temp = QuerySetCell(myQuery, "MyDate", "07-22-2003", 5)>
<cfset temp = QuerySetCell(myQuery, "Dollar", "13.75", 5)>
<cfset therow = 0>
<cfoutput query="myQuery" startrow="1">
<cfset therow = myQuery.currentrow + 1>
<cfset SpreadsheetSetCellValue(s, DateFormat(MyDate, 'mm/dd/yyyy'), therow, 1)>
<cfset SpreadsheetSetCellValue(s, Dollar, therow, 2)>
#myQuery.currentrow# <br>
#myQuery.MyDate# <br>
#myQuery.Dollar# <br>
</cfoutput>
<cfheader name="content-disposition" value="attachment;
filename=Departures_(#DateFormat(now(),'mmddyy')#).xls">
<cfcontent type="application/msexcel" variable="#spreadsheetReadBinary(s)#" reset="true">
You can open the file in MS Excel or in Google Sheets. Test one, with the first row frozen, we should be able to sort on the date field. My results are: The dates are not being sorted properly. On column 2 with the currency, if we try to do a SUM that does work! This had not worked before but it does now.
Also, when I try to open the file I am given the warning that this file is corrupt and Excel will try to open it. I get no such warning on Google Sheets.
CF can be a bit quirky when working with date cells. Excel is pretty good about guessing the correct cell type when a value is entered manually. However, it is a little trickier with CF. Since CF is relatively typeless, it does not always match up values and cell types correctly. Using functions that utilize a query object, instead of SpreadsheetSetCellValue(), usually produces better results. Most likely because query objects contains both values and data types. Though as of CF11, SpreadsheetSetCellValue supports a new data parameter, which allows you to specify both the value and cell data type. Since you are using CF10, try using SpreadsheetAddRows to populate the values instead.
Regarding, the warning that the file is corrupt, it is caused by the fact that the actual file content and the file extension in the download code do not match. The code is reading in an .xlsx file, but the download claims it is an .xls (application/msexcel) file. To get rid of the error, make sure the two match.
Here is a working example tested with CF11
<!---
Test.xlsx contains two columns, with headers on row 1
- Column A format: *m/d/yyyy
- Column B format: number with 2 decimal places
--->
<cfspreadsheet action="read" src="c:/temp/Test.xlsx" name="sheet" >
<cfset myQuery = QueryNew("")>
<cfset QueryAddColumn(MyQuery, "Dollar", "Decimal", [ 403.45, 703.22, 103.55, 3.33, 13.75] )>
<cfset QueryAddColumn(MyQuery, "MyDate", "date", [ parseDateTime("2000-03-11", "yyyy-mm-dd")
, parseDateTime("2009-01-01", "yyyy-mm-dd")
, parseDateTime("2013-09-21", "yyyy-mm-dd")
, parseDateTime("2005-01-15", "yyyy-mm-dd")
, parseDateTime("2003-07-22", "yyyy-mm-dd")] ) >
<cfset spreadsheetAddRows(sheet, myQuery)>
<cfset spreadsheetFormatColumn(sheet, {dataFormat="m/d/yy"}, 1)>
<cfset spreadsheetFormatColumn(sheet, {dataFormat="##,####0.00"}, 2)>
<cfheader name="content-disposition" value="attachment; filename=Departures_(#DateFormat(now(),'mmddyy')#).xlsx">
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" variable="#spreadsheetReadBinary(sheet)#" reset="true">
I need to generate excel spreadsheet with coldfusion 10 from a query. So far its working fine except the headers of the table. They are dynamically generated [month Year] December 2012. When I add a header column I get it in the date format like '01/12/2013'. There are other types of date formatting and other types of cell formatting. How do I force a cell to format as a string. Kind of when you add single quotation.
This is my code:
<cfset VARIABLES.vcFilename = "billtotals_" & DateFormat(Now(), "yyyymmdd") & "-" & TimeFormat(Now(), "HHmmss") & ".xls">
<cfset VARIABLES.sheet = SpreadSheetNew( "Summary" )>
<cfset VARIABLES.columns = arrayToList(GetBillPremTotals.getMeta().getColumnLabels())>
<cfset SpreadSheetAddRow( VARIABLES.sheet,VARIABLES.columns)>
<cfset format1 = StructNew()>
<cfset format1.bold = "true">
// tried this just for kicks doesn't work <cfset format1.dataformat = "'">
// tried this converts to a number <cfset format1.dataformat = "text">
<cfset SpreadsheetFormatRow(VARIABLES.sheet, format1, 1)>
<cfset SpreadSheetAddRows(VARIABLES.sheet,GetBillPremTotals)>
<cfset SpreadSheetAddRows(VARIABLES.sheet,GetBillPremGrandTotals)>
<cfset VARIABLES.sheetAsBinary = SpreadSheetReadBinary(VARIABLES.sheet)>
<cfheader name="Content-Disposition" value="attachment; filename=#Chr(34)##VARIABLES.vcFilename##Chr(34)#">
<cfcontent type="application/msexcel" variable="#VARIABLES.sheetAsBinary#" reset="true">
This is a table with data from query analyzer, displays fine in the browser in html format
No November 2012 December 2012 January 2013 February 2013
----------- --------------------------------------- --------------------------------------- --------------------------------------- ---------------------------------------
25 60117.56000 61515.17000 60791.62000 60745.29000
28 1564.69000 1564.69000 1564.69000 1590.44000
30 110599.11000 173954.08000 178064.11000 172892.65000
Thank you in advance,
Gena
This did the trick.
<cfset format1.dataformat = "mmmm yyyy">
I am using a cfloop to generate the titles of a bunch of variables.
Problem is on output I just get the actual variable name ie #qQuery.varName# instead of its value ie "Item Name".
Heres a quick taste of my code:
<cfloop query="qQuery">
<cfloop query="qTest">
<cfset varTest = "qQuery." & varName>
<cfoutput>#varTest#</cfoutput>
</cfloop>
</cfloop>
Thanks :)
Try something like this:
<cfset vartest = qQuery[varName]>
I would like to insert a line break into the first space between words in a string variable. Here is my code so far:
<cfset myPosition = find(" ", #myVar#)>
<cfset lineBreak = Chr(13)&Chr(10)>
<cfset myVar = insert(#lineBreak#, #myVar#, #myPosition#)>
What am I doing wrong?
I don't think that you are doing anything wrong. Your code seems to work. When you output your variable, try wrapping it in <pre></pre> tags for testing purposes. If you want the linebreak to show up on a html page you have to replace the space with <br />.
This works for me and shows the carriagereturn / linefeed:
<cfset myVar="The quick brown fox">
<cfset myPosition = find(" ", myVar)>
<cfset lineBreak = Chr(13) & Chr(10)>
<cfset myVar = insert(lineBreak, myVar, myPosition)>
<cfoutput>
<pre>#myVar#</pre>
</cfoutput>
BTW: there is no need to enclose your variables in #'s unless you want to output the variable or to have it evaluated between quotation marks.