creating multiple sheets using Coldfusion SpreadsheetWrite and cfscript - coldfusion

I'd like to create a single excel file with two sheets using CF9, SpreadsheetWrite and cfscript. Something like:
var data= spreadsheetNew( 'data' );
var key= spreadsheetNew( 'key');
spreadsheetAddRow( data, dataInfo );
spreadsheetAddRow( key, keyInfo );
spreadsheetWrite( data, filePath );
spreadsheetWrite( key, filePath );
I don't find documentation that explains how to combine multiple sheets in one file. Here's what I find.
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSe9cbe5cf462523a0-7b585809122c5a12c54-7fff.html
It states that one can 'Write multiple sheets to a single file.' but whether that means more than one sheet at a time is not clear. You can accomplish this using tags but I need to use cfscript.
<cfspreadsheet action="update" filename = "filePath" sheetname = "key" >
How does one write the above tag-based call using cfscript?

Yes, it is not very clear from the documentation. SpreadsheetNew creates a Workbook with a single worksheet. To add additional sheets, use the SpreadSheetCreateSheet function. Before you can manipulate the new sheet, it must be made active with SpreadSheetSetActiveSheet. Here is a quick example of creating a workbook with two sheets:
<cfscript>
// Create new workbook with one worksheet.
// By default this worksheet is active
Workbook = SpreadsheetNew("Sheet1");
// Add data to the currently active sheet
SpreadSheetAddRow(Workbook, "Apples");
SpreadSheetAddRow(Workbook, "Oranges");
//Add second worksheet, and make it active
SpreadSheetCreateSheet(Workbook, "Sheet2");
// Add data to the second worksheet
SpreadSheetSetActiveSheet(Workbook, "Sheet2");
SpreadSheetAddRow(Workbook, "Music");
SpreadSheetAddRow(Workbook, "Books");
//Finally, save it to a file
SpreadSheetWrite(Workbook, "c:/path/to/yourFile.xls", true);
</cfscript>
Side note, I would not recommend using <cfspreadsheet action="update"> anyway. Last I recall it was a bit buggy.

Related

How to create a pygsheets worksheet without the default sheet1?

Is there a way to create a pygsheets worksheet without the default sheet1?
Looking through the documentation didn't help, but googling seems to indicate that it's possible to eliminate sheet1 in excel, so presumably, it should be possible in pygsheets.
sheet1 just refers to the first sheet which is automatically created when you creates the spreadsheet. It is automatically created by google sheets and you can't control it from any library. google sheets required you to have at-least one worksheet in a spreadsheet. So you cannot remove all the sheets.
But if you just want to remove the sheet named sheet1, you can do
sh.del_worksheet(sh.sheet1)
or if you wanna rename it , you can do
sh.sheet1.title="new_sheet"
Simply rename the default sheet1 to your desired worksheet name (my_sheet1)
sh = gc.create("my_google_sheet", parent_id="56uyjJcWghbtyuwA")
wks = sh.sheet1
# rename to your desired worksheet name
wks.title = ('my_sheet1')

ColdFusion Object to String

I'm really new to ColdFusion and am trying to pull data out of the database and send it to an email function I have created.
myQry = new Query();
myQry.setSQL("select * from stocknotifications LEFT JOIN options ON stocknotifications.stocknotification_id = options.option_id ORDER BY stocknotification_id DESC LIMIT 1 "); //set query
qryRes = myQry.execute();
writedump(qryRes.getResult(), false);
Mail = variables.NotificationService.newMail();
Mail.setTo("bfrench#destinationcms.co.uk");
Mail.setSubject( "New Stock Request" );
// render body with layout which uses the rc.emailView
Mail.setBody(ToString(qryRes.getResult()));
variables.NotificationService.sendMail( Mail );
My writeDump() works and shows the last item in table. The only problem is I can't pass it into setBody() without it throwing an error.
Can't cast Complex Object Type Query to String
Use Built-In-Function "serialize(Query):String" to create a String from Query
Any ideas?
Per the error message you received, you could actually replace toString with serialize and you'd be good to go.
If all you want is the data going to e-mail without caring about presentation, quick and dirty, you might want to try SerializeJSON(); it will convert the query into a JSON string with COLUMNS and DATA:
Mail.setBody(SerializeJSON(qryRes.getResult()));
The easiest way to do this is with cfsavecontent. I'm not sure if there is a script version of this so I'll show you how to use is with tags. You already have a query result named qryRes.
<cfsavecontent variable = "eMailBody">
<cfoutput query = "qryRes">
#field1#, #field2# etc
</cfoutput>
</cfsavecontent>
Then for mail function, you can do this:
mail.setBody(emailBody);
If you want to send your email in html format, put the appropriate html tags inside the cfsavecontent block. Otherwise, pay attention to the carraige returns of your source code. They get included in the variable produced by cfsavecontent. For the code sample above, you will get 3 blank lines at the top of the body, and the data rows will be double spaced.

Images and formatting not working on a multi-tabbed XLSx file generated with ColdFusion

The code below will generate the file with two notable errors:
The SpreadSheetSetColumnWidth appears to stop working after 21 lines on the second tab
The image does not appear on the second tab
Hopefully this is just a rookie mistake and not something along the lines of the date formatting issue. Any help or constructive criticism to fix/improve would be greatly welcomed.
<!--- We cannot directly reference the image --->
<cfimage source="img/A2LA_Logo.jpg" name="A2LA_Logo">
<!--- We need an absolute path, so get the current directory path. --->
<cfset theFile=GetDirectoryFromPath(GetCurrentTemplatePath()) & "Final_Report.xlsx">
<cfscript>
/*********************************************************************** Page 1 ***********************************************************************/
//Create a new Excel spreadsheet object - SpreadsheetNew("Tab name", "yes=2007+ no=2003");
Tab1 = SpreadsheetNew("Final Report Page 1","yes");
SpreadSheetSetRowHeight(Tab1,1,45);
SpreadsheetSetCellValue(Tab1,"Final Test Report",1,1); SpreadsheetMergeCells(Tab1,1,1,1,10);
SpreadsheetAddImage(Tab1, A2LA_Logo,"jpg","1,12,2,20");
SpreadsheetSetCellValue(Tab1,"Confidential",1,21); SpreadsheetMergeCells(Tab1,1,1,21,30);
</cfscript>
<cfscript>
/*********************************************************************** Page 2 ***********************************************************************/
//Create a new Excel spreadsheet object - SpreadsheetNew("Tab name", "yes=2007+ no=2003");
Tab2 = SpreadsheetNew("Final Report Page 2","yes");
SpreadSheetSetRowHeight(Tab2,1,45);
SpreadsheetSetCellValue(Tab2,"Final Test Report",1,1); SpreadsheetMergeCells(Tab2,1,1,1,10);
SpreadsheetAddImage(Tab1, A2LA_Logo,"jpg","1,12,2,20");
SpreadsheetSetCellValue(Tab2,"Confidential",1,21); SpreadsheetMergeCells(Tab2,1,1,21,30);
</cfscript>
<!--- There must be a better way --->
<cfscript>
for(index=1; index LTE 30; index++) {SpreadSheetSetColumnWidth(Tab1,index,3);}
for(index=1; index LTE 30; index++) {SpreadSheetSetColumnWidth(Tab2,index,3);}
</cfscript>
<!--- Write the spreadsheet to a file, replacing any existing file, then append the other tabs. --->
<cfspreadsheet action="write" filename="#theFile#" name="Tab1" overwrite=true>
<cfspreadsheet action="update" filename="#theFile#" name="Tab2">
<!--- Needs to be at the bottom --->
<cfheader name="Content-disposition" value="attachment;filename=Final_Report.xlsx">
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" file="#theFile#">
<!--- Clean up your mess after it is served to the browser --->
<cffile action="delete" file="#theFile#">
(From the comments)
The images show up when saved separately. So I am guessing it is an update bug. My usual recommendation is "do not use update if you can avoid it". Create a single workbook, add multiple sheets and save it with a single write action.
Update: As for why, in your original code, you are creating two separate workbook objects. Conceptually think of it like creating two separate Excel files, with one sheet each. Then trying to merge them into one file:
c:/path/to/MyWorkbookNamedTab1.xlsx
| Sheet1 /
c:/path/to/MyWorkbookNamedTab2.xlsx
| Sheet1 /
That is different than creating a single workbook, with multiple sheets (like in the link above):
c:/path/to/MySingleWorkbook.xlsx
| Sheet1 / Sheet2 /
There is no easy way to merge separate files (or workbooks). You basically have to copy everything from one workbook into another (which is a lot more involved than it sounds). That is what action=update does. Somewhere in the copying process it loses one of the images. I am not sure if it that is due to a CF bug one in POI.
In any case, the simplest solution is to avoid the need for copying altogether. If you stick with a single workbook (and add multiple sheets to it) then there is no need for copying or merging. Everything is already contained in one workbook. So all action=write has to do is save it to disk, exactly "as is".

Export to Excel and formatting cells using ColdFusion 10

I have a query which I'd like to output in a spreadsheet in Excel. I'd like some of the cell columns to be formatted in a certain way, which is thousands grouping and in Number format so that sums, additions etc can be done on that row without any further alteration.
I have read through the documentation but it has left me a bit confused on how to output to Excel in the first place.
I started out with a comment but it will be easier to read as an answer.
What have you tried? Have you read through the CFSpreadsheet documentation? Should be pretty straight forward. One of the parameters to the CFSpreadsheet tag is 'query'. Why not start with that and see how it formats the columns for you by default to see what needs tweaking.
Here is an example taken directly from the referenced documentation page:
<cfquery name="courses" datasource="cfdocexamples">
SELECT CORNUMBER, DEPT_ID, COURSE_ID, CORNAME
FROM COURSELIST
</cfquery>
<cfscript>
//Use an absolute path for the files. --->
theDir=GetDirectoryFromPath(GetCurrentTemplatePath());
theFile=theDir & "courses.xls";
//Create an empty ColdFusion spreadsheet object. --->
theSheet = SpreadsheetNew("CourseData");
//Populate the object with a query. --->
SpreadsheetAddRows(theSheet,courses);
</cfscript>
<!--- Write the sheet to a file --->
<cfspreadsheet action="write" filename="#theFile#" name="theSheet" sheetname="courses" overwrite=true>
See the documentation for SpreadsheetFormatColumn, SpreadsheetFormatColumns, SpreadsheetFormatRow and SpreadsheetFormatRows to read about formatting particular cells.
You just need to use the cfspreadsheet tag to create the file, and you can format the cells with the spreadsheetFormat* functions. You can find an example of how to do this at Ray Camden's site.

Is it possible to create new worksheet and add data from file to it?

I have file what have two worksheets which I wish to use as templates.
In php I create new PHPExcel object and load data from first worksheet to it.
$objReader = new PHPExcel_Reader_Excel5();
$objReader->setLoadSheetsOnly('Page1');
$objPHPExcel = $objReader->load('template.xls');
Then I need to create another worksheet in objPHPExcel and fill it with template from worksheet 'Page2' of file template.xls
But when I do like this:
$objReader->setLoadSheetsOnly('Page2');
$objWorksheet = $objPHPExcel->createSheet();
$objWorksheet->setTitle('Sheet'.$sheetIndex);
$objPHPExcel = $objReader->load($timesheetTemplatePath);
I get file with only last results.
How can I create worksheet and read data (with styles) from another file?
Try passing an index to createSheet method, in this case it would be 1:
$objWorksheet = $objPHPExcel->createSheet(1);