详解如何实现phpoffice的excel导入功能解耦
发布:smiling 来源: PHP粉丝网 添加日期:2023-08-19 16:27:59 浏览: 评论:0
在业务中开发中,表格的导入导出功能很常见。但是这里主要是使用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 (emptyempty($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效率 */
- emptyempty($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 (!emptyempty($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.消费业务逻辑。
Tags: phpoffice excel导入
- 上一篇:PHP的instanceof详解及使用方法介绍
- 下一篇:最后一页
相关文章
- ·PHPEXCEL导入excel表格生成数组(2014-08-26)
- ·PHP把excel(xls)文件导入mysql数据库(2014-09-10)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)