February 26,2008

[PHP] Excel檔案轉入的方式

依然是專案管理系統的功能。因為之前Excel檔案的匯入是採用另存新檔後的csv匯入;因為以PHP來說,xls的Excel檔內含太多不可確定的格式,不如單純的逗號分隔檔案csv的資料來的純粹。不過站在使用者的角度,「另存新檔」本身就是一個多餘的動作,何況再轉存成csv檔後並不是直接按確定這麼簡單;因為Excel檔案格式的改變,所以會有M$貼心的提醒...總之最後導致整個匯入動作感覺很不友善。

儘管PTT PHP版一面倒的建議採用csv檔作資料的讀入處理,但是使用者才不管你這麼多勒!對使用者友善,就是對程式設計者的殘忍啊...然而,之所以會需要程式設計者,也是為了要對使用者更友善啊~所以,我找了一下網路上直接上傳Excel檔轉入資料的方法,目前找到二種試驗後都成功的方法:

第一種是利用PHP的COM()函數,呼叫PHP所在Server的M$ Office程式做處理。這個函數運用的感覺比較像是在寫bat檔,利用一連串指令在使用者不知情的狀況下完成想要達到的目的;當然,缺點就是這種方式只適用在M$ Windows的作業系統,而且Server上還必須要有M$ Office...

雖然說是直接上傳Excel檔轉入資料,但說穿了不過是利用COM()函數在使用者不知情的情況下另存成csv檔後,再作處理。以下是利用COM()函數另存新檔的程式碼:

$excel = new COM("excel.application") or die("Unable to instanciate excel");  //調用COM class,順便判斷是否能正常連結Excel應用程式
$excel->DisplayAlerts = 0;  //關閉開啟Excel時的警告
$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$file_name;  //上傳成功檔案的絕對路徑
$excel->Workbooks->Open($strTemp);  //打開該檔案
$csvfile_name = substr($file_name, 0,strlen($file_name)-4).'.csv';  //利用原檔名將副檔名改寫成csv
$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$csvfile_name;  //另存成csv檔後的絕對路徑
$excel->ActiveWorkbook->SaveAs($strTemp ,6);  //另存新檔,6代表csv逗號分隔檔案                     
$excel->Quit();  //退出Excel
//$excel->Release();  //釋放Excel所佔用的記憶體...吧?不過我的電腦必須註解掉這行才能動作,不知道為什麼
$excel = null;  //釋放Excel所佔用的記憶體...吧?其實我不太知道這跟上面有什麼不同

下來就是利用另存的csv檔對資料做處理囉!基本上作法沒有變,只是使用者可以省略自己另存的動作,而由Server代替轉存,使用者自然會覺得方便許多。可惜本公司的Server雖然是M$ Windows系統,但是並沒有安裝M$ Office;所以只能用第二種方法囉。

第二種方法是偉大的前輩事先做好的class:PHP-ExcelReader。PHP真不愧為網路程式設計的龍頭,許多功能其實前輩們都已經想好了!其實主要用的的檔案也只有二個:oleread.inc跟reader.php。而且因為已經封裝成class,使用方面也非常的簡單,以下式簡單的程式碼:

require_once '../Excel/reader.php';
$data = new Spreadsheet_Excel_Reader();  //調用Spreadsheet_Excel_Reader class
$data->setOutputEncoding('utf-8');  //設定輸出的編碼,可直接選擇輸出為UTF8編碼
$data->read("../xxx/xxx/test.xls");  //檔案的路徑(可使用相對路徑)
error_reporting(E_ALL ^ E_NOTICE);  //錯誤顯示

for ($i = 1; $i <= $data->sheets[0]['numRows']; $i++) {
    for ($j = 1; $j <= $data->sheets[0]['numCols']; $j++) {
        echo "\"".$data->sheets[0]['cells'][$i][$j]."\",";
    }
    echo "\n";
}

利用陣列的方式,擷取Excel檔裡面的資料;['numRows']列、['numCols']行、['cells']元素,搭配二維陣列取得。擷取出來的資料就可以直接對其作處理,非常容易使用!

關於Excel檔寫入也有另一個class:Spreadsheet_Excel_Writer。這個class需要pear的支援,所以使用前必須先安裝pear;這個部份我還沒有深入研究測試,就先行打住。另外還有一個class比較新,是支援M$ Office Excel 2007的格式:PHPExcel。這個class同時支援讀入跟寫出,不過目前只針對Excel 2007的版本作處理。目前我們公司仍以2003為主,所以這個版本也沒有深究。當然2007一定是未來的趨勢,所以以後應該還是有機會會接觸到吧。



Posted by taikobo0 at 樂多Roodo! │09:08 │回應(6)引用(0)PHP
樂多分類:日記/一般 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/5597727
回應文章

這個 "PHP-ExcelReader" 是否存在著php對應版本的問題呢? 因為我用php-4.2.3 讀取再echo中文會變成亂碼!!
但是用php 5.2.5 讀取Excel檔再echo 則中文部分是正常的
Posted by SSStylish at April 25,2008 21:57

基本上我在使用的時候是直接把Excel擷取後的資料塞進資料庫,所以並不會經由網頁輸出...如果在echo的時候會呈現亂碼,那就要看你網頁的編碼為何?編輯PHP所儲存的文件編碼為何?依照這個範例,利用PHP-ExcelReader讀出的編碼我是設定成UTF8($data->setOutputEncoding('utf-8')),所以在echo的時候網頁的編碼、以及編輯PHP所儲存的文件都要是UTF8,中文字才能正常顯示唷!
Posted by 台扣啵 at April 25,2008 22:33

其實就是因為我用舊版php(4.2.3)直接寫進mysql 結果卻是看到亂碼,再來 $data->setOutputEncoding('utf-8')不管是設成big5或utf-8 也是一樣,所以才有這個疑問
Posted by SSStylish at April 26,2008 20:05

我在使用上都是用PHP5,所以沒辦法回答這個問題;只是我直覺這應該跟PHP的版本沒什麼關係吧...但或許這真的跟PHP的版本有關~總之,如果要尋求進一步解答,只好請您自行參閱他的專案網頁囉:http://sourceforge.net/projects/phpexcelreader/
Posted by 台扣啵 at April 26,2008 21:20

PHP-ExcelReader
怎麼我下載套件之後無法正常執行~
是否可以提供更進一步的執行方式!!
Excel的檔案格式大概是長怎樣???
Posted by TT先生 at October 27,2009 16:11

你好~PHP-ExcelReader 是一個 class,只要在程式中正確的 require 應該就能被建立;請問「無法正常執行」是怎樣的情況呢?另外 Excel 的格式當初用的應該是 2003 吧~不確定 2007 是否能被正確的讀取。
Posted by 台扣啵 at October 31,2009 21:52