詳解如何實(shí)現(xiàn)phpoffice的excel導(dǎo)入功能解耦
前言:
在業(yè)務(wù)中開發(fā)中,表格的導(dǎo)入導(dǎo)出功能很常見。但是這里主要是使用PhpOffice類庫介紹實(shí)現(xiàn)導(dǎo)入表格數(shù)據(jù)的功能。
沖突:
大部分的導(dǎo)入功能,就是通過點(diǎn)擊按鈕上傳一張表格,然后后臺(tái)讀取表格數(shù)據(jù)根據(jù)業(yè)務(wù)整理后直接插入到數(shù)據(jù)庫,最后再返回給前端。但是如果表格數(shù)據(jù)龐大,業(yè)務(wù)邏輯復(fù)雜的時(shí)候,就會(huì)導(dǎo)致導(dǎo)入那一塊很臃腫不好維護(hù)。
解決方法:
處理方式是把導(dǎo)入與業(yè)務(wù)數(shù)據(jù)插入分離,所以在二者之間添加一個(gè)隊(duì)列就可以了。導(dǎo)入只負(fù)責(zé)將表格數(shù)據(jù)存入隊(duì)列。業(yè)務(wù)部分可以是單獨(dú)的系統(tǒng),最后就是消費(fèi)隊(duì)列中的數(shù)據(jù)了。這樣一來,不但提升了導(dǎo)入速度,而且還讓導(dǎo)入與系統(tǒng)解耦,不會(huì)因?yàn)楫惓6绊懙狡渌麡I(yè)務(wù)。
編碼:
1.下載PhpOffice。
composer repuire phpoffice/phpspreadsheet
2.導(dǎo)入導(dǎo)出代碼。
<?php namespace app\common\helper; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use think\Exception; class Excel { // 導(dǎo)出 public function outPut($data, $columns, $table = '導(dǎo)出文件') { $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); // 設(shè)置第一欄的標(biāo)題 foreach ($columns as $k => $v) { $sheet->setCellValue($k . "1", $v['title']); } //第二行起 設(shè)置內(nèi)容 $baseRow = 2; //數(shù)據(jù)從N-1行開始往下輸出 這里是避免頭信息被覆蓋 foreach ($data as $key => $value) { foreach ($columns as $k1 => $v1) { $i = $key + $baseRow; $sheet->setCellValue($k1 . $i, $value[$v1['field']]); } } $writer = new Xlsx($spreadsheet); $filename = $table . date("Y-m-d", time()) . '_' . time() . '.xlsx'; $writer->save('./excel/' . $filename); return '/excel/' . $filename; } // 導(dǎo)入 public function importExcel($file = '', $sheet = 0, $columnCnt = 0, &$options = []) { try { $file = iconv("utf-8", "gb2312", $file); if (empty($file) OR !file_exists($file)) { throw new \Exception('文件不存在!'); } $objRead = IOFactory::createReader('Xlsx'); if (!$objRead->canRead($file)) { $objRead = IOFactory::createReader('Xls'); if (!$objRead->canRead($file)) { throw new \Exception('只支持導(dǎo)入Excel文件!'); } } /* 如果不需要獲取特殊操作,則只讀內(nèi)容,可以大幅度提升讀取Excel效率 */ empty($options) && $objRead->setReadDataOnly(true); /* 建立excel對(duì)象 */ $obj = $objRead->load($file); /* 獲取指定的sheet表 */ $currSheet = $obj->getSheet($sheet); //$currSheet = $obj->getSheetByName($sheet); // 根據(jù)名字 if (isset($options['mergeCells'])) { /* 讀取合并行列 */ $options['mergeCells'] = $currSheet->getMergeCells(); } if (0 == $columnCnt) { /* 取得最大的列號(hào) */ $columnH = $currSheet->getHighestColumn(); /* 兼容原邏輯,循環(huán)時(shí)使用的是小于等于 */ $columnCnt = Coordinate::columnIndexFromString($columnH); } /* 獲取總行數(shù) */ $rowCnt = $currSheet->getHighestRow(); $data = []; /* 讀取內(nèi)容 */ for ($_row = 1; $_row <= $rowCnt; $_row++) { $isNull = true; for ($_column = 1; $_column <= $columnCnt; $_column++) { $cellName = Coordinate::stringFromColumnIndex($_column); $cellId = $cellName . $_row; $cell = $currSheet->getCell($cellId); if (isset($options['format'])) { /* 獲取格式 */ $format = $cell->getStyle()->getNumberFormat()->getFormatCode(); /* 記錄格式 */ $options['format'][$_row][$cellName] = $format; } if (isset($options['formula'])) { /* 獲取公式,公式均為=號(hào)開頭數(shù)據(jù) */ $formula = $currSheet->getCell($cellId)->getValue(); if (0 === strpos($formula, '=')) { $options['formula'][$cellName . $_row] = $formula; } } if (isset($format) && 'm/d/yyyy' == $format) { /* 日期格式翻轉(zhuǎn)處理 */ $cell->getStyle()->getNumberFormat()->setFormatCode('yyyy/mm/dd'); } $data[$_row][$cellName] = trim($currSheet->getCell($cellId)->getFormattedValue()); if (!empty($data[$_row][$cellName])) { $isNull = false; } } if ($isNull) { unset($data[$_row]); } } return $data; } catch (\Exception $e) { throw $e; } } }
3.抽取指定的字段格式化Excel數(shù)據(jù)。
return [ // 導(dǎo)入的表格標(biāo)題 "bidding" => [ "stock_no" => "編號(hào)", "price" => "價(jià)格", "mobile" => "手機(jī)", "nickname" => "姓名" ] ]; // 格式化指定列數(shù)據(jù)(默認(rèn)第一行表頭) public static function formattingCells(array $data, array $cellConfig) { $res = array_values($data); // 表頭 $header = $res[0]; $cellKeys = []; foreach ($header as $key => $value) { foreach ($cellConfig as $k => $v) { if ($value == $v) { $cellKeys[$key] = $k; } } } if (count($cellKeys) != count($cellConfig)) { throw new Exception('表格不完整'); } // 需要添加過濾 $temp = []; for ($i = 1; $i <= count($res) - 1; $i++) { foreach ($cellKeys as $m => $n) { $temp[$i][$n] = $res[$i][$m]; } } return array_values($temp); }
4.導(dǎo)入部分,上傳接口。
// 導(dǎo)入表格,上傳接口 public function importExcel() { $upload_file = $_FILES['files']['tmp_name']; $input = $this->input; // ID $id = isset($input['id']) ? $input['id'] : 0; // 默認(rèn)取第一工作表 $excelData = (new Excel())->importExcel($upload_file, 0); // 取Excel字段 $config = config('excel_export.bidding'); $price_offer = Excel::formattingCells($excelData, $config); // 判斷每條記錄的手機(jī)和價(jià)格格式 // …… $jsonList = json_encode(compact('id', 'price_offer')); //$jsonList = json_encode($price_offer); // 入MQ $host = config("mq.host"); $options = config("mq.price_offer_import"); try { $mq = new ProductMQ($host, $options); $mq->publish($jsonList); $mq->close(); } catch (\Exception $e) { return $this->jsonData(200, $e->getMessage()); } // 入MQ return $this->jsonData(200, '導(dǎo)入成功'); }
5.消費(fèi)業(yè)務(wù)邏輯。
以上就是詳解如何實(shí)現(xiàn)phpoffice的excel導(dǎo)入功能解耦的詳細(xì)內(nèi)容,更多關(guān)于phpoffice excel導(dǎo)入解耦的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
thinkphp ajaxfileupload實(shí)現(xiàn)異步上傳圖片的示例
本篇文章主要介紹了thinkphp ajaxfileupload實(shí)現(xiàn)異步上傳圖片的示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08PHP中的使用curl發(fā)送請(qǐng)求(GET請(qǐng)求和POST請(qǐng)求)
本篇文章主要介紹了PHP中的使用curl發(fā)送請(qǐng)求(GET請(qǐng)求和POST請(qǐng)求),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02PHP實(shí)現(xiàn)的連貫操作、鏈?zhǔn)讲僮鲗?shí)例
這篇文章主要介紹了PHP實(shí)現(xiàn)的連貫操作、鏈?zhǔn)讲僮鲗?shí)例,本文用一個(gè)數(shù)據(jù)庫操作類作為實(shí)例,需要的朋友可以參考下2014-07-07分享ThinkPHP3.2中關(guān)聯(lián)查詢解決思路
這篇文章主要介紹了ThinkPHP3.2中關(guān)聯(lián)查詢解決思路的相關(guān)資料,需要的朋友可以參考下2015-09-09PHP房貸計(jì)算器實(shí)例代碼,等額本息,等額本金
下面小編就為大家?guī)硪黄狿HP房貸計(jì)算器實(shí)例代碼,等額本息,等額本金。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-04-04PHP啟動(dòng)windows應(yīng)用程序、執(zhí)行bat批處理、執(zhí)行cmd命令的方法(exec、system函數(shù)詳解)
這篇文章主要介紹了PHP啟動(dòng)windows應(yīng)用程序、執(zhí)行bat批處理、執(zhí)行cmd命令的方法(exec、system函數(shù)詳解),需要的朋友可以參考下2014-10-10thinkPHP5.0框架應(yīng)用請(qǐng)求生命周期分析
這篇文章主要介紹了thinkPHP5.0框架應(yīng)用請(qǐng)求生命周期,較為詳細(xì)的分析了thinkPHP5.0框架應(yīng)用請(qǐng)求生命周期所涉及的各個(gè)執(zhí)行流程,需要的朋友可以參考下2017-03-03