【问题标题】:Read Excel file without signature in PHP在PHP中读取没有签名的Excel文件
【发布时间】:2016-02-06 10:52:13
【问题描述】:

问题:如何读取或修改没有签名的 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
}

【问题讨论】:

  • 欢迎来到 SO。请阅读What topics can I ask aboutHow to ask a good questionthe perfect question SO 不是免费的编码或教程服务 你必须证明你已经为解决自己的问题付出了一些努力。
  • 您正在下载一个带有 xlsx 扩展名的 csv 文件。在不使用服务器端脚本的情况下从 html 构建 excel 的最快方法。 csv有什么问题?你可以在没有phpexcel的情况下用php解析它!这对你来说更容易!
  • 该文件当然没有 Excel 签名,但我不知道它到底是什么
  • @RiggsFolly 我编辑了我的帖子以反映我在解析此文件时所做的代码尝试。我也为 unix excel 修复脚本做了很多谷歌搜索,但没有任何成功。有一个网站可以让您上传文件并为您修复它,但与在 Excel 中打开并重新保存相比没有优势。
  • Marco Pontello's identifier 以 100.0% 的把握表明它是 100.0% Targa 位图(原始 TGA 格式)?!?

标签: php excel phpexcel


【解决方案1】:

LibreOffice 确实将该文件作为 Excel 文件读取,因此此必须是 LibreOffice 已知的格式,即使 file magic 将其标识为 Apple BASIC (!) 并将其他实用程序标识为 TARGA(其中仅表示“长度为三的倍数的二进制数据”)。

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

要在 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
        ...
    )

【讨论】:

  • 谢谢,我从来没有想过每列之间有 12 个字节的控制字符,因为我一直更专注于在特定控制字符中查找模式。似乎在最后一列中,它重复了\x04 \x02 \x12,但不幸的是,这也发生在其他一些地方,这绝对是一个很好的起点。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2018-08-21
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-14
  • 1970-01-01
相关资源
最近更新 更多