0

I wrote a class to wrap around the PhpSpreadSheet so that all I would need to do is pass it an array. Then it would generate the proper spreadsheet. Life was fine in testing. In production, the file generated only has HTML in it.

enter image description here

Yes, I am calling it from inside a loaded page. Can this be stopped? I have the function above where the page is loaded.

namespace OpenEMR\Services;

class ImmunizationSpreadsheet extends SpreadSheetServices
{

public function generateSpreadsheetArray($res, $filename)
{
    $sheet = [];
    $i = 1;
    while ($row = sqlFetchArray($res)) {
        //Convert array to a string
        $sheet[] =
            "Q$i, "
            . $row['patientid'] . ", "
            . $row['language'] . ", "
            . $row['cvx_code'] . ", "
            . $row['immunizationdate'] . ", "
            . $row['immunizationid'] . ", "
            . $row['immunizationtitle'];
        ++$i;
    }

    $ss = new SpreadSheetServices();
    $ss->setArrayData([$sheet]);
    $ss->setFileName($filename);
    $ss->makeXlsReport();
}
}

The only thing I can think to do is find a way to send the data without loading the page. But because this is supposed to be the export of a report to xlsx. The user needs to see the data set first before exporting.

Here is my wrapper class.

/**
 *  @package OpenEMR
 *  @link    http://www.open-emr.org
 *  @author  Sherwin Gaddis <sherwingaddis@gmail.com>
 *  @copyright Copyright (c) 2021 - 2022  Sherwin Gaddis <sherwingaddis@gmail.com>
 *  @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
 *
 * This middleware is to allow a uniform use of the spreadsheet library.
 * By passing an array values, a spreadsheet can be dropped to the client from anywhere
 * To use this service send the file name and an array like this
 * The first row is the headers that can be dynamcally generated or static
 * $sheet_array = [
 *     [NULL, 2010, 2011, 2012],
 *     ['Q1',   12,   15,   21],
 *     ['Q2',   56,   73,   86],
 *     ['Q3',   52,   61,   69],
 *     ['Q4',   30,   32, 'Harry'],
 *     ];
 */

namespace OpenEMR\Services;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use OpenEMR\Common\Database\QueryUtils;

class SpreadSheetServices
{
    private $arrayData;
    private $fileName;

    /**
     * @param mixed $fileName
     */
    public function setFileName($fileName): void
    {
        $this->fileName = $fileName;
    }

    /**
     * @param mixed $arrayData
     */
    public function setArrayData($arrayData): void
    {
        $this->arrayData = $arrayData;
    }

    public function __construct()
    {
        //do epic stuff!!
    }

    public function makeXlsReport()
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->fromArray($this->arrayData);

        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename=' . $this->fileName);
        $writer = new Xlsx($spreadsheet);
        $writer->save("php://output");
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='. basename($this->fileName));
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($this->fileName));
        readfile($this->fileName);
    }
}
user1794918
  • 1,131
  • 2
  • 16
  • 34
  • You say you're calling it from inside a "loaded page", you can't really do that. Serving a webpage sends HTML data and the web browser interprets that. When you want to send a file, the only content you should be sending are the headers that tell the browser it's a file and the actual file content. Trying to mix these won't work. – Rylee May 13 '22 at 04:54
  • So the simplest way is to have a separate file which purely generates and serves the excel file. You can run all the some code to get the required data but don't send any HTML here. – Rylee May 13 '22 at 04:55
  • Ok, then my thinking was on the right path. I have to figure out how to separate the call to the PhpSpreadSheet so that it is purely data. Thanks @Rylee – user1794918 May 13 '22 at 10:13

0 Answers0