PHP создал Excel Sheet создает ошибки при открытии

Итак, мой текущий код работает на 100%, файл сделан, и он открывается в Excel. Но при открытии есть несколько ошибок, которые нужно щелкнуть, чтобы открыть файл. Они заключаются в следующем:

Формат файла и расширение файла address-book.xls не совпадают. Файл может быть поврежден или небезопасен. Если вы не доверяете его источнику, не открывайте его. Вы все равно хотите его открыть?

Затем:

Excel обнаружил, что address-book.xls является файлом SYLK, но не может его загрузить. Либо файл содержит ошибки, либо это не файл формата SYLK. Нажмите OK, чтобы попытаться открыть файл в другом формате.

Тогда наконец:

Формат файла и расширение файла address-book.xls не совпадают. Файл может быть поврежден или небезопасен. Если вы не доверяете его источнику, не открывайте его. Вы все равно хотите его открыть?

После этого он неохотно открывается. Вот код, который его создает. Любая помощь в форматировании электронной таблицы, например, наличие достаточно больших ячеек для содержимого, была бы полезной. Но избавление от ошибок при открытии - мой приоритет.

<?PHP
require_once('conn.php');

$colnames = array(
    'id' => "ID",
    'Title' => "Title",
    'First_Name' => "First name",
    'Last_Name' => "Last Name",
    'Address' => "Address",
    'City' => "City",
    'State' => "State",
    'Zipcode' => "Zipcode",
    'Home_Phone' => "Home Phone",
    'Cell_Phone' => "Cell Phone",
    'Email1' => "Email #1",
    'Email2' => "Email #2"
);

function map_colnames($input){
    global $colnames;
    return isset($colnames[$input]) ? $colnames[$input] : $input;
}
function cleanData(&$str){
    $str = preg_replace("/\t/", "\\t", $str);
    $str = preg_replace("/\r?\n/", "\\n", $str);
    if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}

$filename = "address-book";

header("Content-type: application/octet-stream"); 
header("Content-Disposition: attachment; filename=".$filename.".xls"); 
header("Pragma: no-cache"); 
header("Expires: 0");
$flag = false;
$sql = "SELECT * FROM ".$sDB_table." ORDER BY Last_Name";
$query = $sDBConn -> prepare($sql);
$query -> execute();
while(false !== ($row = $query->fetch(PDO::FETCH_ASSOC))) {
    if(!$flag){
        $firstline = array_map(__NAMESPACE__ . '\map_colnames', array_keys($row));
        echo implode("\t", $firstline) . "\r\n";
        $flag = true;
    }
    array_walk($row, __NAMESPACE__ . '\cleanData');
    echo implode("\t", array_values($row)) . "\r\n";
}
exit;

?>

Ошибка PHPExcel:

$colnames = array("Title","First name","Last Name","Address","City","State","Zipcode","Home Phone","Cell Phone","Email #1","Email #2");
$col = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');

// Add Headers
for($i=0;$i<count($colnames);$i++){
$objPHPExcel->setActiveSheetIndex(0)
            ->setCellValue($col[$i]."1", $colnames[$i]);
}

$sql = "SELECT * FROM ".$sDB_table." ORDER BY Last_Name";
$query = $sDBConn -> prepare($sql);
$query -> execute();

$rownum = 1;
//Add Content
while(false !== ($row = $query->fetch(PDO::FETCH_ASSOC))) {
    $rownum++;
    for($i=0;$i<count($row);$i++){
        $objPHPExcel->setActiveSheetIndex(0)
                    ->setCellValue($col[$i]."".$rownum, $row[$i]);        
    }
}

Ошибка возникает, когда она попадает в оператор while, если я убираю эту часть, она работает.

Ответы на вопрос(1)

Решение Вопроса

ID как первые два байта вашего файла. Это подпись для файла SYLK, старого формата электронных таблиц, используемого Multiplan (символьный обмен ссылками - формат файла SYLK), предшественника Microsoft Excel.

Самый простой способ решить эту проблему - это избежатьID в качестве заголовка и использоватьId (IIRC, подпись SYLK чувствительна к регистру) илиKey или какое-то другое текстовое значение вместо

Вы сохраняете свой файл сxls расширение, но вы на самом деле не используете формат Excel, просто формат CSV; поэтому MS Excel будет жаловаться, что формат не соответствует расширению .... либо измените расширение на.csv соответствовать фактическому формату файла, который вы создаете; или создайте настоящий файл Excel в формате BIFF

Any help with formatting the spreadsheet, such as having the cells be big enough for the content would be great.

Используемый формат csv (с разделителем табуляции) не поддерживает форматирование любого вида, включая ширину столбцов. Если вы этого хотите, то вам нужно переключиться на настоящий формат электронных таблиц (по совпадению, SYLK - это настоящий формат электронных таблиц, хотя он довольно устарел, и я бы не стал его особенно рекомендовать), таких как BIFF для реальных файлов xls, OfficeOpenXML для xlsx файлы, OASIS для файлов ods.

Заголовки, которые я использую для файлов OfficeOpenXML xlsx:

// Redirect output to a client’s web browser (Excel2007)
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="01simple.xlsx"');
header('Cache-Control: max-age=0');
// If you're serving to IE 9, then the following may be needed
header('Cache-Control: max-age=1');
// If you're serving to IE over SSL, then the following may be needed
header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified
header ('Cache-Control: cache, must-revalidate'); // HTTP/1.1
header ('Pragma: public'); // HTTP/1.0
 Mark Baker29 мая 2016 г., 16:38
Я бы порекомендовалPHPExcelпотому что я написал это
 Michael Adair29 мая 2016 г., 16:56
Я работал с PHPExcel, за исключением того, что он ломается, когда попадает в создание моей ячейки из mysql. Обновленный основной пост с дополнительной информацией.
 Mark Baker29 мая 2016 г., 17:29
Я бы предложил прочитатьPHPExcel документация.... для автоматической установки ширины столбца,Смотри сюда
 Mark Baker29 мая 2016 г., 15:34
Если вы хотите дать ему расширениеxlsтогда Excel будет жаловаться, если это что-то кроме формата BIFF; лично я предпочитаюxlsx используя формат OfficeOpenXML .... OfficeOpenXML был форматом по умолчанию MS Excel в течение последних 9 лет
 Michael Adair29 мая 2016 г., 17:24
Это удивительно, спасибо. Сейчас я начинаю форматирование, но я не могу найти что-то, чтобы изменить ширину столбцов. Есть ли функция, которая позволяет авто-ширину, чтобы ячейки хорошо подходили?
 Michael Adair29 мая 2016 г., 15:46
Это говорит о том, что расширение файла xlsx является недействительным. Это связано с тем, что файл загружается?
 Mark Baker29 мая 2016 г., 15:35
Вам будет весело, если вы хотите попробовать и создатьxlsb формат, вы не найдете библиотек, которые могут вам помочь
 Michael Adair29 мая 2016 г., 15:35
Хорошо, я попытаюсь реализовать это, есть ли у вас шанс показать мне, как будут выглядеть мои измененные заголовки, если я перейду на xlsx?
 Michael Adair29 мая 2016 г., 16:02
Последний вопрос, какую библиотеку вы рекомендуете использовать для создания файлов .xlsx?
 Mark Baker29 мая 2016 г., 17:15
PDO::FETCH_ASSOC означает «по имени столбца»;PDO::FETCH_NUM означает "по номеру столбца" ....PHP Документы
 Mark Baker29 мая 2016 г., 17:08
Срывается с проблемами с памятью? Разрывы со слишком большим количеством строк? Ломается каким образом?
 Michael Adair29 мая 2016 г., 17:12
Я обнаружил проблему, я пытался просмотреть строку, сгенерированную sql по номеру, но я должен использовать их имена столбцов. Как и $ row ['Title'], есть ли способ сделать это, чтобы я мог просто использовать $ row [1]?
 Mark Baker29 мая 2016 г., 15:53
Ничего общего с этим ..... вы не можете просто изменить заголовки, вы должны изменить формат файла того, что вы создаете ...... файл CSV является файлом CSV независимо от заголовков, которые вы send: если вам нужен файл xls в формате BIFF, вам нужно создать файл формата BIFF для отправки в браузер, а не файл csv; если вы хотите файл xlsx в формате OffiecOpenXML, то вам нужно создать файл OfficeOpenXMLformat для отправки в браузер, а не файл csv ..... простое изменение заголовков не изменит содержание / структуру файла, который вы отправляете любым способом
 Mark Baker29 мая 2016 г., 17:19
Вы также можете упростить это, записав каждый набор столбцов в одном вызове, вместо того, чтобы зацикливаться на каждом столбце: replacefor($i=0;$i<count($row);$i++){ $objPHPExcel->setActiveSheetIndex(0) ->setCellValue($col[$i]."".$rownum, $row[$i]); } с$objPHPExcel->getActiveSheet()->fromArray($row, null, 'A'.$rownum);

Ваш ответ на вопрос