簡體   English   中英

在Spreadsheet :: ParseExcel中識別日期類型

[英]Identifying date types in Spreadsheet::ParseExcel

我們正在從基於MS Excel OLE的模塊遷移到Spreadsheet::ParseExcel (或類似文件)。 由於我們有數百個使用模塊的程序,因此我們希望替換掉,即返回的數據相同。

問題是日期-使用Excel,我們得到類型為VT_DATEWin32::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模塊的情況下准備就緒。

您知道什么列應該是日期嗎?

在我的用法中,我這樣做,並將其轉換為:

$val = $cell->unformatted();
# if it was properly set as a Date cell, the value will be a number of days since 1900 or 1904
# that we can convert to a date, regardless of the format they were shown.
if ( $val =~ /^[0-9]{5}(?:\.[0-9]+)?\z/ ) {
    $date = Spreadsheet::ParseExcel::Utility::ExcelFmt( 'YYYY-MM-DD', $val, $wb->{'Flg1904'} );
}
else {
    $val = $cell->value();
    $val =~ s/^'//;
    # try parsing it with Date::Manip, which handles all common formats (see its ParseDateString doc)
    use Date::Manip ();
    Date::Manip::Date_Init("TZ=GMT","DateFormat=US");
    $date = Date::Manip::UnixDate( $val, '%Y-%m-%d' );
}

更新:聽起來您最好修改ExcelFmt,類似這樣(未經測試):

--- Utility.pm.orig 2014-12-17 07:16:06.609942082 -0800
+++ Utility.pm  2014-12-17 07:18:14.453965764 -0800
@@ -69,7 +69,7 @@
 #
 sub ExcelFmt {

-    my ( $format_str, $number, $is_1904, $number_type, $want_subformats ) = @_;
+    my ( $format_str, $number, $is_1904, $number_type, $want_subformats, $want_format_mode ) = @_;

     # Return text strings without further formatting.
     return $number unless $number =~ $qrNUMBER;
@@ -956,8 +956,14 @@
     $result =~ s/^\$\-/\-\$/;
     $result =~ s/^\$ \-/\-\$ /;

-    # Return color and locale strings if required.
-    if ($want_subformats) {
+    # Return format mode and/or color and locale strings if required.
+    if ( $want_subformats && $want_format_mode ) {
+        return ( $result, $color, $locale, $format_mode );
+    }
+    elsif ($want_format_mode) {
+        return ( $result, $format_mode );
+    }
+    elsif ($want_subformats) {
         return ( $result, $color, $locale );
     }
     else {

確保將其提交給維護者,以包括在以后的版本中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM