1.问题描述
现在有一个总表staff.xls,每一行代表一个人的数据,要求将该表转换为若干个表people.xls,每一个人为一个表。或者问题反过来,要求将若干个表汇总。
2.思路
将问题简单化,仔细想想,也就几个步骤:
(0)我们知道staff.xls和people.xls的格式布局,知道两个表转换时数据是怎样对应的,比如staff的‘BS’对应people的‘D3’等 (这个需要人工写成数组)。
(1)加载总表staff.xls,将数据以行为单位读取到数组中。
(2)加载模板people.xls表,将数组中的数据按照对应格式写入表格,保存到相应的路径。
ps:phpExcel常用方法可以自己在搜搜,我这里也转载了一篇:phpExcel常用方法
3.遇到的问题
(1)图片的大小处理,phpExcel只提供图片等比例缩放的函数,如$objDrawing->setWidth()、$objDrawing->setHeight()等,根据需要,我查看了源码"Classes\PHPExcel\Worksheet\BaseDrawing.php",自己增加了单独设置高度和宽度的函数。
// function added by myself public function setWidthOnly($pValue = 0) { // Resize proportional? // Set width if ($this->_resizeProportional) { $this->_width = $pValue; } return $this; } public function setHeightOnly($pValue = 0) { // Resize proportional? Set height if ($this->_resizeProportional) { $this->_height = $pValue; } return $this; }
(2)总表太大,500*60个单元格左右,运行一会后会报超内存问题。
phpExcel内存消耗过大是一个比较常见的问题,很多人问道,网上也有很多解答的方案,绝大多数要么没说清楚要么说的没用,各大网站也爬来爬去= =这种现象真的很不好,这里我来整理一下找到的比较好的方法。方法3、4非常有效,建议4种结合起来用。
<1>开大内存时间限制。
ini_set('max_execution_time','0'); // 设置时间上限为不限时间
ini_set('memory_limit', '512M'); // 设置内存
<2>设置缓存。
参考:点击打开链接
我采取的方法是:
// 设置缓存模式为序列化模式
$cacheMethod =PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized;
PHPExcel_Settings::setCacheStorageMethod($cacheMethod);
<3>及时释放内存
这里要注意一点,phpExcel自己对内存释放做的不是很好,需要我们及时手动调用他提供的函数来释放内存。
在函数中也要手动调用来释放。
$objPHPExcel->disconnectWorksheets(); //及时手动释放内存资源
unset($objPHPExcel);
<4>表格过大,分批读取,每次只读取固定行,不必要的列不用读取,如果不关心格式,只读取数据。
参考:点击打开链接
方法是自己实现一个类来读取表格,每次只读取固定行,分批读取
class chunkReadFilter implements PHPExcel_Reader_IReadFilter { private $_startRow = 0; private $_endRow = 0; /** Set the list of rows that we want to read */ public function setRows($startRow, $chunkSize) { $this->_startRow = $startRow; $this->_endRow = $startRow + $chunkSize; } public function readCell($column, $row, $worksheetName = '') { // Only read the heading row, and the rows that are configured in $this->_startRow and $this->_endRow if (($row == 1) || ($row >= $this->_startRow && $row < $this->_endRow)) { return true; } return false; } } /** Create a new Reader of the type defined in $inputFileType **/ $objReader = PHPExcel_IOFactory::createReader('Excel5'); /** Define how many rows we want to read for each "chunk" **/ $chunkSize = 20; /** Create a new Instance of our Read Filter **/ $chunkFilter = new chunkReadFilter(); /** Tell the Reader that we want to use the Read Filter that we've Instantiated **/ $objReader->setReadFilter($chunkFilter); /** Loop to read our worksheet in "chunk size" blocks **/ /** $startRow is set to 2 initially because we always read the headings in row #1 **/ for ($startRow = 2; $startRow <= 600; $startRow += $chunkSize) { /** Tell the Read Filter, the limits on which rows we want to read this iteration **/ $chunkFilter->setRows($startRow,$chunkSize); /** Load only the rows that match our filter from $inputFileName to a PHPExcel Object **/ $objPHPExcel = $objReader->load('test2.xls'); // Do some processing here // Free up some of the memory $objPHPExcel->disconnectWorksheets(); unset($objPHPExcel); }