From 623caa89bc3adec5c7e1731f60159f13962c2fb2 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Tue, 9 May 2023 21:41:39 -0700 Subject: [PATCH] Changes for Chart Rendering Samples (#3551) * Changes for Chart Rendering Samples PR #3521 added chart rendering to the 33* samples. Some of those samples had rendering problems; this PR fixes some of the errors by changing some of the code in JpGraphRendererBase. I am discussing approaches to some other problems with mitoteam. The changes in 3521 applied only when running the samples as web pages. A new member 35_Chart_render33 is added to do the same when running the samples from the command line. Because of 3521, 35_Chart_render and new 35_Chart_render33 (in web page mode) display rendering which is already displayed by other samples and so are superfluous as web pages, so they are no longer presented as options. The samples in 35_Chart_render properly accounted for multiple charts on a single worksheet, but did not properly account for charts on multiple worksheets. This problem is fixed. 33_Chart_create_stock2 was added using a base from before 3521, but did not incorporate the 3521 changes. It now does so. 32_Chart_read_write_HTML and 32_Chart_read_write_PDF are made consistent with the 32* Xlsx samples by allowing the download of the generated file when run as web pages. Helper/Downloader needed a minor change to support Html. Some of the changes in PR #3522 require the Downloader change to work properly. Some samples which were not changed by 3522 are changed in this PR to give a more uniform look and feel to the web samples. * Scrutinizer Fix class name conflict. Ignore "complexity" problem. * Improve Sample 26 The UTF8 sample 26 includes CJK characters. These are generated in Xls, Xlsx, Html, and Csv (with BOM) correctly. Csv without BOM has a problem, but that's Microsoft's problem, not ours. That leaves PDF, which currently does not display the CJK characters (nor a Latin extension character). Mpdf, in combination with editHtmlCallback (and earlier commits in this PR), can support them; change the sample to do so. Dompdf, which had been used for the sample, apparently supported Web Fonts at one time, which might also have solved this problem, but no longer seems to do so. * Fix Style Problem Need blank line. * Change Some Spacing in Source Code Make Header PSR12-compliant. --- samples/Basic/17_Html.php | 10 +- samples/Basic/17a_Html.php | 17 +-- samples/Basic/17b_Html.php | 18 ++-- samples/Basic/26_Utf8.php | 50 ++++++--- samples/Chart/32_Chart_read_write_HTML.php | 6 +- samples/Chart/32_Chart_read_write_PDF.php | 6 +- samples/Chart/33_Chart_create_stock2.php | 9 +- samples/Chart/35_Chart_render.php | 6 +- samples/Chart/35_Chart_render33.php | 101 ++++++++++++++++++ samples/Header.php | 35 +++++- samples/Pdf/21a_Pdf.php | 16 ++- samples/Pdf/21b_Pdf.php | 48 ++++++--- samples/Pdf/21c_Pdf.php | 9 +- samples/Pdf/21d_FitToHeightPdf.php | 8 +- .../Chart/Renderer/JpGraphRendererBase.php | 29 ++++- src/PhpSpreadsheet/Helper/Downloader.php | 1 + src/PhpSpreadsheet/Helper/Sample.php | 7 +- 17 files changed, 282 insertions(+), 94 deletions(-) create mode 100644 samples/Chart/35_Chart_render33.php diff --git a/samples/Basic/17_Html.php b/samples/Basic/17_Html.php index b90b7212d..54f031ece 100644 --- a/samples/Basic/17_Html.php +++ b/samples/Basic/17_Html.php @@ -1,13 +1,7 @@ getProperties()->setTitle('Non-embedded images'); -$filename = $helper->getFilename(__FILE__, 'html'); -$writer = IOFactory::createWriter($spreadsheet, 'Html'); - -$callStartTime = microtime(true); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); +$helper->write($spreadsheet, __FILE__, ['Html']); diff --git a/samples/Basic/17a_Html.php b/samples/Basic/17a_Html.php index 20578fbe3..5804c77c7 100644 --- a/samples/Basic/17a_Html.php +++ b/samples/Basic/17a_Html.php @@ -4,11 +4,14 @@ use PhpOffice\PhpSpreadsheet\Writer\Html; require __DIR__ . '/../Header.php'; $spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php'; +$spreadsheet->getProperties()->setTitle('Embedded images'); -$filename = $helper->getFilename(__FILE__, 'html'); -$writer = new Html($spreadsheet); - -$callStartTime = microtime(true); -$writer->setEmbedImages(true); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); +$helper->write( + $spreadsheet, + __FILE__, + ['Html'], + false, + function (Html $writer): void { + $writer->setEmbedImages(true); + } +); diff --git a/samples/Basic/17b_Html.php b/samples/Basic/17b_Html.php index 97bb29a33..0e677e3ed 100644 --- a/samples/Basic/17b_Html.php +++ b/samples/Basic/17b_Html.php @@ -5,16 +5,18 @@ use PhpOffice\PhpSpreadsheet\Writer\Html; require __DIR__ . '/../Header.php'; $spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php'; -$filename = $helper->getFilename(__FILE__, 'html'); -$writer = new Html($spreadsheet); - function changeGridlines(string $html): string { return str_replace('{border: 1px solid black;}', '{border: 2px dashed red;}', $html); } -$callStartTime = microtime(true); -$writer->setEmbedImages(true); -$writer->setEditHtmlCallback('changeGridlines'); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); +$helper->write( + $spreadsheet, + __FILE__, + ['Html'], + false, + function (Html $writer): void { + $writer->setEmbedImages(true); + $writer->setEditHtmlCallback('changeGridlines'); + } +); diff --git a/samples/Basic/26_Utf8.php b/samples/Basic/26_Utf8.php index 52a64509b..2eeca067b 100644 --- a/samples/Basic/26_Utf8.php +++ b/samples/Basic/26_Utf8.php @@ -1,6 +1,8 @@ log('Load Xlsx template file'); $reader = IOFactory::createReader('Xlsx'); $spreadsheet = $reader->load(__DIR__ . '/../templates/26template.xlsx'); +$spreadsheet->getActiveSheet()->setPrintGridlines(true); // at this point, we could do some manipulations with the template, but we skip this step $helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']); -// Export to PDF (.pdf) -$helper->log('Write to PDF format'); -IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf::class); -$helper->write($spreadsheet, __FILE__, ['Pdf']); +// Export to PDF (mpdf) +function mpdfCjkWriter(Mpdf $writer): void +{ + /** @var callable */ + $callback = 'mpdfCjk'; + $writer->setEditHtmlCallback($callback); +} + +function mpdfCjk(string $html): string +{ + $html = str_replace("'Calibri'", "'Calibri',Sun-ExtA", $html); + + return str_replace("'Times New Roman'", "'Times New Roman',Sun-ExtA", $html); +} + +$helper->log('Write to Mpdf'); +IOFactory::registerWriter('Pdf', Mpdf::class); +/** @var callable */ +$callback = 'mpdfCjkWriter'; +$filename = __FILE__; +//$filename = str_replace('.php', '.mdpf.php', __FILE__); +$helper->write($spreadsheet, $filename, ['Pdf'], false, $callback); // Remove first two rows with field headers before exporting to CSV $helper->log('Removing first two heading rows for CSV export'); @@ -25,16 +46,17 @@ $worksheet->removeRow(1, 2); // Export to CSV (.csv) $helper->log('Write to CSV format'); /** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writer */ -$writer = IOFactory::createWriter($spreadsheet, 'Csv'); -$filename = $helper->getFilename(__FILE__, 'csv'); -$callStartTime = microtime(true); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); +$helper->write($spreadsheet, __FILE__, ['Csv']); // Export to CSV with BOM (.csv) -$filename = str_replace('.csv', '-bom.csv', $filename); +$filename = str_replace('.php', '-bom.php', __FILE__); $helper->log('Write to CSV format (with BOM)'); -$writer->setUseBOM(true); -$callStartTime = microtime(true); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); +$helper->write( + $spreadsheet, + $filename, + ['Csv'], + false, + function (Csv $writer): void { + $writer->setUseBOM(true); + } +); diff --git a/samples/Chart/32_Chart_read_write_HTML.php b/samples/Chart/32_Chart_read_write_HTML.php index 90d61c5d5..3cb377873 100644 --- a/samples/Chart/32_Chart_read_write_HTML.php +++ b/samples/Chart/32_Chart_read_write_HTML.php @@ -79,11 +79,7 @@ foreach ($inputFileNames as $inputFileName) { // Save $filename = $helper->getFilename($inputFileName, 'html'); - $writer = IOFactory::createWriter($spreadsheet, 'Html'); - $writer->setIncludeCharts(true); - $callStartTime = microtime(true); - $writer->save($filename); - $helper->logWrite($writer, $filename, $callStartTime); + $helper->write($spreadsheet, $filename, ['Html'], true); $spreadsheet->disconnectWorksheets(); unset($spreadsheet); diff --git a/samples/Chart/32_Chart_read_write_PDF.php b/samples/Chart/32_Chart_read_write_PDF.php index 214c3d380..e3d702a9d 100644 --- a/samples/Chart/32_Chart_read_write_PDF.php +++ b/samples/Chart/32_Chart_read_write_PDF.php @@ -81,11 +81,7 @@ foreach ($inputFileNames as $inputFileName) { // Save $filename = $helper->getFilename($inputFileName, 'pdf'); - $writer = IOFactory::createWriter($spreadsheet, 'Pdf'); - $writer->setIncludeCharts(true); - $callStartTime = microtime(true); - $writer->save($filename); - $helper->logWrite($writer, $filename, $callStartTime); + $helper->write($spreadsheet, $filename, ['Pdf'], true); $spreadsheet->disconnectWorksheets(); unset($spreadsheet); diff --git a/samples/Chart/33_Chart_create_stock2.php b/samples/Chart/33_Chart_create_stock2.php index 0d5ebf2c0..bc9faf3db 100644 --- a/samples/Chart/33_Chart_create_stock2.php +++ b/samples/Chart/33_Chart_create_stock2.php @@ -8,7 +8,6 @@ use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; -use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; @@ -116,12 +115,8 @@ $chart->setBottomRightPosition('H20'); // Add the chart to the worksheet $worksheet->addChart($chart); +$helper->renderChart($chart, __FILE__); $worksheet->setSelectedCells('G2'); // Save Excel 2007 file -$filename = $helper->getFilename(__FILE__); -$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); -$writer->setIncludeCharts(true); -$callStartTime = microtime(true); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); +$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart/35_Chart_render.php b/samples/Chart/35_Chart_render.php index 7b1e4ed97..4c403d993 100644 --- a/samples/Chart/35_Chart_render.php +++ b/samples/Chart/35_Chart_render.php @@ -54,6 +54,7 @@ foreach ($inputFileNames as $inputFileName) { $spreadsheet = $reader->load($inputFileName); $helper->log('Iterate worksheets looking at the charts'); + $renderedCharts = 0; foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { $sheetName = $worksheet->getTitle(); $helper->log('Worksheet: ' . $sheetName); @@ -63,7 +64,8 @@ foreach ($inputFileNames as $inputFileName) { $helper->log(' There are no charts in this worksheet'); } else { natsort($chartNames); - foreach ($chartNames as $i => $chartName) { + foreach ($chartNames as $j => $chartName) { + $i = $renderedCharts + $j; $chart = $worksheet->getChartByName($chartName); if ($chart->getTitle() !== null) { $caption = '"' . implode(' ', $chart->getTitle()->getCaption()) . '"'; @@ -86,6 +88,8 @@ foreach ($inputFileNames as $inputFileName) { } catch (Exception $e) { $helper->log('Error rendering chart: ' . $e->getMessage()); } + + ++$renderedCharts; } } } diff --git a/samples/Chart/35_Chart_render33.php b/samples/Chart/35_Chart_render33.php new file mode 100644 index 000000000..bd8075de4 --- /dev/null +++ b/samples/Chart/35_Chart_render33.php @@ -0,0 +1,101 @@ +getTemporaryFolder() . '/33_Chart_create_*.xlsx'; + +if ((isset($argc)) && ($argc > 1)) { + $inputFileNames = []; + for ($i = 1; $i < $argc; ++$i) { + $inputFileNames[] = __DIR__ . '/../templates/' . $argv[$i]; + } +} else { + $inputFileNames = glob($inputFileNames); +} +if (count($inputFileNames) === 1) { + $unresolvedErrors = []; +} else { + $unresolvedErrors = [ + // The following spreadsheet was created by 3rd party software, + // and doesn't include the data that usually accompanies a chart. + // That is good enough for Excel, but not for JpGraph. + '33_Chart_create_bar_stacked.xlsx', + ]; +} +foreach ($inputFileNames as $inputFileName) { + $inputFileNameShort = basename($inputFileName); + + if (!file_exists($inputFileName)) { + $helper->log('File ' . $inputFileNameShort . ' does not exist'); + + continue; + } + if (in_array($inputFileNameShort, $unresolvedErrors, true)) { + $helper->log('*****'); + $helper->log('***** File ' . $inputFileNameShort . ' does not yet work with this script'); + $helper->log('*****'); + + continue; + } + + $helper->log("Load Test from $inputFileType file " . $inputFileNameShort); + + $reader = IOFactory::createReader($inputFileType); + $reader->setIncludeCharts(true); + $spreadsheet = $reader->load($inputFileName); + + $helper->log('Iterate worksheets looking at the charts'); + $renderedCharts = 0; + foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { + $sheetName = $worksheet->getTitle(); + $helper->log('Worksheet: ' . $sheetName); + + $chartNames = $worksheet->getChartNames(); + if (empty($chartNames)) { + $helper->log(' There are no charts in this worksheet'); + } else { + natsort($chartNames); + foreach ($chartNames as $j => $chartName) { + $i = $renderedCharts + $j; + $chart = $worksheet->getChartByName($chartName); + if ($chart->getTitle() !== null) { + $caption = '"' . implode(' ', $chart->getTitle()->getCaption()) . '"'; + } else { + $caption = 'Untitled'; + } + $helper->log(' ' . $chartName . ' - ' . $caption); + + $pngFile = $helper->getFilename('35-' . $inputFileNameShort, 'png'); + if ($i !== 0) { + $pngFile = substr($pngFile, 0, -3) . "$i.png"; + } + if (file_exists($pngFile)) { + unlink($pngFile); + } + + try { + $chart->render($pngFile); + $helper->log('Rendered image: ' . $pngFile); + } catch (Exception $e) { + $helper->log('Error rendering chart: ' . $e->getMessage()); + } + + ++$renderedCharts; + } + } + } + + $spreadsheet->disconnectWorksheets(); + unset($spreadsheet); + gc_collect_cycles(); +} + +$helper->log('Done rendering charts as images'); diff --git a/samples/Header.php b/samples/Header.php index eb0766be5..670776851 100644 --- a/samples/Header.php +++ b/samples/Header.php @@ -1,7 +1,9 @@ isCli()) { diff --git a/samples/Pdf/21a_Pdf.php b/samples/Pdf/21a_Pdf.php index 33b61c9f5..377f59287 100644 --- a/samples/Pdf/21a_Pdf.php +++ b/samples/Pdf/21a_Pdf.php @@ -1,5 +1,6 @@ log('Write to Mpdf'); -$writer = new Mpdf($spreadsheet); -$filename = $helper->getFileName('21a_Pdf_mpdf.xlsx', 'pdf'); -$writer->setEditHtmlCallback('changeGridlines'); -$writer->save($filename); +IOFactory::registerWriter('Pdf', Mpdf::class); +$helper->write( + $spreadsheet, + __FILE__, + ['Pdf'], + false, + function (Mpdf $writer): void { + $writer->setEmbedImages(true); + $writer->setEditHtmlCallback('changeGridlines'); + } +); diff --git a/samples/Pdf/21b_Pdf.php b/samples/Pdf/21b_Pdf.php index 421e0867e..d7a1cb51e 100644 --- a/samples/Pdf/21b_Pdf.php +++ b/samples/Pdf/21b_Pdf.php @@ -1,9 +1,10 @@ log('Set orientation to landscape'); $spreadsheet->getActiveSheet()->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE); $helper->log('Write to Dompdf'); -$writer = new Dompdf($spreadsheet); -$filename = $helper->getFileName('21b_Pdf_dompdf.xlsx', 'pdf'); -$writer->setEditHtmlCallback('replaceBody'); -$writer->save($filename); +IOFactory::registerWriter('Pdf', Dompdf::class); +$filename = str_replace('.php', '_dompdf.php', __FILE__); +$helper->write( + $spreadsheet, + $filename, + ['Pdf'], + false, + function (Dompdf $writer): void { + $writer->setEditHtmlCallback('replaceBody'); + } +); $helper->log('Write to Mpdf'); -$writer = new Mpdf($spreadsheet); -$filename = $helper->getFileName('21b_Pdf_mpdf.xlsx', 'pdf'); -$writer->setEditHtmlCallback('replaceBody'); -$writer->save($filename); +IOFactory::registerWriter('Pdf', Mpdf::class); +$filename = str_replace('.php', '_mpdf.php', __FILE__); +$helper->write( + $spreadsheet, + $filename, + ['Pdf'], + false, + function (Mpdf $writer): void { + $writer->setEditHtmlCallback('replaceBody'); + } +); $helper->log('Write to Tcpdf'); -$writer = new Tcpdf($spreadsheet); -$filename = $helper->getFileName('21b_Pdf_tcpdf.xlsx', 'pdf'); -$writer->setEditHtmlCallback('replaceBody'); -$writer->save($filename); +IOFactory::registerWriter('Pdf', TcpdfClass::class); +$filename = str_replace('.php', '_tcpdf.php', __FILE__); +$helper->write( + $spreadsheet, + $filename, + ['Pdf'], + false, + function (TcpdfClass $writer): void { + $writer->setEditHtmlCallback('replaceBody'); + } +); diff --git a/samples/Pdf/21c_Pdf.php b/samples/Pdf/21c_Pdf.php index 6fe12664b..211f8be9a 100644 --- a/samples/Pdf/21c_Pdf.php +++ b/samples/Pdf/21c_Pdf.php @@ -1,7 +1,7 @@ log('Write to Mpdf'); -$writer = new Mpdf($spreadsheet); -$filename = $helper->getFileName('21c_Pdf_mpdf.xlsx', 'pdf'); -$writer->save($filename); -$helper->log("Saved $filename"); +IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class); +$helper->write($spreadsheet, __FILE__, ['Pdf']); +$spreadsheet->disconnectWorksheets(); diff --git a/samples/Pdf/21d_FitToHeightPdf.php b/samples/Pdf/21d_FitToHeightPdf.php index 1b02d9d53..577eac0c4 100644 --- a/samples/Pdf/21d_FitToHeightPdf.php +++ b/samples/Pdf/21d_FitToHeightPdf.php @@ -1,7 +1,7 @@ load($fileWithPath); $sheet = $spreadsheet->getActiveSheet(); $helper->log('Write to Mpdf'); -$writer = new Mpdf($spreadsheet); -$filename = $helper->getfilename($filename, 'pdf'); -$writer->save($filename); -$helper->log("Saved $filename"); +IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class); +$helper->write($spreadsheet, __FILE__, ['Pdf']); $spreadsheet->disconnectWorksheets(); diff --git a/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php b/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php index cb9b544b8..d676f1d33 100644 --- a/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php +++ b/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php @@ -434,12 +434,33 @@ abstract class JpGraphRendererBase implements IRenderer // Loop through each data series in turn for ($i = 0; $i < $seriesCount; ++$i) { - $dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); + $plotCategoryByIndex = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i); + if ($plotCategoryByIndex === false) { + $plotCategoryByIndex = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0); + } + $dataValuesY = $plotCategoryByIndex->getDataValues(); $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); - foreach ($dataValuesY as $k => $dataValueY) { - $dataValuesY[$k] = $k; + $redoDataValuesY = true; + if ($bubble) { + if (!$bubbleSize) { + $bubbleSize = '10'; + } + $redoDataValuesY = false; + foreach ($dataValuesY as $dataValueY) { + if (!is_int($dataValueY) && !is_float($dataValueY)) { + $redoDataValuesY = true; + + break; + } + } } + if ($redoDataValuesY) { + foreach ($dataValuesY as $k => $dataValueY) { + $dataValuesY[$k] = $k; + } + } + //var_dump($dataValuesY, $dataValuesX, $bubbleSize); $seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY); if ($scatterStyle == 'lineMarker') { @@ -483,7 +504,7 @@ abstract class JpGraphRendererBase implements IRenderer $dataValues = []; foreach ($dataValuesY as $k => $dataValueY) { - $dataValues[$k] = implode(' ', array_reverse($dataValueY)); + $dataValues[$k] = is_array($dataValueY) ? implode(' ', array_reverse($dataValueY)) : $dataValueY; } $tmp = array_shift($dataValues); $dataValues[] = $tmp; diff --git a/src/PhpSpreadsheet/Helper/Downloader.php b/src/PhpSpreadsheet/Helper/Downloader.php index a45c358f6..e66ae4258 100644 --- a/src/PhpSpreadsheet/Helper/Downloader.php +++ b/src/PhpSpreadsheet/Helper/Downloader.php @@ -17,6 +17,7 @@ class Downloader 'xls' => 'application/vnd.ms-excel', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'csv' => 'text/csv', + 'html' => 'text/html', 'pdf' => 'application/pdf', ]; diff --git a/src/PhpSpreadsheet/Helper/Sample.php b/src/PhpSpreadsheet/Helper/Sample.php index 0e6a427d1..6244375fe 100644 --- a/src/PhpSpreadsheet/Helper/Sample.php +++ b/src/PhpSpreadsheet/Helper/Sample.php @@ -123,7 +123,7 @@ class Sample * @param string $filename * @param string[] $writers */ - public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls'], bool $withCharts = false): void + public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls'], bool $withCharts = false, ?callable $writerCallback = null): void { // Set active sheet index to the first sheet, so Excel opens this as the first sheet $spreadsheet->setActiveSheetIndex(0); @@ -132,8 +132,9 @@ class Sample foreach ($writers as $writerType) { $path = $this->getFilename($filename, mb_strtolower($writerType)); $writer = IOFactory::createWriter($spreadsheet, $writerType); - if ($writerType === 'Xlsx' && $withCharts === true) { - $writer->setIncludeCharts(true); + $writer->setIncludeCharts($withCharts); + if ($writerCallback !== null) { + $writerCallback($writer); } $callStartTime = microtime(true); $writer->save($path);