[TOC]
### 1、composer 安装phpoffice/phpexcel
~~~
composer require phpoffice/phpexcel
~~~
### 2、通用建议放在common模块
~~~
php think make:controller common/Import --plain
--plain 表示仅仅生成控制器
~~~
### 3、该控制器设置了两种通用导出设置
~~~
1、commmonImport excel导入通用获取数据--支持多个工作区
2、importBaseVerify excel导入数据基于基础数据校验
~~~
### 4、开始代码之前说明
1.1 commmonImport通用导出需要引入
~~~
use app\common\controller\Files
//Files类--参考***Files通用封装***
~~~
1.2 importBaseVerify通用导出需要引入
~~~
use app\common\controller\ImportBaseVerify
ImportBaseVerify类--参考***ImportBaseVerify辅助封装***
~~~
### 5、开始commmonImport--直接看代码
~~~
/**
* excel导入通用获取数据--支持多个工作区
*
* @param array $map 参数值配置
* $map = [
* //每个数组的下标为工作区,确保采用的是正确的索引排序
* [
* 'row' => 2, //从第几行开始读取----行下标为1
* 'col' => 0, //从第几列开始读取----列下标为0
* 'firstHidden' => false //该参数配置的为true的话,表示在excel第一行隐藏了列对应的key值数据,返回的数据将会是以键值对返回
* ],
* [],
* ];
*
* @param string $path 文件路径 如果默认为空,采用文件上传方式
* @return array
*/
public static function commmonImport(array $map, $path = null)
{
if (is_null($path)) {
$data = (new Files())->upload('default.only_excel');
if (!$data['status']) {
return $data;
}
$path = $data['data']['file_path'];
}
if (!file_exists($path)) {
return [
'status' => false,
'message' => $path . '文件不存在'
];
}
if (empty($map)) {
return [
'status' => false,
'message' => 'map参数不正确'
];
}
$suffix = pathinfo($path)['extension'];
$loadReader = $suffix == 'xls' ? 'Excel5' : 'Excel2007';
$objReader = \PHPExcel_IOFactory::createReader($loadReader);
$objPHPExcel = $objReader->load($path);
$jsonData = [];
$sheetIndex = 0;
foreach ($map as $data) {
$row = $data['row'] ?? 2;
$col = $data['col'] ?? 0;
$firstHidden = $data['firstHidden'] ?? false;
$result = self::getCommanData(
$objPHPExcel,
$sheetIndex,
$row,
$col,
$firstHidden
);
if (!$result['status']) {
return $result;
} else {
$jsonData['sheet' . $sheetIndex] = $result['data'];
}
$sheetIndex++;
}
return $jsonData;
}
~~~
其中调用了getCommanData方法--方法如下
~~~
/**
* 获取普通excel数据
*
* @param object $objPHPExcel
* @param integer $sheetIndex
* @param integer $rowstart
* @param integer $col
* @param bool $firstHidden
* @return array
*/
protected static function getCommanData(
$objPHPExcel,
$sheetIndex,
$rowstart,
$col,
$firstHidden
)
{
$sheet = $objPHPExcel->getSheet($sheetIndex);
$highestRow = $sheet->getHighestRow();
$highestColumm = $sheet->getHighestColumn();
$highestColumm = \PHPExcel_Cell::columnIndexFromString($highestColumm);
$fieldKeys = [];
if ($firstHidden) {
for ($column = $col; $column < $highestColumm; $column++) {
$cellData = trim(strval($sheet->getCellByColumnAndRow($column, 1)->getValue()));
array_push($fieldKeys, $cellData);
}
}
$excel_data = [];
for ($row = $rowstart; $row <= $highestRow; $row++) {
$temp = 0;
$datatemp = [];
for ($column = $col; $column < $highestColumm; $column++) {
$cellData = trim(strval($sheet->getCellByColumnAndRow($column, $row)->getValue()));
if ($firstHidden) {
if (isset($fieldKeys[($column - $col)]) && $fieldKeys[($column - $col)] != '') {
$datatemp[$fieldKeys[($column - $col)]] = $cellData;
} else {
return ['status' => false, 'message' => 'sheet' . $sheetIndex . '工作区key值少于数据值'];
}
} else {
array_push($datatemp, $cellData);
}
if($temp == ($highestColumm - 1)) break;
$temp++;
}
if (!empty($datatemp)) $excel_data[] = $datatemp;
}
$jsonData = ['status' => true, 'data' => $excel_data];
return $jsonData;
}
~~~
### 6、开始importBaseVerify--直接上代码
~~~
/**
* excel导入数据基于基础数据校验
*
* @param string $key excel配置文件中的import key
* @param string $path 文件路径 如果默认为空,采用文件上传方式
*/
public static function importBaseVerify($key, $path = null)
{
if (empty($key)) {
return [
'status' => false,
'message' => 'key值不能为空'
];
}
if (is_null($path)) {
$data = (new Files())->upload('default.only_excel');
if (!$data['status']) {
return $data;
}
$path = $data['data']['file_path'];
}
if (!file_exists($path)) {
return [
'status' => false,
'message' => $path . '文件不存在'
];
}
$suffix = pathinfo($path)['extension'];
$loadReader = $suffix == 'xls' ? 'Excel5' : 'Excel2007';
$objReader = \PHPExcel_IOFactory::createReader($loadReader);
$objPHPExcel = $objReader->load($path);
$map = Config::get($key);
$jsonData = [];
$sheetIndex = 0;
foreach ($map as $data) {
$row = $data['row'] ?? 2;
$col = $data['col'] ?? 0;
$firstHidden = $data['firstHidden'] ?? false;
$verify = $data['verify'] ?? [];
$result = self::getBaseVerifyData(
$objPHPExcel,
$sheetIndex,
$row,
$col,
$firstHidden,
$verify
);
if (!$result['status']) {
return $result;
} else {
$jsonData['sheet' . $sheetIndex] = $result['data'];
}
$sheetIndex++;
}
return $jsonData;
}
~~~
其中调用了getBaseVerifyData方法如下
~~~
/**
* 获取普通excel数据
*
* @param object $objPHPExcel
* @param integer $sheetIndex
* @param integer $rowstart
* @param integer $col
* @param bool $firstHidden
* @param array $verify
* @return array
*/
protected static function getBaseVerifyData(
$objPHPExcel,
$sheetIndex,
$rowstart,
$col,
$firstHidden,
array $verify
)
{
$sheet = $objPHPExcel->getSheet($sheetIndex);
$highestRow = $sheet->getHighestRow();
$highestColumm = $sheet->getHighestColumn();
$highestColumm = \PHPExcel_Cell::columnIndexFromString($highestColumm);
$fieldKeys = [];
if ($firstHidden) {
for ($column = $col; $column < $highestColumm; $column++) {
$cellData = trim(strval($sheet->getCellByColumnAndRow($column, 1)->getValue()));
array_push($fieldKeys, $cellData);
}
}
$v_flag = !empty($verify) ? true : false;
$excel_data = [];
$error = 0;
$error_msg = '';
for ($row = $rowstart; $row <= $highestRow; $row++) {
$temp = 0;
$datatemp = [];
for ($column = $col; $column < $highestColumm; $column++) {
$cellData = trim(strval($sheet->getCellByColumnAndRow($column, $row)->getValue()));
//数据校验
if ($v_flag
&& isset($verify['col' . ($column - $col)])
) {
$verifyResult = ImportBaseVerify::ImportBaseVerifyEnum($verify['col' . ($column - $col)], $cellData);
if (!$verifyResult['status']) {
$error ++;
$error_msg .= 'sheet' . $sheetIndex . '在第' . $row . '行,第' . ($column + 1) . '列' . $verifyResult['message'] . ';';
}
}
if ($firstHidden) {
if (isset($fieldKeys[($column - $col)]) && $fieldKeys[($column - $col)] != '') {
$datatemp[$fieldKeys[($column - $col)]] = $cellData;
} else {
return ['status' => false, 'message' => 'sheet' . $sheetIndex . '工作区key值少于数据值'];
}
} else {
array_push($datatemp, $cellData);
}
if($temp == ($highestColumm - 1)) break;
$temp++;
}
if (!empty($datatemp)) $excel_data[] = $datatemp;
}
$jsonData = $error ? [
'status' => false,
'message' => $error_msg
] :
[
'status' => true,
'data' => $excel_data
];
return $jsonData;
}
~~~
其中的importBaseVerify中的key到底是什么?
key是在config目录下excel.php中的配置key如下:
~~~
//代码中调用key通过Config::get('excel.import.test')即可
'import' => [
'test' => [
[
//从第几行开始读取
'row' => 3,
//从第几列开始读取
'col' => 0,
//是否有隐藏的第一行字段
'firstHidden' => true,
//每一列对应的的校验方法(列下标从0开始)
'verify' => [
'col2' => 'idcard',//ok
'col3' => 'date_ymd',//ok
'col4' => 'number_2dot',//ok
'col5' => 'number',//ok
'col6' => 'date_y-m-d',//ok
'col7' => 'number_2dot',
],
],
[]
],
],
~~~
### 7、作者有话说
1.说明一下解惑信息
commmonImport中如果传入了文件path,则直接解析
如果是直接文件上传的模式则调用了Files类的上传upload方法
----其中importBaseVerify一样
2.firstHidden是干什么用的
这个参数是为了有些量非常大,一般提供了模板导出的然后导入
然而一些数据库字段要与该列的值一一对应
如果firstHidden设为false表示excel中第一行没有隐藏的字段
那么返回的已普通数组模式返回即:
```
[
'sheet0' => [
['aa','bb','cc'],
['a2a','b2b','c2c'],
],
'sheet1' => [],
]
```
说明:该方法支持多个sheet工作区导入
如果firstHidden设为true表示excel中第一行有隐藏的字段
那么返回的将会以第一行的字段以键值对返回
```
[
'sheet0' => [
[
'name'=> 'aa',
'addr' => 'bb',
'age' => 20
],
[],
],
'sheet1' => [],
]
```
3.具体可以参考代码的注释
4.相信这些简单的代码难不倒各位phper
5.如果有一些不明白的直接留言
6.为了该方法的更直接了解,立马写Files类是怎么的
7.再插一句import配置中的verify是什么意思
col2=>idcard
col2表示的是第三列
idcard对应的是ImportBaseVerify中需要校验的一个type
该type会在ImportBaseVerify中调用相应的方法
- 产品介绍
- 功能介绍
- 联系合作
- 修订记录
- 环境安装
- 依赖环境
- 依赖服务
- 前端环境
- 核心功能
- 流程引擎
- 流程编辑步骤
- 流程设计
- 业务表设计
- 表单设计
- 报表设计
- 节点配置
- 全局配置
- 规则引擎
- 模块功能
- 系统管理
- 平台架构
- 平台(单位)管理
- 组织架构
- 用户管理
- 角色管理
- 运维管理
- 菜单管理
- 流程管理
- 代码管理
- 字典管理
- 车型库管理
- 报表管理
- 产品管理
- 经销商管理
- 数据字典
- 业务设置
- 业务报表设置
- 系统配置
- 微信小程序设置
- OCR识别
- 钉钉通知
- 钉钉登录授权
- 云储存设置
- 服务规划
- 其他产品
- 教育点播
- 退役政务
- 三方报表
- 微信社群
- 场景名片
- 合同电子签
- TP5实用封装
- 通用封装
- Export通用封装
- Import通用封装
- 配合Import通用封装的ImportBaseVerify类
- Files通用封装
- Directory通用封装
- Pdf通用封装
- Words通用封装
- Nredis(redis封装)
- ZipArchives压缩zip文件封装
- BarQrcode条形码二维码
- Publics公共方法封装
- Curls(cUrl请求封装)
- extend扩展开发
- 何时编写扩展文件包
- 扩展文件包如何编写
- 题外话
- 常用的compose安装
- 一些建议及细节
- 实用工具
- 源码分析
- 入口文件index.php
- think\Facade类详解
- App对接Api设计
- 设计模式说明(为什么这么做)
- 代码设计逻辑方案
- 数据库备份
- 实用案例
- 如何“偷”JAVA代码
- SAAS接口设计
- 1、创建saas基类文件
- 2、初始化控制器服务
- 3、身份校验
- 4、创建登录控制器
- 5、实现登录服务层
- 6、服务层继承的service类
- 7、该案例的完整模块包
- 校验型规则校验扩展包
- 自定义规则解析(可供参考)
- 通用文件扩展包(File,Zip)
- PHP实现word转PDF功能环境搭建
- 日志通用扩展包
- 定时任务
- PHP视频处理器安装环境搭建
- 日常开发问题记录
- 1、mysql存储中带一些不可见字符
- 2、php开发规范校验及修复