在PHP

时间:2016-02-06 10:52:14

标签: php excel phpexcel

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

对于我的项目,我想使用PHP自动从国家排球协会(Nevobo)下载并阅读Excel file。下载很好。阅读没有。这个问题似乎与以下事实有关:前8个字​​节中没有签名告诉PHPExcel它是一个OLE文件,因此PHPExcel将其识别为CSV文件,但绝对不是。 Excel本身可以打开该文件,但会强制我将其保存在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
}

1 个答案:

答案 0 :(得分:0)

LibreOffice会将该文件作为Excel文件读取,因此即使file magic将其标识为Apple BASIC(!)以及其他实用程序为TARGA,此必须为LibreOffice的已知格式(这意味着“长度为3的长度的二进制数据”)。

但是,这是一种分隔文字格式。可能它是一个文字处理器格式,奇怪的字符是用于制表和输入的控制字符吗?

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

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

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

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

我不能使用序列作为分隔符的CSV分析,因为序列在整个文件中是不同的。它们通常还包括回车符,它强制使用正则表达式中的空格/线修饰符。

此解析器似乎有效:

<?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
        ...
    )