I know this isn't the right place to ask about this specific vague problem, but maybe someone knows this library well enough to enlighten me. Here is the thing:
I am writting an Excel5 over an existing Excel file with PHPExcel. I need to upload that Excel to the Zoom website, so it can provide me with a list of tracking numbers. However, for some reason the library they are using to read the uploaded Excel files cannot read the rows written by PHPExcel and the only solution I've found so far is to manually copy the contents of my dynamically generated Excel to another document using MS Excel 2007.
In other words, the Zoom website can read the rows written natively by Excel but not rows written by PHPExcel. My file has only one single sheet, and I can open it no problem with Excel 2007.
Even if I manually add some rows to the template and then add more rows with PHPExcel, Zoom will read the rows written manually by me, but not the rows written by PHPExcel.
This is how I'm doing it:
// Starting with the PHPExcel library
$this->load->library('PHPExcel');
$this->load->library('PHPExcel/IOFactory');
$template_file = 'zoom_tracking_template.xls';
$i = 3;
$objReader = IOFactory::createReader('Excel5');
$objPHPExcel = $objReader->load($template_file);
$objPHPExcel->setActiveSheetIndex(0);
// Fetching ML payments
foreach($payments as $row)
{
$objPHPExcel->getActiveSheet()->setCellValue('A'.$i, 'VANESSA NEISZER');
$objPHPExcel->getActiveSheet()->setCellValue('B'.$i, '02127616116');
$objPHPExcel->getActiveSheet()->setCellValue('C'.$i, '1ER PISO MINITIENDAS 199 BLVD SABANA GRANDE, CRUCE C / CALLE NEGRIN');
$objPHPExcel->getActiveSheet()->setCellValue('D'.$i, $row->mailing_city);
$objPHPExcel->getActiveSheet()->setCellValue('E'.$i, $row->mailing_name);
$objPHPExcel->getActiveSheet()->setCellValue('F'.$i, $row->mailing_name);
$objPHPExcel->getActiveSheet()->setCellValue('G'.$i, $row->mailing_personal_id);
$objPHPExcel->getActiveSheet()->setCellValue('H'.$i, $row->mailing_phone);
$objPHPExcel->getActiveSheet()->setCellValue('I'.$i, $row->mailing_address1.' '.$row->mailing_address2);
$objPHPExcel->getActiveSheet()->setCellValue('J'.$i, $row->nickname);
$objPHPExcel->getActiveSheet()->setCellValue('K'.$i, '1');
$objPHPExcel->getActiveSheet()->setCellValue('L'.$i, '0.3');
$objPHPExcel->getActiveSheet()->setCellValue('M'.$i, 'M');
$objPHPExcel->getActiveSheet()->setCellValue('N'.$i, 'PRODUCTO');
$objPHPExcel->getActiveSheet()->setCellValue('O'.$i, '0');
$i++;
}
$objPHPExcel->setActiveSheetIndex(0);
$objWriter = IOFactory::createWriter($objPHPExcel, 'Excel5');
// Sending headers to force the user to download the file
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="Envios'.date('dMy').'.xls"');
header('Cache-Control: max-age=0');
$objWriter->save('php://output');
I have no clue of what PHP library they are using to read Excel files and I am certain they wont tell me if I ask them. I know they use PHP, and their library only read Excel 2003 files, however, I don't know why they can't read my files but they can read other files written manually on MS Excel.
Any clues, ideas or suggestions I could try would be greatly appreciated.
And PHPExcel's main developer is looking at this issue (among others), somewhere in between trying to find a new day job and having a life. I'm not familiar with the zoom website, or the software that they use. PHPExcel BIFF8 files can be read by Excel, OOCalc and Gnumeric without error... but a couple of questions spring to mind.
What version of PHPExcel?
Does any of the data contain UTF-8 characters?
Are there any formulae in the template worksheet?
If so, what are they?
Related
I am trying to open an existing excel file, modify some cells and save it. I am using Excel2007 for reader and writer.
The input file is about 1 MB large and it has few formulas, protected data and hidden rows and columns and worksheets which I do not modify.
I am able to load the data and read and write some values into it, which I check with various var_dumps in the code.
The problem is while saving it. It throws some fatal errors on timing outs and also if it writes the file the file size is bloated to 9.2 MB, which is okay if I can open it.
code snippet - nothing fancy.
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objPHPExcel = $objReader->load($inputFile);
$objPHPExcel->setActiveSheetIndex(2);
$activeSheet = $objPHPExcel->getActiveSheet();
$currCell = $activeSheet->getCell("O3");
$cellValidation = $currCell->getDataValidation("O3");
$values = array();
if ($cellValidation->getShowDropDown() == true)
{
$values = $cellValidation->getFormula1();
$valArray = explode(",", $values);
$currCell->setValue($valArray[0]);
}
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter -> setPreCalculateFormulas(false);
$objWriter->save($outputFile);
I use MS Excel 2010 to open the resultant file but it just takes forever and has not opened it even once.
Please help me to troubleshoot this by giving me pointers as to where I should be looking.
Any help is greatly appreciated.
Instead of saving it to a file, save it to php://outputĀDocs:
$objWriter->save('php://output');
This will send it AS-IS to the browser.
You want to add some headersĀDocs first, like it's common with file downloads, so the browser knows which type that file is and how it should be named (the filename):
// We'll be outputting an excel file
header('Content-type: application/vnd.ms-excel');
// It will be called file.xls
header('Content-Disposition: attachment; filename="file.xls"');
// Write file to the browser
$objWriter->save('php://output');
First do the headers, then the save. For the excel headers see as well the following question: Setting mime type for excel document.
So the final code would have below lines -
// Save Excel 2007 file
#echo date('H:i:s') . " Write to Excel2007 format\n";
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
ob_end_clean();
// We'll be outputting an excel file
header('Content-type: application/vnd.ms-excel');
// It will be called file.xls
header('Content-Disposition: attachment; filename="file.xlsx"');
$objWriter->save('php://output');
I think this line:
ob_end_clean();
Should solve your problem.
Thanks!
There's a whole lot of reasons for that "bloat" and it very much depends on the actual data in the worksheet, but MS Excel itself uses a lot of different techniques to keep the filesize small, whereas PHPExcel writes a simple version of the OfficeOpenXML format.
For example, MS Excel looks at the string content of all cells, and stores the individual strings in a string table. If a string is used by two or more cells, there will only be a single entry in the string table. However, there's a performance overhead in checking if a string already exists in the string table, so PHPExcel doesn't perform that check but will duplicate entries in the string table. This means that it will create a large file because of the duplication, but keeps the save speed as fast as possible.
Similarly, MS Excel looks at all formulae, and if the formula is similar to an existing formula (with only a row/column offset difference) it will store it as a shared formula rather than a cell formula, so the actual formula data is only stored once. Again, PHPExcel won't perform this check, because it is a big performance overhead in the save, so it stores every formula as a cell formula rather than a shared formula.
And no, I can't explain why the file doesn't load in MS Excel 2010, nor will I be able to explain it without being able to run the whole thing through debug
HI i am exporting some data from database in .xls format but when i try to save my file it alerts me that file type is not .xls format. I need to store it in excel 97-2003 Workbook. when i pretend for save as option, default file type is in as tab delimited.. how can i overcome it?? below is my code..
if ( $_POST["frmDownload"] == "Excel") {
header("Content-disposition: attachment; filename=employee_details.xls");
header("Content-Type: application/vnd.ms-excel");
header("Content-type: application/x-msexcel");
}
use phpExcel which is excellent for all excel manipulation.
Here is the list of examples.
use the method fromArray to write excel from array which is fetched from persistent data.
use the method toArray to form a php array from excel sheet.
The learning curve is very simple first try first example only from official site.
Then try the fromArray and toArray its very easy and also phpExcel have lots of functionality like gradient background for a cell, border size increasing, formula manipulation and new worksheet also easy to create.
Important: read documentation on when ever you get free time
The format is tab delimited... You are just 'naming' it excel in this way... Look at gvgvgvijayan's answer for the solution to your problem.
I'm generating a Excell 2003 using PHPExcel 1.8 with this code:
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save('toUploadFtp.xls');
The file seems ok, and I can read it using MS Office and LibreOffice.
But I have to upload the file to a system that says the format has to be Excell 2003, and he prompts next error:
Oops! Your file is not in the proper Microsoft Excel 2003 XLS format.
If I open the file with LibreOffice and save it again, then I can upload the file correctly to the system.
Any idea?
Thanks,
Create your file by passing the proper version to factory:
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
Hope it helps.
Not understanding the exact problem entirely: it seems to be with the additional transfer of the Excel file.
One error is often, that the PHP script outputs spurious data.
Leaving out the final %> is a standard trick to make sure no extra final new line characters are added to the file.
Comparing the files generated and transferred should yield insight on what went wrong.
You may need to set the content to non-text to prevent some text conversion:
header('Content-Type: application/octet'):
Finally I couldn't find a solution. It has to be some kind of bug in the XLS 2003 format.
But I generated a XLSX with $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); and the system recognizes it correctly.
I think you can overcome this problem in changing the filed of Excel5.Since i havnt tried phpexcel i dont know much about this..But i think you can find a solution for this [here].1
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);
This is right now I am using.
$mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
header('Content-Description: File Transfer');
header('Content-Type: ' . $mimeType);
header('Content-Disposition: attachment; filename='.basename($type.'.xlsx'));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
print "$header\n$data";
exit;
$header variable contains the header row of excel to be generated and looks like this
$header= "Business_Name\tBusiness_Type\tType";
separated by \t
and $data contains rows to be generated under header columns. They are also separated by \t and a row is terminated by \n.
With the current setup file is downloaded but it is not opening with ms excel and showing this message.
Excel cannot open the file "file name"
because the file format or file
extension is not valid. Verify that
the file format has not been corrupted
and that the file extension matches
the format of the file.
What header should be sent to server? or how do I generate that file?
I achieve this in a fast, sort of cheapskate way - because it's long and winded I'll just explain it in concept rather than code.
XLSX adheres to ISO 29500 which is publicly available if you want to manipulate a document thoroughly in php. Otherwise, realise that xlsx files are zipped archives of a bunch of xml files.
Make a template that you want, say it has alternating rows with styles of different types, making that in excel or an open xml editor of some description. Make sure you put some data in there, and make sure some fields are equal (just for learning purposes).
Then save your file as xlsx, rename it .zip, or open it in an archive extractor and observe the contents.
Firstly, note the [Content_Types].xml file, this describes the location of the major files in the archive and the standards to which it itself adheres and the content types of those files.
Everything outside the xl/ folder is just meta data really. But observe docProps/core.xml contains author, modification and timestamp information - which you can replace in php when you recreate this file. Also everything that is pointed to say, docProps/core.xml can be renamed to your tastes, [Content_Types].xml can't.
Okay so now you understand this, you'll begin observing ids thrown around the place. They love to use this in the file format, everything refers to everything else by its index in a particular xml property list or similar. They also usually describe the quantity of items in such lists.
In xl/ you'll see themes.xml, styles.xml, workbook.xml, sharedStrings.xml, _rels/, worksheets/.
Styles is going to be inflated with a whole lot of unnecessary styles that excel builds by default if you used it. But you should be able to see how these styles work such that you can customise your own.
Themes to me is rather pointless so I delete it and its referenced ids throughout.
Next up you'll see workbook, that's the file containing information regarding the sheets which are inside of the spreadsheet document since you can have more than 1 obviously. It also contains some sheet metadata such as its size etc.
Now comes the first big hua you'll encounter. sharedStrings.xml is a weird file which stores all the information that will be inserted into cells in a static spreadsheet. They are indexed, but the engine reading the document figures out what their indexes are. Anything which repeats can be referred back to its old index in the sheet itself (inside worksheets folder) as to save on file size in large documents with repeated values.
Not the attributes count and uniquecount in the sst element and what they obviously mean.
This is the stage in php where you populate an array of data containing what you want in your sheet, and dump it into an xml formatted list such as this file appears. Also note these files don't need to be jammed up without newlines or linefeed characters as with or without is still valid xml and they will work in readers regardless.
Check out the _rels folder, it's fairly obvious again.
Lastly is the sheet itself. The numbers in fields here refer to the indexed locations of strings in sharedStrings.xml. The attribute s is the style, t is the type of data in the field. R is the cell location though why it needs that is beyond me when it could really be figured out rather easily.
Producing this file in php shouldn't be too difficult either. Just use your indexes from your data array you used to make your sharedStrings.xml file.
Oh also sheet has column width information in it which you can figure out based on the font you used and automatically size them in php too if need be.
Lastly is the packaging of it all in php.
My code is in a class which receives data and specific saved files I created with excel to keep it simple.
$this->folder_structure_simple = Array(
"_rels/.rels" => "_rels__rels",
"docProps/app.xml" => "docProps_app_xml",
"docProps/core.xml" => "docProps_core_xml",
"xl/_rels/workbook.xml.rels",
"xl/theme/theme1.xml",
"xl/worksheets/sheet1.xml",
"xl/sharedStrings.xml",
"xl/styles.xml",
"xl/workbook.xml",
"[Content_Types].xml" => "Content_Types_xml"
);
$zip = new ZipArchive;
$res = $zip->open($this->file_name, ZipArchive::CREATE);
if($res === TRUE){
foreach($this->folder_structure_simple as $file => $function){
$zip->addFromString($file, $this->$funtion);
}
$zip->close();
echo 'ok';
}else{
return FALSE;
}
And functions produce the required data. Very fast, not very flexible.
What you have is actually a CSV file. Depending on your OS, your browser and your Excel version, then the browser will differently let you or not let your open the extensions CSV, XLS XLSX with the Excel software.
If you do want to have your data opened with Excel, then you can merge the data with an Excel template using OpenTBS. Use version 1.6.0 (or greater) which is currently in Release Candidate because it brings major facilities for Excel files.
In your title there is "no excel library PHP". I don't know why you have this specification but OpenTBS is not exactly an Excel library. It's a PHP tool for merging OpenOffice and Ms Office documents using templates.
What you have a CSV, not an XLSX file. XLSX is a ZIP-wrapped blob of XML. Change your MIME type to text/csv.