web-dev-qa-db-fra.com

PHP Tableau au format CSV

J'essaie de convertir un tableau de produits en un fichier CSV, mais cela ne semble pas se dérouler comme prévu. Le fichier CSV est une longue ligne, voici mon 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;
    }

En outre, l'en-tête ne force pas le téléchargement. J'ai copié et collé la sortie, puis enregistré au format .csv 

MODIFIER

PROBLÈME RÉSOLU: 

Si quelqu'un d'autre cherchait la même chose, trouva une meilleure façon de le faire:

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

Au lieu d’écrire des valeurs, envisagez d’utiliser fputcsv()

Cela peut résoudre votre problème immédiatement.

73
Martin Lyne

Essayez d'utiliser;

PHP_EOL

Pour terminer chaque nouvelle ligne dans votre sortie CSV.

Je suppose que le texte est délimitant, mais ne passe-t-il pas à la rangée suivante?

C'est une constante PHP. Cela déterminera la bonne fin de ligne dont vous avez besoin.

Windows, par exemple, utilise "\ r\n". Je me suis creusé la tête avec celui-là alors que ma sortie ne dépassait pas une nouvelle ligne.

comment écrire une nouvelle ligne unifiée en PHP?

4
Martyn Shutt

Je sais que c’est vieux, j’avais un cas dans lequel j’avais besoin que la clé de tableau fût également incluse dans le fichier CSV, aussi j’ai mis à jour le script de Jesse Q pour le faire . t ajouter une nouvelle ligne (la nouvelle ligne est quelque chose que j’ai ajouté et qui devrait vraiment être là).

Veuillez noter que cela ne fonctionne qu'avec des tableaux à valeur unique (key, value). mais pourrait facilement être mis à jour pour gérer (key, array()) multi-dimensionnelle.

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
J nui

Dans mon cas, mon tableau était multidimensionnel, potentiellement avec des tableaux comme valeurs. J'ai donc créé cette fonction récursive pour détruire complètement le tableau:

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

Comme les différents niveaux de mon tableau ne se prêtaient pas bien au format CSV plat, j'ai créé une colonne vierge avec la clé du sous-tableau pour servir d'introduction descriptive au niveau de données suivant. Exemple de sortie:

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

Vous pouvez facilement supprimer cette colonne "intro" (descriptive), mais dans mon cas, j'avais des en-têtes de colonne répétitifs, à savoir inbound_leads, dans chaque sous-tableau, ce qui m'a donné une rupture/un titre précédant la section suivante. Retirer:

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

après le is_array () pour compacter le code et supprimer la colonne supplémentaire.

Puisque je voulais à la fois une ligne de titre et une ligne de données, je passe deux variables à la fonction et, une fois l'appel de la fonction terminé, je termine les deux avec PHP_EOL:

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

Oui, je sais que je laisse une virgule supplémentaire, mais par souci de brièveté, je ne l'ai pas manipulée ici.

1
Jesse Q

Les tableaux de données sont convertis au format csv 'text/csv' par la fonction php intégrée fputcsv prend en charge les virgules, les guillemets, etc.
Regarder
https://coderwall.com/p/zvzwwa/array-to-comma-separated-string-in-php
http://www.php.net/manual/en/function.fputcsv.php

1
Avraham Markov

C'est une solution simple qui exporte un tableau en chaîne 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));
0
ktran