Only save changes in PHPExcel - php

I am using PHPExcel for editing a large XLSX file (~230kb, 20 sheets). They way I do it yet is:
load the file (create the PHPExcel object)
do the changes on the PHPExcel object
overwrite the XLSX file with a new one
This is very slow (~6 seconds), although there are only small changes (some cells in just one worksheet).
Is there a way to save just the changes in the file? Or if not, with another library?

You can try to do it with Spout: https://github.com/box/spout. It should not take more than a second and your code should look like this:
$reader = ReaderFactory::create(Type::XLSX);
$reader->open('path/to/file/to/read.xlsx');
$writer = WriterFactory::create(Type::XLSX);
$writer->openToFile('path/to/file/to/write.xlsx'); // needs to be different than the one read for now
while ($reader->hasNextSheet()) {
$reader->nextSheet();
while ($reader->hasNextRow()) {
$row = $reader->nextRow();
// change the row here if needed
$writer->addRow($row);
}
}
$reader->close();
$writer->close();
// And at the end, you can replace the old file with the new one:
rename('path/to/file/to/read.xlsx', 'path/to/file/to/write.xlsx');
Hope that helps!

Related

Copy charts from (.xls or .xlsx) using PHP

I am working on a template excel file for some projects and my goal is to populate it with PHP. I create an excel document with two sheets, one is a table with all of the information that I am going to plot, and the second sheet is just a graph that is based on the table from the previous sheet.
Whenever I use (https://github.com/PHPOffice/PhpSpreadsheet) PHPSpreadsheet (since PHPExcel is deprecated) I am able to read/write/copy/etc the first sheet, but whenever I try to save the sheet without touching the graph sheet at all, nothing happens. I save the file successfully but when I try to open it I get an error stating that Excel found unreadable content in the file and to repair it. I repair it and the second sheet with the graph is empty.
https://github.com/PHPOffice/PhpSpreadsheet/issues/382
This is the closest thing I found to my issue, and I did add the setIncludeChart functions, but nothing seems to work.
I also feel that I have exhausted online searches and am now hoping that there is an alternative to PHPSpreadsheet that will allow me to use a chart in a template (supplied) excel file.
$xls = 'KPI_ReadinessTemplate.xls';
$xlsxTarget = 'NEWX_KPI_ReadinessTemplate.xlsx';
$xlsTarget = 'NEW_KPI_ReadinessTemplate.xls';
$inputFileType = 'Xlsx';
$inputFileName = $xlsx;
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
$reader->setIncludeCharts(true);
$spreadsheet = $reader->load($inputFileName);
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->getCell('A1')->setValue('Help me');
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->setIncludeCharts(true);
$fileData = $writer->save($xlsxTarget);
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
$reader->setIncludeCharts(TRUE);
$workbook = $reader->load($xls);
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls($workbook);
$writer->setIncludeCharts(TRUE);
$writer->save($xlsTarget);
I am expecting the chart to be copied, in the code from above there is no modification of the file, it should be an exact one-to-one copy of the supplied file but it isn't working at all as it seems the graph gets corrupted and I have to repair the excel the next time I open it.
EDIT: I also installed the archived PHPExcel and tried it using Graph disapear read and write excel file using PHPExcel and I still had the same issue.

Xlsx file, Read all spreadsheet in php

I am using simplexlsx to read xlsx sheet,
I have multiple tabs in my xlsx file, When I am trying to read data, its shows data only for first tab,
for better understanding i have attach print screen.
Try This,
$this->load->library('simplexlsx');
$xlsx = new SimpleXLSX( $file_path );
$data['csv_data'] = $xlsx->rows();
It is because when you select something from an excel file it performs that action with the active sheet which is by default is the first one.
You need to change that to the required sheet
Use the following code to do that
$objPHPExcel->setActiveSheetIndex($count); // Use no of the sheet you want to select -1 as count

Cloning the content and styling of one sheet to another - PHP Excel

I need to copy the content of one sheet in an Excel Workbook to a sheet in a new excel workbook. The issue is, I have no idea what the sheets contain or their formatting. However, it will only be the first sheet every time.
I've tried an approach but I run out of memory every time. So I thought I'd do it row by row for 100 000 rows. Anyway, I started with a row, and it gets the data, but no luck in writing it to a new sheet. How would I do that?
Here is what I have so far:
// Open the current worksheet
App::import('Vendor', 'PHPExcel');
if (!class_exists('PHPExcel')) {
throw new CakeException('Vendor class PHPExcel not found!');
$this->xls = PHPExcel_IOFactory::load($path);
// Read all content
$this->xls->getActiveSheet()->rangeToArray('A1:ZZZZ1');
// Close current worksheet
$this->xls->disconnectWorksheets();
// Delete worksheet
unlink($destination);
// Open new worksheet
$this->xls = new PHPExcel();
$newWorksheet = new PHPExcel_Worksheet($this->xls, 'Sheet 1');
$this->xls->addSheet($newWorksheet);
$this->xls->setActiveSheetIndexByName('Sheet 1');
// Write all the content
$this->xls->getActiveSheet()->fromArray($array,null,'A1');
// Save current worksheet
$objWriter = PHPExcel_IOFactory::createWriter($this->xls, 'Excel2007');
$objWriter->save($destination);
What am I doing wrong?
Then also, is there an easier way to do this? I don't want to write all this code and in the end it's all reinventing the wheel?
Thanks in advance
There's a built-in method that's specifically written to do this for you:
$objPHPExcel1 = PHPExcel_IOFactory::load($path);
$objPHPExcel2 = new PHPExcel();
// Copy active worksheet from $objPHPExcel1 to $objPHPExcel2
$worksheet = $objPHPExcel1->getActiveSheet();
$objPHPExcel2->addExternalSheet($worksheet)
and if you're running out of memory, building large arrays in memory to try and copy manually isn't going to help.
There are approaches designed to reduce memory such as cell caching, look to use those to reduce memory usage

PHPExcel removes chart style when template is loaded

I am using PHPExcel to read and write values to Excel. I have a template that has a graph and a style on it.
Here's the issue:
After I appended some value on the Excel sheet, the style of the chart has been remove and it shows the default style.
I am using this code to read:
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
// Tell the reader to include charts when it loads a file
$objReader->setIncludeCharts(TRUE);
// Load the file
$objPHPExcel = $objReader->load("rcca.xlsx");
And this to write
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->setIncludeCharts(TRUE);
$objWriter->save('rcca.xlsx');
Am I missing something?
Please see the screenshot of the chart style before and after:
Had the same problems with charts using PHPExcel
(my main problem was to change colors of chart bars)
First of all if some one did not know or forgot xlsx files are zip archs
So the main problem is that PHPExcel when saving xlsx file adds default theme file xl/theme/theme1.xml even if you change it at $objReader->load file it will overwrite it to default at $objWriter->save.
Charts colors in that file theme1.xml at <a:accent1> (...2,3,4,5,6)
so i took theme1.xml changed colors to which i need, saved and using The ZipArchive class overwrite it after
$objWriter->save with simple code
$zip = new ZipArchive;
if ($zip->open('filename.xlsx') === TRUE) {
$zip->addFile('mytheme1.xml', 'xl/theme/theme1.xml');
$zip->close();
echo 'ok';
} else {
echo 'err';
}
I hope it will help someone
It seems that chart styling need to be hard-coded at this time.
On this other thread someone explain how to add some styling PHPExcel graph design (border, graph color, graph inner position)

phpexcel - using it with excel template (chart goes missing) php

I have tried to use phpexcel with my own template file. phpexcel loads the file and writes data to some cells A2, A3, A4 for example.. and opens an output file with the new data.
my template file has chart built-in.. all i want to phpexcel to do is to populate values in cells and don't touch the chart. And, open the new file. (Please note that I don't want to make the chart in code.. I want the chart to pre-exist with in my template in same format as I created originally). Only the data should update.
But, when i try to do this.. the chart itself goes missing from the resulting file. After trying various ways.. still failed.
And, i found the following code from http://phpexcel.codeplex.com/discussions/397263
require_once 'Classes/PHPExcel.php';
/** PHPExcel_IOFactory */
include 'Classes/PHPExcel/IOFactory.php';
$target ='Results/';
$fileType = 'Excel2007';
$InputFileName = $target.'Result.xlsx';
$OutputFileName = $target . '_Result.xlsx';
//Read the file (including chart template)
$objReader = PHPExcel_IOFactory::createReader($fileType);
$objReader->setIncludeCharts(TRUE);
$objPHPExcel = $objReader->load($InputFileName);
//Change the file
$objPHPExcel->setActiveSheetIndex(0)
// Add data
->setCellValue('C3','10' )
->setCellValue('C4','20' )
->setCellValue('C5','30')
->setCellValue('C5','40' );
//Write the file (including chart)
PHPExcel_Settings::setZipClass(PHPExcel_Settings::PCLZIP);
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, $fileType);
$objWriter->setIncludeCharts(TRUE);
$objWriter->save($OutputFileName);
The above code works in excel 2010 and now keeps my chart in tact... but still when I try to use filetype "Excel5" it doesn't work.
It throws the following error:
Fatal error: Call to undefined method PHPExcel_Reader_Excel5::setIncludeCharts()
in D:\IT\bfstools\PHPExcel\MyExamples\test1.php on line 16
Please provide a simple solution where I want my template file to work with .xls and .xlsx and all my original chart in the template file should stay intact. I do not want the chart removed it from the resulting file. Neither do I plan to create the chart using phpexcel code. (why write unnecessary code when excel can do all the work for you).
I want the easiest way out which is just to use everything with in my template and just populate cells with new data. And, my existing chart in the template comes live automatically. I don't want to write unnecessary code while I can safely rely on excel template and charting functions.
Please help.
There's a very good reason for this:
Charting is only implemented in core, and for the Excel2007 Readers and Writers at this point in time, so all of the other readers or writers will ignore charts, treat them as though they simply don't exist. The intention is to roll out charting to the other readers/writers over the coming year.
EDIT
I see from your comment that you don't understand how PHPExcel works at all, so I have a lot of explaining to do.
PHPExcel is not a library for "editing" workbook files: you're not using PHPExcel to change a file, you're changing a PHPExcel object that can be loaded from a file, and can subsequently be written to a file.
PHPExcel Core is an in-memory representation of the spreadsheet, with the different constituent objects such as worksheets, cells, images, styles, etc all represented as PHP Objects.
The PHPExcel Readers parse a spreadsheet file and load all the components from a file that they have been programmed to recognise, and create the appropriate PHPExcel core objects from those file components. If there is no equivalent PHPExcel Core object (such as Pivot Tables), then that file component can't be "loaded"; if the loader hasn't been programmed to recognise a file component, then it can't be loaded. In these cases, those elements from the file are simply ignored. Once the Reader has done it's job, a PHPExcel object exists, and the spreadsheet file is closed and forgotten.
When a PHPExcel Core object exists in memory, you have a set of methods allowing you to manipulate and change it, to add, modify or delete Core elements; but these work purely on the "in memory" collection of worksheet, cell, style objects that comprise the PHPExcel Core. The Core exists without knowledge of having been loaded from a file or having been created using a PHP "new PHPExcel()" statement; it makes no changes to files in any way.
When writing, the reverse is true. Each Writer takes the PHPExcel core objects, and writes them to a file in the appropriate format (Excel BIFF, OfficeOpenXML, HTML, etc). Like the Readers, each writer can only write those PHPExcel Core objects that it has been programmed to write. If it has not been programmed to write (for example, charts) then any charts defined in the PHPExcel Core will be ignored because that writer simply doesn't know how to write them yet. Likewise, features that exist in PHPExcel Core that are not supported by the file format that is being written to (such as cell styles for the CSV Writer) are ignored.
So to support a spreadsheet feature such as charts, it is necessary for the PHPExcel Core object collection to have been modified to provide an "in memory" representation of those elements, and for the different Readers to have been programmed to recognise those elements in the file they are loading and to convert them to the appropriate PHPExcel Core objects, and for the different Writers to have been programmed to convert the PHPExcel core representation to the appropriate file representation.
Each Reader and each Writer needs to be programmed individually. Charts is a relatively new feature, only added to the PHPExcel Core in the 1.7.7 release, and at this point only the Reader and Writer for the Excel2007 format have been programmed to recognise chart elements.
While it is the intention of the developers to extend this to cover the other formats as well, the necessary code isn't created automagically. Programming each individual Reader and Writer takes time and effort. While the Chart code for the Excel2007 Reader and Writer has now stabilised to the point where it is now no longer considered "experimental", and development focus is turning to writing the necessary code for chart handling in the Excel5 Reader and Writer, it is work that has not yet been completed.
If you can use Golang, try Excelize. Support save file without losing original charts of XLSX.
Try set setIncludeCharts
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
// Tell the reader to include charts when it loads a file
$objReader->setIncludeCharts(TRUE);
// Load the file
$objPHPExcel = $objReader->load($filePath);

Categories