前言:
在业务中开发中,表格的导入导出功能很常见。但是这里主要是使用phpoffice类库介绍实现导入表格数据的功能。
冲突:
大部分的导入功能,就是通过点击按钮上传一张表格,然后后台读取表格数据根据业务整理后直接插入到数据库,最后再返回给前端。但是如果表格数据庞大,业务逻辑复杂的时候,就会导致导入那一块很臃肿不好维护。
解决方法:
处理方式是把导入与业务数据插入分离,所以在二者之间添加一个队列就可以了。导入只负责将表格数据存入队列。业务部分可以是单独的系统,最后就是消费队列中的数据了。这样一来,不但提升了导入速度,而且还让导入与系统解耦,不会因为异常而影响到其他业务。
编码:
1.下载phpoffice。
composer repuire phpoffice/phpspreadsheet
2.导入导出代码。
<?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 { // 导出 public function output($data, $columns, $table = '导出文件') { $spreadsheet = new spreadsheet(); $sheet = $spreadsheet->getactivesheet(); // 设置第一栏的标题 foreach ($columns as $k => $v) { $sheet->setcellvalue($k . "1", $v['title']); } //第二行起 设置内容 $baserow = 2; //数据从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; } // 导入 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('只支持导入excel文件!'); } } /* 如果不需要获取特殊操作,则只读内容,可以大幅度提升读取excel效率 */ empty($options) && $objread->setreaddataonly(true); /* 建立excel对象 */ $obj = $objread->load($file); /* 获取指定的sheet表 */ $currsheet = $obj->getsheet($sheet); //$currsheet = $obj->getsheetbyname($sheet); // 根据名字 if (isset($options['mergecells'])) { /* 读取合并行列 */ $options['mergecells'] = $currsheet->getmergecells(); } if (0 == $columncnt) { /* 取得最大的列号 */ $columnh = $currsheet->gethighestcolumn(); /* 兼容原逻辑,循环时使用的是小于等于 */ $columncnt = coordinate::columnindexfromstring($columnh); } /* 获取总行数 */ $rowcnt = $currsheet->gethighestrow(); $data = []; /* 读取内容 */ 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'])) { /* 获取公式,公式均为=号开头数据 */ $formula = $currsheet->getcell($cellid)->getvalue(); if (0 === strpos($formula, '=')) { $options['formula'][$cellname . $_row] = $formula; } } if (isset($format) && 'm/d/yyyy' == $format) { /* 日期格式翻转处理 */ $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数据。
return [ // 导入的表格标题 "bidding" => [ "stock_no" => "编号", "price" => "价格", "mobile" => "手机", "nickname" => "姓名" ] ]; // 格式化指定列数据(默认第一行表头) 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.导入部分,上传接口。
// 导入表格,上传接口 public function importexcel() { $upload_file = $_files['files']['tmp_name']; $input = $this->input; // id $id = isset($input['id']) ? $input['id'] : 0; // 默认取第一工作表 $exceldata = (new excel())->importexcel($upload_file, 0); // 取excel字段 $config = config('excel_export.bidding'); $price_offer = excel::formattingcells($exceldata, $config); // 判断每条记录的手机和价格格式 // …… $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, '导入成功'); }
5.消费业务逻辑。
以上就是详解如何实现phpoffice的excel导入功能解耦的详细内容,更多关于phpoffice excel导入解耦的资料请关注代码网其它相关文章!
发表评论