在 PHP 中读取 Excel 个没有签名的文件

Read Excel file without signature in PHP

问题:如何读取或修改没有签名的 Excel 文件以允许 PHP 正确解析它?

对于我的项目,我想自动下载并阅读 Excel file from the national volleyball association (Nevobo) using PHP. Downloading goes fine. Reading does not. The issue seems to be related to the fact that there's no signature in the first 8 bytes that tell PHPExcel that it is an OLE file, as such PHPExcel identifies it as a CSV file, which it definitely is not. Excel itself can open the file but will force me to save it in a different format

我以前从同一来源下载过文件(虽然内容不同),但也没有签名。但是,在这些文件上,我设法过滤了 PHP 中的所有控制字符(\x00\xFF),并在看到日期时自动创建一个新行(因为它们都在列中A), 不幸的是,这不适用于此文件。

function cleanPart ( $part )
{
    $part = trim(preg_replace('/[\x00\x01\x03-\x0A\x0D-\x1F\x80-\xFF]/', '', trim($part, ' ')), ' ');
    $part = preg_replace('/\x0B/', "\x0C", $part);
    $part = preg_replace('/\"/', "\x0C", $part);
    $part = preg_replace('/\x0C+/', "\x0C", $part);
    $part = preg_replace('/\x0C\x02/', "\x0C", $part);
    if ( $part == "\x02\x0C" || $part == "\x02\x0B" ) return false;
    $part = trim(preg_replace('/[\x00-\x1F\x80-\xFF]/', "\x02", $part), ' ');
    $part = trim(preg_replace('/\x02+/', "\x02", $part), ' ');
    $part = trim(preg_replace('/[\x00\x01\x03-\x1F\x80-\xFF]/', '', $part), ' ');
    if ( strlen($part) == 0 ) return false;
    $part = trim(preg_replace('/\x02/', "", $part), ' ');

    return $part;
}

foreach ( explode("\x04", preg_replace('!\x04+!', "\x04", $data)) as $part )
{
    if ( ! ( $part = cleanPart($part) ) )
    {
        continue;
    }

    // create array
}

LibreOffice 确实将文件读取为 Excel 文件,因此此 必须 是 LibreOffice 已知的格式,即使 file magic 将其识别为 Apple BASIC (!) 和其他实用程序如 TARGA(这意味着比 "binary data with length multiple of three" 多一点)。

但是,这是一种带分隔符的文本格式。可能是文字处理器格式,奇怪的字符是制表和打字的控制字符?

要更可靠地转换为 CSV 类型,您可以将所有控制序列替换为制表,跳过前 12 个字符。所有控制序列似乎也是 12 个字节长,以 \x04 \x02 为前缀,所以:

$clean = preg_replace('#\x04\x02..........#ms', "\t", substr($dirty, 24));

(我也跳过了第一个控制序列,跳过了 12+12 = 24 个字节)。

然后您可以拆分成字段块,然后 PHP CSV 解析函数应该可以工作,每行 20 个字段。

我无法使用序列作为分隔符使用 CSV 解析,因为整个文件中的序列不同。它们还经常包含回车 returns,这会强制在正则表达式中使用 whitespace/line 修饰符。

此解析器似乎可以工作:

<?php
$clean = preg_split(
    '#\x04\x02..........#ms',
    substr(file_get_contents('excelgen.xls'), 24)
);
$rows  = array();
while (!empty($clean)) {
    $rows[]   = array_splice($clean, 0, 20);
}
// $header = array_shift($rows);
print_r($rows);

产量:

Array
(
[0] => Array
    (
        [0] => Datum
        [1] => Tijd
        [2] => Team thuis
        [3] => Team uit
        [4] => Locatie
        [5] => Veld
        [6] => Regio
        [7] => Poule
        [8] => Code
        [9] => Zaal code
        [10] => Zaal
        [11] => Plaats
        [12] => Eerste scheidsrechter
        [13] => Tweede scheidsrechter
        [14] => Rapporteur / begeleider / Jurylid
        [15] => Lijnrechter 1
        [16] => Lijnrechter 2
        [17] => Lijnrechter 3
        [18] => Lijnrechter 4
        [19] => Reserve
...
...
[54] => Array
    (
        [0] => 2016-04-23
        [1] => 19:30
        [2] => Ecare Apollo 8 HS 1
        [3] => Lycurgus HS 2
        [4] => de Veste, Borne
        [5] => 1
        [6] => Nationaal
        [7] => 1AH
        [8] => AL
        [9] => BNEVE
        [10] => de Veste
        [11] => Borne
        ...
    )