Tablica PHP do CSV

105

Próbuję przekonwertować szereg produktów do pliku CSV, ale wydaje mi się, że to nie jest plan. Plik CSV to jedna długa linia, oto mój kod:

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

Ponadto nagłówek nie wymusza pobierania. Kopiowałem i wklejałem wynik i zapisałem jako .csv

EDYTOWAĆ

PROBLEM ROZWIĄZANY:

Jeśli ktoś szukał tego samego, znalazł lepszy sposób na zrobienie tego:

$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
źródło
Użyj $ info [] = $ result-> fetch_array (); w przeciwnym razie będzie miał ostatnie szczegóły produktu
GBD
@JohnnyFaldo: Dzięki stary! Właśnie tego potrzebowałem.
Cesar
Hej! Wiem, że to stare pytanie, ale możesz odpowiedzieć na swoje własne pytanie. Może pomóc ludziom znaleźć rozwiązanie podobnego problemu.
Gustavo Straube
czy ktoś inny otrzymuje pierwszą linię i pierwsze dwa bloki drugiej linii puste?
mach2

Odpowiedzi:

97

Zamiast wypisywać wartości rozważ użycie fputcsv().

Może to natychmiast rozwiązać problem.

Martin Lyne
źródło
1
Powinienem wspomnieć, że spowoduje to utworzenie pliku na twoim serwerze, więc będziesz musiał przeczytać zawartość tego pliku przed wyprowadzeniem go, również jeśli nie chcesz zapisywać kopii, będziesz musiał ù odłączyć` plik, gdy gotowe.
Martin Lyne
Dzięki za edycję Vyktor, moje dzisiejsze pisanie jest okropne! Zwykle jestem taka ostrożna.
Martin Lyne
czy mogę edytować kod, który mam powyżej, aby to zrobić? ponieważ wypisuje wszystkie pola i używając przykładów fputcsv w podręczniku, nie mogę tego zrobić
JohnnyFaldo
7
tablica_to_CSV (dane $); function array_to_CSV ($ data) {$ outstream = fopen ("php: // wyjście", 'r +'); fputcsv ($ outstream, $ data, ',', '"'); rewind ($ outstream); $ csv = fgets ($ outstream); fclose ($ outstream); return $ csv;}
JohnnyFaldo
tak, to rozwiązałem dziękuję, dodałem rozwiązanie w pierwotnym pytaniu
JohnnyFaldo
16

To jest proste rozwiązanie, które eksportuje tablicę do łańcucha 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
źródło
5

Spróbuj użyć;

PHP_EOL

Aby zakończyć każdy nowy wiersz w pliku wyjściowym CSV.

Zakładam, że tekst jest ogranicznikiem, ale nie przechodzi do następnego wiersza?

To stała PHP. To określi właściwy koniec linii, którego potrzebujesz.

Na przykład Windows używa "\ r \ n". Niszczyłem sobie tym mózgiem, gdy moje wyniki nie wychodziły na nowy poziom.

jak napisać ujednoliconą nową linię w PHP?

Martyn Shutt
źródło
2

Wiem, że to jest stare, miałem przypadek, w którym potrzebowałem klucza tablicy, który również powinien być uwzględniony w pliku CSV, więc zaktualizowałem skrypt Jesse Q, aby to zrobić. Użyłem łańcucha jako wyjścia, ponieważ implode nie może dodać nowej linii (nowa linia to coś, co dodałem i naprawdę powinno tam być).

Należy pamiętać, że działa to tylko z tablicami o pojedynczej wartości (key, value). ale można go łatwo zaktualizować, aby obsługiwał wiele wymiarów (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
źródło
1

W moim przypadku moja tablica była wielowymiarowa, potencjalnie z tablicami jako wartościami. Utworzyłem więc tę funkcję rekurencyjną, aby całkowicie rozerwać tablicę:

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

Ponieważ różne poziomy mojej tablicy nie nadawały się dobrze do płaskiego formatu CSV, utworzyłem pustą kolumnę z kluczem podtablicy, aby służyć jako opisowe „wprowadzenie” do następnego poziomu danych. Przykładowe dane wyjściowe:

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

Możesz łatwo usunąć tę kolumnę "intro" (opisową), ale w moim przypadku miałem powtarzające się nagłówki kolumn, tj. Inbound_leads, w każdej podtablicy, dzięki czemu otrzymałem przerwę / tytuł poprzedzający następną sekcję. Usunąć:

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

po is_array (), aby dalej kompaktować kod i usunąć dodatkową kolumnę.

Ponieważ chciałem zarówno wiersz tytułu, jak i wiersz danych, przekazuję dwie zmienne do funkcji i po zakończeniu wywołania funkcji kończę oba za pomocą PHP_EOL:

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

Tak, wiem, że zostawiam dodatkowy przecinek, ale ze względu na zwięzłość nie poradziłem sobie z tym tutaj.

Jesse Q
źródło
Wydaje się, że jest to konkretna odpowiedź na bardzo ogólne pytanie i trzeba przyznać, że zostawiłeś dodatkowe przecinki (ze względu na rzeczywisty problem z używaniem ciągów znaków zamiast tablic), a także nie zacytowałeś wiersza nagłówka i miałeś kilka dodatkowych niepotrzebnych wywołań. Przekształciłem to wszystko w odpowiedzi na inne pytanie .
LWC
1

Tablice danych są konwertowane do formatu csv „text / csv” przez wbudowaną funkcję php fputcsv dba o przecinki, cudzysłowy itp.
Patrz
https://coderwall.com/p/zvzwwa/array-to-comma-separated -string-in-php
http://www.php.net/manual/en/function.fputcsv.php

Abraham Markov
źródło
Link do rozwiązania jest mile widziany, ale upewnij się, że Twoja odpowiedź jest przydatna bez niego: dodaj kontekst wokół linku, aby inni użytkownicy mieli pojęcie, co to jest i dlaczego się tam znajduje, a następnie zacytuj najbardziej odpowiednią część strony, którą podałeś. ponowne łącze w przypadku, gdy strona docelowa jest niedostępna. Odpowiedzi, które są niewiele więcej niż linkiem, mogą zostać usunięte.
geisterfurz007
0

U mnie to zadziałało.

 $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
źródło