cfspreadsheet 可以从查询中输出空值而不将它们更改为空白吗?
Can cfspreadsheet output null values from a query without changing them to blanks?
我正在 运行 宁 SQL 查询以获取一些数据。然后使用 CF 的电子表格功能将其导出为 Excel 文件。问题是查询中为空的单元格中出现了非空字符。当您打开电子表格时,它们看起来是空白的,但事实并非如此。它特别会干扰 Excel 的 ctrl-arrow 功能查找下一个非空白单元格的使用。
Field looks null but actually isn't
在数据库中,如果没有值,则颜色列为空。在 Excel 中,ctrl-向下箭头应将您带到单元格 D9 或 "blue",但事实并非如此。它将带您一直到该栏的底部。
如果在 Excel 中,我转到每个 "blank" 单元格,然后按删除键,然后功能 returns。很明显,Coldfusion 没有正确处理它。
我将范围缩小到 Coldfusion,因为如果我 运行 在 SSMS 中使用相同的查询,然后将数据从那里剪切并粘贴到 Excel 中,它会保留空值,并且 ctrl-downarrow 有效正确。
<cfquery datasource="test" name="qdata">
select ID,Name,Email,Color from TestTable
</cfquery>
<cfscript>
columns = qdata.getMetaData().getColumnLabels();
sheet=spreadsheetNew("Sheet1",true);
spreadsheetAddrows(sheet,qdata,1,1,true,[""],true);
sheetAsBinary = SpreadSheetReadBinary( sheet );
</cfscript>
<cfset filename = "TestFile.xlsx">
<cfheader name="Content-Disposition" value="attachment; filename=#filename#">
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" variable="#sheetAsBinary#" reset="true">
所使用的查询实际上是无关紧要的,因为我可以用 returns 字段中某些字段为 null 的任何查询重现该问题。
我最终结合使用了一些东西来让它工作。循环查询并为每一列使用 SpeadSheetSetCellValue,并使用 if 语句检查列是否为空。如果它为空,我根本就没有填充该列。现在,这有效。
感谢大家的评论,感谢@Ageax 引导我找到最终的解决方案。
这是我改编自 this post:
的最终代码(不包括查询,无关紧要)
<cfsilent>
<cfscript>
variables.cont = false;
/*variables.qdata is the name of my query object*/
switch(IsQuery(variables.qdata)){
case true:
variables.cont = true;
variables.rqCols = ArrayToList(variables.qdata.getColumnNames(),',');
variables.rqLen = ListLen(variables.rqCols,',');
variables.thisFileName = "JSM2020ProgramExport-" & DateTimeFormat(now(),'yyyymmdd_HHnnss') & ".xlsx";
variables.ssObj = SpreadsheetNew(left(trim(variables.thisFileName),30),'true');/* Setting last argument to 'true' makes this an xlsx, not xls. */
variables.format = StructNew();
variables.format.font = "Arial";
variables.format.textwrap = "true";
variables.format.verticalalignment = "VERTICAL_TOP";
variables.format.dataformat = "text";
SpreadsheetFormatColumns(variables.ssObj,variables.format,"1-#val(variables.rqLen)#");
SpreadsheetFormatRows(variables.ssObj,variables.format,"1,2");
SpreadsheetSetCellValue(variables.ssObj,variables.thisFileName, 1, 1); /* This is the name of the report, top row */
SpreadsheetAddFreezePane(variables.ssObj,0,2); /* Freeze top two rows */
for(x = 1; x lte val(variables.rqLen); x++){ /* This inserts the column names as row headers */
variables.colName = ListGetAt(variables.rqCols,x);
SpreadsheetSetCellValue(variables.ssObj,variables.colName,2,x);
}
for(y = 1; y lte val(variables.qdata.recordCount); y++){ /* This loops the query records */
for(x = 1; x lte val(variables.rqLen); x++){ /* This loops each column per recordset */
variables.colName = ListGetAt(variables.rqCols,x);
variables.thisValue = REreplaceNoCase(variables.qdata[variables.colName][y],"&##59;",";","all"); /* These make sure that no HTML entities are in the data */
variables.thisValue = REreplaceNoCase(variables.thisValue,"&apos(&##59)?;","'","all");
variables.thisValue = REreplaceNoCase(variables.thisValue,""(&##59)?;",'"',"all");
variables.thisValue = REreplaceNoCase(variables.thisValue,"<(&##59)?;",'<',"all");
variables.thisValue = REreplaceNoCase(variables.thisValue,">(&##59)?;",'>',"all");
variables.thisValue = REreplaceNoCase(variables.thisValue,"&##40(&##59|;)","(","all");
variables.thisValue = REreplaceNoCase(variables.thisValue,"&##41(&##59|;)",")","all");
if (variables.thisValue is not 'NULL'){SpreadsheetSetCellValue(variables.ssObj,variables.thisValue,val(y + 2),x);}
}
}
SpreadsheetFormatColumns(variables.ssObj,variables.format,"1-#val(variables.rqLen)#");
SpreadsheetFormatRows(variables.ssObj,variables.format,"1,2");
break;
default: /* Do nothing if the query object doesn't exist */
break;
}
</cfscript>
</cfsilent>
我正在 运行 宁 SQL 查询以获取一些数据。然后使用 CF 的电子表格功能将其导出为 Excel 文件。问题是查询中为空的单元格中出现了非空字符。当您打开电子表格时,它们看起来是空白的,但事实并非如此。它特别会干扰 Excel 的 ctrl-arrow 功能查找下一个非空白单元格的使用。
Field looks null but actually isn't 在数据库中,如果没有值,则颜色列为空。在 Excel 中,ctrl-向下箭头应将您带到单元格 D9 或 "blue",但事实并非如此。它将带您一直到该栏的底部。
如果在 Excel 中,我转到每个 "blank" 单元格,然后按删除键,然后功能 returns。很明显,Coldfusion 没有正确处理它。
我将范围缩小到 Coldfusion,因为如果我 运行 在 SSMS 中使用相同的查询,然后将数据从那里剪切并粘贴到 Excel 中,它会保留空值,并且 ctrl-downarrow 有效正确。
<cfquery datasource="test" name="qdata">
select ID,Name,Email,Color from TestTable
</cfquery>
<cfscript>
columns = qdata.getMetaData().getColumnLabels();
sheet=spreadsheetNew("Sheet1",true);
spreadsheetAddrows(sheet,qdata,1,1,true,[""],true);
sheetAsBinary = SpreadSheetReadBinary( sheet );
</cfscript>
<cfset filename = "TestFile.xlsx">
<cfheader name="Content-Disposition" value="attachment; filename=#filename#">
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" variable="#sheetAsBinary#" reset="true">
所使用的查询实际上是无关紧要的,因为我可以用 returns 字段中某些字段为 null 的任何查询重现该问题。
我最终结合使用了一些东西来让它工作。循环查询并为每一列使用 SpeadSheetSetCellValue,并使用 if 语句检查列是否为空。如果它为空,我根本就没有填充该列。现在,这有效。
感谢大家的评论,感谢@Ageax 引导我找到最终的解决方案。
这是我改编自 this post:
的最终代码(不包括查询,无关紧要)<cfsilent>
<cfscript>
variables.cont = false;
/*variables.qdata is the name of my query object*/
switch(IsQuery(variables.qdata)){
case true:
variables.cont = true;
variables.rqCols = ArrayToList(variables.qdata.getColumnNames(),',');
variables.rqLen = ListLen(variables.rqCols,',');
variables.thisFileName = "JSM2020ProgramExport-" & DateTimeFormat(now(),'yyyymmdd_HHnnss') & ".xlsx";
variables.ssObj = SpreadsheetNew(left(trim(variables.thisFileName),30),'true');/* Setting last argument to 'true' makes this an xlsx, not xls. */
variables.format = StructNew();
variables.format.font = "Arial";
variables.format.textwrap = "true";
variables.format.verticalalignment = "VERTICAL_TOP";
variables.format.dataformat = "text";
SpreadsheetFormatColumns(variables.ssObj,variables.format,"1-#val(variables.rqLen)#");
SpreadsheetFormatRows(variables.ssObj,variables.format,"1,2");
SpreadsheetSetCellValue(variables.ssObj,variables.thisFileName, 1, 1); /* This is the name of the report, top row */
SpreadsheetAddFreezePane(variables.ssObj,0,2); /* Freeze top two rows */
for(x = 1; x lte val(variables.rqLen); x++){ /* This inserts the column names as row headers */
variables.colName = ListGetAt(variables.rqCols,x);
SpreadsheetSetCellValue(variables.ssObj,variables.colName,2,x);
}
for(y = 1; y lte val(variables.qdata.recordCount); y++){ /* This loops the query records */
for(x = 1; x lte val(variables.rqLen); x++){ /* This loops each column per recordset */
variables.colName = ListGetAt(variables.rqCols,x);
variables.thisValue = REreplaceNoCase(variables.qdata[variables.colName][y],"&##59;",";","all"); /* These make sure that no HTML entities are in the data */
variables.thisValue = REreplaceNoCase(variables.thisValue,"&apos(&##59)?;","'","all");
variables.thisValue = REreplaceNoCase(variables.thisValue,""(&##59)?;",'"',"all");
variables.thisValue = REreplaceNoCase(variables.thisValue,"<(&##59)?;",'<',"all");
variables.thisValue = REreplaceNoCase(variables.thisValue,">(&##59)?;",'>',"all");
variables.thisValue = REreplaceNoCase(variables.thisValue,"&##40(&##59|;)","(","all");
variables.thisValue = REreplaceNoCase(variables.thisValue,"&##41(&##59|;)",")","all");
if (variables.thisValue is not 'NULL'){SpreadsheetSetCellValue(variables.ssObj,variables.thisValue,val(y + 2),x);}
}
}
SpreadsheetFormatColumns(variables.ssObj,variables.format,"1-#val(variables.rqLen)#");
SpreadsheetFormatRows(variables.ssObj,variables.format,"1,2");
break;
default: /* Do nothing if the query object doesn't exist */
break;
}
</cfscript>
</cfsilent>