Read and write XLSM file in PHP - php

I want to read and write XLSM type file using PHP. I tried using PHPSpreadsheet for this but it doesn't support XLSM extension.
One possible solution could be to use EasyXLS (https://www.easyxls.com/manual/basics/import-from-xlsx-file-format.html)
// Create an instance of the class that imports XLSM files
$workbook = new COM("EasyXLS.ExcelDocument");
// Import XLSM file
$workbook->easy_LoadXLSXFile("C:\\Samples\\Excel to import.xlsm");
// Get the table of the second worksheet
$xlsSecondTable = $workbook->easy_getSheet("Second tab")->easy_getExcelTable();
// Add more data to the second sheet
$xlsSecondTable->easy_getCell_2("A1")->setValue("Data added by Tutorial37");
for ($column=0; $column<5; $column++)
{
$xlsSecondTable->easy_getCell(1, $column)->setValue("Data " . ($column + 1));
}
// Generate the XLSM file
$workbook->easy_WriteXLSXFile("C:\Samples\Excel with macro.xlsm");
But I was unable to find any Library for this.
Does anyone have any possible solution for this or some other way for this?

function excel($excelfile, $sheet = false){//from stores.blade.php
$tempfile = resource_path("uploads/excel.xlsm");//it just needs a place to store the XML file temporarily, this function only works in Laravel, replace with a filename
if($sheet){//load XML file
//$XML = file_get_contents($tempfile);
$XML = simplexml_load_file($excelfile);
$XML = json_decode(json_encode((array)$XML), TRUE);
$excelfile = pathinfo($sheet)['basename'];
if($excelfile == "workbook.xml"){
$RET = [];
foreach($XML["sheets"]["sheet"] as $data){
$RET[ $data["#attributes"]["sheetId"] ] = $data["#attributes"]["name"];
}
return [
'Filename' => $excelfile,
'SheetName' => "sys_workbook",
'SheetData' => $RET,
];
} else if($excelfile == "sharedStrings.xml"){
foreach($XML["si"] as $index => $value){
if(isset($value["t"])){
$value = $value["t"];
} else {
foreach($value["r"] as $index2 => $value2){
if(is_array($value2["t"])){
$value2["t"] = $value2["t"][0];
}
$value["r"][$index2] = $value2["t"];
}
$value = implode("", $value["r"]);
}
if(is_array($value)){
$value = $value[0];
}
$XML["si"][$index] = $value;
}
return [
'Filename' => $excelfile,
'SheetName' => "sys_strings",
'SheetData' => $XML["si"],
];
} else if(isset($XML["sheetPr"])){
return [
'Filename' => $excelfile,
'SheetName' => $XML["sheetPr"]["#attributes"]["codeName"],
'SheetData' => $XML["sheetData"]["row"],
];
}
return false;
} else {//load ZIPped XLSM file
$files = [];
$zip = new ZipArchive;
if ($zip->open($excelfile) === TRUE) {
for($i = 0; $i < $zip->numFiles; $i++) {
$filename = $zip->getNameIndex($i);
if(startswith($filename, "xl/worksheets/") || $filename == "xl/workbook.xml" || $filename = "xl/sharedStrings.xml"){
copy("zip://" . $excelfile . "#" . $filename, $tempfile);
$XML = excel($tempfile, $filename);
if($XML !== false){
$files[ $XML["SheetName"] ] = $XML["SheetData"];
}
}
}
#unlink($tempfile);
$zip->close();
}
var_dump($files);
die();
}
}
I started work on this, I got this far. The problem is, I don't know how the shared strings (sys_strings) are referenced, and you'd need an equation evaluator to handle the functions. I HOPE, the sheets are in order, so Sheet1 becomes the first array value in sys_workbook.

For anyone still looking for a solution to this problem, the following XLSX reader can parse XLSM without a problem. Also saves the headache in interpreting Excel timestamps and data formats. Tried and tested.
I did not test the Writer though, yet!
https://github.com/shuchkin/simplexlsx

Related

How to remove __MACOSX while using ZipArchive

After hours of trying to figure out why php "ZipArchive" does not work as expected, due to Mac OS adding a "__MACOSX" folder in the zip compression process.
How would I go about deleting "__MACOSX" folder in a zip archive during the upload process in a form?
Below is what I'm working with:
<?php
public function uploadZip($file)
{
$advert_index;
$zip = new \ZipArchive;
if (true === $zip->open($file['tmp_name'])) {
$source = trim($zip->getNameIndex(0), '/');
for ($i = 0; $i < $zip->numFiles; $i++) {
$name = $zip->getNameIndex($i);
// Determine output filename (removing the `$source` prefix).
$substring_name = substr($name, strlen($source)+1);
$file = $this->option['uploads_path'] . $this->option['advert_id'] . '/' . $substring_name;
// Store the adverts `index.html` file URL to be returned.
if ('html' === pathinfo($name, PATHINFO_EXTENSION)) {
$advert_index = basename($name);
}
// Create the directories if necessary.
$dir = dirname($file);
if (! is_dir($dir)) {
mkdir($dir, 0777, true);
}
// Read from Zip and write to disk.
$fpr = $zip->getStream($name);
$fpw = fopen($file, 'w');
while ($data = fread($fpr, 1024)) {
fwrite($fpw, $data);
}
fclose($fpr);
fclose($fpw);
}
$zip->close();
return array(
'status' => true,
'message' => array(
'index' => $advert_index,
'type' => 'text/html', // #HACK: Set MIME type manually. #TODO: Read MIME type from file.
),
);
}
return array(
'status' => false,
'message' => 'Upload failed',
);
}
Any help would be much appreciated :)
Note: I Managed to find the file just can't get it to be removed.
// Check to see the __MACOSX
if($zip->getNameIndex($i) === "__MACOSX/") {
error_log($zip->getNameIndex($i) . ' - Error here continue');
$zip->deleteName("__MACOSX/");
continue; // Move on to the next iteration
// $zip->deleteIndex($i);
} else {
$name = $zip->getNameIndex($i);
}
It was actually very simple, instead to trying to delete the folder within the zip-archive just had to skip all indexes aka filename that begin with a certain string while looping through the files.
if(substr($zip->getNameIndex($i), 0, 9) === "__MACOSX/") {
continue;
} else {
$name = $zip->getNameIndex($i);
}

Renaming filenames and immediately reading files having issues in php

I have pdf files which are report cards of students.The report card names format is <student full name(which can have spaces)><space><studentID>.I need to download files.For this I have used the following code.
if(file_exists($folder_path.'/') && is_dir(folder_path)) {
$report_files = glob(folder_path.'/*'.'_*\.pdf' );
if(count($report_files)>0)
{
$result_data = '';
$result_data = rename_filenamespaces($report_files);
var_dump($result_data);//this shows the edited filename
foreach ($result_data as $file) {
if (strpos($file,$_GET['StudentID']) !== false) {
//code for showing the pdf docs to download
}
}
}
}
//function for renaming if filename has spaces
function rename_filenamespaces($location)
{
$new_location = $location;
foreach ($location as $file) {
//check file has spaces and filename has studentID
if((strpos($file," ")!==false)&& (strpos($file,$_GET['StudentID']) !== false))
{
$new_filename = str_replace(" ","-",$file);
rename($file,$new_filename);
$new_location = $new_filename;
}
}
return $new_location;
}
The variable $result_data gives me the filename without spaces,but the for each loop is showing Warning:Invalid argument supplied for foreach(). But the filename is changed in the server directory immediately after running the function. This warning shows only for first time. I am unable to solve this.
$new_location = $new_filename;
$new_location is a array
$new_filename is a string
You have to use $new_location[$index]
or try
foreach ($new_location as &$file) {
...
...
$file = $new_filename;

how to unzip txt.gz file and store into database using php

My zip file name is Product_Catalog.txt.gz. this zip file contain one txt file.
how can i extract and store into my database
i have already done in zip file unzip and store into my database. but i can't understand .gz format. so please advise
my zip file code is here
if (realpath($destinationname."/".$filename)){
if ($zip = zip_open(realpath($directory."/".$filename)))
{
while (($zip_entry = zip_read($zip))){
$zipfilename=zip_entry_name($zip_entry );
$zipfilename."<br>";
$tmpfname = tempnam("/tmp", "");
$handle = fopen($tmpfname, "w+");
while($data = zip_entry_read($zip_entry,50000000000)){
fwrite($handle,$data);
}// end while $data
fseek($handle,0);
if ($separatetables);
$table=strtok($zipfilename,"-");
$sql="CREATE TABLE IF NOT EXISTS `$table` LIKE `cjfeeds`";
mysql_query($sql);
how can i convert this code into txt.gz
gzip, which is generally used for single files, is not the same file format as ZIP. Although the same compression algorithm (DEFLATE) is used in both formats, the headers are entirely different, so PHP's Zip functions will not recognize your file.
Instead, you can use the compress.zlib:// wrapper to open gzip-compressed files. You can then use the normal stream functions to read the file.
$handle = fopen("compress.zlib://$filename", 'r');
However, there are some limitations; for example, opening a gzipped file in read-write mode is not possible, and seeking may be slow. If necessary, you can work around these by making a temporary uncompressed copy:
copy("compress.zlib://$filename", $tmpfname);
You don't extract.
if ($rrpath){
if ($zip = gzopen($rrpath, "rb"))
{
$filenamen = $_SESSION['files_list'][$i];
$zipfilename = str_replace('.gz', '', $_SESSION['files_list'][$i]);
$tmpfname = tempnam("/home/demoosiz/tmp", "");
$handle = fopen($tmpfname, "w+");
ini_set("max_execution_time",3000000000000);
while($data = gzread($zip, 4096)){
fwrite($handle,$data);
}// end while $data
fseek($handle,0);
if ($separatetables);
$table=strtok($zipfilename,"-");
// $sqly = "TRUNCATE TABLE `cjfeeds`";
//mysql_query($sqly);
// I'm not too sure if this is windows specific
$tmpfile=addslashes($tmpfname);
//if the script times out uncomment the next line
ini_set("max_execution_time",3000000000000);
$sql22 ="LOAD DATA LOCAL INFILE '$tmpfile' REPLACE INTO TABLE `cjfeeds` FIELDS TERMINATED BY '$fieldseparator' IGNORE 1 LINES;";
You can use this code. This code is very helpful for you.
You keep calling it a zip file. It's not a zip file (.zip). It's a gzip file (.gz). Different format.
You can use gzdecode() to decompress a gzip file.
You can interact with .gz files through the functions of the zlib module.
Responding to your comment:
You won't need to do the while($zip_entry = zip_read($zip)) since gz files don't hold multiple files within them. A .gz file is just a single file that has been compressed. Unfortunately, this also means that there is no equivalent to zip_entry_name either, since there is only one file.
If you're trying to read a tarball - an archive of files which have been concatenated together and gzipped to form a .tar.gz file - then Zlib isn't for you, since it's not designed to handle that. You'll want something like PharData instead:
$phar = new PharData($filename);
foreach ($phar as $phar_stream) {
$file_data = file_get_contents($phar_stream);
// process $file_data how you like
}
If these are just single-file gz files, then you can read the files with the gz versions of the usual filesystem functions.
You can use gzread to process chunks of the file the way you're currently doing with zip_entry_read, or you can read all lines into an array with gzfile. There is a readgzfile function which grabs the whole file, but unfortunately it seems like it just dumps the output directly to the client, rather than do a file. You could use output buffering to capture that output, but it seems like too much of a hassle considering your other options.
Try this....
if(isset($_FILES['zipfile']))
{
$filename = $_FILES['zipfile']['name'];
$source = $_FILES['zipfile']['tmp_name'];
$type = $_FILES['zipfile']['type'];
/*$name = explode('.zip', $filename); # $name[0] returns the name of the file. $name[1] returns the extension (zip)
; */ # Where the file will be saved. I.E. 'extracted/myFile-02151985/'
$target = PHYSICAL_PATH."upload/";
// Ensures that the correct file type was chosen.
$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed');
foreach($accepted_types as $mime_type)
{
if($mime_type == $type)
{
$okay = true;
break;
}
}
$okay = strtolower($name[1]) == 'zip' ? true : false;
if(!$okay)
{
$msg="Please choose a zip file, dummy!";
}
$saved_file_location = $target.$filename;
if(move_uploaded_file($source, $target . $filename))
{
global $target;
global $unique_folder;
$zip = new ZipArchive();
$x = $zip->open($saved_file_location);
if ($x === true)
{
$folder=$zip->extractTo($target);
for ( $i=0; $i < $zip->numFiles; $i++ )
{
echo $entry = $zip->getNameIndex($i);
$filename=explode('/',$entry);
print_r($filename);
if($filename[1] != '')
{
$filename_folder=$filename[0];
$filename = $filename[1]; //
$name = explode('.zip', $filename_folder); # $name[0] returns the name of the file. $name[1] returns the extension (zip)
//echo 'sfkdf'.$name[0];
$target = PHYSICAL_PATH."upload/";
$sql = "select `id` from `tracks` order by `id` desc";
$list = mysql_query($sql);
$list_num = mysql_num_rows($list);
if($list_num > 0)
{
$res = mysql_fetch_array($list);
$new_id=$res['id'];
} else {
$new_id=1;
}
$check_for_jpg = strpos($filename, '.mp3');
if ($check_for_jpg === false ){
echo 'Check file format.';
$source=$target . $name[0].'/'.$filename;
unlink($source);
} else {
$srch = array(' ','--','"','!','#','#','$','%','^','&','*','(',')','_','+','{','}','|',':','"','<','>','?','[',']','\\',';',"'",',','/','*','+','~','`','=');
$rep = array('_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_');
$name_song[$i]= str_replace($srch,$rep,$filename);
$title_name=explode('.',$filename);
$new_id=$new_id+1;
$new_filename=$new_id.'-'.$name_song[$i];
mysql_query("insert into `tracks` set track='".addslashes(stripslashes($new_filename))."',title='".addslashes(stripslashes($title_name[0]))."',tape_id='".$id_last."',addDate=NOW(),status=1 ");
$source=$target . $name[0].'/'.$filename; $target_move=$target.$new_filename;
if(rename($source,$target_move)) { unlink($source); } else { echo 'not';}
echo 'folder zip';
echo '<li>' . $new_filename . '</li>';
}
rmdir($target . $name[0]);
}
else { echo $target = PHYSICAL_PATH."upload/";
$sql = "select `id` from `test_table` order by `id` desc";
$list = mysql_query($sql);
$list_num = mysql_num_rows($list);
if($list_num > 0) {
//and, instead of using "while":
$res = mysql_fetch_array($list); // will return the highest "id" number
echo $new_id=$res['id'];
} else {
$new_id=1;
}
$check_for_jpg = strpos($entry, '.mp3');
if ($check_for_jpg === false ){
echo 'Check file format.';
$source=$target .$entry;
unlink($source);
} else {
$srch = array(' ','--','"','!','#','#','$','%','^','&','*','(',')','_','+','{','}','|',':','"','<','>','?','[',']','\\',';',"'",',','/','*','+','~','`','=');
$rep = array('_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_');
$name_song[$i]= str_replace($srch,$rep,$entry);
$title_name=explode('.',$entry);
$new_id=$new_id+1;
$new_filename=$new_id.'-'.$name_song[$i];
mysql_query("insert into `tracks` set track='".addslashes(stripslashes($new_filename))."',title='".addslashes(stripslashes($title_name[0]))."',tape_id='".$id_last."',status=1 ");
$source=$target .$entry; $target_move=$target.$new_filename;
if(rename($source,$target_move)) { unlink($source); } else { echo 'not';}
echo 'only zip';
echo '<li>' . $new_filename . '</li>';
}
}
}
$zip->close();
unlink($saved_file_location); #deletes the zip file. We no longer need it.
} else {
die("There was a problem. Please try again!");
}
} else {
$msg="There was a problem";
}
}

multi picture upload in zend framework, how to?

i have an issue with uploading multiple files to disk. here is my code.
i have a request with 2 pictures that gets sent to a upload function. the 2 pictures are in a var called $multiUpload
$folderPath = '/var/www/';
if (is_array($multiUpload)){
$file = array();
$filename = array();
foreach($multiUpload as $key=>$val){
// get the file extension
$file[] = explode('.',$val);
// create custom file name
$filename[] = time().'.'.$file[$key][1];
//send to the upload function
$this->uploadToDisk($folderPath, $filename[$key]);
// sleep 1 sec so that the pic names will be different
sleep(1);
}
return $filename;
}
public function uploadToDisk($folderPath, $filename)
{
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->setDestination($folderPath);
$adapter->addFilter( 'Rename',array(
'target' => $folderPath."/".$filename,
'overwrite' => true
) );
if ($adapter->receive()) {
$message = "success";
} else {
$message = "fail";
}
return $message;
}
this will return
Array
(
[0] => Array
(
[0] => 1332977938.jpg
[1] => 1332977939.jpg
)
)
but only array[0][0] or 1332977938.jpg will actually get saves to the disk.
Why are they now both get saved? wired
any ideas?
I suspect the second call to uploadToDisk is returning fail because you can only call Zend_File_Transfer_Adapter_Http::receive() once for each file. Since you are not specifying a file when calling receive, it is receiving all of the files the first time you call uploadToDisk and subsequently is failing with a File Upload Attack error.
Here is some code you can try. This tries to receive each file individually and then save them one at a time with each call to uploadToDisk.
A few notes about the code:
The first parameter to uploadToDisk ($val) may need to be changed as I am not sure what the original values are. It should correspond to one of the element names used for the file upload (See Zend_File_Transfer_Adapter_Http::getFileInfo()) for a list of the files.
I changed the method for generating a unique filename so you don't have to sleep(1)
Zend_File_Transfer_Adapter_Abstract::setDestination() is deprecated and will go away in the future. Instead, just use the Rename filter. When using Rename, setDestination() has no effect.
And here it is...
<?php
$folderPath = '/var/www/';
if (is_array($multiUpload)){
$filenames = array();
foreach($multiUpload as $key => $val){
// get the file extension
$ext = explode('.', $val);
$ext = $ext[sizeof($ext) - 1];
// create custom file name
do {
$filename = uniqid(time()) . '.' . $ext;
$diskPath = $folderPath . $filename;
} while (file_exists($diskPath));
$filenames[$key] = $filename;
//send to the upload function
// $val is the file to receive, $diskPath is where it will be moved to
$this->uploadToDisk($val, $diskPath);
}
return $filename;
}
public function uploadToDisk($file, $filename)
{
// create the transfer adapter
// note that setDestination is deprecated, instead use the Rename filter
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->addFilter('Rename', array(
'target' => $filename,
'overwrite' => true
));
// try to receive one file
if ($adapter->receive($file)) {
$message = "success";
} else {
$message = "fail";
}
return $message;
}

Is there a way to get the worksheet names from 20MB+ Excel files with PHPExcel?

I am using PHPExcel to read data out of Excel files.
With the following code, I am able to read one particular worksheet out of a 3MB Excel file in just a couple seconds. Works nicely.
However, I now have 27MB and 88MB Excel files which I need to get data out of. They are so large that even OpenOffice cannot open them.
I have found that I can use an index number instead of a name when I load a sheet, but this seems inconsistent, e.g. in one particular Excel file setLoadSheetsOnly(0) gave me the third sheet while setLoadSheetsOnly(1) gave me an error even though there were four worksheets in the file. So that seems unreliable for some reason.
Is there a way I can read out the names of the worksheets from a large file so that I can access only one of its worksheets at a time?
$objReader = PHPExcel_IOFactory::createReaderForFile("data/" . $file_name);
$objReader->setLoadSheetsOnly(array($sheet_name));
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("data/" . $file_name);
echo '<table border="1">';
for ($row = 1; $row < $number_of_rows; $row++) {
echo '<tr>';
for ($column = 0; $column < $number_of_columns; $column++) {
$value = $objPHPExcel->setActiveSheetIndex(0)->getCellByColumnAndRow($column, $row)->getValue();
echo '<td>';
echo $value . ' ';
echo '</td>';
}
echo '</tr>';
}
echo '</table>';
die;
ADDENDUM:
I found some code that gets close, but it doesn't seem to always be accurate, e.g. here it missed the second worksheet in a 27MB file:
and here it only got the third worksheet and missed 3 others:
$objReader = PHPExcel_IOFactory::createReaderForFile("data/" . $file_name);
$objReader->setLoadSheetsOnly(0);
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("data/" . $file_name);
echo $objPHPExcel->getSheetCount(), ' worksheets<hr/>';
$loadedSheetNames = $objPHPExcel->getSheetNames();
foreach ($loadedSheetNames as $sheetIndex => $loadedSheetName) {
echo $sheetIndex, ' -> ', $loadedSheetName, '<br />';
}
die;
Unfortunately, it isn't possible to read the names of the worksheets without loading the whole file.
Using an index number rather than a name when calling setLoadSheetsOnly() won't give a predictable result: the code logic that performs that check uses in_array() to test if the sheetname that it is about to read is in the array of sheetnames to read. e.g.
// check if sheet should be skipped
if (isset($this->_loadSheetsOnly) && !in_array($sheet['name'], $this->_loadSheetsOnly)) {
continue;
}
I would suspect that the comparison of a string against a numeric value will be giving a true result for 0 == "mySheetName" when executing this test (based on PHP's loose typing and comparison casting rules).
I could probably provide a Reader method that would return a list of worksheet names without actually loading the entire file, although there would be a performance hit involved.
EDIT
If you add the following method to Classes/PHPExcel/Reader/Excel2007.php
/**
* Reads names of the worksheets from a file, without loading the whole file to a PHPExcel object
*
* #param string $pFilename
* #throws Exception
*/
public function listWorksheetNames($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$worksheetNames = array();
$zip = new ZipArchive;
$zip->open($pFilename);
$rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships");
foreach ($rels->Relationship as $rel) {
switch ($rel["Type"]) {
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
$xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main");
if ($xmlWorkbook->sheets) {
foreach ($xmlWorkbook->sheets->sheet as $eleSheet) {
// Check if sheet should be skipped
$worksheetNames[] = (string) $eleSheet["name"];
}
}
}
}
$zip->close();
return $worksheetNames;
}
You can call it by using:
$inputFileType = 'Excel2007';
$inputFileName = 'biostat-behfisk-2005.xlsx';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$worksheetNames = $objReader->listWorksheetNames($inputFileName);
foreach ($worksheetNames as $sheetName) {
echo $sheetName, '<br />';
}
the returned $worksheetNames should contain an array of all worksheet names as UTF-8 strings. Because it's only reading the absolute minimum from the .xlsx to retrieve these names, it should be fairly fast. I'll do some more tests before checking it into the PHPExcel SVN, but (for now) it seems to do what you need.
EDIT2
Equivalent method for the Excel5 Reader
/**
* Reads names of the worksheets from a file, without loading the whole file to a PHPExcel object
*
* #param string $pFilename
* #throws Exception
*/
public function listWorksheetNames($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$worksheetNames = array();
// Read the OLE file
$this->_loadOLE($pFilename);
// total byte size of Excel data (workbook global substream + sheet substreams)
$this->_dataSize = strlen($this->_data);
$this->_pos = 0;
$this->_sheets = array();
// Parse Workbook Global Substream
while ($this->_pos < $this->_dataSize) {
$code = self::_GetInt2d($this->_data, $this->_pos);
switch ($code) {
case self::XLS_Type_BOF: $this->_readBof(); break;
case self::XLS_Type_SHEET: $this->_readSheet(); break;
case self::XLS_Type_EOF: $this->_readDefault(); break 2;
default: $this->_readDefault(); break;
}
}
foreach ($this->_sheets as $sheet) {
if ($sheet['sheetType'] != 0x00) {
// 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module
continue;
}
$worksheetNames[] = $sheet['name'];
}
return $worksheetNames;
}
Not as efficient as the Excel2007 Reader version, but should still be faster than parsing the whole .xls file just for the sheet names because I'm only parsing the global stream.
I didn't want to amend phpexcel so I went with this:
public function getWorksheetNames($pFilename) {
$worksheetNames = array ();
$zip = zip_open ( $pFilename );
while ( $entry = zip_read ( $zip ) ) {
$entry_name = zip_entry_name ( $entry );
if ($entry_name == 'xl/workbook.xml') {
if (zip_entry_open ( $zip, $entry, "r" )) {
$buf = zip_entry_read ( $entry, zip_entry_filesize ( $entry ) );
$workbook = simplexml_load_string ( $buf );
foreach ( $workbook->sheets as $sheets ) {
foreach( $sheets as $sheet) {
$attributes=$sheet->attributes();
$worksheetNames[]=$attributes['name'];
}
}
zip_entry_close ( $entry );
}
break;
}
}
zip_close ( $zip );
return $worksheetNames;
}
It only works on excel 2007 or later but did what I needed

Categories