詳解如何實(shí)現(xiàn)phpoffice的excel導(dǎo)入功能解耦
前言:
在業(yè)務(wù)中開(kāi)發(fā)中,表格的導(dǎo)入導(dǎo)出功能很常見(jiàn)。但是這里主要是使用PhpOffice類(lèi)庫(kù)介紹實(shí)現(xiàn)導(dǎo)入表格數(shù)據(jù)的功能。
沖突:
大部分的導(dǎo)入功能,就是通過(guò)點(diǎn)擊按鈕上傳一張表格,然后后臺(tái)讀取表格數(shù)據(jù)根據(jù)業(yè)務(wù)整理后直接插入到數(shù)據(jù)庫(kù),最后再返回給前端。但是如果表格數(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ù)了。這樣一來(lái),不但提升了導(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行開(kāi)始往下輸出 這里是避免頭信息被覆蓋
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)開(kāi)頭數(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('表格不完整');
}
// 需要添加過(guò)濾
$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)文章
ThinkPHP5.0框架實(shí)現(xiàn)切換數(shù)據(jù)庫(kù)的方法分析
這篇文章主要介紹了ThinkPHP5.0框架實(shí)現(xiàn)切換數(shù)據(jù)庫(kù)的方法,結(jié)合實(shí)例形式分析了thinkPHP5.0數(shù)據(jù)庫(kù)的配置與動(dòng)態(tài)連接相關(guān)操作技巧,需要的朋友可以參考下2019-10-10
php制作圓形用戶(hù)頭像的實(shí)例_自定義封裝類(lèi)源代碼
下面小編就為大家?guī)?lái)一篇php制作圓形用戶(hù)頭像的實(shí)例_自定義封裝類(lèi)源代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
Yii2中設(shè)置與獲取別名的函數(shù)(setAlias和getAlias)用法分析
這篇文章主要介紹了Yii2中設(shè)置與獲取別名的函數(shù)(setAlias和getAlias)用法,較為詳細(xì)的分析了別名的概念、用法及Yii中設(shè)置與獲取別名的具體實(shí)現(xiàn)方法,需要的朋友可以參考下2016-07-07
TP5 基于bootstrap實(shí)現(xiàn)多圖上傳插件
這篇文章主要介紹了TP5 基于bootstrap實(shí)現(xiàn)多圖上傳插件,需要的朋友可以參考下2018-07-07
php單例模式的簡(jiǎn)單實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇php單例模式的簡(jiǎn)單實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06
實(shí)例(Smarty+FCKeditor新聞系統(tǒng))
實(shí)例(Smarty+FCKeditor新聞系統(tǒng))...2007-01-01
PHP7使用ODBC連接SQL Server2008 R2數(shù)據(jù)庫(kù)示例【基于thinkPHP5.1框架】
這篇文章主要介紹了PHP7使用ODBC連接SQL Server2008 R2數(shù)據(jù)庫(kù),結(jié)合實(shí)例形式分析了基于thinkPHP5.1框架使用ODBC連接SQL Server2008數(shù)據(jù)庫(kù)相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
PHP獲取短鏈接跳轉(zhuǎn)后的真實(shí)地址和響應(yīng)頭信息的方法
這篇文章主要介紹了PHP獲取短鏈接跳轉(zhuǎn)后的真實(shí)地址和響應(yīng)頭信息的方法,本文使用get_headers函數(shù)實(shí)現(xiàn),需要的朋友可以參考下2014-07-07

