使用PHP创建CSV文件

83

我想创建一个csv文件,但是当我运行代码时,返回的是一个空白页面并且没有csv文件。我使用的是PHP 5。 我使用了以下代码:

<?php
    $data = array ('aaa,bbb,ccc,dddd',
                   '123,456,789',
                   '"aaa","bbb"');

    $fp = fopen('data.csv', 'w');
    foreach($data as $line){
             $val = explode(",",$line);
             fputcsv($fp, $val);
    }
    fclose($fp);
?>

谢谢!


1
fclose($fp); 之后,您需要使用 echo 命令输出结果。 - Funk Forty Niner
您没有任何“回显”,因此页面将为空白。它只会根据您的代码为您创建CSV文件。 - Rikesh
6个回答

144

是因为你正在写入文件,所以它是空白的。你应该使用php://output来写入输出,并发送头信息指示它是csv格式。

例如:

header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="sample.csv"');
$data = array(
        'aaa,bbb,ccc,dddd',
        '123,456,789',
        '"aaa","bbb"'
);

$fp = fopen('php://output', 'wb');
foreach ( $data as $line ) {
    $val = explode(",", $line);
    fputcsv($fp, $val);
}
fclose($fp);

我可以知道如何提供现有的Excel表路径吗? - Asha
@Howdy_McGee 当然可以,但是在输出已经发送后无法设置标头。您必须先设置标头,然后再发送输出。 - TheRealChx101

83

@Baba的回答很好,但您不需要使用explode,因为fputcsv接受数组作为参数。

例如,如果您有一个包含三列、四行的文档,这里是一个更简单的版本:

header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="sample.csv"');

$user_CSV[0] = array('first_name', 'last_name', 'age');

// very simple to increment with i++ if looping through a database result 
$user_CSV[1] = array('Quentin', 'Del Viento', 34);
$user_CSV[2] = array('Antoine', 'Del Torro', 55);
$user_CSV[3] = array('Arthur', 'Vincente', 15);

$fp = fopen('php://output', 'wb');
foreach ($user_CSV as $line) {
    // though CSV stands for "comma separated value"
    // in many countries (including France) separator is ";"
    fputcsv($fp, $line, ',');
}
fclose($fp);

肯定没问题,甚至可能更合适。更多详情请看这里 - Buzut

5

如果有人想要保存CSV文件到特定路径以作为邮件附件,可以按照以下步骤进行:

我知道我添加了很多注释是为了新手们 :)

我添加了一个示例,以便您可以很好地总结。

$activeUsers = /** Query to get the active users */

/** Following is the Variable to store the Users data as 
    CSV string with newline character delimiter, 

    its good idea of check the delimiter based on operating system */

$userCSVData = "Name,Email,CreatedAt\n";

/** Looping the users and appending to my earlier csv data variable */
foreach ( $activeUsers as $user ) {
    $userCSVData .= $user->name. "," . $user->email. "," . $user->created_at."\n";
}
/** Here you can use with H:i:s too. But I really dont care of my old file  */
$todayDate  = date('Y-m-d');
/** Create Filname and Path to Store */
$fileName   = 'Active Users '.$todayDate.'.csv';
$filePath   = public_path('uploads/'.$fileName); //I am using laravel helper, in case if your not using laravel then just add absolute or relative path as per your requirements and path to store the file

/** Just in case if I run the script multiple time 
    I want to remove the old file and add new file.

    And before deleting the file from the location I am making sure it exists */
if(file_exists($filePath)){
    unlink($filePath);
}
$fp = fopen($filePath, 'w+');
fwrite($fp, $userCSVData); /** Once the data is written it will be saved in the path given */
fclose($fp);

/** Now you can send email with attachments from the $filePath */

注意:以下内容是一个非常糟糕的想法,用于增加memory_limittime limit,但我只是为了确保如果有人遇到连接超时或其他问题。在坚持使用之前,请务必找到一些替代方案。

您需要在上述脚本的开头添加以下内容。

ini_set("memory_limit", "10056M");
set_time_limit(0);
ini_set('mysql.connect_timeout', '0');
ini_set('max_execution_time', '0');

3

如果有人仍在寻找答案(简单的方法),这里是使用PHP创建CSV文件的简单方法。

//Let's say you want your csv file to have something like this:

**Title 1** | **Title 2** | **Title 3**
Value 1     |  Value 2    | Value 3
Value 4     |  Value 5    | Value 6


//create a variable and add your data to it
$data = "TITLE 1, TITLE 2, TITLE 3 \n";
$data .= val1 .",". val2 .",". val3 \n ;
$data .= val3 .",". val4 .",". val5 \n ;
//you can use a loop to add dynamic data to this variable, if you want.

//give your file a name.
$fileName   = 'myData.csv';

//add the file path where you want to store your csv file
//you can use **$_SERVER['DOCUMENT_ROOT']** in your file path. Avoid using absoultue paths like **../** this
$filePath   = 'your_path_to' . $fileName;


$fp = fopen($filePath, 'w+');
fwrite($fp, print_r($data, true)); 
//Once the data is written, it will be saved in the path given.

fclose($fp);

0

我认为这是最短的方式

    $columns = [
        'id',
        'product_name',
        'product_url',
        'price',
        'category'
    ];

    $products = [
      [1, 'product 1', 'https://example.com/product-1', '9.99', 'category 1'],
      [2, 'product 2', 'https://example.com/product-2', '19.99', 'category 2'],
      [3, 'product 3', 'https://example.com/product-3', '29.99', 'category 3'],
      [4, 'product 4', 'https://example.com/product-4', '39.99', 'category 4'],
    ];

    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="products.csv"');

    echo implode(',', $columns) . PHP_EOL;
    foreach ($products as $product){
        echo implode(',', $product) . PHP_EOL;
    }

@YourCommonSense 只是一个小 bug,我修复了它。 - Gurkan Atik

0
使用此函数将对象数组写入CSV文件(假设它们都包含相同的属性):
function writeToCsv($array, $filename) {
    $fp = fopen($filename, 'w');

    $keys = array_keys(get_object_vars($array[0]));
    fputcsv($fp, $keys);

    foreach ($array as $entry) {
        $values = array_values(get_object_vars($entry));
        fputcsv($fp, $values);
    }

    fclose($fp);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接