PHP Array zu CSV

103

Ich versuche, eine Reihe von Produkten in eine CSV-Datei zu konvertieren, aber es scheint nicht nach Plan zu verlaufen. Die CSV-Datei ist eine lange Zeile, hier ist mein Code:

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

Außerdem erzwingt der Header keinen Download. Ich habe die Ausgabe kopiert und eingefügt und als .csv gespeichert

BEARBEITEN

PROBLEM GELÖST:

Wenn jemand anderes nach dem gleichen suchte, fand er einen besseren Weg, dies zu tun:

$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
quelle
Verwenden Sie $ info [] = $ result-> fetch_array (); Andernfalls werden die letzten Produktdetails angezeigt
GBD
@ JohnnyFaldo: Danke Mann! Genau das, was ich brauchte.
Cesar
Hallo! Ich weiß, dass dies eine alte Frage ist, aber Sie könnten Ihre eigene Frage beantworten. Es kann Menschen helfen, eine Lösung für ein ähnliches Problem zu finden.
Gustavo Straube
Bekommt sonst noch jemand die erste Zeile und die ersten beiden Blöcke der zweiten Zeile leer?
mach2

Antworten:

96

Anstatt Werte aufzuschreiben, sollten Sie die Verwendung in Betracht ziehen fputcsv().

Dies kann Ihr Problem sofort lösen.

Martin Lyne
quelle
1
Ich sollte erwähnen, dass dadurch eine Datei auf Ihrem Server erstellt wird. Sie müssen daher den Inhalt dieser Datei lesen, bevor Sie sie ausgeben. Wenn Sie keine Kopie speichern möchten, müssen Sie die Datei wann verknüpfen du bist fertig.
Martin Lyne
Vielen Dank für die Bearbeitung von Vyktor, meine Eingabe ist heute schrecklich! Ich bin normalerweise so vorsichtig.
Martin Lyne
Könnte ich den Code bearbeiten, den ich oben habe, um dies zu tun? Da es alle Felder ausgibt und Beispiele für fputcsv im Handbuch verwendet, kann ich es nicht dazu bringen
JohnnyFaldo
7
array_to_CSV ($ data); Funktion array_to_CSV ($ data) {$ outstream = fopen ("php: // output", 'r +'); fputcsv ($ outstream, $ data, ',', '"'); Rücklauf ($ outstream); $ csv = fgets ($ outstream); fclose ($ outstream); return $ csv;}
JohnnyFaldo
Ja, das hat es gelöst. Danke, ich habe die Lösung in der ursprünglichen Frage hinzugefügt
JohnnyFaldo
16

Dies ist eine einfache Lösung, die ein Array in eine CSV-Zeichenfolge exportiert:

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
quelle
5

Versuchen Sie es mit;

PHP_EOL

So beenden Sie jede neue Zeile in Ihrer CSV-Ausgabe.

Ich gehe davon aus, dass der Text begrenzt ist, aber nicht in die nächste Zeile wechselt.

Das ist eine PHP-Konstante. Es bestimmt das richtige Zeilenende, das Sie benötigen.

Windows verwendet beispielsweise "\ r \ n". Ich habe mir damit den Kopf zerbrochen, als meine Ausgabe nicht in eine neue Zeile überging.

Wie schreibe ich eine einheitliche neue Zeile in PHP?

Martyn Shutt
quelle
2

Ich weiß, dass dies alt ist. Ich hatte einen Fall, in dem der Array-Schlüssel auch in der CSV enthalten sein musste. Deshalb habe ich das Skript von Jesse Q aktualisiert, um dies zu tun. Ich habe einen String als Ausgabe verwendet, da implode keine neue Zeile hinzufügen kann (neue Zeile habe ich hinzugefügt und sollte wirklich vorhanden sein).

Bitte beachten Sie, dass dies nur mit einwertigen Arrays funktioniert (key, value). könnte aber leicht aktualisiert werden, um mehrdimensional zu handhaben (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
quelle
1

In meinem Fall war mein Array mehrdimensional, möglicherweise mit Arrays als Werten. Also habe ich diese rekursive Funktion erstellt, um das Array vollständig zu sprengen:

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

Da sich die verschiedenen Ebenen meines Arrays nicht gut für das flache CSV-Format eignen, habe ich eine leere Spalte mit dem Schlüssel des Sub-Arrays erstellt, um als beschreibendes "Intro" für die nächste Datenebene zu dienen. Beispielausgabe:

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

Sie könnten diese "beschreibende" "Intro" -Spalte leicht entfernen, aber in meinem Fall hatte ich wiederholte Spaltenüberschriften, dh inbound_leads, in jedem Unterarray, so dass ich vor dem nächsten Abschnitt eine Unterbrechung / einen Titel erhielt. Entfernen:

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

nach dem is_array (), um den Code weiter zu komprimieren und die zusätzliche Spalte zu entfernen.

Da ich sowohl eine Titelzeile als auch eine Datenzeile haben wollte, übergebe ich zwei Variablen an die Funktion und beende beide nach Abschluss des Aufrufs der Funktion mit PHP_EOL:

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

Ja, ich weiß, dass ich ein zusätzliches Komma hinterlasse, aber der Kürze halber habe ich hier nicht damit umgegangen.

Jesse Q.
quelle
Dies scheint eine spezifische Antwort auf eine sehr allgemeine Frage zu sein, und Sie haben zugegebenermaßen zusätzliche Kommas übrig gelassen (aufgrund des eigentlichen Problems, Zeichenfolgen anstelle von Arrays zu verwenden) sowie die Kopfzeile nicht zitiert und einige zusätzliche nicht benötigte Aufrufe erhalten. Ich habe das alles in einer Antwort auf eine andere Frage umgestaltet .
LWC
1

Arrays von Daten werden umgewandelt in csv ‚text / csv‘ -Format von in PHP - Funktion fputcsv gebaut kümmert sich um Kommas, Zitate und etc ..
Blick auf
https://coderwall.com/p/zvzwwa/array-to-comma-separated -string-in-php
http://www.php.net/manual/en/function.fputcsv.php

Avraham Markov
quelle
Ein Link zu einer Lösung ist willkommen, aber stellen Sie sicher, dass Ihre Antwort ohne sie nützlich ist: Fügen Sie dem Link einen Kontext hinzu, damit Ihre Mitbenutzer eine Vorstellung davon haben, was es ist und warum es dort ist, und zitieren Sie dann den relevantesten Teil der Seite, die Sie verwenden. erneutes Verknüpfen mit, falls die Zielseite nicht verfügbar ist. Antworten, die kaum mehr als ein Link sind, können gelöscht werden.
geisterfurz007
0

Es hat bei mir funktioniert.

 $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
quelle