PHP Dizisinden CSV'ye


106

Bir dizi ürünü bir CSV dosyasına dönüştürmeye çalışıyorum, ancak plan yapacak gibi görünmüyor. CSV dosyası uzun bir satırdır, işte kodum:

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

Ayrıca, başlık bir indirme işlemini zorlamaz. Çıktıyı kopyalayıp yapıştırıyorum ve .csv olarak kaydediyorum

DÜZENLE

ÇÖZÜLEN SORUN:

Aynı şeyi arayan başka biri olsaydı, bunu yapmanın daha iyi bir yolunu buldu:

$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");

$ İnfo [] = $ sonuç-> fetch_array () kullanın; aksi takdirde son ürün ayrıntılarına sahip olur
GBD

@JohnnyFaldo: Teşekkürler dostum! Tam ihtiyacım olan şey.
Cesar

Hey! Bunun eski bir soru olduğunu biliyorum ama kendi sorunuzu cevaplayabilirsiniz. İnsanların benzer bir soruna çözüm bulmalarına yardımcı olabilir.
Gustavo Straube

başka biri ilk satırı ve ikinci satırın ilk iki bloğunu boş bırakıyor mu?
mach2

Yanıtlar:


98

Değerleri yazmak yerine kullanmayı düşünün fputcsv().

Bu, sorununuzu hemen çözebilir.


1
Bunun sunucunuzda bir dosya oluşturacağını belirtmeliyim, bu nedenle çıktı vermeden önce bu dosyanın içeriğini okumanız gerekecek, ayrıca bir kopyasını kaydetmek istemiyorsanız, o zaman dosyanın bağlantısını kesmeniz gerekecektir. bitirdiniz.
Martin Lyne

Vyktor'u düzenlediğiniz için teşekkürler, bugün yazmam çok kötü! Genelde çok dikkatliyimdir.
Martin Lyne

bunu yapmak için yukarıdaki kodu düzenleyebilir miyim? tüm alanların çıktısını aldığından ve kılavuzda fputcsv örneklerini kullandığından bunu yapamıyorum
JohnnyFaldo

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

evet bu çözüldü teşekkür ederim, çözümü orijinal soruya
eklediniz

16

Bu, bir diziyi csv dizesine aktaran basit bir çözümdür:

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

5

Kullanmayı deneyin;

PHP_EOL

CSV çıktınızdaki her yeni satırı sonlandırmak için.

Metnin sınırlayıcı olduğunu varsayıyorum, ancak bir sonraki satıra geçmiyor mu?

Bu bir PHP sabiti. İhtiyacınız olan doğru hat sonunu belirleyecektir.

Örneğin Windows, "\ r \ n" kullanır. Çıktım yeni bir çizgiye geçmediğinde beynimi bununla mahvettim.

PHP'de birleştirilmiş yeni satır nasıl yazılır?


2

Bunun eski olduğunu biliyorum, dizi anahtarının da CSV'ye dahil edilmesine ihtiyaç duyduğum bir durum vardı, bu yüzden bunu yapmak için Jesse Q tarafından komut dosyasını güncelledim. Implode yeni satır ekleyemediği için çıktı olarak bir string kullandım (yeni satır eklediğim bir şey ve gerçekten orada olmalı).

Lütfen bunun yalnızca tek değerli dizilerle çalıştığını unutmayın (key, value). ancak çok boyutlu işlemek için kolayca güncellenebilir (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

Benim durumumda, dizim çok boyutluydu ve potansiyel olarak değer olarak diziler vardı. Bu yüzden diziyi tamamen parçalamak için bu özyinelemeli işlevi yarattım:

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

Dizimin çeşitli düzeyleri düz bir CSV biçimine pek uygun olmadığından, sonraki veri düzeyine açıklayıcı bir "giriş" işlevi görecek alt dizinin anahtarıyla boş bir sütun oluşturdum. Örnek çıktı:

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

Bu "intro" (tanımlayıcı) sütununu kolayca kaldırabilirsiniz, ancak benim durumumda her alt dizide tekrarlanan sütun başlıkları vardı, yani inbound_leads, böylece bana bir sonraki bölümden önce bir break / title verdi. Kaldırmak:

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

kodu daha fazla sıkıştırmak ve fazladan sütunu kaldırmak için is_array () 'den sonra.

Hem bir başlık satırı hem de veri satırı istediğim için, işleve iki değişken aktarıyorum ve işleve çağrı tamamlandıktan sonra her ikisini de PHP_EOL ile sonlandırıyorum:

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

Evet, fazladan virgül bıraktığımı biliyorum, ama kısalık uğruna, burada halletmedim.


Bu, çok genel bir soruya özel bir cevap gibi görünüyor ve kuşkusuz fazladan virgül bıraktınız (diziler yerine dizeleri kullanmanın gerçek sorunu nedeniyle), başlık satırından alıntı yapmadınız ve fazladan gereksiz çağrılar aldınız. Bütün bunları başka bir sorunun cevabında yeniden şekillendirdim .
LWC

1

Veri dizileri yerleşik php fonksiyonu tarafından csv 'text / csv' formatına dönüştürülür fputcsv virgül, tırnak vb. İle ilgilenir. Https://coderwall.com/p/zvzwwa/array-to-comma-separated adresine
bakın.
-string-in-php
http://www.php.net/manual/en/function.fputcsv.php


Bir çözüme bağlantı memnuniyetle karşılanır, ancak lütfen cevabınızın o olmadan yararlı olduğundan emin olun: Bağlantının etrafına bağlam ekleyin, böylece diğer kullanıcılarınız bunun ne olduğu ve neden orada olduğu konusunda fikir sahibi olur, ardından sayfanın en alakalı bölümünü alıntı yapın ' hedef sayfanın mevcut olmaması durumunda yeniden bağlanma. Bir bağlantıdan biraz daha fazla olan cevaplar silinebilir.
geisterfurz007

0

Benim için çalıştı.

 $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);```
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.