cfspreadsheet save as .csv, Excel says "The file format and extension of FILE.csv don't match." - coldfusion

I've created a cold fusion page to output a client list from MYSQL into a CSV file for easy uploading to SalesForce.com
I can generate the file with all the correct information. However, when I try to open it with excel I get the error:
"The file format and extension of 'SalesForceDailyLeads-20160613125138.csv' don't match. The file could be corrupted or unsafe. Unless you trust its source, don't open it. Do you want to open it anyway?" I can open it(excel for MAC), but it appears to me that CFSpreadsheet is not creating a legit .csv file and is instead making a xlsx.
<cfset FileCSV = "SalesForceDailyLeads-#dateformat(getBatch.BATCH,"yyyymmdd")##timeformat(getBatch.BATCH,"HHmmss")#.csv" >
<cfset filename = "/SF/#fileCSV#">
<cfset s = spreadsheetNew() >
<cfset spreadsheetAddRow(s, "FIRST, LAST, MIDDLE, STREET, CITY, ZIP, STATE")>
<cfinclude template="SFgetList.cfm">
<cfset spreadsheetAddRows(s, getList)>
<cfspreadsheet
action="write"
overwrite = "true"
format ="csv"
name ="s"
filename ="#filename#"
>
If I make an XLS file I have no issues like I do with CSVs. Is this a problem with the code, CFSpreadsheet, or excel(for mac)? Can I fix it?

Use cffile, not cfspreadsheet to create the files. Per the documentation:
The cfspreadsheet tag writes only XLS[X] format files. To write a CSV
file, put your data in a CSV formatted string variable and use the
cffile tag to write the variable contents in a file.

Thanks! Of course, right after I posted this I found the docs and saw that I was using it incorrectly and I used CFFILE instead. I used a script/function I found to do this. It took a little work however, to convert the query into CSV- luckily someone else already did it. In case anyone care to see it:
I got the querytoCSV script here:
https://gist.github.com/CreativeNotice/2775372
<cfscript>
/**
* queryToCsv
* Allows us to pass in a query object and returns that data as a CSV.
* This is a refactor of Ben Nadel's method, http://www.bennadel.com/blog/1239-Updated-Converting-A-ColdFusion-Query-To-CSV-Using-QueryToCSV-.htm
* #param {Query} q {required} The cf query object to convert. E.g. pass in: qry.execute().getResult();
* #param {Boolean} hr {required} True if we should include a header row in our CSV, defaults to TRUE
* #param {String} d {required} Delimiter to use in CSV, defaults to a comma (,)
* #return {String} CSV content
*/
public string function queryToCsv(required query q, required boolean hr = true, required string d = ","){
var colNames = listToArray( lCase(arguments.q.columnlist) );
var newLine = (chr(13) & chr(10));
var buffer = CreateObject('java','java.lang.StringBuffer').Init();
// Check if we should include a header row
if(arguments.hr){
// append our header row
buffer.append(
ArrayToList(colNames,arguments.d) & newLine
);
}
// Loop over query and build csv rows
for(var i=1; i <= arguments.q.recordcount; i=i+1){
// this individual row
var thisRow = [];
// loop over column list
for(var j=1; j <= arrayLen(colNames); j=j+1){
// create our row
thisRow[j] = replace( replace( arguments.q[colNames[j]][i],',','','all'),'""','""""','all' );
}
// Append new row to csv output
buffer.append(
JavaCast( 'string', ( ArrayToList( thisRow, arguments.d ) & iif(i < arguments.q.recordcount, "newLine","") ) )
);
}
return buffer.toString();
};
</cfscript>
<cfinclude template="getDups.cfm">
<cfinclude template="SFgetList.cfm">
<cfset FileCSV = "SalesForceDailyLeads-#dateformat(getBatch.BATCH,"yyyymmdd")##timeformat(getBatch.BATCH,"HHmmss")#.CSV" >
<cfset filename = "/mnt/nas-share/data/feed/SF/#fileCSV#">
<cfset qc = #queryToCsv(getList, false, ",")# >
<cfoutput>#qc#</cfoutput>
<cfset heads= "FIRST, LAST, MIDDLE, STREET, CITY, ZIP, STATE">
>
<cffile
action = "write"
file = #filename#
output = #heads#
addNewLine = "yes"
fixnewline = "no">
<cffile
action = "append"
file = #filename#
output = #qc#
addNewLine = "yes"
fixnewline = "no">

Related

Coldfusion output string not defined

When I execute the code below, resources_gathered is a string, but I get the following error ('Rx222y280.....' is the string in the column resources_gathered):
visualize_resources.cfm?subject_id=395229:105 Uncaught ReferenceError: Rx222y208Rx224y208Rx224y210Rx244y231Rx246y231Rx246y233Rx233y244Rx217y243R is not defined
<cfquery name="getField" datasource="exmind" result="result">
select resources_gathered, completed_fields from dbo.sf
where subject_id=#subject_id#
</cfquery>
<cfset record = getField>
resourcesGathered = JSON.stringify(eval(<cfoutput>#record.resources_gathered#</cfoutput>));
//resourcesGathered = (<cfoutput>#record.resources_gathered#</cfoutput>).toString();
alert(resourcesGathered);
I have tried formatting the string differently before it gets inserted into the table, but I get a reference error anytime I have to read it. Below you can see how I insert it into the table (all code below this point happens in another html file):
<cfquery datasource="exmind">
update dbo.sf
set resources_gathered = <cfqueryparam value="#resources_gathered#"
cfsqltype="cf_sql_nvarchar">
where subject_id = #subject_id#
</cfquery>
The table is correct when I do this, so I am unsure what I need to change to be able to use this data in another html file. I am able to insert/select integers (such as completed_fields) which have been converted to strings, but not this more complex string. Below you can see how the string gets created. It is passed to the query html using a cfform.
for (i=0; i<resources.length; i++) { //resources is an array
if (resources[i].visibility == true){
resourcesFormString += "x";
resourcesFormString += resources[i].x.toString(); //x and y are ints
resourcesFormString += "y";
resourcesFormString += resources[i].y.toString();
resourcesFormString += "R";
}
}
document.getElementById("resources_gathered").value = resourcesFormString;

SpreadsheetFormats not working as expected

I am able to populate data from a query into a spreadsheet. However, I am having problems getting "ranged" formatting to work properly. The formatting for specific column (date) and row (header) work fine. But SpreadsheetFormatColumns, ...Rows, ...CellRange is not. I need to set the font and fontsize to the whole dataset.
Here is what I have tried.
<cfscript>
//Current directory path.
theFile = GetDirectoryFromPath(GetCurrentTemplatePath()) & "GridDump.xls";
//Create a new Excel spreadsheet object and add the query data.
theSheet = SpreadsheetNew("Raw Data");
FormatDate.dataformat = "dd-mmm-yy";
//Get Row Count and Row Range
RC = toString(result.recordcount+1);
RR = "1-" & RC;
//Get Column Count
CC = toString(ListLen(GridFieldNames));
//Get Column Letter
CL = chr(CC + 64);
//Get Column Range (Nummerical)
CRN = "1-" & CC;
//Get Column Range (Alphabetical)
CRA = "A-" & CL;
//Set Sheet Format
WholeSheet = StructNew();
WholeSheet.font="Consolas";
WholeSheet.fontsize=12;
//Set header Row Format
HeadRow = StructNew();
HeadRow.bold="true";
//Insert the Header Row
SpreadsheetAddRow(theSheet,GridFieldNames);
//Insert the Data
SpreadsheetAddRows(theSheet,result);
//Format the Data
SpreadsheetFormatCellRange(theSheet,WholeSheet,1,1,RC,CC);
//SpreadsheetFormatRows(theSheet,WholeSheet,RR);
//SpreadsheetFormatColumns(theSheet,WholeSheet,CRN);
SpreadsheetFormatRow(theSheet,HeadRow,1);
//Header Row
SpreadsheetFormatColumn(theSheet,FormatDate,1);//Date Column
SpreadsheetAddFreezePane(theSheet,0,1);//Top Row Only
//SpreadSheetAddAutofilter(theSheet,"A1:J1");
</cfscript>
Here are the results
I'm getting the same result for all three of the "ranged" formatting functions. The format stops part way through the spreadsheet. I expect the whole dataset to accept any of the ranged function formats.
I got the same result with CF 2018,0,04,314546. Could just be a limitation of XLS format.
Switching to XLSX worked fine for me:
theSheet = SpreadsheetNew("Raw Data", true);
YMMV, but what also worked with CF2018 was using SpreadsheetFormatColumns() instead of SpreadsheetFormatCellRange().

getting result metadata from coldfusion newQuery() in cfscript

Documentation on CFscript is a bit sparse in the docs, and searching for a cfscript specific answer gets lost in CF tag answers. So here's my question:
How do I get the result metadata from a query that was performed using script? Using tags I can add result="myNamedResultVar" to my cfquery. I can then refer to the query name for data, or myNamedResultVar for some metadata. However, now I'm trying to write everything in script, so my component is script based, top-to-bottom. What I'm ultimately after is the last inserted Id from a MySQL insert. That ID exists in the result metadata.
myNamedResultVar.getPrefix().generatedkey
Here's my query code:
public any function insertUser( required string name, required string email, required string pass ) {
// insert user
var sql = '';
var tmp = '';
var q = new query();
q.setDatasource( application.dsn );
q.addParam(
name='name'
,value='#trim( arguments.name )#'
,cfsqltype='CF_SQL_VARCHAR'
);
q.addParam(
name='email'
,value='#trim( arguments.email )#'
,cfsqltype='CF_SQL_VARCHAR'
);
q.addParam(
name='pass'
,value='#hashMyString( arguments.pass )#'
,cfsqltype='CF_SQL_VARCHAR'
);
sql = 'INSERT INTO
users
(
name
,email
,pass
,joined
,lastaccess
)
VALUES
(
:name
,:email
,:pass
,CURRENT_TIMESTAMP
,CURRENT_TIMESTAMP
);
';
tmp = q.execute( sql=sql );
q.clearParams();
}
How do I specify the result data? I've tried something like this:
...
tmp = q.execute( sql=sql );
var r = tmp.getResult();
r = r.getPrefix().generatedkey;
q.clearParams();
return r;
However, on an insert the getResult() returns a NULL as best I can tell. So the r.getPrefix().generatedkey does NOT work after an insert. I get r is undefined
You are getting the result property of the query first and then from that you are trying to get the prefix property in result. But this is not the case. You can directly get the prefix property and then the generated key like this:
tmp.getPrefix().generatedkey;
For reference you can check this blog entry: Getting the Generated Key From A Query in ColdFusion (Including Script Based Queries)
after some futzing... THIS seems to work
... tmp = q.execute( sql=sql );
var r = tmp.getPrefix( q ).generatedkey;
q.clearParams();
return r;

Reading XLSX file from Java, discards the very first row which is blank

I am reading an ".xlsx" file by the following code. I have found that this discards the very first row in the xls file which is completely blank without any value in any of its cell.
Here is the code>>
file = new FileInputStream(new File(qlfied_fileName));
XSSFWorkbook workbook = new XSSFWorkbook (file);
XSSFSheet sheet = workbook.getSheetAt(j);
Iterator<Row> rowIterator = sheet.iterator();
while(rowIterator.hasNext()) {
XSSFRow row = ((XSSFRow) rowIterator.next());
Iterator<Cell> cellIterator = row.cellIterator();
....
}
Can someone please guide me what exactly I have to do so that it will not discard the very first row which is blank ?

Photoshop Action with save as unique name step

I have a need to create an action that will:
1. copy a selected part (selected by hand) of an image in an already opened file
2. paste selection into new file
3. save new file as jpg file, but not with default file name of "untitled.jpg" - instead use a unique name or use a auto-increment suffix
Because the action will be run multiple times on different selections from the same image, saving each selection with a unique name or auto-incremented suffix would save the step of manually supplying the filename each time a different selection is saved.
I can create an action that gets to the save-as step, but don't know if it is possible to modify the default save as name as described above. Is it possible?
No. Tried it before with no success. You have to save manually.
Don't think this is possible with an action but you can write a script do to it.
I have created a script for similar work. It uses a technique to generate unique filenames and save the file.
/************************************************************************
* Author: Nishant Kumar
* Description: This script iterates through a template to create
* jpg images with id card numbers.
* Date: 08-03-2015
***********************************************************************/
//current id count
var id_count = 0;
//total no of id cards to produce
var total_id_cards = 42;
//no. of cards per sheet
var card_per_sheet = 21;
//Save path related to current file
var save_path = app.activeDocument.path;
//do an iteration, number the cards and save file
do{
//iterate 24 nos in each document
for(var i = 0; i<card_per_sheet; i++){
id_count++;
app.activeDocument.layers[i].textItem.contents = id_count;
}
//Create a jpg document with standard options
jpgSaveOptions = new JPEGSaveOptions();
jpgSaveOptions.embedColorProfile = true;
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgSaveOptions.matte = MatteType.NONE;
jpgSaveOptions.quality = 12;
//Save jpg with incremental file names (1.jpg, 2.jpg), make sure the path exists
jpgFile = new File( save_path + "/output/" + id_count/card_per_sheet + ".jpeg" );
app.activeDocument.saveAs(jpgFile, jpgSaveOptions, true, Extension.LOWERCASE);
}while(id_count < total_id_cards);
I know this is old, but still. You can use the following script.
How to use a script:
Copy the following script in notepad, and save it in directory similar to "C:\Program Files (x86)\Adobe\Adobe Photoshop CS2\Presets\Scripts" with the extension JSX.
To run the scrip in photoshop, go to File > Scripts > "Your Script".
#target photoshop
main();
function main(){
if(!documents.length) return;
var Name = app.activeDocument.name.replace(/.[^.]+$/, '');
Name = Name.replace(/\d+$/,'');
try{
var savePath = activeDocument.path;
}catch(e){
alert("You must save this document first!");
}
var fileList= savePath.getFiles(Name +"*.jpg").sort().reverse();
var Suffix = 0;
if(fileList.length){
Suffix = Number(fileList[0].name.replace(/\.[^\.]+$/, '').match(/\d+$/));
}
Suffix= zeroPad(Suffix + 1, 4);
var saveFile = File(savePath + "/" + Name + "_" + Suffix + ".jpg");
SaveJPG(saveFile);
}
function SaveJPG(saveFile){
//Create a jpg document with standard options
jpgSaveOptions = new JPEGSaveOptions();
jpgSaveOptions.embedColorProfile = true;
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpgSaveOptions.matte = MatteType.NONE;
jpgSaveOptions.quality = 12;
//Save jpg with incremental file names (1.jpg, 2.jpg), make sure the path exists
activeDocument.saveAs(saveFile, jpgSaveOptions, true, Extension.LOWERCASE);
};
function zeroPad(n, s) {
n = n.toString();
while (n.length < s) n = '0' + n;
return n;
};