判断Excel 2007电子表格中xlsx单元格是否为日期格式
我正在处理一些代码,这些代码通过解析xml来读取xlsx文件中的数据。整体过程都挺简单的,唯一复杂的地方是日期单元格。
日期是以整数形式存储的,并且有一个“s”属性,这个属性是样式表中的一个索引,可以用来获取日期格式字符串。以下是之前在StackOverflow上提到的一些例子:
19 = 'h:mm:ss AM/PM';
20 = 'h:mm';
21 = 'h:mm:ss';
22 = 'm/d/yy h:mm';
这些是ooxml标准中内置的日期格式字符串,不过看起来Excel通常会使用自定义的格式字符串,而不是这些内置的。下面是一个来自Excel 2007电子表格的格式示例。numFmtId大于164的就是自定义格式。
<numFmt formatCode="MM/DD/YY" numFmtId="165"/>
判断一个单元格是否应该格式化为日期是比较困难的,因为我能找到的唯一指示就是formatCode。这个显然是一个日期,但单元格的格式可能有很多种。我最初的尝试是查找formatCode中的M、D和Y,但这似乎有点问题。
有没有人解决过这个问题?目前看起来标准的Excel读取库在xlsx支持方面有些不足。我已经阅读了相关标准,并且翻阅了很多xlsx文件,但没有太大进展。
看起来最好的信息来自于这个StackOverflow的问题:
什么表示一个Office Open XML单元格包含日期时间值
谢谢!
2 个回答
仅仅寻找数字格式代码中的Ms、Ds和Ys是不够的。
[Red]#,##0 ;[Yellow](#,##0)
这个格式是完全有效的数字格式,它同时包含Y和D,但它并不是日期格式。我特别检查了所有标准的日期/时间格式字符('y'、'm'、'd'、'H'、'i'、's'),这些字符是在方括号('[' ']')之外的。即便如此,我发现还是有一些错误的情况出现,主要和会计和货币格式有关。因为这些格式通常以一个下划线('_')或一个空格后面跟着零(' 0')开头(而这些在日期格式中我从未见过),所以我特别把这些值过滤掉。
这是我(PHP)代码的一部分,用来判断一个格式是否是日期格式:
private static $possibleDateFormatCharacters = 'ymdHis';
// Typically number, currency or accounting (or occasionally fraction) formats
if ((substr($pFormatCode,0,1) == '_') || (substr($pFormatCode,0,2) == '0 ')) {
return false;
}
// Try checking for any of the date formatting characters that don't appear within square braces
if (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$pFormatCode)) {
return true;
}
// No date...
return false;
我相信可能还有一些我没有考虑到的例外情况,但如果有的话,它们可能都是极端的例子。
日期是以整数形式存储的
在Excel的数据模型中,其实没有真正的整数。所有的东西都是浮点数。日期和时间都是浮点数,表示从某个特定时间点开始的天数和小数部分。时间则是一天的一部分。
目前看来,标准的Excel读取库在支持xlsx格式方面有些不足。
可以在网上搜索“xlsxrd”。为了保持更新,可以加入python-excel小组。
编辑 我看到你在那里已经问过一个问题。如果你在那儿问的问题和这个一样具体,或者回应我请求澄清的内容,你早就能得到这些信息了。
看看xlrd的文档。在前面有关于Excel日期的讨论。这些内容适用于Excel 2007以及更早的版本。特别是:需要解析自定义格式。还需要有一个“标准”格式索引表,用于日期格式。有些地方列出的“标准”格式不包括CJK地区使用的格式。
你可以选择:
(1) 从xlrd
的源代码中借用,包括xldate_as_tuple函数。
(2) 选项(1) + 获取xlsxrd
的附加工具包,并从它的源代码中借用。
(3) [推荐] 获取xlsxrd
的附加工具包并使用它……你将获得一套可以在Excel 2.0到2007版本和Python 2.1到2.7版本之间操作的API。