PHPExcel使用中遇到的幾個問題
最近做項目,接觸了幾次PHPExcel,過程中遇到了幾個問題,現對PHPExcel的一些常見用法和我遇到的問題及解決方案總結如下。(推薦還是要看一下PHPExcel官網的手冊)
?
一、常見用法
??? 這個部分網站上有很多資料了,我這裡不再一一羅列,只是將我用到的幾個地方寫了一下。
?
getProperties ()->setCreator ( "Miss Yang" )->setLastModifiedBy ( "Miss Yang" )->setTitle ( "Office 2003 XLS Document" )->setSubject ( "Office 2003 XLS Document" )->setDescription ( "TrunkBow" )->setKeywords ( "TrunkBow" )->setCategory ( "TrunkBow" ); //設定當前的sheet索引,用於後續的內容操作。 //預設情況下,PHPExcel會自動建立第一個sheet被設定SheetIndex=0 $objExcel->setActiveSheetIndex(0); $objActSheet = $objExcel->getActiveSheet(); //設定當前活動sheet的名稱 $objActSheet->setTitle('Sheet1'); //設定儲存格內容 $objActSheet->setCellValue('A1', '字串內容'); // 字串內容 $objActSheet->setCellValue('A2', 26); // 數值 $objActSheet->setCellValue('A3', true); // 布爾值 $objActSheet->setCellValue('A4', '=SUM(A2:A2)'); // 公式 //顯式指定內容類型 $objActSheet->setCellValueExplicit('A5','8757584',PHPExcel_Cell_DataType::TYPE_STRING);//設定儲存格格式$objActSheet ->getStyle ('A1' ) ->getFont () ->getColor() ->setARGB(PHPExcel_Style_Color::COLOR_RED); $objActSheet ->getStyle ('A1' ) ->getFont () ->setBold(true); $objActSheet ->getStyle ('A') ->getNumberFormat() ->setFormatCode ( PHPExcel_Style_NumberFormat::FORMAT_TEXT );$objActSheet ->getColumnDimension ('A') ->setWidth(20); $objActSheet ->getColumnDimension ('B') ->setAutoSize(true); $activeSheet ->getColumnDimension('C') ->setVisible(false); //產生下拉式清單方塊$list = "item1,item2,item3";$objValidation1 = $activeSheet->getCell('A1')->getDataValidation();$objValidation1->setType( PHPExcel_Cell_DataValidation::TYPE_LIST ) ->setErrorStyle(PHPExcel_Cell_DataValidation::STYLE_INFORMATION ) ->setAllowBlank(false) ->setShowInputMessage(true) ->setShowErrorMessage(true) ->setShowDropDown(true) ->setErrorTitle('輸入的值有誤') ->setError('您輸入的值不在下拉框列表內.') ->setPromptTitle('下拉選擇框') ->setPrompt('請從下拉框中選擇您需要的值!') ->setFormula1('"' . $list . '"'); //下載輸出$filename = "testphp.xls";$filename = iconv("utf-8", 'gbk', $filename);$objWriter = PHPExcel_IOFactory::createWriter ( $objPHPExcel, 'Excel5' );header ( 'Content-Type: application/vnd.ms-excel' );header ( "Content-Disposition: attachment;filename=$filename" );header ( 'Cache-Control: max-age=0' );$objWriter->save ( 'php://output' );exit(0);
?
?
?
二、問題總結
1.儲存格內容為長數位,輸出時,總是轉成科學計數法。
?
??? 這個問題網上也有不少資料提到的,大多是說要修改幾個地方的源碼。但是我一直沒找到對應的源碼在哪裡,可能是版本不同的原因。我是這樣解決的:
?
//顯示指定內容類型 $objActSheet->setCellValueExplicit('A5','8757584',PHPExcel_Cell_DataType::TYPE_STRING);
??
2.PHPExcel佔用記憶體過大。
?
PHPExcel是一個很強大的處理Excel的PHP開源類,但是很大的一個問題就是它佔用記憶體太大,從1.7.3開始,它支援設定cell的緩衝方式,但是推薦使用目前穩定的版本1.7.6,因為之前的版本都會不同程度的存在bug。
官網上是這麼說的:PHPExcel平均下來使用1k/儲存格的記憶體,因此大的文檔會導致記憶體消耗的也很快。儲存格緩衝機制能夠允許PHPExcel將記憶體中的小的儲存格對象緩衝在磁碟或者APC,memcache或者Wincache中,儘管會在讀取資料上消耗一些時間,但是能夠協助你降低記憶體的消耗。預設情況下,PHPExcel依然將儲存格對象儲存在記憶體中,但是你可以自訂。你可以使用PHPExcel_Settings::setCacheStorageMethod()方法,將緩衝方式作為參數傳遞給這個方法來設定緩衝的方式。
??
$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_in_memory; PHPExcel_Settings::setCacheStorageMethod($cacheMethod);
?
?
setCacheStorageMethod()方法會返回一個BOOL型變數用於表示是否成功設定(比如,如果APC不能使用的時候,你設定使用APC緩衝,將會返回false)。每一個worksheet都會有一個獨立的緩衝,當一個worksheet執行個體化時,就會根據設定或配置的緩衝方式來自動建立。一旦你開始讀取一個檔案或者你已經建立了第一個worksheet,就不能在改變緩衝的方式了。目前,有以下幾種緩衝方式可以使用:
1). PHPExcel_CachedObjectStorageFactory::cache_in_memory;
預設情況下,如果你不初始化任何緩衝方式,PHPExcel將使用記憶體緩衝的方式。
2).PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized;??
使用這種緩衝方式,儲存格會以序列化的方式儲存在記憶體中,這是降低記憶體使用量率效能比較高的一種方案。
3). PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip;
與序列化的方式類似,這種方法在序列化之後,又進行gzip壓縮之後再放入記憶體中,這回跟進一步降低記憶體的使用,但是讀取和寫入時會有一些慢。
4). PHPExcel_CachedObjectStorageFactory::cache_to_discISAM;
當使用cache_to_discISAM這種方式時,所有的儲存格將會儲存在一個臨時的磁碟檔案中,只把他們的在檔案中的位置儲存在PHP的記憶體中,這會比任何一種緩衝在記憶體中的方式都慢,但是能顯著的降低記憶體的使用。臨時磁碟檔案在指令碼運行結束是會自動刪除。
5). PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
????? 類似cache_to_discISAM這種方式,使用cache_to_phpTemp時,所有的儲存格會還存在php://temp I/O流中,只把他們的位置儲存在PHP的記憶體中。PHP的php://memory包裹器將資料儲存在記憶體中,php://temp的行為類似,但是當儲存的資料大小超過記憶體限制時,會將資料儲存在臨時檔案中,預設的大小是1MB,但是你可以在初始化時修改它:
$cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_phpTemp; $cacheSettings = array( ' memoryCacheSize ' => '8MB' ); PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
?
?
php://temp檔案在指令碼結束是會自動刪除。
?
6). PHPExcel_CachedObjectStorageFactory::cache_to_apc;
當使用cach_to_apc時,儲存格儲存在APC中,只在記憶體中儲存索引。APC緩衝預設逾時時間時600秒,對絕大多數應用是足夠了,當然你也可以在初始化時進行修改:
?
?
$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_APC; $cacheSettings = array( 'cacheTime' => 600 ); PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings); ?
?
?
當指令碼運行結束時,所有的資料都會從APC中清楚(忽略緩衝時間),不能使用此機製作為持久緩衝。
?
7).PHPExcel_CachedObjectStorageFactory::cache_to_memcache
??????? 使用cache_to_memory時,儲存格對象儲存在memcache中,只在記憶體中儲存索引。預設情況下,PHPExcel會在localhost和連接埠11211尋找memcache服務,逾時時間600秒,如果你在其他伺服器或其他連接埠運行memcache服務,可以在初始化時進行修改:
?
$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_memcache; $cacheSettings = array( 'memcacheServer'=> 'localhost', 'memcachePort' => 11211, 'cacheTime' => 600 ); PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
??
???????從初始化設定的形式上看,MS還不支援多台memcache伺服器輪詢的方式,比較遺憾。
?當指令碼結束時,所有的資料都會從memcache清空(忽略緩衝時間),不能使用該機制進行持久儲存。
?
3.下拉式清單的資料來源過長
?
?
??? 我們還是先來看手冊是怎麼說的:
???
It is important to remember that any string participating in an Excel formula is allowed to be maximum 255 characters (not bytes).
?
???
???? 當下拉式清單的資料來源過長(more than 255 characters)時,該下拉式清單會顯示不正確(我遇到的情況是:該下拉式清單顯示了別的正常的下拉式清單的資料來源).
以下是我的解決辦法:
//解決下拉框資料來源字串長度過大:將每個來源字串分解到一個閒置儲存格中$str_list = "item1,item2,item3,......" ;$str_len = strlen($str_list);if($str_len>=255){ $str_list_arr = explode(',', $str_list); if($str_list_arr) foreach($str_list_arr as $i =>$d){ $c = "P".($i+1); $activeSheet->setCellValue($c,$d); } $endcell = $c; $activeSheet->getColumnDimension('P')->setVisible(false); } $objValidation2 = $activeSheet->getCell("A1")->getDataValidation(); $objValidation2->setType( PHPExcel_Cell_DataValidation::TYPE_LIST ) ->setErrorStyle( PHPExcel_Cell_DataValidation::STYLE_INFORMATION ) ->setAllowBlank(true) ->setShowInputMessage(true) ->setShowErrorMessage(true) ->setShowDropDown(true) ->setErrorTitle('輸入的值有誤') ->setError('您輸入的值不在下拉框列表內.') ->setPromptTitle('下拉選擇框') ->setPrompt('請從下拉框中選擇您需要的值!');if($str_len<255) $objValidation2->setFormula1('"' . $str_list . '"'); else $objValidation2->setFormula1("sheet1!P1:{$endcell}");
?
4.本地運行正常,伺服器上PHPExcel不能運行
官網:
????????? The following software is required to develop using PHPExcel:
?????????? ? PHP version 5.2.0 or newer
?????????? ? PHP extension php_zip enabled *)
???????????? PHP extension php_xml enabled
???????????? PHP extension php_gd2 enabled (if not compiled in)
? 另外,請檢查iconv擴充是否正常,PHPExcel需要他的支援
?
?
?