工作中經常要遇到將xlsx文件中的部分內容導入到數據庫。通常我們都是用PHPExcel來讀取。
通過下面的方法我們可以很容易將一個excel表格讀取成為php數組,之后就可以為所欲為了:
- $input_file = "data.xlsx";
- $objPHPExcel = PHPExcel_IOFactory::load($input_file);
- $sheetData = $objPHPExcel->getSheet(0)->toArray(null, true, true, true);
如果文章到此結束,那價值就不大了。
很不幸的情況總是存在的,當data.xlsx有上萬行,每一行又有很多列,每一列又有很長的字符串,並且有的還有顏色等效果時,用上面的方法經常發生的情況就是內存不足。
好吧,我們還有ini_set來加大內存,還可以用set_time_limit來設置較長的超時,如下:
- set_time_limit(90);
- ini_set("memory_limit", "1024M");
- $input_file = "data.xlsx";
- $objPHPExcel = PHPExcel_IOFactory::load($input_file);
- $sheetData = $objPHPExcel->getSheet(0)->toArray(null, true, true, true);
但很負責任的說,這些都不是終極的方案。
我曾經試過將內存設置到了2G,超時設置到了90秒,也仍然讀不出一個4000行的花花綠綠的表格。原因都出在toArray這個方法上,它會將處理的結果全保存到數組中,這種方式在處理簡單表格時還是很方便的,但在處理大表格時,真的是很杯具。
我們的解決方案如下:
- require 'lib/PHPExcel.php';
- set_time_limit(90);
- $input_file = "data.xlsx";
- $objPHPExcel = PHPExcel_IOFactory::load($input_file);
- // 讀取規則
- $sheet_read_arr = array();
- $sheet_read_arr["sheet1"] = array("A","B","C","D","F");
- $sheet_read_arr["sheet2"] = array("A","B","C","D","F");
- // 循環所有的頁
- foreach ($sheet_read_arr as $key => $val)
- {
- $currentSheet = $objPHPExcel->getSheetByName($key);// 通過頁名稱取得當前頁
- $row_num = $currentSheet->getHighestRow();// 當前頁行數
- // 循環從第二行開始,第一行往往是表頭
- for ($i = 2; $i <= $row_num; $i++)
- {
- $cell_values = array();
- foreach ($val as $cell_val)
- {
- $address = $cell_val . $i;// 單元格坐標
- // 讀取單元格內容
- $cell_values[] = $currentSheet->getCell($address)->getFormattedValue();
- }
- // 看看數據
- print_r($cell_values);
- }
- }
上面的方式算是較復雜的情況了,如果只是想將所有的單元格全讀出來,用下面的方法就行了:
- require 'lib/PHPExcel.php';
- set_time_limit(90);
- $input_file = "data.xlsx";
- $objPHPExcel = PHPExcel_IOFactory::load($input_file);
- $sheet_count = $objPHPExcel->getSheetCount();
- for ($s = 0; $s < $sheet_count; $s++)
- {
- $currentSheet = $objPHPExcel->getSheet($s);// 當前頁
- $row_num = $currentSheet->getHighestRow();// 當前頁行數
- $col_max = $currentSheet->getHighestColumn(); // 當前頁最大列號
- // 循環從第二行開始,第一行往往是表頭
- for($i = 2; $i <= $row_num; $i++)
- {
- $cell_values = array();
- for($j = 'A'; $j < $col_max; $j++)
- {
- $address = $j . $i; // 單元格坐標
- $cell_values[] = $currentSheet->getCell($address)->getFormattedValue();
- }
- // 看看數據
- print_r($cell_values);
- }
- }
我們可以將上面的print_r地方改成組拼sql語句並寫入文件,然后用mysql導入,當然也可以直接連接數據庫向表中插入記錄,這就隨意了。
用這種方法可以將上萬行的記錄很輕松的導入到表中,希望對大家有所幫助。