PHP масив до CSV


104

Я намагаюся перетворити масив продуктів у файл CSV, але це, схоже, не збирається планувати. CSV-файл - один довгий рядок, ось мій код:

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

Також заголовок не змушує завантажувати. Я копіював і вставляв вихідний файл і зберігав його як .csv

EDIT

ЗАВДАННЯ ПРОБЛЕМИ:

Якщо хтось шукав те саме, знайшов кращий спосіб зробити це:

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

Використовуйте $ info [] = $ result-> fetch_array (); інакше він буде мати останні дані про продукт
GBD

@JohnnyFaldo: Спасибі людина! Тільки те, що мені було потрібно.
Сезар

Гей! Я знаю, що це давнє запитання, але ви можете відповісти на власне запитання. Це може допомогти людям у пошуку рішення подібної проблеми.
Густав Страубе

хто-небудь ще отримує перший рядок і перші два блоки другого рядка?
mach2

Відповіді:


97

Замість того, щоб виписувати значення, розгляньте використання fputcsv().

Це може негайно вирішити вашу проблему.


1
Я мушу зазначити, що це буде створення файлу на вашому сервері, тому вам потрібно буде прочитати вміст цього файлу, перш ніж виводити його, також, якщо ви не хочете зберігати копію, тоді вам потрібно буде з'єднати файл, коли ви закінчили.
Мартін Лін

Дякую за редагування "Викторе", моє друкування зараз жахливо! Я зазвичай такий обережний.
Мартін Лін

Чи можу я відредагувати код, який я маю вище, щоб це зробити? оскільки він виводить усі поля, і використовуючи приклади fputcsv у посібнику, я не можу це зробити
JohnnyFaldo

7
array_to_CSV ($ дані); функція array_to_CSV ($ data) {$ outstream = fopen ("php: // output", 'r +'); fputcsv ($ outstream, $ data, ',', '"'); перемотка назад ($ outstream); $ csv = fgets ($ outstream); fclose ($ outstream); повернення $ csv;}
JohnnyFaldo

так, що вирішили це спасибі, додали рішення в оригінальне питання
JohnnyFaldo

16

Це просте рішення, яке експортує масив у рядок 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

Спробуйте використовувати;

PHP_EOL

Щоб припинити кожен новий рядок у вашому CSV-виході.

Я припускаю, що текст розмежовує, але не переходить до наступного рядка?

Це константа PHP. Він визначить правильний кінець рядка, який вам потрібен.

Наприклад, Windows використовує "\ r \ n". Я обернув мізки тим, коли мій вихід не перейшов на новий рядок.

як написати уніфікований новий рядок у PHP?


2

Я знаю, що це по-старому, у мене був випадок, коли мені знадобився також ключ масиву, щоб він був включений до CSV, тому я оновив сценарій Джессі Q для цього. Я використовував рядок як вихід, оскільки implode не може додати новий рядок (новий рядок - це те, що я додав, і він дійсно повинен бути там).

Зверніть увагу, це працює лише з масивами з одним значенням (key, value). але може бути легко оновлений для обробки багатовимірних (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

У моєму випадку мій масив був багатовимірним, потенційно з масивами як значеннями. Тому я створив цю рекурсивну функцію, щоб повністю розбити масив:

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

Оскільки різні рівні мого масиву не піддавались плоскому формату CSV, я створив порожній стовпець із ключем підмасиву, який послужить описовим "введенням" до наступного рівня даних. Вибірка зразка:

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

Ви можете легко видалити цей "вступний" (описовий) стовпчик, але в моєму випадку я мав повторювані заголовки стовпців, тобто inbound_leads, у кожному підмасиві, так що це дало мені перерву / заголовок перед наступним розділом. Видалити:

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

після is_array () для подальшого ущільнення коду та видалення зайвого стовпця.

Оскільки я хотів і рядок заголовка, і рядок даних, я передаю дві змінні у функцію, а після завершення виклику функції припиняю обидві функції PHP_EOL:

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

Так, я знаю, що залишаю зайву коску, але заради стислості я тут не впорався.


Це здається специфічною відповіддю на дуже загальне запитання, і ви, мабуть, залишили зайві коми (через реальну проблему використання рядків замість масивів), а також не цитували рядок заголовка та мали кілька зайвих непотрібних дзвінків. Я переробив усе це всередині відповіді на інше питання .
LWC

1

Формат Масиви даних перетворюються в формат CSV «текст / CSV» з допомогою вбудованого в функції PHP fputcsv бере на себе коми, лапки і т.д ..
Подивіться на
https://coderwall.com/p/zvzwwa/array-to-comma-separated -string-in-php
http://www.php.net/manual/en/function.fputcsv.php


Посилання на рішення вітається, але будь ласка, переконайтеся, що ваша відповідь корисна без неї: додайте контекст навколо посилання, щоб ваші колеги користувачі мали уявлення про те, що це таке і чому воно є, а потім наведіть найвідповіднішу частину сторінки, яку ви ' повторне посилання на випадок, якщо цільова сторінка недоступна. Відповіді, які є трохи більше ніж посилання, можуть бути видалені.
geisterfurz007

0

Це працювало для мене.

 $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);```
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.