Every time i make the xlsx file, i can't open it without error: "content that could not be read was found in the book".
Code:
function getNameFromNumber($num) {
$numeric = ($num - 1) % 26;
$letter = chr(65 + $numeric);
$num2 = intval(($num - 1) / 26);
if ($num2 > 0) {
return getNameFromNumber($num2) . $letter;
} else {
return $letter;
}
}
require_once $_SERVER['DOCUMENT_ROOT'] . '/local/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$objPHPExcel = new Spreadsheet();
$date = date("Y-m-d H:i:s");
// Set document properties
$objPHPExcel->getProperties()
->setTitle("Выгрузка заявлений от" . $date)
->setSubject("Выгрузка заявлений от" . $date)
->setDescription("Выгрузка заявлений по фильтру от" . $date);
// Rename worksheet
$objPHPExcel->getActiveSheet()->setTitle('Выгрузка заявлений по фильтру');
// Set active sheet index to the first sheet, so Excel opens this as the first sheet
$objPHPExcel->setActiveSheetIndex(0);
$headers = ['ID', 'Фамилия абитуриента', 'Имя абитуриента', 'Отчество абитуриента', 'EMAIL', 'Статус', 'Условния приема', 'Уровень образования', 'Дата отправки заявления'];
if($arParams['GET_DOCS'] == 'Y')
$headers[] = 'Ссылки на файлы';
$activeSheet = $objPHPExcel->setActiveSheetIndex(0);
foreach( $headers as $key => $header ){
$activeSheet->setCellValue(getNameFromNumber($key + 1) . '1' , $header);
}
foreach($arResult["ITEMS"] as $rowIndex => $arItem){
//Here i prepare $row to set values
$c = 0;
foreach($row as $columnIndex => $item ){
$c++;
$activeSheet->setCellValue(getNameFromNumber($c) . (2+$rowIndex) , $item);
}
$c = 0;
foreach($row as $columnIndex => $item ){
$c++;
$activeSheet->getColumnDimension(getNameFromNumber($c))->setAutoSize(true);
}
}
$APPLICATION->RestartBuffer();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $date . '.xlsx"');
header('Cache-Control: max-age=0');
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($objPHPExcel, 'Xlsx');
$writer->save('php://output');
I tried to make empty file -
$objPHPExcel = new Spreadsheet();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="123.xlsx"');
header('Cache-Control: max-age=0');
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($objPHPExcel, 'Xlsx');
$writer->save('php://output');
it doesn't help. Error doesn't disappear
My MS Excel can recovery this file correctly, but it wouldn't open in OpenOffice or something else, so my client can't open it on MAC. How can i resolve this problem?
mb_internal_encoding('latin1');
That helps
Related
i want to download a file of projet but i get it empty. i'am using a spreadsheet librairy
Notice : i a make a dump after save function , my file is full and not empty in the path directory of project
Someone can help me !
bellow is my code :
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('template.xlsx');
$worksheet = $spreadsheet->getActiveSheet();
$filename = 'write.xls';
$worksheet->getCell('A1')->setValue('John');
$worksheet->getCell('A2')->setValue('Smith');
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xls');
$writer->save($filename); die;
// to download file
header('Content-Type: application/vnd.ms-excel');
header("Content-Length:".filesize($filename));
header("Content-Disposition: attachment;filename=$filename");
header('Cache-Control: max-age=0');
$writer->save('php://output');
exit();
i except a full file after downloading it
This function would work:
define ("ONE_DAY", 86400);
function getExisting()
{
$rootFolder = "pathTodirectory";
//first clear old files
$files = scandir($rootFolder,1);
array_pop($files); array_pop($files);
foreach($files as $file)
{
$fp = $rootFolder . DIRECTORY_SEPARATOR . $file;
$filemtime=filemtime($fp);
if (time() - $filemtime >= (2 * ONE_DAY))unlink($fp);
}//end clearing old files
//second rescan folder for current files
$files = scandir($rootFolder,1);
array_pop($files); array_pop($files);
$existing = array_reverse($files);
return $existing;
}
$existing = getExisting();
echo "\n<p> Select file or enter office number to review inventory:";
echo "\n <ul>";
foreach($existing as $rpt)
{
$spd = "pathTodirectory" . $rpt; \\make sure to follow up with relative path name here also
echo "\n <li><a href=\"$spd\" >" . $rpt ."</a></li>";
}
echo "\n </ul>";
I think it is the load() usage issue, your code works with following correction in my site :
$file_loc = 'template.xlsx';
$file_type = \PhpOffice\PhpSpreadsheet\IOFactory::identify($file_loc);
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($file_type);
// $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('template.xlsx');
$spreadsheet = $reader->load($file_loc);
$worksheet = $spreadsheet->getActiveSheet();
$filename = 'write.xls';
$worksheet->getCell('A1')->setValue('John');
$worksheet->getCell('A2')->setValue('Smith');
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xls');
// save a physical file in server, you can skip this actually
$writer->save($target_dir . $filename);
// die; // don't die, be happy (^_^)
// to download file
header('Content-Type: application/vnd.ms-excel');
header("Content-Length:" . filesize($filename));
header("Content-Disposition: attachment;filename=$filename");
header('Cache-Control: max-age=0');
$writer->save('php://output');
exit();
I'm trying to export several tables from a database and creating a excel file for each table using PHP. The loop however is "bugged". Instead of creating a new file for each loop it just puts all data into the same file.
The code:
foreach ($pdo->query("SHOW TABLES;") as $allTables) {
$table = $allTables[0];
$allDataStmt = $pdo->prepare("SELECT * FROM $table;");
$allDataStmt->execute();
$fieldcount = $allDataStmt->columnCount();
$col_title = "";
$data = "";
for ($i = 0; $i < $fieldcount; $i++) {
$col = $allDataStmt->getColumnMeta($i);
$column = $col['name'];
$col_title .= '<Cell ss:StyleID="2"><Data ss:Type="String">' . $column . '</Data></Cell>';
}
$col_title = '<Row>' . $col_title . '</Row>';
while ($row = $allDataStmt->fetch(PDO::FETCH_NUM)) {
$line = '';
foreach ($row as $value) {
if ((!isset($value)) or ($value == "")) {
$value = '<Cell ss:StyleID="1"><Data ss:Type="String"></Data></Cell>\t';
} else {
$value = str_replace('"', '', $value);
$value = '<Cell ss:StyleID="1"><Data ss:Type="String">' . $value . '</Data></Cell>\t';
}
$line .= $value;
}
$data .= trim("<Row>" . $line . "</Row>") . "\n";
}
$data = str_replace("\r", "", $data);
header("Content-Type: application/vnd.ms-excel;");
header("Content-Disposition: attachment; filename=" . $table . ".xls");
header("Pragma: no-cache");
header("Expires: 0");
}
}
If I kill the loop after the first iteration it exports the data correctly from ONE table. If I let the loop run it just loads the same file with the data and the file becomes corrupted. I can't even open it in Excel.
What am I missing? Been stuck with this for hours.
Thank you!
What you are attempting with making multiple different attachments in the same HTTP request is not possible. The HTTP protocol does not have support for downloading multiple files. The most common workaround is to put the files in a zip archive for the client to download, so something like this:
$zip = new ZipArchive;
$zip_name = "excel_tables.zip";
if ($zip->open($zip_name, ZipArchive::CREATE|ZipArchive::OVERWRITE) === TRUE) {
foreach ($pdo->query("SHOW TABLES;") as $allTables) {
// (Your logic to build Excel file)
$file_content = $col_title . "\n" . $data;
$file_name = $table . ".xls";
file_put_contents($file_name, $file_content);
// Add file to the zip file
$zip->addFile($file_name);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=' . $zip_name);
header("Content-Length: " . filesize($zip_name));
header("Pragma: no-cache");
header("Expires: 0");
ob_clean();
flush();
readfile(__DIR__ . "/" . $zip_name);
}
I need to generate an excel file (xls) and trigger the download after it is generated.
I found this example in the documentation.
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'Hello World !');
$writer = new Xlsx($spreadsheet);
$writer->save('hello world.xlsx');
It shows how to create a excel file and save it on the server.
How can I serve the result to the client instead and "force" him to download it?
I need to get the data of the $writer somehow.
I am currently solving it without PhpSpreadsheet:
// Excel Export
$filename = 'export_'.date('d-m-y').'.xls';
$filename = $validator->removeWhitespace($filename);
header('Content-type: application/ms-excel');
header('Content-Disposition: attachment; filename='.$filename);
exit($response["output"]); // <-- contains excel file content
But it is not working with my delimiter (semicolon). The semicolon is not getting interpreted and everything is getting written into one column.
If I export it as .csv, then it works. But I need it as .xls or .xlsx
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class DownloadExcel
{
public static function createExcel(array $data, array $headers = [],
$fileName = 'data.xlsx')
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
for ($i = 0, $l = sizeof($headers); $i < $l; $i++) {
$sheet->setCellValueByColumnAndRow($i + 1, 1, $headers[$i]);
}
for ($i = 0, $l = sizeof($data); $i < $l; $i++) { // row $i
$j = 0;
foreach ($data[$i] as $k => $v) { // column $j
$sheet->setCellValueByColumnAndRow($j + 1, ($i + 1 + 1), $v);
$j++;
}
}
$writer = new Xlsx($spreadsheet);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="'. urlencode($fileName).'"');
$writer->save('php://output');
}
}
This is what I use to create a spreadsheet with PhpSpreadsheet and output directly to php://output for download.
I had the same problem and found a solution here : https://github.com/PHPOffice/PhpSpreadsheet/issues/217
I ended my method with $writer->save('php://output'); then exit()
My answer :
PHP:
$writer = new Xlsx($spreadsheet);
ob_start();
$writer->save('php://output');
$ret['data'] = base64_encode(ob_get_contents());
ob_end_clean();
JS:
var linkSource = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,'+ response.data ;
var downloadLink = document.createElement("a");
var fileName = 'clients.' + format;
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();
I solved it with a workaround. I temporarily save the file on the server, then I load the content into a variable and serve it as a download file. Then I delete the file from the server.
Workaround:
$date = date('d-m-y-'.substr((string)microtime(), 1, 8));
$date = str_replace(".", "", $date);
$filename = "export_".$date.".xlsx";
try {
$writer = new Xlsx($response["spreadsheet"]);
$writer->save($filename);
$content = file_get_contents($filename);
} catch(Exception $e) {
exit($e->getMessage());
}
header("Content-Disposition: attachment; filename=".$filename);
unlink($filename);
exit($content);
call ob_end_clean(); just before the $writer->save('php://output').
ob_end_clean();
$writer->save('php://output');
This worked for me:
$excel = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $excel->getActiveSheet();
$sheet->setTitle('This is a test', true);
ob_end_clean();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="filename_' . time() . '.xlsx"');
header('Cache-Control: max-age=0');
$xlsxWriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($excel, 'Xlsx');
$xlsxWriter = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($excel);
exit($xlsxWriter->save('php://output'));
If you have problems where the files download corrupted, it is always good to check if there is any extra whitespace at the top of your file output. If your PHP files have blank white lines, whilst HTML won't have a problem, your phpspreadsheet file will. Spent a good chunk of time trying to fix these issues but the problem was with the whitespace!
Below is my code. I'm getting the data as a string with 2 parts. First part is all about headers for an excel sheet. And the 2nd part is about the actual data. They are separated by a special delimiter.
Again the second part (actual data) is separated with '\n' for each row with each column again divided with delimiter '|'.
Now if i click on download, the excel is being generated after 1 min 20 secs.. Please help me finding the culprit as I'm new to php.
Im using PHPExcel_IOFactory plugin here..
if (!empty($json_decodeArr))
$dataExists = 1;
else
$dataExists = 0;
$service_name = $params['service_name'];
$company_name = $params["company_name"];
$language = $params["language"];
$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
$cacheSettings = array(' memoryCacheSize ' => '32MB');
PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
// Create new PHPExcel object
$objPHPExcel = new PHPExcel();
if (isset($GLOBALS[$service_name]["TEMPLATE_NAME"]) && $GLOBALS[$service_name]["TEMPLATE_NAME"] != '') {
$template = $GLOBALS[$service_name]["TEMPLATE_NAME"];
$ext = $GLOBALS[$service_name]["TEMPLATE_NAME_EXT"];
$path = $GLOBALS[$service_name]["TEMPLATE_PATH"];
$filepath = $path . $template.$language . "." . $ext;
try {
//load Excel template file
$objPHPExcel = PHPExcel_IOFactory::load($filepath);
} catch(Exception $e) {
die('Error loading file ' . $e -> getMessage());
}
} else {
$template = $GLOBALS["TEMPLATE_BLANK"];
$ext = $GLOBALS[$service_name]["TEMPLATE_BLANK_EXT"];
$path = $GLOBALS["TEMPLATE_BLANKPATH"];
$filepath = $path . $template . "." . $ext;
try {
//load Excel template file
$objPHPExcel = PHPExcel_IOFactory::load($filepath);
} catch(Exception $e) {
die('Error loading file ' . $e -> getMessage());
}
}
$temp_array = array();
//Named Configuration XLS Generation
//Writing Values into the excel sheet
$counter = 0;
$objPHPExcel -> setActiveSheetIndex(1);
$currentSheet = $objPHPExcel -> getActiveSheet();
foreach ($json_decodeArr as $key => $value) {
if ($key == 0) {
$headerNamesArr = explode("|",$GLOBALS[$service_name][$template][0]["HeaderNames"]);
$headerExcelPositionArr = explode("|",$GLOBALS[$service_name][$template][0]["HeaderExcelPosition"]);
$headerDataArr = explode("|",$value);
foreach ($headerNamesArr as $headerName) {
$headerData = getHeaderValue($headerName,$headerDataArr);
$currentSheet -> setCellValue(getHeaderValue($headerName,$headerExcelPositionArr), $headerData);
}
//file_put_contents("testResponse.txt", getHeaderValue('daysleft:',$headerDataArr));
} else {
//$activeWS = "B";
$index = $GLOBALS[$service_name][$template][0]["ROW_START"];
//file_put_contents("testResponse.txt", $GLOBALS[$service_name][$template][0]["COL_START"]);
$rows = explode("\n", $value);
foreach ($rows as $values1) {
$activeWS = $GLOBALS[$service_name][$template][0]["COL_START"];
$rowData = explode("|", $values1);
//file_put_contents("testResponse.txt",$rowData);
foreach ($rowData as $vals) {
$WSName = $activeWS . $index;
$currentSheet -> setCellValue($WSName, $vals);
$activeWS++;
}
$index++;
}
$counter++;
}
}
//$objPHPExcel->removeSheetByIndex($rowStart);
$objPHPExcel -> setActiveSheetIndex(0);
// Redirect output to a client.s web browser (Excel5)
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Disposition: attachment;filename=" . $filename . ".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
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, "Excel2007");
unset($objPHPExcel);
ob_start();
$objWriter -> save("php://output");
ob_flush();
exit ;
This code works fine on localhost but on live server it shows
File Not Found
Check the file name for capitalization or other typing errors.
Check to see if the file was moved, renamed or deleted.
Here is my code
excel.php
<?php
error_reporting(1);
ini_set('display_errors', 0);
ini_set('display_startup_errors', TRUE);
$target = 'Myfile.xlsx';
include 'phpexcel/Classes/PHPExcel/IOFactory.php';
$inputFileType = PHPExcel_IOFactory::identify($target);
function datefix_excel($excel) {
$dif=(41885-$excel)*86400;
$seconds=1409737670-$dif;
$date=date("d/m/Y",$seconds);
return $date; }
//echo 'File ',pathinfo($inputFileName,PATHINFO_BASENAME),' has been identified as an ',$inputFileType,' file<br />';
//echo 'Loading file ',pathinfo($inputFileName,PATHINFO_BASENAME),' using IOFactory with the identified reader type<br />';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objPHPExcel = $objReader->load($target);
$i = 0;
$found = false;
try
{
//
foreach ($objPHPExcel->getWorksheetIterator() as $worksheet)
{
//
//$objWorksheet = $objPHPExcel->getActiveSheet();
//now do whatever you want with the active sheet
$worksheet->setShowGridLines(false);
$worksheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A2_PAPER );
$worksheet->getPageSetup()->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A2_PAPER );
$worksheet->getPageSetup()->setFitToPage(true);
$worksheet->getPageSetup()->setFitToWidth(1);
$worksheet->getPageSetup()->setFitToHeight(0);
$worksheet->getPageSetup()->setScale(40);
$worksheet->getStyle('F1:F4')->getAlignment()->setWrapText(false);
$worksheet->getStyle('D6:D8')->getAlignment()->setWrapText(false);
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
$count = 0;
$found == false;
//
$worksheetTitle = $worksheet->getTitle();
$highestRow = $worksheet->getHighestRow(); // e.g. 10
$highestColumn = $worksheet->getHighestColumn(); // e.g 'F'
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
$nrColumns = ord($highestColumn) - 64;
for ($row = 1; $row <= $highestRow; ++ $row) {
for ($col = 0; $col < $highestColumnIndex; ++ $col) {
$cell = $worksheet->getCellByColumnAndRow($col, $row);
$val = $cell->getValue();
if($val==$_REQUEST['roll'])
{
//echo "Roll Number found: ".$_REQUEST['roll']." <br/>";
$found = true;
// $objPHPExcel->getActiveSheet()->setCellValue('C23',$val);
$objPHPExcel->getActiveSheet()->setCellValue('C23',datefix_excel($objPHPExcel->getActiveSheet()->getCell('C23')->getValue()));
$rendererName = PHPExcel_Settings::PDF_RENDERER_DOMPDF;
$rendererLibrary = 'dompdf';
$rendererLibraryPath = './' . $rendererLibrary;
//require_once (realpath(dirname(dirname(dirname(__FILE__))))."/libraries/pdf.php");
//echo $rendererName.' and '.$rendererLibraryPath;
if (!PHPExcel_Settings::setPdfRenderer($rendererName,$rendererLibraryPath)) {
die('NOTICE: Please set the $rendererName and $rendererLibraryPath values' .EOL .'at the top of this script as appropriate for your directory structure');
}
header("HTTP/1.1 200 OK");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header('Content-Type: application/pdf');
header('Content-Disposition: attachment;filename="rename.pdf"'); //tell browser what's the file name
header('Cache-Control: max-age=0'); //no cache
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'PDF');
$objWriter->setSheetIndex($i);
//$objWriter->save('test.pdf');
$objWriter->save('php://output');
break;
}
else{
continue;
}
}
}
//
}
}
catch(Exception $e)
{
//echo $e;
}
?>
I would check: 1) is current folder writeable? 2) pdf.php is commented out, try enabling it (why? local machine probably has PDF installed, server does not), 3) try saving to file instead of outputting to browser, this will bypass any browser / security issues.