0

I know this might have been asked in several pieces, but I could not find an exact answer to the issue. I am using PHPExcel to generate an Excel file (obviously), and the code works to generate the file, but not when I include the code for Force Download, it corrupts the file. My latest version of the script looks like this:

function make_xls_spreadsheet(){

/** Error reporting */
error_reporting(E_ALL);

/* Set the save path */
define('XLSX_SAVE_PATH', 'tmp/');

/** Include path **/
set_include_path(get_include_path() . PATH_SEPARATOR . 'Classes/');

/** PHPExcel */
include 'PHPExcel.php';

/** PHPExcel_Writer_Excel2007 */
include 'PHPExcel/Writer/Excel2007.php';


/* Create a new PHPExcel Object */
$objPHPExcel = new PHPExcel();


/* Add some metadata to the file */
$objPHPExcel->getProperties()->setCreator("Maarten Balliauw");
$objPHPExcel->getProperties()->setLastModifiedBy("Maarten Balliauw");
$objPHPExcel->getProperties()->setTitle("Office 2007 XLSX Test Document");
$objPHPExcel->getProperties()->setSubject("Office 2007 XLSX Test Document");
$objPHPExcel->getProperties()->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.");

/* Set active worksheet to first */
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->setTitle('Segments');

/* Add some data to the worksheet */
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->SetCellValue('A1', 'Hello');
$objPHPExcel->getActiveSheet()->SetCellValue('B2', 'world!');
$objPHPExcel->getActiveSheet()->SetCellValue('C1', 'Hello');
$objPHPExcel->getActiveSheet()->SetCellValue('D2', 'world!');


/* Write to server */
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);

$filename = "tony1.xlsx";

// Works fine up to here

header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="'.$filename.'"');
header('Cache-Control: max-age=0');

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
//$objWriter->save('php://output');
$objWriter->save(XLSX_SAVE_PATH . $filename);
readfile(XLSX_SAVE_PATH . $filename);


echo "DONE!";

$objPHPExcel->disconnectWorksheets();
unset($objPHPExcel);



}

Remember, when I remove the force code section, the file generates and I can FTP it down fine. However, doing both generating and forcing the file gives me a corrupt file. Normally I can click "Open & Repair" (Office2011 MacOSX) but obviously this is not desirable.

Could someone please help me understand:

  1. Why it is being generated as corrupt? And why it works fine when I don't force download.
  2. What the proper order for saving/forcing is (using PHP's header() function)
  3. If there is a better way of doing this.

Much appreciated!!

**** Update **** Here is the code when I click "Fix & Repair":

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <logFileName>Repair Result to tony1 03178.xml</logFileName>
    <summary>Errors were detected in file 'Macintosh HD:Users:tony.diloreto:Downloads:tony1.xlsx'</summary>
    <additionalInfo><info>Excel completed file level validation and repair. Some parts of this workbook may have been repaired or discarded.</info></additionalInfo>
</recoveryLog>
Tony D
  • 184
  • 2
  • 12
  • instead of saving it to a file, save it to `php://output`, unless you need a local copy then `$objWriter->save('php://output');` –  Oct 08 '14 at 20:04
  • Thanks - do I need the readfile() line then? What would go in it if I do? – Tony D Oct 08 '14 at 20:10
  • replace everything after the line `$objWriter =` .. with `$objWriter->save('php://output');` –  Oct 08 '14 at 20:12
  • No dice - new bottom of script is: `header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="'.$filename.'"'); header('Cache-Control: max-age=0'); $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); $objWriter->save('php://output'); return;` – Tony D Oct 08 '14 at 20:18
  • fyi "no dice" and "Close but no cigar." is a tad condescending to the *free* help –  Oct 08 '14 at 20:18
  • what exactly happens now? and whats `return;` ? –  Oct 08 '14 at 20:19
  • apologies - obv peace & love for all the free help. =D I removed the `return;` (added just to ensure the function ended) but still did not work. :-( – Tony D Oct 08 '14 at 20:21
  • all good, but `does not work` can mean many things ;) –  Oct 08 '14 at 20:25
  • Sorry - file is still generated, but when I save & open, I still get an error opening the file. The error is: "excel could not open because some content is unreadable". OSX - Excel2011 – Tony D Oct 08 '14 at 20:27
  • save the file, open with text editor, check for php errors in the top –  Oct 08 '14 at 20:28
  • I'm still not having any luck - here is the file http://tonydiloreto.com/files/tony1.xlsx Would you mind trying to open if you have a non-mac? – Tony D Oct 08 '14 at 20:33
  • open that file in text editior - scroll down - see something funny? –  Oct 08 '14 at 20:38
  • When I open in Sublime, all I see are quartets of numbers all the way down. When I try in TextWrangler, it shows me folders of .XML files, but they look fine to me. Which Mac text-editor would you recommend? – Tony D Oct 08 '14 at 20:41
  • never used a mac. it's full of html after the excel, add `exit();` to end of function –  Oct 08 '14 at 20:41
  • You are a genius among men! If you ever come to NYC let me know and I'll buy you a beer! Thank you so much Dagon! – Tony D Oct 08 '14 at 20:45

3 Answers3

2

// answer actually belongs to @Dagon

The answer is actually straightforward, only needing a simple exit(); call.

Final code block:

function make_xls_spreadsheet(){

/** Include path **/
set_include_path(get_include_path() . PATH_SEPARATOR . 'Classes/');

/** PHPExcel */
include 'PHPExcel.php';

/** PHPExcel_Writer_Excel2007 */
include 'PHPExcel/Writer/Excel2007.php';


/* Create a new PHPExcel Object */
$objPHPExcel = new PHPExcel();

/** Determine filename **/
$filename = "tony1.xlsx";

/** Set header information **/
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="' . $filename . '"');
header('Cache-Control: max-age=0');


/* Add some metadata to the file */
$objPHPExcel->getProperties()->setCreator("Maarten Balliauw");
$objPHPExcel->getProperties()->setLastModifiedBy("Maarten Balliauw");
$objPHPExcel->getProperties()->setTitle("Office 2007 XLSX Test Document");
$objPHPExcel->getProperties()->setSubject("Office 2007 XLSX Test Document");
$objPHPExcel->getProperties()->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.");

/* Set active worksheet to first */
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->setTitle('Segments');

/* Add some data to the worksheet */
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->SetCellValue('A1', 'Hello');
$objPHPExcel->getActiveSheet()->SetCellValue('B2', 'world!');
$objPHPExcel->getActiveSheet()->SetCellValue('C1', 'Hello');
$objPHPExcel->getActiveSheet()->SetCellValue('D2', 'world!');


header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="'.$filename.'"');
header('Cache-Control: max-age=0');

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');

exit();

}
Tony D
  • 184
  • 2
  • 12
  • actully the 2nd question i answered today with the answer of `exit();` http://stackoverflow.com/questions/26264997/passing-get-variables-using-header-in-php –  Oct 08 '14 at 20:48
0

This spits out the excel file to the browser:

readfile(XLSX_SAVE_PATH . $filename);  

and then you spit this out, which becomes PART of the excel file as downloaded by the browser

echo "DONE!";

essentially you're sending

[excel data]DONE!

when Excel is expecting only

[excel data]
Marc B
  • 356,200
  • 43
  • 426
  • 500
  • Close but no cigar. It still says some content is "unreadable" and it must fix & repair. Any other ideas? – Tony D Oct 08 '14 at 19:47
0

Try to modify File.php like this :

protected static $_useUploadTempDirectory = TRUE;

in folder phpexcel/Classes/PHPExcel/Shared (it's not the best way but it worked for me).