1、Excel表格导出
先上大图:(可放大查看,当作壁纸再好不过,超高清壁纸)
正题:
首先、thinkPHP6框架内在admin应用下,自定义文件夹,存放公共类,里面封装公共方法。
命名空间写好,记得引入Db查询构造器的类等
命令:安装扩展命令:composer require phpoffice/phpspreadsheet
接着:导出代码
/** * Excel表格导出 * Excel扩展名为xlsx和xls两种,默认为false */ public static function exportExcel($table = '' , $database = '' , $type = false , $fileName = '新建Excel表格') { /** * author:柔情柴少 * time:2021/12/17 * title:封装Excel导出header头 * 优点:不用自己定义,被柴少写活,只需要传入参数,也就是表名和数据库名 */ $res =Db::query("SELECT column_comment FROM INFORMATION_SCHEMA.Columns WHERE table_name='$table' AND table_schema='$database'"); $column_length = count($res); $arr = []; for ($i='A';$i<=chr(ord('A')+$column_length-1);$i++){ array_push($arr,$i.'1'); } $newArr = []; foreach ($res as $k=>$v){ array_push($newArr,implode(array_values($v))); } $header = []; for ($i=0;$i<$column_length;$i++){ $header["$arr[$i]"] = $newArr[$i]; } /** * @data 从数据库查询的数据 * @method/Db查询构造器或者从模型查询(依赖注入、静态、实例化对象) * Db查询构造器查询完成,转化成二维关联数组 */ $data = Db::table($table)->select()->toArray(); foreach ($data as $k=>$v){ $array = array_values($v); $data[$k] = $array; } /** * 实例化类 */ $preadsheet = new Spreadsheet(); /** * 创建sheet纸张 */ $sheet = $preadsheet->getActiveSheet(); /** * 循环header表头数据 */ foreach ($header as $k => $v) { $sheet->setCellValue($k, $v); } /** * 生成数据 */ $sheet->fromArray($data, null, "A2"); /** * 样式设置 */ $sheet->getDefaultColumnDimension()->setWidth(12); /** * 下载与后缀 */ if ($type) { header("Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); $type = "Xlsx"; $suffix = "xlsx"; } else { header("Content-Type:application/vnd.ms-excel"); $type = "Xls"; $suffix = "xls"; } /** * 清除缓存区 */ ob_end_clean(); /** * 激活浏览器窗口 */ header("Content-Disposition:attachment;filename=$fileName.$suffix"); /** * 缓存控制 */ header("Cache-Control:max-age=0"); /** * 调用方法执行下载 */ $writer = IOFactory::createWriter($preadsheet, $type); /** * 数据流 */ $writer->save("php://output"); }
调用参数:
$database = 'week1'; $table='goods'; $type = false; $fileName = '商品表'; $res = $excel::exportExcel($table,$database,$type,$fileName);
自己定义路由,跳到某个方法内,在方法内,写上述代码,即可调用公共函数exportExcel将数据库内某个表的内容完美导出:注意------表内字段,最好有comment(注释)不然导出的Excel表格没有表头。
赵教授封装的Excel导出方法,极大地简化了工作量,只需要传入四个参数;
$database 你当前操作的数据库名
$table 你要导出的表名
$type 决定Excel表格是xlsx还是xls后缀,一般默认为false
$fileName 为导出的Excel表格的名字(可以再加工一下,直接让$table代替$fileName)
导出完毕!!!
2、Excel表格导入
再上大图:
导入公共方法:
/** * @param string $filename * @return array|string * @throws \PhpOffice\PhpSpreadsheet\Exception * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception */ public static function importExcel($filename = "",$table = "",$database = "") { /** * 注意,导入时,需要自行建表,和Excel表格格式相同 * 可以再深度封装,加入迁移建表,但考虑到字段无法自动识别进行创建,暂时封装到这里 */ $file[] = $filename; try { /** * 验证文件大小为2M * 后缀为Excel表格的后缀 */ validate(['file' => 'fileSize:2097152|fileExt:xls,xlsx']) ->check($file); /** * 将文件保存到本地 */ $savename = \think\facade\Filesystem::disk('public')->putFile('file', $file[0]); /** * 获取文件后缀 */ $fileExtendName = substr(strrchr($savename, '.'), 1); /** * xls和xlsx两种格式 */ if ($fileExtendName == 'xlsx') { $objReader = IOFactory::createReader('Xlsx'); } else { $objReader = IOFactory::createReader('Xls'); } /** * 设置文件为只读 */ $objReader->setReadDataOnly(TRUE); /** * 读取文件,thinkPHP默认上传文件,在runtime目录下,可根据实际情况进行更改,在config目录下,filesystem.php中更改 */ $objPHPExcel = $objReader->load(public_path() . 'storage/' . $savename); /** * excel中的第一张纸 */ $sheet = $objPHPExcel->getSheet(0); /** * 获取总行数 */ $highestRow = $sheet->getHighestRow(); /** * 获取总列数 */ $highestColumn = $sheet->getHighestColumn(); Coordinate::columnIndexFromString($highestColumn); $lines = $highestRow - 1; if ($lines <= 0) { return "数据为空数组"; } /** * 直接取出Excel中的数据 */ $data = $objPHPExcel->getActiveSheet()->toArray(); /** * 删除第一行元素,Excel表格的表头 * 第一行,也可以留着,插入对应字段后,当注释,具体请百度,本尊不再详细讲解 */ array_shift($data); /** * 删除文件 */ unlink(public_path() . 'storage/' . $savename); /** * 输入表名,查找对应字段 */ $columns =Db::query("select column_name from information_schema.columns where table_name='$table' and table_schema='$database'"); /** * 将查询的字段放入对应索引数组 */ $array = []; foreach ($columns as $k=>$v){ array_push($array,implode(array_values($v))); } /** * 循环数据,也就是二维关联数组,生成对应的键,方便插入 * 注意:表中字段,一定要和Excel表格的列数一样,不然会报错,也就是对应的字段数据,没有键 */ $count_column = count($array); $newArray = []; $finalArray = []; foreach($data as $k=>$v){ for ($i=1;$i<$count_column;$i++){ $newArray[$array[$i]] = $v[$i]; } $finalArray[] = $newArray; } foreach ($finalArray as $k=>$v){ Db::table($table)->insert($v); } /** * 循环添加,将数据插入数据库 * 注意:由于使用了Db查询构造器插入 * 表内字段,出了主键不能为空且自增以外 * 其他字段最好不要在不能为空的方框内打对号 * 不然Excel导入数据有空值的情况下,会报错 * 若是用模型插入,并且,字段有默认值的情况下,不会出现这种错误 * 也就是说,Db查询构造器,字段有默认值,不能为空,当你Excel表格存在空值,依旧报错 */ } catch (ValidateException $e) { return $e->getMessage(); } }
调用代码:
public function import(Excel $excel){ $file = \request()->file('file'); $table = 'good'; $database = 'week1'; $res = $excel::importExcel($file,$table,$database); }
Excel类的引入,可以使用依赖注入
$file 文件域上传的Excel文件
$table 为表名
$database 为当前要插入数据的表所在的数据库名字
只需要三个参数
但是:注意!!!
表需要提前建好,最好依据Excel表格建表,对应好列column
因为导入方法,插入数据时,调用了Db查询构造器,所以建表时,字段后的小方格,不要打对号。
即便有默认值也不行,除了自增的主键可以不为空
防止-------你的Excel表格存在单元格空数据,报错
如果是模型插入则不存在这个问题,只要有默认值,即便插入对应字段数据为空,也能插入。
但,赵教授封装的方法,却是用Db查询构造器插入的数据,用模型还得调用模型,会增加不必要的麻烦!
例如:
varchar类型数据,不为空,默认为字符串,模型插入时,这个字段对应数据为空,能插进去,Db查询构造器就会报错。
谨记!!!
Excel表格的导入和导出讲解完,最后上大图,同学们最爱看!
大图:
本学期的课程接近尾声,thinkPHP6框架分为5层架构,控制器层--业务逻辑层--lib基础库--模型层--视图层
祝愿同学们,在清华大学计算机系web语言编程的课程学习上,学有所成,愉快成长!