CF Upgrade Issue while binding dropdown value to a bind in cfgrid - coldfusion

We are upgrading our CF Server 9 to latest CF 2018. And i am facing bind issue between dropdown selected value and cfgrid bind.
There is dropdown just above the cfgrid that is set empty at first and has values listed of a query, and just below is a grid that binds the dropdown selection value to the query that is fetched.
At first as empty is selected it would not fetch records and grid would be empty. Also the bind URL is correctly formed.
http://127.0.0.1:8501/app/dummy.cfm?&DbFunc=getRecords&SrcID=&newSrcID=&flt_nm=&flt_iv=&flt_ct=&flt_sc=&flt_in=&pageSize=174&_cf_ajaxproxytoken=6D89B1BFAE8D17997E5A&_cf_clientid=1AFC4F973849FBAE6EAAA465492A0E0B&_cf_rc=0&_cf_nodebug=true&_cf_nocache=true&returnFormat=json&_dc=1549690631545&start=0&limit=174&page=1&sortCol=&sortDir=ASC
But next when i select the dropdownto a new value the URL is formed in this way.
http://127.0.0.1:8501/app/dummy.cfm?&&DbFunc=getRecords&SrcID=Test&SrcID=&&newSrcID=Test&&flt_nm=&&flt_iv=&&flt_ct=&&flt_sc=&&flt_in=&pageSize=174&_cf_ajaxproxytoken=6D89B1BFAE8D17997E5A&_cf_clientid=1AFC4F973849FBAE6EAAA465492A0E0B&_cf_rc=0&_cf_nodebug=true&_cf_nocache=true&returnFormat=json&_dc=1549690634739&start=0&limit=174&page=1&sortCol=&sortDir=ASC
As you can see the SrcID is getting appended twice for first time empty and next adding the selected value. I am receiving this as a comma separated value on my next page which is incorrect.
the query params are getting added as a separate instead of overwiting the old params.
The SrcID param is defined at top and next is the dropdown and directly at the bottom is the cfgrid where it is used in bind.
Thanks in advance
Here is a sample code below
<cfajaximport tags="cfform, cfinput-datefield, cftooltip, cfwindow, cfgrid, cfmessagebox">
<script type="text/javascript" language="javascript">
function doRefresh(form){
cSrcID = form.SrcID.options[form.SrcID.selectedIndex].value;
console.log('me'+cSrcID+'u');
cSortFld = '';
form.newSrcID.value = cSrcID;
}
// get client area of the browser
var cliWt = getClientWt(); // client width
var cliHt = getClientHt(); // client height
// set grid dimensions scrWidth, scrHeidht
var gWt = 34; // right margin
var gHt = 180; // top margin
var minWt = 500; // min width of the table
var minHt = 280; // min height of the table
var scrWidth = cliWt - gWt;
var scrHeight = cliHt - gHt;
if (scrWidth < minWt) scrWidth = minWt;
if (scrHeight < minHt) scrHeight = minHt;
// set winEdit popup window dimensions
var popwinWt = 1150;
var popwinHt = 680;
var bResizePopup = 0;
if (popwinWt > cliWt) {
bResizePopup = 1;
popwinWt = cliWt - 10;
}
if (popwinHt > cliHt) {
bResizePopup = 1;
popwinHt = cliHt - 10;
}
// set winEdit2 popup window dimensions
var popwinWt2 = 900;
var popwinHt2 = 510;
var bResizePopup2 = 0;
if (popwinWt2 > cliWt) {
bResizePopup2 = 1;
popwinWt2 = cliWt - 10;
}
if (popwinHt2 > cliHt) {
bResizePopup2 = 1;
popwinHt2 = cliHt - 10;
}
// set winEdit3 popup window dimensions
var popwinWt3 = 800;
var popwinHt3 = 550;
var bResizePopup3 = 0;
if (popwinWt3 > cliWt) {
bResizePopup3 = 1;
popwinWt3 = cliWt - 10;
}
if (popwinHt3 > cliHt) {
bResizePopup3 = 1;
popwinHt3 = cliHt - 10;
}
</script>
<cfset maxRowCnt = 174>
<!--- Set Grid default params --->
<cfparam name="page" default="1">
<cfparam name="pageSize" default="#maxRowCnt#">
<cfparam name="cfgridsortcolumn" default="">
<cfparam name="cfgridsortdirection" default="">
<cfform name="mainForm">
<cfoutput>
<br /><cfselect name="SrcID" title="Select a Source" style="width:200px;" onchange="doRefresh(this.form)">
<option value="">Select a Data Source</option>
<option value="Test">Test</option>
</cfselect>
<input type="hidden" name="newSrcID" value="">
<input type="hidden" name="flt_nm" value="" />
<input type="hidden" name="flt_iv" value="" />
<input type="hidden" name="flt_ct" value="" />
<input type="hidden" name="flt_sc" value="" />
<input type="hidden" name="flt_in" value="" />
</cfoutput>
<!--- Main Grid title="List of Records" --->
<cfgrid format="html" name="mainGrid" sort="yes" style="border:1px solid ##002D96;" visible="no" pagesize="#maxRowCnt#" maxrows="#maxRowCnt#" vspace="20"
striperows="yes" striperowcolor="#gcGray#" bgcolor="#gcRowWhite#" colheaderbold="yes" colheadertextcolor="##464646" width="scrWidth" height="scrHeight"
selectcolor="##FFCC99" selectmode="edit" selectonload="false" picturebar="yes" gridlines="yes" autowidth="yes"
bind="url:dummy.cfm?DbFunc=getRecords&SrcID={SrcID}&newSrcID={newSrcID}&flt_nm={flt_nm}&flt_iv={flt_iv}&flt_ct={flt_ct}&flt_sc={flt_sc}&flt_in={flt_in}&page={cfgridpage}&pageSize={cfgridpagesize}&sortCol={cfgridsortcolumn}&sortDir={cfgridsortdirection}"
onchange="url:dummy.cfm?DbFunc=doNothing&action={cfgridaction}&row={cfgridrow}&changed={cfgridchanged}"
font="arial" fontsize="14px" colheaderfont="arial" colheaderfontsize="14px" textcolor="##464646">
<cfgridcolumn name="si_id" header="ID" display="yes" select="no" width="45"/> <!--- FDB-164 --->
</cfgrid>
</cfform>
On the dummy.cfm
returns a query data in JSON format based on the Src Id selected

Related

Dynamic options not showing up after adding Chosen

Initially I had everything working with Chosen plugin when the options were directly passed from python to the html template.
I then tried to make the options filled dynamically depending on one of the buttons clicked, the options were not rendered so nothing showed up (but if I inspect the Elements, each optgroup was filled correctly with options).
And if I remove $(".chosen-select").chosen() , then the options are rendered.
Here's my code:
<!-- language: html -->
<div class="container" style="margin:auto; padding-top: 2%; text-align: center;">
<b>Choose the Program:</b>
<ul id="programs" class="no-bullets" data-tag="programList">
<li onclick="selectProgram(this)">Type1</li>
<li onclick="selectProgram(this)">Type2</li>
<li onclick="selectProgram(this)">Type3</li>
</ul>
<b>Choose the Documents:</b>
<select id="documentOptions" name="documents" data-placeholder="Your Documents" class="chosen-select" multiple>
<optgroup label="Group1" id="Group1"></optgroup>
<optgroup label="Group2" id="Group2"></optgroup>
<optgroup label="Group3" id="Group3"></optgroup>
</select>
</div>
<!-- language: lang-js -->
<script>
$(".chosen-select").chosen()
function selectProgram(el){
Array.prototype.slice.call(document.querySelectorAll('ul[data-tag="programList"] li')).forEach(function(element){
element.classList.remove('selected');
});
el.classList.add('selected');
programSelected = el.innerText;
//console.log(programSelected);
fetch(`/api/data/get_program/${programSelected}`)
.then(function(response){
return response.json();
}).then(function(documentList){
documentListJSON = {"documents":documentList};
//console.log(documentListJSON);
$.ajax({
type: 'POST',
url: '/api/data/programDocuments',
contentType: 'application/json',
data: JSON.stringify(documentListJSON),
success: function( allDocuments ){
console.log(allDocuments);
const Type1_Options = document.getElementById("Group1");
const Type2_Options = document.getElementById("Group2");
const Type3_Options = document.getElementById("Group3");
Type1_Options.innerHTML = "";
Type2_Options.innerHTML = "";
Type3_Options.innerHTML = "";
let docs_type1 = allDocuments['type1'];
let docs_type2 = allDocuments['type2'];
let docs_type3 = allDocuments['type3'];
// create list of options
var options = "";
for(var i = 0; i<docs_type1.length;i++){
options += "<option value='" + docs_type1[i] +"'>" + docs_type1[i] + "</option>";
}
Type1_Options.innerHTML += options;
$(Type1_Options).appendTo('#Group1');
var options = "";
for(var i = 0; i<docs_type2.length;i++){
options += "<option value='" + docs_type2[i] +"'>" + docs_type2[i] + "</option>";
}
Type2_Options.innerHTML += options;
$(Type2_Options).appendTo('#Group2');
var options = "";
for(var i = 0; i<docs_type3.length;i++){
options += "<option value='" + docs_type3[i] +"'>" + docs_type3[i] + "</option>";
}
Type3_Options.innerHTML += options;
$(Type3_Options).appendTo('#Group3');
}
})
})
}
</script>
I'm quite new to JavaScript and Jquery..Could someone please help explain why this happens?
Any help is very much appreciated. Thank you!

How to use if statments to run second function Google script

I am trying to speed up my script, right now I currently have it set up so that on a button click a custom dialog (HTML) appears asking some questions. On submit, it calls out a gs function to pull the info back as variables. Depending on the first answer I have a series of If statments that trigger. Each of them pull up a different template, make a copy, populate some cells, emails it to you, and then dumps the data into a tracker. Each of them are different so the script is rather long - is there a way to have each if statment its own function? Would this even help the speed? I am new to scripting so any feedback is appreciated. Below is the Code and HTML
function onOpen() //adds option to top row in case buttons are not working.
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('Create Doc.')
.addItem('Create Tracked Document', 'addItem')
.addToUi();
}
function addItem()//starts the initiation process
{
var html = HtmlService.createTemplateFromFile('form')
.evaluate()
.setWidth(300)
.setHeight(550);
SpreadsheetApp.getUi()
.showModalDialog(html, 'Create New Document');
}
function addNewItem(form_data)//pulls data from form
{
var ui = SpreadsheetApp.getUi();
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var n = new Date();
var now = ((n.getMonth()+1) + "/" + n.getDate() + "/" + n.getFullYear());
var doctyp = form_data.Document_Type;
var name = form_data.Name;
var title = form_data.Title;
var platform = form_data.Platform;
var area = form_data.Area;
var rota = form_data.Rotation;
var works = form_data.WorkSt;
var recipient = Session.getEffectiveUser().getEmail();
if (form_data.Document_Type == "Text2"){
var dumpfolder = DriveApp.getFolderById("12345")
var templateSheet = DriveApp.getFileById("67890");
var Newform2= templateSheet.makeCopy(title+ " "+now,dumpfolder);
var qs = SpreadsheetApp.open(Newform2);
var dropSheet = qs.getSheetByName("blank");
var URL3 = Newform2.getUrl();
dropSheet.getRange("i8").setValue(title);
dropSheet.getRange("bc5").setValue(now);
dropSheet.getRange("b5").setValue(platform);
dropSheet.getRange("p5").setValue(area);
dropSheet.getRange("x5").setValue(rota);
dropSheet.getRange("al5").setValue(works);
dropSheet.getRange("at6").setValue(name);
NewOPLPOA.setSharing(DriveApp.Access.DOMAIN,DriveApp.Permission.COMMENT);
NewOPLPOA.setOwner("ME");
sheet.appendRow([now,doctyp,name,title,platform,area,rota,works,URL3]);
GmailApp.sendEmail(recipient, title+ " has been created.", "Your document has been created." +'\n'+ "Here is the link to your copy! Link: " + URL3);
ui.alert("Email Sent", "An email has been sent with your documents link. You can also use the below link to view the document now, click ctrl C to copy. \
" + URL3, ui.ButtonSet.OK);
}
else if (form_data.Document_Type == "Text1"){
var dumpfolder = DriveApp.getFolderById("abcd")
var templateSheet = DriveApp.getFileById("bgtrd");
var Newform1 = templateSheet.makeCopy(title+ " "+now,dumpfolder);
var qs = SpreadsheetApp.open(Newform1);
var dropSheet = qs.getSheetByName("DOC1");
var URL4 = Newform1.getUrl();
dropSheet.getRange("aa3").setValue(platform);
dropSheet.getRange("ah3").setValue(area);
dropSheet.getRange("ao3").setValue(works);
NewSEWO.setSharing(DriveApp.Access.DOMAIN, DriveApp.Permission.COMMENT);
NewSEWO.setOwner("Me");
sheet.appendRow([now,doctyp,name,title,platform,area,rota,works,URL4]);
GmailApp.sendEmail(recipient, title+ " has been created.", "Your document has been created." +'\n'+ "Here is the link to your copy! Link: " + URL4);
ui.alert("Email Sent", "An email has been sent with your documents link. You can also use the below link to view the document now, click ctrl C to copy. \
" + URL4, ui.ButtonSet.OK);
}
else{
ui.alert("Error, Please try again, make sure you are listing all required information.");
}
}
--HTML--
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<form id="myform">
<div class="form-group">
<label for="Document_Type">Document Type</label>
<select class="form-control" id="Document_Type" name = "Document_Type" required="required">
<?
var SS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Set Up");
var Avals = SS.getRange("A2:A").getValues();
var numberOfValues = Avals.filter(String).length;
var RangeVals = SS.getRange(2,1,numberOfValues).getValues();
?>
<option disabled selected value> -- select an option -- </option>
<? for (var i = 0; i < RangeVals.length; ++i) { ?>
<option><?!= RangeVals[i] ?></option>
<? } ?>
</select>
</div>
<div class="form-group">
<label for ="Name">Your Name</label>
<select class="form-control" name='Name' id="Name" required="required">
<?
var AvalN = SS.getRange("E2:E").getValues();
var numberOfValuesN = AvalN.filter(String).length;
var RangeValsN = SS.getRange(2,5,numberOfValuesN).getValues();
?>
<option disabled selected value> -- select an option -- </option>
<? for (var i = 0; i < RangeValsN.length; ++i) { ?>
<option><?!= RangeValsN[i] ?></option>
<? } ?>
</select>
</div>
<div class="form-group">
<label for="Platform">Platform</label>
<select class="form-control" id="Platform" name = "Platform" required="required">
<?
var AvalP = SS.getRange("C2:C").getValues();
var numberOfValuesP = AvalP.filter(String).length;
var RangeValsP = SS.getRange(2,3,numberOfValuesP).getValues();
?>
<option disabled selected value> -- select an option -- </option>
<? for (var i = 0; i < RangeValsP.length; ++i) { ?>
<option><?!= RangeValsP[i] ?></option>
<? } ?>
</select>
</div>
<div class="form-group">
<label for="Area">Area</label>
<select class="form-control" id="Area" name = "Area" required="required">
<?
var AvalA = SS.getRange("D2:D").getValues();
var numberOfValuesA = AvalA.filter(String).length;
var RangeValsA = SS.getRange(2,4,numberOfValuesA).getValues();
?>
<option disabled selected value> -- select an option -- </option>
<? for (var i = 0; i < RangeValsA.length; ++i) { ?>
<option><?!= RangeValsA[i] ?></option>
<? } ?>
</select>
</div>
<div class="block form-group">
<label for="Rotation">Rotation</label>
<select class="form-control" name='Rotation' id="Rotation">
<?
var AvalR = SS.getRange("F2:F").getValues();
var numberOfValuesR = AvalR.filter(String).length;
var RangeValsR = SS.getRange(2,6,numberOfValuesR).getValues();
?>
<option disabled selected value> -- select an option -- </option>
<? for (var i = 0; i < RangeValsR.length; ++i) { ?>
<option><?!= RangeValsR[i] ?></option>
<? } ?>
</select>
</div>
<div class="block form-group">
<label for="WorkSt">Work Station</label>
<input type='text' name='WorkSt' id="WorkSt" />
</div>
<div class="block form-group">
<label for="Title">Title</label>
<input type='text' name='Title' id="Title" required="required"/>
</div>
<div class="block">
<button type="submit" class="action">Submit</button>
</div>
</form>
<script>
document.querySelector("#myform").addEventListener("submit",
function(e)
{
e.preventDefault(); //stop form from submitting
google.script.run.addNewItem(this);
google.script.host.close();//close this dialogbox
}
);
</script>
</body>
</html>
is there a way to have each if statement its own function?
For visibility purposes, you certainly can modify your code as
function addNewItem(form_data)//pulls data from form
{
var ui = SpreadsheetApp.getUi();
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var n = new Date();
var now = ((n.getMonth()+1) + "/" + n.getDate() + "/" + n.getFullYear());
var doctyp = form_data.Document_Type;
var name = form_data.Name;
var title = form_data.Title;
var platform = form_data.Platform;
var area = form_data.Area;
var rota = form_data.Rotation;
var works = form_data.WorkSt;
var recipient = Session.getEffectiveUser().getEmail();
if (form_data.Document_Type == "Text2"){
function1();
}
else if (form_data.Document_Type == "Text1"){
function2();
}
else{
ui.alert("Error, Please try again, make sure you are listing all required information.");
}
function function1(){
var dumpfolder = DriveApp.getFolderById("12345")
var templateSheet = DriveApp.getFileById("67890");
...
}
function function2(){
var dumpfolder = DriveApp.getFolderById("abcd")
...
}
Would this even help the speed?
Not really. To help up speed, you should rather try to implement Best Practices.
In particular: Reduce repeated calls to external services, including SpreadsheetApp.
For example, try to position the cells to which you want to assign values into an adjacent range, so you can use the method setValues() instead of multiple setValue() and thus make your code more efficient.
Sample:
var range = dropSheet.getRange("I8:N8");
var values = [];
values[0] = [];
values[0].push(title, now, platform, area, rota, works, name);
range.setValues(values);
Also, try to avoid repeating the same request for each if condition and rather make a single request after exiting the if statement, e.g. for:
sheet.appendRow([now,doctyp,name,title,platform,area,rota,works,URL3]);
GmailApp.sendEmail(recipient, title+ " has been created.", "Your document has been created." +'\n'+ "Here is the link to your copy! Link: " + URL3);
ui.alert("Email Sent", "An email has been sent with your documents link. You can also use the below link to view the document now, click ctrl C to copy. \
" + URL3, ui.ButtonSet.OK);
I hope this helps!

cfgrid not working after upgrade from Coldfusion 11 to Coldfusion 2018

After upgrading from CF11 to CF2018, Update 3, none of my editable cfgrids are working. When I make an edit and then submit the form, the columns seem to get jumbled. I created the simplest cfgrid I could (below) but am still getting the same behavior.
<cfif isDefined("form.submitname")>
<cfdump var="#form#">
<cfelse>
<cfform action="test.cfm" method="post" name="testform" id="testformId">
<cfinput type="Submit" name="submitname" id="submitid">
<cfgrid name="TestGrid" format="html" selectmode="edit">
<cfgridcolumn name="A">
<cfgridcolumn name="B">
<cfgridrow data="john,doe">
<cfgridrow data="steve,anon">
</cfgrid>
</cfform>
</cfif>
The grid displays correctly, but what I change 'john' to 'peter' and submit, I get the following dump:
enter image description here
As you can see, it thinks 'peter' was entered as both the first and last name, and it also thinks that 'peter' was the original first name.
When I modify any of the fields in the second column, I get the following javascript error in the console:
TypeError: _dd.values[_de] is undefined.
The error is thrown by cfgrid.js
If I submit only a change in the second column, the dump is completely empty.
It seems like the cfgrid is mixing up columns or something.
Your thoughts?
Ultimately the solution here is to move away from ColdFusion's implementation of <cfgrid> and roll your own grid-UI or.... wait for a patch from Adobe.
This is definitely a bug in ColdFusion, the error you are seeing is specifically a bug in the function ColdFusion.Grid.Actions.afterEdit()
I spent a little bit of time fiddling around with the JS generated with <cfgrid> and found that they index into the columns incorrectly
You can override ColdFusion's implementation of ColdFusion.Grid.Actions.afterEdit() with your own to create a possible workaround ( I ran on Solaris 11.4 - Apache - ColdFusion 2018 : Update 3 )
<Body>
<cfif isDefined("form.submitname")>
<cfdump var="#form#">
<cfelse>
<cfform action="test.cfm" method="post" name="testform" id="testformId">
<cfinput type="Submit" name="submitname" id="submitid">
<cfgrid name="TestGrid" format="html" selectmode="edit">
<cfgridcolumn name="A">
<cfgridcolumn name="B">
<cfgridrow data="john,doe">
<cfgridrow data="steve,anon">
</cfgrid>
</cfform>
</cfif>
<script>
ColdFusion.Grid.Actions.afterEdit = function(_d8, _d9, _da) {
var _db = _d9.value;
if (_db == this.editOldValue) {
return;
}
if (this.insertInProgress == false && this.onChangeFunction) {
this.onChangeHandler("U", this.selectedRow, _d9);
} else {
if (!this.dynamic) {
rowidx = _d9.rowIdx;
if (!rowidx && rowidx != 0) {
rowidx = _d9.row;
}
var _dc = ColdFusion.Grid.computeActualRow_editField(this.editFieldState, _d9.record.data.CFGRIDROWINDEX);
var _dd = this.editFieldState[_dc - 1];
var _de = _d9.colIdx;
if (!_de && _de != 0) {
_de = _d9.column;
}
_de = _de + 1;
if (_dd) {
if (this.multiRowSelection === true && this.insertInProgress == true) {
_de = _de - 1;
}
//-------------------------------------------------------------------
//Subtracted 1 from column index to correctly index array
//-------------------------------------------------------------------
_dd.values[_de -1][1] = _db;
} else {
var _df = this.grid.getStore().getById(_d9.record.data.CFGRIDROWINDEX);
_dd = ColdFusion.Grid.Actions.initEditState(this, "U", _df, _dc);
var _e0 = this.editOldValue + "";
if (_d9.column.type == "date") {
if (_e0 && typeof _e0 == "string") {
_e0 = new Date(_e0);
}
var _e1 = "F, j Y H:i:s";
if (_d9.column && _d9.column.format) {
_e1 = _d9.column.format;
}
_dd.values[_de][1] = Ext.Date.format(_db, _e1);
_dd.values[_de][0] = _e0 ? Ext.Date.format(_e0, _e1) : _e0;
} else {
//-------------------------------------------------------------------
//Subtracted 1 from column index to correctly index array
//-------------------------------------------------------------------
_dd.values[_de -1][0] = _e0;
_dd.values[_de -1][1] = _db;
}
}
ColdFusion.Grid.Actions.computeEditField(this);
}
}
this.editOldValue = null;
this.fireSelectionChangeEvent();
}
;
</script>
</BODY>
There are definitely a ton of other bugs plaguing this tag ... and its definitely worth noting that Lucee ( opensource ColdFusion engine) DOES NOT support this tag

Custom function works in ColdFusion 10/11 but throws error in Lucee

I have the following function, inherited from some CF code. It works, but only in ColdFusion version 10 and 11. I am not concerned with 2016 as no plans for upgrade. I'm trying to run it under Lucee, but it is not working.
<cffunction name="QueryToArray" access="public" returntype="array" output="false" hint="This turns a query into an array of structures.">
<!--- Define arguments. --->
<cfargument name="Data" type="query" required="yes" />
<cfscript>
var LOCAL = StructNew(); // Define the local scope.
LOCAL.Columns = data.getMetaData().getColumnLabels(); // Get the column names as an array.
LOCAL.QueryArray = ArrayNew(1); // Create an array that will hold the query equivalent.
for (LOCAL.RowIndex = 1 ; LOCAL.RowIndex LTE ARGUMENTS.Data.RecordCount;
LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
LOCAL.Row = StructNew();
for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen(LOCAL.Columns);
LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
LOCAL.ColumnName = LOCAL.Columns[LOCAL.ColumnIndex];
LOCAL.Row[LOCAL.ColumnName] = ARGUMENTS.Data[LOCAL.ColumnName][LOCAL.RowIndex];
}
ArrayAppend(LOCAL.QueryArray, LOCAL.Row);
}
return(LOCAL.QueryArray);
</cfscript>
</cffunction>
In Lucee, I tried making these changes:
<cffunction name="QueryToArray" access="public" returntype="array" output="false" hint="This turns a query into an array of structures.">
<!--- Define arguments. --->
<cfargument name="Data" type="query" required="yes" />
<cfscript>
var LOCAL = StructNew(); // Define the local scope.
LOCAL.Columns = data.getColumnlist(false); // Get the column names as an array.
LOCAL.QueryArray = ArrayNew(1); // Create an array that will hold the query equivalent.
for (LOCAL.RowIndex = 1 ; LOCAL.RowIndex LTE ARGUMENTS.Data.RecordCount;
LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
LOCAL.Row = StructNew();
for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen(LOCAL.Columns);
LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
LOCAL.ColumnName = LOCAL.Columns[LOCAL.ColumnIndex];
LOCAL.Row[LOCAL.ColumnName] = ARGUMENTS.Data[LOCAL.ColumnName][LOCAL.RowIndex];
}
ArrayAppend(LOCAL.QueryArray, LOCAL.Row);
}
return(LOCAL.QueryArray);
</cfscript>
</cffunction>
but I'm getting this error:
Message: Can't cast String [name,value] to a value of type [Array]
Detail: Java type of the object is java.lang.String
Stacktrace:
The Error Occurred in
C:\home\website\wwwroot\controller\production\cfc\kernel.cfc: line 12
10: LOCAL.RowIndex = (LOCAL.RowIndex + 1)){
11: LOCAL.Row = StructNew();
12: for (LOCAL.ColumnIndex = 1 ; LOCAL.ColumnIndex LTE ArrayLen(LOCAL.Columns);
13: LOCAL.ColumnIndex = (LOCAL.ColumnIndex + 1)){
14: LOCAL.ColumnName = LOCAL.Columns[LOCAL.ColumnIndex];
To get your code to work, all you need to do is change line 6 from
LOCAL.Columns = data.getColumnlist(false); // Get the column names as an array.
to this
LOCAL.Columns = data.getColumnNames(); // Get the column names as an array.
However I found a gist here that works in both ColdFusion and Lucee. I decided to create some sample code and test it at https://trycf.com/. I verified that it works in Lucee 4.5 and 5. It also works in ColdFusion 10, 11, 2016 as well. Hope this helps!
<!--- Create a new three-column query, specifying the column data types --->
<cfset myQuery = QueryNew("Name, Time, Advanced", "VarChar, Time, Bit")>
<!--- Make two rows in the query --->
<cfset QueryAddRow(MyQuery, 2)>
<!--- Set the values of the cells in the query --->
<cfset QuerySetCell(myQuery, "Name", "The Wonderful World of CMFL", 1)>
<cfset QuerySetCell(myQuery, "Time", "9:15 AM", 1)>
<cfset QuerySetCell(myQuery, "Advanced", False, 1)>
<cfset QuerySetCell(myQuery, "Name", "CFCs for Enterprise
Applications", 2)>
<cfset QuerySetCell(myQuery, "Time", "12:15 PM", 2)>
<cfset QuerySetCell(myQuery, "Advanced", True, 2)>
<h4>The query</h4>
<cfdump var="#myQuery#">
<h4>The array of objects</h4>
<cfset myArray = QueryToArray(myQuery)>
<cfdump var="#myArray#">
<cfscript>
/**
* #hint Returns reasonable array of objects from a cfquery
*/
public function queryToArray(
required query query,
string excludeColumns = ""
){
if (server.coldfusion.productName == "ColdFusion Server") {
local.columns = arguments.query.getMetaData().getColumnLabels();
} else if (server.coldfusion.productName == "Lucee") {
local.columns = arguments.query.getColumnNames();
} else {
local.columns = [];
}
local.response = arrayNew(1);
for (local.rowIndex=1; local.rowIndex<=arguments.query.recordCount; local.rowIndex++) {
local.response[local.rowIndex] = structNew();
for (local.columnIndex=1; local.columnIndex<=arrayLen(local.columns); local.columnIndex++) {
local.columnName = local.columns[local.columnIndex];
if(local.columnName != "" && (arguments.excludeColumns == "" || !listFindNoCase(arguments.excludeColumns, local.columnName))) {
local.response[local.rowIndex][local.columnName] = arguments.query[local.columnName][local.rowIndex];
}
}
}
return local.response;
}
</cfscript>

Why is the file I uploaded locked by ColdFusion 10?

I'm trying to delete the file if not a spreadsheet, but keep getting the following error when I uploaded testFile.text:
ColdFusion could not delete the file D:\ColdFusion10\cfusion\runtime\work\Catalina\localhost\tmp\testFile.text
I verified its not a permission issue, because if I go back and execute the code to try to delete the file again, it will work.
<cffile action="upload" destination="#dest#" filefield="xlsfile" result="upload" nameconflict="makeunique">
<cfif upload.fileWasSaved>
<cfset theFile = dest & upload.serverFile>
<cfif isSpreadsheetFile(theFile)>
<cfspreadsheet action="read" src="#theFile#" query="data" headerrow="1">
<cfset showForm = false>
<cfelse>
<cfscript>
thisFile = theFile;
fileRead = createObject("java", "java.io.FileInputStream");
thisThread = CreateObject("java", "java.lang.Thread");
loopCT = 1;
while(1 EQ 1)
{
try
{
fileRead.init(thisFile);
break;
}
catch(any ecpt)
{
thisThread.sleep(1000);
}
incrementValue(loopCT);
if(loopCT GT 60)
{
fileRead.close();
return;
}
}
loopCT = 1;
while(1 EQ 1)
{
sizeA = fileRead.available();
thisThread.sleep(1000);
sizeB = fileRead.available();
if(sizeA EQ sizeB)
{
thisThread.sleep(1000);
sizeC = fileRead.available();
if(sizeC EQ sizeB)
{
break;
}
}
incrementValue(loopCT);
if(loopCT GT 60)
{
fileRead.close();
return;
}
}
fileRead.close();
<script type="text/javascript">
</script>
</cfscript>
<!--cffile action="delete" file="#theFile#"-->
<cfset errors = "The file was not an Excel file.">
<span style="font-size:medium;font-weight:bold; color:red"><p>The file was not an excel file!<p></span>
<input type="button" value="TRY AGAIN" class="button" onClick="window.location='bulk_upload.cfm'">
<br><br><br>
</cfif>
<cfset errors = "The file was not properly uploaded.">
</cfif>
I ran into the exact same issue with regards to cfimage locking the file and preventing deletion. The solution I came up with follows. Maybe someone can adapt to their situation:
<cflock name="[lockName]" timeout="5" >
<cfcache action="flush">
<!---[] Replace cfimage read function (CF BUG work around) --->
<cfscript>
imageObj = createObject( "java", "java.awt.Toolkit" );
imagetools = imageObj.getDefaultToolkit();
objImage = imagetools.getImage( "#fullpath#" );
<!---Whatever image I need from the image, or file...--->
<!---such as ---- myImageStruct["width"] = objImage.getWidth();--->
<!--- and then flush the object--->
objImage.flush();
</cfscript>
</cflock>