Array PHP in CSV


104

Sto cercando di convertire una serie di prodotti in un file CSV, ma non sembra che stia andando secondo i piani. Il file CSV è una lunga riga, ecco il mio codice:

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

Inoltre, l'intestazione non forza un download. Ho copiato e incollato l'output e salvato come .csv

MODIFICARE

PROBLEMA RISOLTO:

Se qualcun altro stava cercando la stessa cosa, ha trovato un modo migliore per farlo:

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

Usa $ info [] = $ risultato-> fetch_array (); altrimenti avrà i dettagli dell'ultimo prodotto
GBD

@JohnnyFaldo: Grazie amico! Proprio quello di cui avevo bisogno.
Cesar

Hey! So che questa è una vecchia domanda, ma potresti rispondere alla tua stessa domanda. Può aiutare le persone a trovare una soluzione per un problema simile.
Gustavo Straube

qualcun altro sta ottenendo la prima riga ei primi due blocchi della seconda riga vuota?
mach2

Risposte:


97

Invece di scrivere valori, considera l'utilizzo di fputcsv().

Questo potrebbe risolvere il tuo problema immediatamente.


1
Devo dire che questo creerà un file sul tuo server, quindi dovrai leggere il contenuto di quel file prima di inviarlo in output, inoltre se non vuoi salvare una copia, dovrai eseguire il collegamento del file quando hai fatto.
Martin Lyne

Grazie per la modifica Vyktor, la mia digitazione è orribile oggi! Di solito sono così attento.
Martin Lyne

posso modificare il codice che ho sopra per farlo? poiché sta emettendo tutti i campi e usando esempi di fputcsv nel manuale non riesco a farlo fare questo
JohnnyFaldo

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

sì, l'ho risolto grazie, ho aggiunto la soluzione alla domanda originale
JohnnyFaldo

16

Questa è una soluzione semplice che esporta un array in una stringa 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));

5

Prova a usare;

PHP_EOL

Per terminare ogni nuova riga nell'output CSV.

Presumo che il testo stia delimitando, ma non si passa alla riga successiva?

Questa è una costante PHP. Determinerà la fine della riga corretta di cui hai bisogno.

Windows, ad esempio, utilizza "\ r \ n". Mi sono distrutto il cervello con quello quando la mia produzione non si interrompeva su una nuova linea.

come scrivere una nuova riga unificata in PHP?


2

So che questo è vecchio, ho avuto un caso in cui avevo bisogno che anche la chiave dell'array fosse inclusa nel CSV, quindi ho aggiornato lo script di Jesse Q per farlo. Ho usato una stringa come output, poiché implodere non può aggiungere una nuova riga (la nuova riga è qualcosa che ho aggiunto e dovrebbe essere davvero lì).

Nota che funziona solo con array a valore singolo (key, value). ma potrebbe essere facilmente aggiornato per gestire il multidimensionale (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

Nel mio caso, il mio array era multidimensionale, potenzialmente con array come valori. Quindi ho creato questa funzione ricorsiva per far saltare completamente l'array:

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

Poiché i vari livelli del mio array non si prestavano bene al formato CSV piatto, ho creato una colonna vuota con la chiave del sotto-array per fungere da "introduzione" descrittiva al livello successivo di dati. Output di esempio:

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

Potresti facilmente rimuovere quella colonna "intro" (descrittiva), ma nel mio caso avevo intestazioni di colonna ripetute, cioè inbound_leads, in ogni sotto-array, in modo che mi dava un'interruzione / titolo prima della sezione successiva. Rimuovere:

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

dopo is_array () per compattare ulteriormente il codice e rimuovere la colonna aggiuntiva.

Dato che volevo sia una riga del titolo che una riga di dati, passo due variabili nella funzione e al termine della chiamata alla funzione, le concludo entrambe con PHP_EOL:

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

Sì, lo so di lasciare una virgola in più, ma per brevità, non l'ho gestita qui.


Questa sembra una risposta specifica a una domanda molto generale e devi ammettere che hai lasciato delle virgole extra (a causa del vero problema dell'uso di stringhe invece di array) e non hai citato la riga di intestazione e hai avuto alcune chiamate extra non necessarie. Ho rimodellato tutto questo all'interno di una risposta a un'altra domanda .
LWC

1

Le matrici di dati vengono convertite in formato csv 'testo / csv' dalla funzione php incorporata fputcsv si occupa di virgole, virgolette e così via.
Guarda
https://coderwall.com/p/zvzwwa/array-to-comma-separated -string-in-php
http://www.php.net/manual/en/function.fputcsv.php


Un collegamento a una soluzione è il benvenuto, ma assicurati che la tua risposta sia utile senza di essa: aggiungi un contesto attorno al collegamento in modo che i tuoi colleghi utenti abbiano un'idea di cosa sia e perché sia ​​lì, quindi cita la parte più pertinente della pagina che tu " re collegamento a nel caso in cui la pagina di destinazione non è disponibile. Le risposte che sono poco più di un collegamento possono essere eliminate.
geisterfurz007

0

Ha funzionato per me.

 $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);```
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.