问题:如何在没有签名的情况下读取或修改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
}
答案 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
...
)