Skip to content
This repository has been archived by the owner on Jan 2, 2019. It is now read-only.

HTML Writer: Caching causes "Call to a member function detach() on a non-object" with blank sheets #193

Closed
jmitchell-bf opened this issue May 31, 2013 · 2 comments

Comments

@jmitchell-bf
Copy link

I've got a small script which loops over sheets in a workbook and writes each as HTML. If the writer encounters a blank sheet, and some form of cell caching is turned on (I generally use cache_in_memory_gzip), we get:
PHP Fatal error: Call to a member function detach() on a non-object in /home/dir/phpExcel/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php on line 47

Here's a sample script I use to trigger the error:

#!/usr/bin/php -q
<?php

/* Simple script to loop over sheets in an Excel file and write them out as HTML.
 * Should die if any blank sheet is encountered, such as is the default if you create
 * a new file in Excel/LibreOffice, just fill in the first sheet, and hit Save.
*/

$callStartTime = microtime(true);

error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

$input_filename = realpath($argv[1]);
$output_dir = realpath($argv[2]);

require_once 'Classes/PHPExcel.php';
$cache_method = PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip;
$res = PHPExcel_Settings::setCacheStorageMethod($cache_method);

require_once 'Classes/PHPExcel/IOFactory.php';

# xls[x] file to open
print "Reading file." . PHP_EOL;
$workbook = PHPExcel_IOFactory::load($input_filename);

# count sheets
$num_sheets = $workbook->getSheetCount();
print "Num sheets: $num_sheets" . PHP_EOL;
$path_parts = pathinfo($input_filename);
foreach($workbook->getWorksheetIterator() as $worksheet){
    $sheet_num = $workbook->getIndex($worksheet);
    $sheet_name = $worksheet->getTitle();
    $output_filename = $output_dir . "/" . $path_parts['filename'] . '_' . $sheet_name . '.html';
    print "Writing $output_filename" . PHP_EOL;
    print "Creating writer" . PHP_EOL;
    $writer = PHPExcel_IOFactory::createWriter($workbook, 'HTML');
    print "Setting sheet index to $sheet_num" . PHP_EOL;
    $writer->setSheetIndex($sheet_num);
    print "Saving" . PHP_EOL;
    $writer->save($output_filename);
    unset($writer);
}

$callEndTime = microtime(true);
$callTime = $callEndTime - $callStartTime;
print "Conversion complete." . PHP_EOL;
print 'Call time to write Workbook was ' . sprintf('%.4f', $callTime) . " seconds". PHP_EOL;
print 'Current memory usage: ' . (memory_get_usage(true) / 1024 / 1024) . " MB". PHP_EOL;
print "Peak memory usage: " . (memory_get_peak_usage(true) / 1024 / 1024) . " MB". PHP_EOL;
?>

Workaround
If we loop over the workbook once before the loop doing the writing, check for blank sheets with getHighestColumn() and getHighestRow(), and doing $sheet->getCell() if we find A1 to be the highest, and then iterate the workbook again in a separate loop, this goes away, so we do have a workaround. And, in our case, it's nice to do the blank sheet check anyway, since don't want blank sheets coming out as HTML. But it'd be nice to do them in the same loop :)

Other info
Ubuntu 12.04
php 5.3.10-1ubuntu3.6 (cli)

@mnapoli
Copy link

mnapoli commented Dec 2, 2013

+1 on this, we have the same problem when using PHPExcel with Xport.

@eplaut
Copy link

eplaut commented Dec 29, 2013

this bug backtrace:
#0 PHPExcel_CachedObjectStorage_MemoryGZip->_storeData() called at [C:\Users\eplaut\Documents\php\PHPExcel-develop\Classes\PHPExcel\CachedObjectStorage\MemoryGZip.php:91]
#1 PHPExcel_CachedObjectStorage_MemoryGZip->getCacheData(A1) called at [C:\Users\eplaut\Documents\php\PHPExcel-develop\Classes\PHPExcel\Worksheet.php:2552]
#2 PHPExcel_Worksheet->garbageCollect() called at [C:\Users\eplaut\Documents\php\PHPExcel-develop\Classes\PHPExcel.php:1121]
#3 PHPExcel->garbageCollect() called at [C:\Users\eplaut\Documents\php\PHPExcel-develop\Classes\PHPExcel\Writer\HTML.php:153]
#4 PHPExcel_Writer_HTML->save(C:\Users\eplaut\Documents\php\PHPExcel-develop\Bugs/input1_Sheet1.html) called at [C:\Users\eplaut\Documents\php\PHPExcel-develop\Bugs\bug_193.php:45]

The garbageCollect creates new PHPExcel_CachedObjectStorage_MemoryGZip class, instead of using the existing one.
The default value of $_currentCellIsDirty is "true" but $_currentObject in not set. so there is no option to deatach it.
The easy way is to change the default value to "false", but I don't know the reason it set to true.

MarkBaker pushed a commit that referenced this issue Dec 29, 2013
@Progi1984 Progi1984 added this to the 1.8.0 milestone Aug 14, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants