使用simplexlsx在php中读取excel xlsx文件

10

我正在使用 simplexlsx.class.php 读取 xlsx 文件。当文件中包含日期字段时,它会出现问题。

示例输出:

在文件数据中:

Day Date Thursday 2/2/2012 Friday 2/3/2012

程序输出:

Day Date

Thursday 40941
Friday 40942

它没有给出正确的日期。

<?php

if (isset($_FILES['file'])) {

require_once "simplexlsx.class.php";

$xlsx = new SimpleXLSX( $_FILES['file']['tmp_name'] );

echo '<h1>Parsing Result</h1>';
echo '<table border="1" cellpadding="3" style="border-collapse: collapse">';

list($cols,) = $xlsx->dimension();

foreach( $xlsx->rows() as $k => $r) {
    if ($k == 0) continue; // skip first row
    echo '<tr>';
    for( $i = 0; $i < $cols; $i++)
    {

        echo '<td>'.( (isset($r[$i])) ? $r[$i] : '&nbsp;' ).'</td>';

    }
    echo '</tr>';
}
echo '</table>';
}

?>
<h1>Upload</h1>
<form method="post" enctype="multipart/form-data">
*.XLSX <input type="file" name="file"  />&nbsp;&nbsp;<input type="submit" value="Parse" />

1个回答

11
这是正确的日期,只不过是按照Excel内部格式:自1900年1月1日以来的天数(考虑1900年是闰年)。很明显,simplexlsx类中的某些内容正在将xlsx日期值转换为Excel内部格式。
我之前没用过simplexlsx(这让我很惊讶,因为我认为我知道所有的PHP Excel文件读取器/写入器库)... 但在代码中必须有一种处理该转换的方法,因此我想应该也会有一种方法来进行反向转换(将Excel时间戳转换为PHP日期)。
编辑
您要查找的方法已经在代码中了。
function unixstamp( $excelDateTime ) {
    $d = floor( $excelDateTime ); // seconds since 1900
    $t = $excelDateTime - $d;
    return ($d > 0) ? ( $d - 25569 ) * 86400 + $t * 86400 : $t * 86400;
}

我不能保证这是准确的。
进一步编辑。
function unixstamp( $excelDateTime ) {
    $d = floor( $excelDateTime ); // seconds since 1900
    $t = $excelDateTime - $d;
    return ($d > 0) ? ( $d - 25569 ) * 86400 + $t * 86400 : $t * 86400;
}


$dateVal = 40941;
$unixDateVal = unixstamp($dateVal);
var_dump($unixDateVal);
echo date('d-M-Y',$unixDateVal);

提供

float 1328140800

这个值看起来非常像今年正确范围内的Unix时间戳值,确实如此:

02-Feb-2012

看起来对我来说工作正常


无法工作...我将日期字段发送到unixstamp函数,它没有返回实际日期。 - MAK
只是想提一下,发现这个问题已经过了几年。该值可能是一个浮点数,表示日期时间值,例如43540.101599456。当您在Excel中打开时,它显示为“3/16/2019 2:26 AM”。使用date()方法可能会得到不同的答案,因为它将尝试以本地时间格式化(Excel显然不这样做)。您可以通过使用gmdate('Y-m-d H:i:s',$unixDateVal);来解决这个问题,以获得与Excel匹配的值。 - khartnett
@khartnett - 43540.101599456 应该是 MS Excel 序列化时间戳,而不是 Unix 时间戳... date()gmdate() 等函数使用的是 Unix 时间戳。它与本地时间毫无关系,而与它们完全不同类型的值有关,计算不同的时间间隔,并具有完全不同的基准点。 - Mark Baker
@MarkBaker,您是在说MS Excel序列化时间戳与您答案中的$excelDateTime不同吗?使用您答案中的计算方法,我能够得到正确的值,当考虑到时间时(与在Excel中打开时匹配)精确到分钟。因此它们肯定是相关的。 - khartnett
澄清一下,我并不是说43540.101599456是Unix时间戳,它仍然是自1900年1月1日以来的天数。似乎这种格式没有特定的时区,但使用您的计算将其转换为Unix时间戳将使其相对于UTC时区,并使用gmdate将正确地进行转换。 - khartnett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接