在ColdFusion 11中,我使用cfSpreadsheet将.xls文件转换为查询对象。以下是我的演示电子表格的屏幕截图:
我使用此代码在创建后立即查看查询对象:
<cfspreadsheet action="read" src="demo_spreadsheet.xls"
excludeHeaderRow="true"
headerrow="1" query="demo_query"/>
<cfdump var="#demo_query#">
......我得到了这些结果:
请注意,我在电子表格中的所有4位数年份现在都是2位数年份?当我使用以下代码输出查询对象中的数据时:
<ul>
<cfoutput query="demo_query">
<li>#name# - #dateformat(start_date, 'medium')#</li>
</cfoutput>
</ul>
...我得到以下输出(好吧,我是新来的,所以我不能发布超过两个屏幕截图,所以你必须相信我这个复制/粘贴):
1907年现在是2007年,1917年现在是2017年,1929年现在是2029年,2030年现在是1930年。看来1930年1月1日之前的任何一年的年份读作20xx,并且在2029年12月31日之后读作19xx。
我错过了什么吗?我以为我们用Y2K想出了这种事情。在某处我有不正确的简单设置吗?我已经用Google搜索了这个问题,我找不到任何相关信息。
欢迎任何建议。
答案 0 :(得分:4)
您的电子表格单元格很可能正在使用内置的regional format *m/d/yy
,这意味着显示的值(或者在这种情况下&#34;读取&#34;)可能会因使用的环境或客户端而异。
以星号(*)开头的日期和时间格式作出响应 更改在中指定的区域日期和时间设置 控制面板。没有星号的格式不受Control的影响 面板设置。
这似乎是cfspreadsheet发生的事情。不确定为什么Excel为格式*m/d/yy
显示四个数字年,而不是两位数。但是,CF / POI根据Excel规范返回正确的结果。请注意,如果您将单元格格式切换为非区域性的四位数年份,即m/d/yyyy
,则输出符合您的预期:
更新:至于为什么您的CF代码显示的年份与您预期的不同,这是由于CF处理的日期字符串有多么模糊。需要注意的是,CFSpreadsheet返回的查询包含 strings ,而不是日期对象。当您将这些字符串传递给DateFormat
时,CF必须首先解释字符串并将其转换为日期对象,然后才能应用日期掩码。 According to CF's rules,两位数的年份解释如下:
包含根据美国格式化的日期/时间值的字符串 区域约定。可以表示100 AD-9999范围内的日期/时间 广告。 0-29岁被解释为2000-2029; 30-99岁 解释为1930-1999。
老实说,CFSpreadsheet旨在提供一种简单的方式来读取和编写电子表格,而不需要花费很多精力。 AFAIK,它不支持更改单元格值的解释方式。如果要强制使用四位数年份,则必须手动或以编程方式更改电子表格以使用非区域日期格式(即,使用CF读取电子表格,然后应用新的单元格格式)。这可能是最简单的选择。
如果您希望在代码方面具有更大的灵活性,您还可以使用spreadsheet functions代替cfspreadsheet。虽然在这种特殊情况下,我认为他们也缺乏必要的功能。因此,您可能会考虑使用底层POI库和一些Java代码。 This thread演示了如何获取有关电子表格单元格和值的各种详细信息。可以很容易地修改它来构建自己的查询或包含值,格式等的结构数组:
<强>代码:强>
<cfscript>
// get the sheet you want to read
cfSheet = SpreadSheetRead("c:/temp/demo_spreadsheet.xls");
workbook = cfSheet.getWorkBook();
sheetIndex = workbook.getActiveSheetIndex();
sheet = workbook.getSheetAt( sheetIndex );
// utility used to distinguish between dates and numbers
dateUtil = createObject("java", "org.apache.poi.ss.usermodel.DateUtil");
// process the rows and columns
rows = sheet.rowIterator();
while (rows.hasNext()) {
currentRow = rows.next();
data = {};
cells = currentRow.cellIterator();
while (cells.hasNext()) {
currentCell = cells.next();
col = {};
col.value = "";
col.type = "";
col.column = currentCell.getColumnIndex()+ 1;
col.row = currentCell.getRowIndex()+ 1;
col.format = currentCell.getCellStyle().getDataFormatString();
if (currentCell.getCellType() EQ currentCell.CELL_TYPE_STRING) {
col.value = currentCell.getRichStringCellValue().getString();
col.type = "string";
}
else if (currentCell.getCellType() EQ currentCell.CELL_TYPE_NUMERIC) {
if (DateUtil.isCellDateFormatted(currentCell)) {
col.value = currentCell.getDateCellValue();
col.type = "date";
}
else {
col.value = currentCell.getNumericCellValue();
col.type = "number";
}
}
else if (currentCell.getCellType() EQ currentCell.CELL_TYPE_BOOLEAN) {
col.value = currentCell.getBooleanCellValue();
col.type = "boolean";
}
// ... handle other types CELL_TYPE_BLANK, CELL_TYPE_ERROR, CELL_TYPE_FORMULA
data["COL"& col.column] = col;
}
// this row is finished. display all values
WriteDump(data);
}
</cfscript>