How to create xlsx file without using any excel library PHP - php

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.

Related

Detect an edited csv file using PHPExcel

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.

PHPExcel saving xlsx to xls, some cells are blank

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

PHP file name and extension restoration

I have a bunch of files in a directory with random 16 digit file-names and no file extensions, e.g. 'RTSWZci59BqXDqaV'
I have a database that through various calls and relationships I can find the files original name, extension and content type. 'Original', as these were all once files that were uploaded to a server via a website (that I did not build).
I've written a small piece of code to loop through the files and re-write them all to their original file-name and extension. This works to a degree, in that .txt files work, but PDF / word docs are corrupted and images are scrambled / fuzzy / off-colour.
It is definitely not the case that these files are just broken.
A part of the website remains that downloads individual files:
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
header('Pragma:');
header('Content-type: '.$originalContentType);
header('Content-Disposition: attachment; filename="'.$originalFileName'].'.'.$originalExt'].'"');
header('Content-Length: '.filesize(FILE_FOLDER.$fileName));
readfile(FILE_FOLDER.$fileName);
My code where I am trying to convert each file back to something use-able is some database stuff, some loops and then this:
#rename($directory.$fileName, $directory.$originalFileName.'.'.$originalExt);
I've also tried using copy(), and can't even get a single file to download by setting headers.
Is there something obvious that I should be doing differently here? Must it be the case that some other encoding happened to the image when it was uploaded? Can I do anything to these files once I've got them off of the server?
The name of a file cannot make it corrupted, other than attempting to open it with the wrong program / import filter (e.g. trying to open a JPEG as a Word Document or vice versa).
If the images look nearly right, then it sounds like some data corruption has occurred, and you have the right filenames but not the right contents.
I'm presuming you exported them from some previous location which is why they have dummy names? Perhaps during that process the files have been truncated to a particular size, or where a NULL byte was encountered. Or perhaps certain bytes have been interpreted as characters in some particular text encoding, rather than copied as-is.
If they were in a database, it's possible that you selected them using a driver or query type not designed for handling binary data.
I ended up just replicating the single header download method I described in my example, with some JS that downloaded the next file every few seconds through the browser.
By far not the most elegant solution, but it saved me some time.
<script type="text/javascript">
$(document).ready ( function(){
var delay = 1000;
<?php
$a=0;
foreach($files as $file) { ?>
delay=delay+3000;
setTimeout(function (){ window.open("<?php echo $file; ?>"); }, delay);
<?php } ?>
});
</script>

I wanted to add data in pre formated Excel sheet using php

I wanted to append data in the pre formated excel sheet that is basically header footer in the excel sheet I wanted to append the contents. And will create many files dynamically.
A simple workaround is:
create a html table with the formatting you need
add values in php to the table (or generate table with php)
save file as .xls (filled with content from html table)
open file (will show formatted table in Excel)
Reason:
handling XLS files is very complex and many libraries have big limits (only available on windows servers....)
html table saved as .xls can be opened in Excel.
Thanks I have found the way PHPExcel is a good library.
In order to get PHPExcel http://www.codeplex.com/PHPExcel working with CodeIgniter, there are a few steps you must take to ensure compatibility with CodeIgniter's naming standards.
1: Class names must match the file names. PHPExcel has a few files(such as PHPExcel/IOFactory.php) that have names like PHPExcel_IOFactory. Change these names by removing the "PHPExcel_" part. These constructors in these files must be public in order for CI to access them.
$this->load->library('phpexcel');
$this->load->library('PHPExcel/iofactory');
$objPHPExcel = new PHPExcel();
$objPHPExcel->getProperties()->setTitle("title")
->setDescription("description");
// Assign cell values
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->setCellValue('A1', 'cell value here');
// Save it as an excel 2003 file
$objWriter = IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save("nameoffile.xls");

Rows written by PHPExcel cannot be read from other libraries

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?

Categories