phpExcel实现表格之间的转换

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); 
}



你可能感兴趣的:(phpExcel实现表格之间的转换)