I am using PHPExcel to validate csv files before parsing them and storing in my database and server. I am trying to use the file properties to determine if the file has been modified or if it is the original file. I have used the following for .xls, .xlsx with great results (using the appropriate reader);
$file = $_FILES['file']['tmp_name'];
$reader = new PHPExcel_Reader_CSV();
if($reader->canRead($file)){
$object = $reader->load($file);
$created = $object->getProperties()->getCreated();
$modified = $object->getProperties()->getModified();
if(!$created===$modified){
//File has been edited and cannot be used
}else{
//File is good, continue processing
}
}
However, when using CSV files, NOTHING is working as expected. I renamed an MS-Word doc to .csv->passed, edited a csv->passed, even used a .jpg->passed. What on earth am I missing?? Any help would greatly appreciated! Edit->I should note that $created and $modifed are an exact match when var_dump($object) despite having edited the file and confirming the changes within the document properties.
The properties values accessible from PHPExcel are those stored within the file itself, not within the directory entries for that file.
CSV files don't have any inherent properties of their own; CSV is purely a raw data file format These property methods are for accessing the properties that do exist in other spreadsheet formats such as BIFF (xls) and OfficeOpenXML (xlsx) which do support them. Loading a CSV (or other format that doesn't support properties) into PHPExcel will provide default value for those properties (so that calls like you're making won't trigger fatal errors), but it cannot provide actual values for something that doesn't natively exist in the format being loaded.
Related
Is it possible and if is how can i change excel file extension while uploading or before saving file on server? I am using php and mysql.
Thankyou
You can do something like this.
move_uploaded_file($_FILES['file']['tmp_name'], upload_PATH.'/'.$_FILES['file']['name'].'x');
But that will only change the file name with the xlsx extension. It will not actually convert the file to xlsx format.
As previously mentioned in a different reply, changing the extension won't actually change the format, and it's not a good idea to serve a .xls file as .xlsx, since this will only confuse anyone trying to read it.
What you could do (disregarding potential problems with converting and verification of the file) is read the uploaded file into a library like PHPExcel (http://phpexcel.codeplex.com) and then use the builtin functions to export it as an .xlsx file. Sample below:
// Create a reader to read .xls format
$reader = PHPExcel_IOFactory::createReader('Excel5');
// Read the .xls file from upload storage
$workbook = $reader->load($_FILES['file']['tmp_name']);
// Create a writer to output in .xlsx format
$writer = PHPExcel_IOFactory::createWriter($workbook, 'Excel2007');
// Save file to destination .xlsx path
$writer->save($destination_path);
Keep in mind that although this might work perfectly well, the conversion might mess with the contents of the file. This might not be desirable, as the conversion can cause data loss, formatting changes and all sorts of weirdness.
I have code for converting xls to xlsx via PHPExcel:
$objPHPexcel = PHPExcel_IOFactory::load('file.xlsx');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPexcel, 'Excel5');
$objWriter->save('new_file.xls');
But when I open created xls file some cells are empty.
What could be the problem?
Thanks!
Link to download original xlsx file
you should use one of following as formate type.
1)Excel5 -> file format between Excel Version 95 to 2003
2)Excel2003XML -> file format for Excel 2003
3)Excel2007 -> file format for Excel 2007
and add following line at line no.3 in your code before save file statement.
$fileType=PHPExcel_IOFactory::identify("file.xlsx"); //We can get file reader type automatically using
it generate file as per your requirement.
I do notice that some of these cells contain references to external files, e.g. cell A23 contains
='[Форма 1-2 от 15.12 ЯНВАРЬ екат.xls]НТТЗМ'!A77
Logically, PHPExcel can't simply access that external file (Форма 1-2 от 15.12 ЯНВАРЬ екат.xls) to retrieve data; nor can it handle references to external files... the file may not even exist; and if it did, there is a major overhead in loading (recursively) every external file that might be referenced in formulae.
While you haven't indicated which cells might be blank in the newly saved file, it would be my guess that they're the cells that contain these external file references
i'm using phpexcel and i have a problem: when creating a reader object i get this error:
Fatal error: Class 'PHPExcel_Reader_excel.php' not found in C:\xampp\htdocs\phpexcel\Classes\PHPExcel\IOFactory.php on line 170
my code is:
<?php
require_once(dirname(__FILE__)."/Classes/phpexcel.php");
//or
require_once(dirname(__FILE__)."/Classes/PHPExcel/IOFactory.php");
//$phpexcel = new PHPExcel();
$reader = PHPExcel_IOFactory::createReader("excel.php");
?>
i checked IOFactory.php on line 170 and found this:
$searchType = 'IReader';
// Include class
foreach (self::$_searchLocations as $searchLocation) {
if ($searchLocation['type'] == $searchType) {
$className = str_replace('{0}', $readerType, $searchLocation['class']);
$instance = new $className();
if ($instance !== NULL) {
return $instance;
}
}
}
but it is not possible to locate any class because they are using _ instead of / (the path is phpexcel\Classes\PHPExcel\Reader and there are files like excel5.php excel2007.php but not excel.php)
what is wrong? documentation is a litle bit confusing
Unless you've added a custom reader of your own called PHPExcel_Reader_excel.php then this will return an error.
As described in section 1 of PHPExcel User Documentation - Reading Spreadsheet Files online and in the /Documentation folder, there are 7 different readers available for 7 different spreadsheet formats:
PHPExcel can read a number of different spreadsheet file formats, although not all features are supported by all of the readers. Check the Functionality Cross-Reference document (Functionality Cross-Reference.xls) for a list that identifies which features are supported by which readers.
Currently, PHPExcel supports the following File Types for Reading:
Excel5
The Microsoft Excel™ Binary file format (BIFF5 and BIFF8) is a binary file format that was used by Microsoft Excel™ between versions 95 and 2003. The format is supported (to various extents) by most spreadsheet programs. BIFF files normally have an extension of .xls. Documentation describing the format can be found online at http://msdn.microsoft.com/en-us/library/cc313154(v=office.12).aspx or from http://download.microsoft.com/download/2/4/8/24862317-78F0-4C4B-B355-C7B2C1D997DB/[MS-XLS].pdf (as a downloadable PDF).
Excel2003XML
Microsoft Excel™ 2003 included options for a file format called SpreadsheetML. This file is a zipped XML document. It is not very common, but its core features are supported. Documentation for the format can be found at http://msdn.microsoft.com/en-us/library/aa140066%28office.10%29.aspx though it’s sadly rather sparse in its detail.
Excel2007
Microsoft Excel™ 2007 shipped with a new file format, namely Microsoft Office Open XML SpreadsheetML, and Excel 2010 extended this still further with its new features such as sparklines. These files typically have an extension of .xlsx. This format is based around a zipped collection of eXtensible Markup Language (XML) files. Microsoft Office Open XML SpreadsheetML is mostly standardized in ECMA 376 (http://www.ecma-international.org/news/TC45_current_work/TC45_available_docs.htm) and ISO 29500.
OOCalc
aka Open Document Format (ODF) or OASIS, this is the OpenOffice.org XML File Format for spreadsheets. It comprises a zip archive including several components all of which are text files, most of these with markup in the eXtensible Markup Language (XML). It is the standard file format for OpenOffice.org Calc and StarCalc, and files typically have an extension of .ods. The published specification for the file format is available from the OASIS Open Office XML Format Technical Committee web page (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=office#technical). Other information is available from the OpenOffice.org XML File Format web page (http://xml.openoffice.org/general.html), part of the OpenOffice.org project.
SYLK
This is the Microsoft Multiplan Symbolic Link Interchange (SYLK) file format. Multiplan was a predecessor to Microsoft Excel™. Files normally have an extension of .slk. While not common, there are still a few applications that generate SYLK files as a cross-platform option, because (despite being limited to a single worksheet) it is a simple format to implement, and supports some basic data and cell formatting options (unlike CSV files).
Gnumeric
The Gnumeric file format is used by the Gnome Gnumeric spreadsheet application, and typically files have an extension of .gnumeric. The file contents are stored using eXtensible Markup Language (XML) markup, and the file is then compressed using the GNU project's gzip compression library. http://projects.gnome.org/gnumeric/doc/file-format-gnumeric.shtml
CSV
Comma Separated Value (CSV) file format is a common structuring strategy for text format files. In CSV flies, each line in the file represents a row of data and (within each line of the file) the different data fields (or columns) are separated from one another using a comma (“,”). If a data field contains a comma, then it should be enclosed (typically in quotation marks ("). Sometimes tabs “\t” or the pipe symbol (“|”) are used as separators instead of a comma. Because CSV is a text-only format, it doesn't support any data formatting options.
You need to specify the reader by name when you use the createReader() method, e.g:
$reader = PHPExcel_IOFactory::createReader("Excel5");
There are plenty of examples in the /Examples folder showing this usage for different readers, for letting PHPExcel itself select the correct reader using load(), and for verifying that your file is of the correct format before setting the reader using the identify() method
I have to confess, I'd thought this documentation was fairly straightforward, especially with the examples that are included
To make it easier you could use
$objReader = PHPExcel_IOFactory::createReaderForFile($file);
and it will automatically pick a reader for your file
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.