cfSpreadsheet 2位数年份

在ColdFusion 11中,我使用cfSpreadsheet将.xls文件转换为查询对象。 以下是我的演示电子表格的屏幕截图:

电子表格的屏幕截图

我使用这段代码来创build查询对象:

<cfspreadsheet action="read" src="demo_spreadsheet.xls" excludeHeaderRow="true" headerrow="1" query="demo_query"/> <cfdump var="#demo_query#"> 

…我得到这些结果:

显示查询对象转储的png

请注意,电子表格中的所有4位数年份现在都是2位数年份? 当我去使用这个代码输出查询对象中的数据时:

 <ul> <cfoutput query="demo_query"> <li>#name# - #dateformat(start_date, 'medium')#</li> </cfoutput> </ul> 

…我得到下面的输出(好吧,我是新来的,所以我不能发布两个以上的屏幕截图,所以你不得不相信我在这个复制/粘贴):

  • 阿尔法 – 2007年1月1日
  • 布拉沃 – 1972年2月2日
  • 查理 – 2017年3月3日
  • 三angular洲 – 1984年4月4日
  • 回声 – 2029年12月31日
  • Foxtrot – 1930年1月1日
  • 高尔夫 – 1930年1月1日

1907年现在是2007年,1917年现在是2017年,1929年现在是2029年,2030年现在是1930年。看来,1930年1月1日之前的任何一年的年份被认为是20xx年,而2029年12月31日之后的年份被认为是19xx年。

我错过了什么吗? 我认为我们用2000年数字来看待这种情况。 有没有一个简单的设置,我有不正确的地方? 我已经Google了谷歌这个问题,我什么都找不到。

任何build议将是最受欢迎的。

很可能您的电子表格单元格正在使用内置的区域格式*m/d/yy ,这意味着显示的值(在本例中为“读取”)可能会因使用的环境或客户端而异。

以星号(*)开头的date和时间格式响应“控制面板”中指定的区域date和时间设置的更改。 不带星号的格式不受控制面板设置的影响。

这似乎是cfspreadsheet正在发生的事情。 不知道为什么Excel格式*m/d/yy显示四位数年份,而不是两位数字。 但是,根据Excel规范,CF / POI正在返回正确的结果。 请注意,如果您将单元格格式切换为非区域性四位数年份,即m/d/yyyy则输出结果如您所料:

区域和非区域格式的比较 非地区日期格式

更新:至于为什么你的CF代码显示不同于你预期的年份,这是由于如何模糊的datestring由CF处理。 重要的是要注意,由CFSpreadsheet返回的查询包含string ,而不是date对象。 将这些string传递到DateFormat ,CF必须首先解释这些string,然后将它们转换为date对象,然后才能应用date掩码。 根据CF的规定 ,两位数年解释如下:

包含根据美国语言环境惯例格式化的date/时间值的string。 可以代表100 AD-9999 AD范围内的date/时间。 0 – 29年被解释为2000 – 2029年; 年30-99被解释为1930-1999。

老实说,CFSpreadsheet旨在提供一个简单的方法来读取和写入电子表格,没有太多的花里胡哨。 AFAIK,它不支持改变单元格值的解释方式。 如果要强制四位数年份,则必须手动或以编程方式将电子表格更改为使用非区域性date格式(即使用CF读取电子表格并应用新的单元格格式)。 这可能是最简单的select。

如果您希望在代码方面有更大的灵活性,您也可以使用电子表格函数而不是cfspreadsheet。 虽然在这个具体案例中,我认为他们也缺乏必要的特征。 所以你可能会考虑使用底层的POI库和一些Java代码。 此线程演示如何获取有关电子表格单元格和值的各种细节。 它可以很容易地修改,以build立自己的查询或包含值,格式等结构数组:

包含单元格数据的结构数组

码:

 <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>