PHP数组到CSV


104

我正在尝试将一系列产品转换为CSV文件,但似乎没有计划。CSV文件是一长行,这是我的代码:

for($i=0;$i<count($prods);$i++) {
$sql = "SELECT * FROM products WHERE id = '".$prods[$i]."'";
$result = $mysqli->query($sql);
$info = $result->fetch_array(); 
}

$header = '';

for($i=0;$i<count($info);$i++)  
  {
    $row = $info[$i];

    $line = '';
    for($b=0;$b<count($row);$b++)
    { 
    $value = $row[$b];                                      
        if ( ( !isset( $value ) ) || ( $value == "" ) )
        {
            $value = "\t";
        }
        else
        {
            $value = str_replace( '"' , '""' , $value );
            $value = '"' . $value . '"' . "\t";
        }
         $line .= $value;
        }
    $data .= trim( $line ) . "\n";
}
$data = str_replace( "\r" , "" , $data );

if ( $data == "" )
{
$data = "\n(0) Records Found!\n";                        
}

header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=your_desired_name.xls");
header("Pragma: no-cache");
header("Expires: 0");

array_to_CSV($data);


function array_to_CSV($data)
    {
        $outstream = fopen("php://output", 'r+');
        fputcsv($outstream, $data, ',', '"');
        rewind($outstream);
        $csv = fgets($outstream);
        fclose($outstream);
        return $csv;
    }

此外,标头不会强制下载。我一直在复制并粘贴输出并保存为.csv

编辑

解决的问题:

如果有人在寻找相同的东西,那么找到更好的方法:

$num = 0;
$sql = "SELECT id, name, description FROM products";
if($result = $mysqli->query($sql)) {
     while($p = $result->fetch_array()) {
         $prod[$num]['id']          = $p['id'];
         $prod[$num]['name']        = $p['name'];
         $prod[$num]['description'] = $p['description'];
         $num++;        
    }
 }
$output = fopen("php://output",'w') or die("Can't open php://output");
header("Content-Type:application/csv"); 
header("Content-Disposition:attachment;filename=pressurecsv.csv"); 
fputcsv($output, array('id','name','description'));
foreach($prod as $product) {
    fputcsv($output, $product);
}
fclose($output) or die("Can't close php://output");

使用$ info [] = $ result-> fetch_array(); 否则,它将提供最后的产品详细信息
GBD 2012年

@JohnnyFaldo:谢谢你!正是我需要的。
Cesar 2013年

嘿! 我知道这是一个老问题,但是您可以回答自己的问题。它可以帮助人们找到类似问题的解决方案。
Gustavo Straube

还有其他人将第一行和第二行的前两个块留空吗?
mach2

Answers:


97

与其写出值,不如考虑使用fputcsv()

这样可以立即解决您的问题。


1
我应该提到这将在您的服务器上创建一个文件,因此您需要在输出文件之前先读取该文件的内容,如果您不想保存副本,则需要在该文件上添加链接。你完成了。
马丁·林恩

感谢您编辑Vyktor,今天的打字太糟糕了!我通常很小心。
马丁·林恩

我可以编辑上面的代码来执行此操作吗?因为它输出所有字段,并使用手册中的fputcsv示例,所以我无法做到这一点
JohnnyFaldo 2012年

7
array_to_CSV($ data); 函数array_to_CSV($ data){$ outstream = fopen(“ php:// output”,'r +'); fputcsv($ outstream,$ data,',','“'); rewind($ outstream); $ csv = fgets($ outstream); fclose($ outstream); return $ csv;}
JohnnyFaldo 2012年

是的,它解决了,谢谢,已经在原始问题中添加了解决方案
JohnnyFaldo 2012年

16

这是将数组导出到csv字符串的简单解决方案:

function array2csv($data, $delimiter = ',', $enclosure = '"', $escape_char = "\\")
{
    $f = fopen('php://memory', 'r+');
    foreach ($data as $item) {
        fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
    }
    rewind($f);
    return stream_get_contents($f);
}

$list = array (
    array('aaa', 'bbb', 'ccc', 'dddd'),
    array('123', '456', '789'),
    array('"aaa"', '"bbb"')
);
var_dump(array2csv($list));


2

我知道这已经很老了,我有一种情况,我也需要将数组键也包含在CSV中,所以我更新了Jesse Q的脚本来做到这一点。我使用字符串作为输出,因为爆裂无法添加新行(新行是我添加的,并且应该确实存在)。

请注意,这仅适用于单值数组(key, value)。但可以轻松进行更新以处理多维数据(key, array())

function arrayToCsv( array &$fields, $delimiter = ',', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
    $delimiter_esc = preg_quote($delimiter, '/');
    $enclosure_esc = preg_quote($enclosure, '/');

    $output = '';
    foreach ( $fields as $key => $field ) {
        if ($field === null && $nullToMysqlNull) {
            $output = '';
            continue;
        }

        // Enclose fields containing $delimiter, $enclosure or whitespace
        if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field ) ) {
            $output .= $key;
            $output .= $delimiter;
            $output .= $enclosure . str_replace($enclosure, $enclosure . $enclosure,     $field) . $enclosure;
            $output .= PHP_EOL;
        }
        else {
            $output .= $key;
            $output .= $delimiter;
            $output .= $field;
            $output .= PHP_EOL;
        }
    }

    return  $output ;
}

1

就我而言,我的数组是多维的,可能以数组作为值。因此,我创建了此递归函数以完全分解数组:

function array2csv($array, &$title, &$data) {
    foreach($array as $key => $value) {      
        if(is_array($value)) {
            $title .= $key . ",";
            $data .= "" . ",";
            array2csv($value, $title, $data);
        } else {
            $title .= $key . ",";
            $data .= '"' . $value . '",';
        }
    }
}

由于数组的各个级别都无法很好地适应纯CSV格式,因此我创建了一个空白列,并使用子数组的键作为下一数据级别的描述性“介绍”。样本输出:

agentid     fname           lname      empid    totals  sales   leads   dish    dishnet top200_plus top120  latino  base_packages
G-adriana   ADRIANA EUGENIA PALOMO PAIZ 886                0    19              0         0         0         0      0

您可以轻松删除该“介绍”(描述性)列,但是在我的情况下,我在每个子数组中都有重复的列标题,即inbound_leads,因此在下一节之前给了我一个break / title。去掉:

$title .= $key . ",";
$data .= "" . ",";

在is_array()之后以进一步压缩代码并删除多余的列。

由于我既需要标题行又需要数据行,因此我将两个变量传递给函数,并且在函数调用完成后,都用PHP_EOL终止:

$title .= PHP_EOL;
$data .= PHP_EOL;

是的,我知道我会留下一个多余的逗号,但是为了简洁起见,我在这里没有处理。


这似乎是对一个非常普遍的问题的特定答案,并且您不得不留下多余的逗号(由于使用字符串而不是数组的实际问题),并且没有引用标题行,并且进行了一些不必要的调用。我在回答另一个问题的过程中重新塑造了这一切。
LWC

1

数据数组通过内置的php函数fputcsv转换为csv'text / csv'格式来处理逗号,引号等。请
查看
https://coderwall.com/p/zvzwwa/array-to-comma-separated -string-in-php
http://www.php.net/manual/zh/function.fputcsv.php


欢迎使用指向解决方案的链接,但是请确保没有该链接的情况下,您的回答是有用的:在链接周围添加上下文,以便您的其他用户可以了解它的含义和含义,然后引用您所使用页面中最相关的部分如果目标页面不可用,请重新链接。只是链接的答案可能会被删除。
geisterfurz007

0

它为我工作。

 $f=fopen('php://memory','w');
 $header=array("asdf ","asdf","asd","Calasdflee","Start Time","End Time" );      
 fputcsv($f,$header);
 fputcsv($f,$header);
 fputcsv($f,$header); 
 fseek($f,0);
 header('content-type:text/csv'); 
 header('Content-Disposition: attachment; filename="' . $filename . '";');
 fpassthru($f);```
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.