Экспорт xlsx файла из php

555
29 июля 2017, 06:46

Пытаюсь сделать экспорт данных в xlsx файл. Сначала сделал экспорт в xls таким образом:

1) Вывожу нужные данные на страницу с помощью echo

2) Выполняю код:

$xls_data = ob_get_clean();
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=export.xls");
echo $xls_data;
exit();

3) Получаю файл export.xls - то есть всё работает.

Проблема возникла с xlsx. Поискал на разных источниках какие нужно писать заголовки для экспорта xlsx, но всевозможные варианты не работают. Файл скачивается, но открыть его не удаётся (ошибка "Файл повреждён или имеет неверное расширение").

Пробую экспортировать xlsx так:

$xls_data = ob_get_clean();
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Disposition: attachment; filename=export.xlsx");
header('Content-Transfer-Encoding: binary');
echo $xls_data;
exit();

Подскажите в чём моя ошибка?

P.S. Различные библиотеки для формирования xlsx прошу не предлагать.

Пример моего файла xlsx, открытого в блокноте:

<table border=1 cellspacing=0>
<tr>
<td style="padding:2px 5px; mso-number-format:\@;">№</td>
<td style="padding:2px 5px; mso-number-format:\@;">Заголовок материала</td>
<td style="padding:2px 5px; mso-number-format:\@;">Эксклюзив</td>
<td style="padding:2px 5px; mso-number-format:\@;">Ссылка на материал на сайте</td>
<td style="padding:2px 5px; mso-number-format:\@;">Дата публикации</td>
<td style="padding:2px 5px; mso-number-format:\@;">Время публикации</td>
<td style="padding:2px 5px; mso-number-format:\@;">Создатель материала</td>
<td style="padding:2px 5px; mso-number-format:\@;">Автор материала</td>
<td style="padding:2px 5px; mso-number-format:\@;">Категории</td>
<td style="padding:2px 5px; mso-number-format:\@;">Просмотры</td>
<td style="padding:2px 5px; mso-number-format:\@;">Просмотры 24</td>
<td style="padding:2px 5px; mso-number-format:\@;">Теги</td>
<td style="padding:2px 5px; mso-number-format:\@;">Символы</td>
</tr>
...
</table> 
Answer 1

<html> 
 
<head> 
    <title>Report</title> 
</head> 
 
<body> 
    <?php 
$conn = mysqli_connect('localhost', 'root', 'admin', 'sfgcjm') or die('Error connecting to MySQL server.'); 
$setSql = "SELECT * FROM table_name"; 
    if (!$query = mysqli_query($conn, $setSql) ) { 
        echo("Error description: " . mysqli_error($conn)); 
        die(); 
    } 
    $columnHeader = ''; 
    $columnHeader = "Name1" . "\t" . "Name2" . "\t" . "Name3" . "\n"; 
 
    $setData = ''; 
 
    while ($rec = mysqli_fetch_row($query)) { 
        $rowData = ''; 
        foreach ($rec as $value) { 
            $value = $value . "\t"; 
            $rowData .= $value; 
        } 
        $setData .= trim($rowData) . "\n"; 
    } 
    $result = str_replace( "\r" , "" , $result ); 
 
 
    header("Content-type: application/octet-stream"); 
    header("Content-Disposition: attachment; filename=Mailing_list_Report.xls"); 
    header("Pragma: no-cache"); 
    header("Expires: 0"); 
 
    echo ucwords($columnHeader) . "\n" . $setData . "\n"; 
 
    mysqli_close($conn); 
    ?> 
</body> 
 
</html> 
 
Либо так: 
 
 
<?php 
 
function cleanData(&$str) 
{ 
    $str = preg_replace("/\t/", "\\t", $str); 
    $str = preg_replace("/\r?\n/", "\\n", $str); 
    if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"'; 
} 
// Имя загружаемого файла файла. 
$filename = "otchet_" . date('Y-m-d') . ".xls"; 
 
header("Content-Disposition: attachment; filename=\"$filename\""); 
header("Content-Type: application/vnd.ms-excel"); 
 
// Подключение к бд 
mysqli_connect ("localhost","root","admin");// Хост юзер и пароль 
mysqli_select_db("mailing_list") or die (mysqli_error());// Имя базы данных 
 
//Указать кодировку выводимых данных 
mysqli_query('SET character_set_database = cp1251_general_ci'); 
mysqli_query ("SET NAMES 'cp1251'"); 
 
//запрос и вывод данных 
$flag = false; 
$result = mysqli_query("SELECT * FROM mailing_list ORDER BY Data DESC") 
or die('Запрос не выполнен!'); 
while(false !== ($row = mysqli_fetch_assoc($result))) { 
    if(!$flag) { 
        // Вывод заголовков 
        echo implode("\t", array_keys($row)) . "\r\n"; 
        $flag = true; 
    } 
    //Вывод данных столбцов 
    array_walk($row, 'cleanData'); 
    echo implode("\t", array_values($row)) . "\r\n"; 
} 
exit;

Answer 2

У вас filename в Content-Disposition не с тем расширением. Измените на xslx

header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Disposition: attachment; filename=export.xlsx");

Ещё можно попробовать заменить Content-Type на application/octet-stream

UPD 1

В моём последнем проекте при экспорте xslx файла высылаются такие заголовки (из полного списка оставил только значимые):

Content-Type: application/vnd.ms-excel; charset=utf-8
Content-Length: 6743
Cache-Control: public
Content-Disposition: attachment; filename="users.xlsx"

UPD 2

Всё, что было написано выше касалось настоящих xslx файлов (т.е. тех, которые запакованы в zip)

Есть ещё один способ передавать данные в Excel - через HTML-таблицы. Создайте пустой файл test.xls со следующим содержимым:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8" />
</head>
<body>
<table>
  <tr>
    <td>1</td>
  </tr>
</table>
</body>
</html>

Файл откроется в Excel. Здесь важно расширение файла xls и <meta /> внутри html с Content-Type.

Чтобы передать такой файл с сервера я передавал такие заголовки:

Pragma: Public
Content-Type: application/octet-stream
Content-Description: File Transfer
Content-Disposition: attachment; filename="file.xls"
Content-Transfer-Encoding: binary
Answer 3

Попробуйте следующий пример:

$file = "myfile.xlsx" ;
header('Content-Disposition: attachment; filename=' . $file );
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Length: ' . filesize($file));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: public');
readfile('myfile.xlsx');

Если этот подход не решит вашу проблему то делаем -

Вывод :

Вы не сможете просто создать один без библиотеки. Прочитайте этот PHPExcel Github, который должен указать вам правильноe направлениe.

Существует много разных форматов файлов электронных таблиц, каждый из которых имеет свои собств> BIFF Format >

  • Used by Microsoft Excel between versions 95 and 2003 File

  • extension: xls

  • PHPEXcel Writer: PHPExcel_Writer_Excel5

  • Mime Type: application/vnd.ms-excel

OfficeOpenXML Format

  • Used by Microsoft Excel since version 2007

  • File extension: xlsx

  • PHPEXcel Writer: PHPExcel_Writer_Excel2007

  • Mime Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

Попробуйте так

$objPHPExcel = new PHPExcel();
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");;
header("Content-Disposition: attachment;filename=test.xlsx");
//header("Content-Disposition: attachment;filename=test.xls");
header("Content-Transfer-Encoding: binary ");
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel); 
$objWriter->setOffice2003Compatibility(true);
$objWriter->save('php://output');
READ ALSO
Как должен выглядеть запрос в данном случае

Как должен выглядеть запрос в данном случае

В цикле вывожу все наименования фирм из таблицы companynameХочу внутри этой таблицы вывести сумму полей из таблицы gtable таким образом

260
Альтернатива циклу на PHP

Альтернатива циклу на PHP

Здравствуйте!

224
Добавление товаров в корзину PHP

Добавление товаров в корзину PHP

Как реализовать функцию добавления товаров в корзину в куки на PHP? Расскажите пожалуйста алгоритм действий

430
Как сделать обновление в базе данных циклом foreach

Как сделать обновление в базе данных циклом foreach

Пожалуйста дайте подскажку как обновить базу при помощи форычаВчера получилось, а щас нифига не получается, записывается во все строки только...

259