PHP Array ke CSV

104

Saya mencoba untuk mengonversi berbagai produk menjadi file CSV, tetapi tampaknya tidak sesuai rencana. File CSV adalah satu baris panjang, ini kode saya:

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;
    }

Selain itu, tajuk tidak memaksa unduhan. Saya telah menyalin dan menempelkan output dan menyimpannya sebagai .csv

EDIT

MASALAH TERPECAHKAN:

Jika ada orang lain yang mencari hal yang sama, temukan cara yang lebih baik untuk melakukannya:

$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");
JohnnyFaldo
sumber
Gunakan $ info [] = $ result-> fetch_array (); jika tidak maka akan ada detail produk terakhir
GBD
@JohnnyFaldo: Terima kasih bung! Hanya apa yang saya butuhkan.
Cesar
Hei! Saya tahu ini pertanyaan lama, tapi Anda bisa menjawab pertanyaan Anda sendiri. Ini dapat membantu orang menemukan solusi untuk masalah serupa.
Gustavo Straube
apakah ada orang lain yang mendapatkan baris pertama dan dua blok pertama dari baris kedua kosong ??
mach2

Jawaban:

97

Daripada menuliskan nilai, pertimbangkan untuk menggunakan fputcsv().

Ini dapat segera menyelesaikan masalah Anda.

Martin Lyne
sumber
1
Saya harus menyebutkan bahwa ini akan membuat file di server Anda, jadi Anda harus membaca konten file itu sebelum mengeluarkannya, juga jika Anda tidak ingin menyimpan salinannya maka Anda harus ùnlink` file ketika kamu selesai.
Martin Lyne
Terima kasih telah mengedit Vyktor, ketikan saya buruk hari ini! Saya biasanya sangat berhati-hati.
Martin Lyne
Bisakah saya mengedit kode yang saya miliki di atas untuk melakukan ini? karena mengeluarkan semua bidang, dan menggunakan contoh fputcsv di manual saya tidak bisa melakukannya untuk melakukan ini
JohnnyFaldo
7
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;}
JohnnyFaldo
ya itu menyelesaikannya terima kasih, telah menambahkan solusi dalam pertanyaan asli
JohnnyFaldo
16

Ini adalah solusi sederhana yang mengekspor array ke string 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));
trank
sumber
5

Coba gunakan;

PHP_EOL

Untuk menghentikan setiap baris baru dalam keluaran CSV Anda.

Saya berasumsi bahwa teksnya membatasi, tetapi tidak berpindah ke baris berikutnya?

Itu adalah konstanta PHP. Ini akan menentukan akhir baris yang benar yang Anda butuhkan.

Windows, misalnya, menggunakan "\ r \ n". Saya merusak otak saya dengan yang satu itu ketika keluaran saya tidak melanggar ke baris baru.

bagaimana menulis baris baru terpadu di PHP?

Martyn Shutt
sumber
2

Saya tahu ini sudah lama, saya punya kasus di mana saya membutuhkan kunci array untuk disertakan dalam CSV juga, jadi saya memperbarui skrip oleh Jesse Q untuk melakukan itu. Saya menggunakan string sebagai output, karena implode tidak dapat menambahkan baris baru (baris baru adalah sesuatu yang saya tambahkan, dan harus benar-benar ada di sana).

Harap dicatat, ini hanya berfungsi dengan array nilai tunggal (key, value). tetapi dapat dengan mudah diperbarui untuk menangani multi-dimensi (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 ;
}
J nui
sumber
1

Dalam kasus saya, array saya multidimensi, berpotensi dengan array sebagai nilai. Jadi saya membuat fungsi rekursif ini untuk menghancurkan array sepenuhnya:

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 . '",';
        }
    }
}

Karena berbagai tingkat array saya tidak cocok dengan format CSV datar, saya membuat kolom kosong dengan kunci sub-array untuk berfungsi sebagai "pengantar" deskriptif ke tingkat data berikutnya. Output sampel:

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

Anda dapat dengan mudah menghapus kolom "intro" (deskriptif) itu, tetapi dalam kasus saya, saya memiliki tajuk kolom berulang, yaitu inbound_leads, di setiap sub-larik, sehingga memberi saya jeda / judul sebelum bagian berikutnya. Menghapus:

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

setelah is_array () untuk memadatkan kode lebih lanjut dan menghapus kolom ekstra.

Karena saya menginginkan baris judul dan baris data, saya meneruskan dua variabel ke dalam fungsi dan setelah menyelesaikan panggilan ke fungsi tersebut, akhiri keduanya dengan PHP_EOL:

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

Ya, saya tahu saya meninggalkan koma ekstra, tetapi demi singkatnya, saya tidak menanganinya di sini.

Jesse Q
sumber
Ini sepertinya jawaban spesifik untuk pertanyaan yang sangat umum dan Anda memang meninggalkan koma tambahan (karena masalah sebenarnya menggunakan string alih-alih array) serta tidak mengutip baris header dan memiliki beberapa panggilan tambahan yang tidak diperlukan. Saya membentuk kembali semua ini di dalam jawaban untuk pertanyaan lain .
LWC
1

Array data diubah menjadi format 'teks / csv' csv dengan fungsi php bawaan fputcsv menangani koma, tanda kutip, dan lain-lain.
Lihat
https://coderwall.com/p/zvzwwa/array-to-comma-separated -string-in-php
http://www.php.net/manual/en/function.fputcsv.php

Avraham Markov
sumber
Tautan ke solusi diperbolehkan, tetapi harap pastikan jawaban Anda berguna tanpanya: tambahkan konteks di sekitar tautan sehingga sesama pengguna Anda akan tahu apa itu dan mengapa itu ada, lalu kutip bagian paling relevan dari halaman Anda ' menautkan ulang jika halaman target tidak tersedia. Jawaban yang tidak lebih dari sebuah tautan dapat dihapus.
geisterfurz007
0

Itu berhasil untuk saya.

 $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);```
Amir Khan
sumber