使用PHP“pack”功能将数据下载到Excel时出现问题

时间:2011-08-12 18:39:31

标签: php excel

我有一个PHP应用程序,可以将MySQL表数据下载到客户端计算机上的电子表格中。我在Web上的许多地方找到了一些代码,可以在运行Redhat的机器上运行Open Office Scalc。我遇到的问题是当我尝试在Windows PC上下载到MS Excel而不是Open Office电子表格时。问题似乎与插入单元格的字符串的长度有关。如果它太长,Excel认为该文件已损坏并且不会加载它。 “太长”似乎是大约255个字符,即使MS Excel规格说32,000是最大长度。

为了进一步调查此问题,我尝试下载与制表符分隔值文件相同的数据,然后让Excel将其转换为电子表格。使用该方法,将非常长的字符串加载到电子表格单元格中没有问题。因此,长度超过255个字符的字符串实际上可以插入到Excel单元格中,但是不能使用我正在使用的代码,即使该代码适用于Open Office。使用tsv文件无法解决我们的问题,因为长字符串具有我们想要保留的回车符,并且当tsv文件加载到电子表格时,回车符被解释为行分隔符。

将字符串写入电子表格单元格的PHP函数是:

 function xlsWriteLabel($Row, $Col, $Value ) {
     $L = strlen($Value);
     echo pack("ssssss", 0x204, 8 + $L, $Row, $Col, 0x0, $L);
     echo $Value;
     return;
 }

除了上述功能外,还可以在以下网址找到转发到电子表格的其他必要代码:

http://www.appservnetwork.com/modules.php?name=News&file=article&sid=8

我没有找到关于上面代码中传递给“pack”函数的各种参数的含义的任何解释,我想知道如果更改上面函数中的参数可以解决问题。

所以,如果有人能解决这个问题,我有兴趣听听它。

3 个答案:

答案 0 :(得分:1)

...除非你的文字有双引号。

您应该使用的是ASCII字符集中的正确分隔符。

Seq    Dec    Hex    Acro   Name
^\     28     1C     FS     File Separator      
^]     29     1D     GS     Group separator     
^^     30     1E     RS     Record Separator    
^_     31     1F     US     Unit separator  

我不知道php,但在perl中,print语句可能如下所示:


    print chr(30), "Field1", chr(30), "Field2", chr(30), "Field3", chr(31);

答案 1 :(得分:1)

我写了一个简单的方法来生成绝对的excel文件。

一个简单的功能。

首先将内容转换为数组(这很简单,每个人都知道。)。然后将数组传递给我在下面给出的函数。

<?php
//array to excel
function arrayToExcel($array, $filename='List') 
{
    if (!is_array($array) or !is_array($array[0])) return false;

    $xl = pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0); //begining of excel file 

    $i = 0;
    foreach ($array as $key => $val)
        {
            $j=0;
            foreach ($val as $cell_key => $cell_val)
                {
                    $cell_val = trim($cell_val);
                    $length = strlen($cell_val);
                        //checking cell value is a number and the length not equal to zero
                            if(preg_match('/^[0-9]*(\.[0-9]+)?$/', $cell_val) && $length!=0) {
                                $xl .= pack("sssss", 0x203, 14, $i, $j, 0x0); //writing number column
                                $xl .= pack("d", $cell_val);
                            }
                            else {
                                $xl .= pack("ssssss", 0x204, 8 + $length, $i, $j, 0x0, $length); //writing string column
                                $xl .= $cell_val;
                            }
                    $j++;
                } //end of 2nd foreach
            $i++;
        } //end of first foreach
    $xl .= pack("ss", 0x0A, 0x00);  //end of excel file
    $filename = $filename.".xls";
    header("Pragma: public");
    header('Content-Type: application/vnd.ms-excel');
    header("Content-Disposition: attachment; filename=$filename");
    header("Cache-Control: no-cache"); 
    echo $xl;
} //end of arrayToExcel function


//eg: arrayToExcel($myarray, "contact_list");
?>

答案 2 :(得分:0)

使用双引号""包围您的单元格值,它将允许您以tsv或csv格式导入数据,而不必担心回车被解释为新行。您还可以使用PHP中的fputcsv函数导出excel可以读取的tsv或csv文件。

这是功能稍微高效的版本,也谢谢你链接,但我不知道他们输出的格式是否真的对于excel是正确的。

function xlsBOF(){
    echo pack("s6", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);
}

function xlsEOF(){
    echo pack("ss", 0x0A, 0x00);
}

function xlsWriteNumber($Row, $Col, $Value){
    echo pack("s5d", 0x203, 14, $Row, $Col, 0x0, $Value);
}

function xlsWriteLabel($Row, $Col, $Value){
    $L = strlen($Value);
    echo pack("s6A*", 0x204, 8 + $L, $Row, $Col, 0x0, $L, $Value);
}