【发布时间】:2015-02-15 10:56:58
【问题描述】:
我们正在从基于 MS Excel OLE 的模块迁移到 Spreadsheet::ParseExcel(或类似模块)。由于我们有数百个程序在使用我们的模块,因此我们希望我们提供一个替换,即返回的数据是相同的。
问题在于日期 - 使用 Excel,我们得到一个 VT_DATE 类型的 Win32::OLE::Variant 对象。作为一种解决方法,我们可以通过检查$cell->type() eq 'Date' 并返回对象来手动构造它。
问题是类型设置不可靠,所以我们不能总是这样做。
Date 类型设置在两个地方。这是FmtDefault.pm中使用的逻辑:
if ( ( ( $iFmtIdx >= 0x0E ) && ( $iFmtIdx <= 0x16 ) )
|| ( ( $iFmtIdx >= 0x2D ) && ( $iFmtIdx <= 0x2F ) ) )
{
return "Date";
}
如果此检查失败并且我们得到Numeric,那么它会在ParseExcel.pm 中进行备份检查:
if ( $FmtStr =~ m{^[dmy][-\\/dmy]*$}i ) {
$rhKey{Type} = "Date";
}
但是,一些常见的格式字符串不起作用,例如:
[$-C09]dddd\\,\\ d\\ mmmm\\ yyyy;@ i.e. Sunday, 24 January 1982
d/m/yyyy;@ i.e. 24/1/1982
我在 openoffice.org 上检查了 Excel 规范,还阅读了诸如 http://jonvonderheyden.net/excel/a-comprehensive-guide-to-number-formats-in-excel/#date_code 之类的指南,似乎以下规则将匹配日期格式字符串:
包含 d、m 或 y 字符的字符串,它们不在 "" 或 [] 之间,除非它是 \\,否则不以 \ 开头,并且后面不带 - 或 *。
这看起来非常复杂且容易出错。有没有更好的办法?
似乎Spreadsheet::ParseExcel::Utility::ExcelFmt() 在$format_mode 下标记了一个日期格式,所以也许可以修改此逻辑以返回该标记?但如果可能的话,我更希望在不更改 Spreadsheet::ParseExcel 模块的情况下准备好一些东西。
【问题讨论】:
标签: excel perl parsing spreadsheet