Initial modifications for XML-based sheet readers to use XMLReader via streaming for large files in the listWorksheetNames() and listWorksheetInfo() methods... still needs some additional work for merged cells to work correctly, but gives a hell of a memory boost and executes more quickly - the same principles will be applied to the core data readers, but that still requires a lot more work. However, when completed, the effort should be worth it for both speed and memory usage, and the code should be a lot cleaner for the core data reader as well

This commit is contained in:
Mark Baker
2013-01-12 12:52:00 +00:00
parent 5de1067a16
commit 0ad3f67da6
5 changed files with 629 additions and 532 deletions
+64 -57
View File
@@ -102,6 +102,40 @@ class PHPExcel_Reader_Gnumeric extends PHPExcel_Reader_Abstract implements PHPEx
}
/**
* Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetNames($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$xml = new XMLReader();
$xml->open(
'compress.zlib://'.realpath($pFilename)
);
$xml->setParserProperty(2,true);
$worksheetNames = array();
while ($xml->read()) {
if ($xml->name == 'gnm:SheetName' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$worksheetNames[] = (string) $xml->value;
} elseif ($xml->name == 'gnm:Sheets') {
// break out of the loop once we've got our sheet names rather than parse the entire file
break;
}
}
return $worksheetNames;
}
/**
* Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns)
*
@@ -115,37 +149,40 @@ class PHPExcel_Reader_Gnumeric extends PHPExcel_Reader_Abstract implements PHPEx
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$gFileData = $this->_gzfileGetContents($pFilename);
$xml = simplexml_load_string($gFileData);
$namespacesMeta = $xml->getNamespaces(true);
$gnmXML = $xml->children($namespacesMeta['gnm']);
$xml = new XMLReader();
$xml->open(
'compress.zlib://'.realpath($pFilename)
);
$xml->setParserProperty(2,true);
$worksheetInfo = array();
while ($xml->read()) {
if ($xml->name == 'gnm:Sheet' && $xml->nodeType == XMLReader::ELEMENT) {
$tmpInfo = array(
'worksheetName' => '',
'lastColumnLetter' => 'A',
'lastColumnIndex' => 0,
'totalRows' => 0,
'totalColumns' => 0,
);
foreach ($gnmXML->Sheets->Sheet as $sheet) {
$tmpInfo = array();
$tmpInfo['worksheetName'] = (string) $sheet->Name;
$tmpInfo['lastColumnLetter'] = 'A';
$tmpInfo['lastColumnIndex'] = 0;
$tmpInfo['totalRows'] = 0;
$tmpInfo['totalColumns'] = 0;
foreach ($sheet->Cells->Cell as $cell) {
$cellAttributes = $cell->attributes();
$rowIndex = (int) $cellAttributes->Row + 1;
$columnIndex = (int) $cellAttributes->Col;
$tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex);
$tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex);
while ($xml->read()) {
if ($xml->name == 'gnm:Name' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$tmpInfo['worksheetName'] = (string) $xml->value;
} elseif ($xml->name == 'gnm:MaxCol' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$tmpInfo['lastColumnIndex'] = (int) $xml->value;
$tmpInfo['totalColumns'] = (int) $xml->value + 1;
} elseif ($xml->name == 'gnm:MaxRow' && $xml->nodeType == XMLReader::ELEMENT) {
$xml->read(); // Move onto the value node
$tmpInfo['totalRows'] = (int) $xml->value + 1;
break;
}
}
$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
$worksheetInfo[] = $tmpInfo;
}
$tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']);
$tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1;
$worksheetInfo[] = $tmpInfo;
}
return $worksheetInfo;
@@ -182,36 +219,6 @@ class PHPExcel_Reader_Gnumeric extends PHPExcel_Reader_Abstract implements PHPEx
}
/**
* Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object
*
* @param string $pFilename
* @throws PHPExcel_Reader_Exception
*/
public function listWorksheetNames($pFilename)
{
// Check if file exists
if (!file_exists($pFilename)) {
throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist.");
}
$gFileData = $this->_gzfileGetContents($pFilename);
$xml = simplexml_load_string($gFileData);
$namespacesMeta = $xml->getNamespaces(true);
$gnmXML = $xml->children($namespacesMeta['gnm']);
$worksheetNames = array();
foreach($gnmXML->Sheets->Sheet as $sheet) {
$worksheetNames[] = (string) $sheet->Name;
}
return $worksheetNames;
}
/**
* Loads PHPExcel from file into PHPExcel instance
*