TP6实现导入导出

2 篇文章 0 订阅

开发过程中经常用到导入导出excel的功能,自己写了段代码记录一下。

  1. 引入phpspreadsheet
    解释一下为什么不用PHPExcel,PHPExcel已被维护为一个用于处理电子表格文件多年的库,并且因为保留对旧版PHP的支持而受到束缚,这使得前进和改进非常困难.它是一个稳定的库,但不会再进一步​​开发。
    而PHPSpreadsheet是PHPExcel的最新版本,其中大部分内容已经过重写,所以我们选择它。
    composer require phpoffice/phpspreadsheet
    

  2. app目录下 创建excel.php,封装了两个方法,导入和导出,一会在控制器里调用。
    个人没做压力测试,导出1W-6W的表应该是没什么问题的,需要的人可以自测一下。
    注释写的比较全面,不懂的或者出现什么bug可以私信问我。

    <?php
    //根据自己的文件位置更改命名空间
    namespace app;
    
    use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
    use PhpOffice\PhpSpreadsheet\IOFactory;
    use PhpOffice\PhpSpreadsheet\Spreadsheet;
    use think\exception\ValidateException;
    use think\facade\Filesystem;
    
    class Excel
    {
    
        /**
         * @param string $filename
         * @return array|string
         * @throws \PhpOffice\PhpSpreadsheet\Exception
         * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
         */
        public static function import($filename = "")
        {
            $file[] = $filename;
            try {
                // 验证文件大小,名称等是否正确
                validate(['file' => 'filesize:51200|fileExt:xls,xlsx'])->check($file);
                // 把上传的excel文件下载到本地一份
                $savename = \think\facade\Filesystem::disk('public')->putFile('file', $file[0]);
                // 读取本地的excel文件
                $spreadsheet = IOFactory::load('storage/' . $savename);
                // 获取excel中的第一张sheet
                $sheet = $spreadsheet->getSheet(0);
                // 取得总行数(例如: 3)
                $highestRow = $sheet->getHighestRow();
                // 取得总列数(例如:F)
                $highestColumn = $sheet->getHighestColumn();
                Coordinate::columnIndexFromString($highestColumn);
                // 去除表头后的总行数
                $lines = $highestRow - 1;
                if ($lines <= 0) {
                    return "数据为空数组";
                }
                // 直接取出excel中的数据
                // toArray() 具体参数参考官方文档
                $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
                // 删除第一个元素(表头)
                array_shift($sheetData);
                // 删除本地下载的文件
                unlink('storage/' . $savename);
                // 返回结果
                return $sheetData;
            } catch (ValidateException $e) {
                return $e->getMessage();
            }
        }
    
    
    
        /**
         * 数据导出Excel(csv文件)
         * @param string $file_name 文件名称
         * @param array $tile 标题
         * @param array $data 数据源
         */
        public static function export($file_name, $tile = [], $data = [])
        {
            ini_set('memory_limit', '512M');
            ini_set('max_execution_time', 0);
            ob_end_clean();
            ob_start();
            header("Content-Type: text/csv");
            header("Content-Disposition:filename=" . $file_name);
            $fp = fopen('php://output', 'w');
            // 转码 防止乱码(比如微信昵称)
            fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
            fputcsv($fp, $tile);
            $index = 0;
            foreach ($data as $item) {
                if ($index == 1000) {
                    $index = 0;
                    ob_flush();
                    flush();
                }
                $index++;
                fputcsv($fp, $item);
            }
            ob_flush();
            flush();
            ob_end_clean();
        }
    
    }
    
  3. 导入:控制器调用上面的封装好的方法
     

        /**
         * 导入
         *
         * @return array|Json
         */
        public function import(Request $request)
        {
            // 接收文件上传信息
            $files = $request->file("file");
            // 调用封装类方法,读取excel中的内容
            $data = Excel::import($files);
            // 重构数组,因为id为主键自增,所以这个字段不需要存在于sql语句内
            $newData = [];
            foreach ($data as $val){
                //存储到数据库中的字段名 和 表格里的列名要一一对应
                $newData[] = [
                    'name'=>$val['B'],
                    'pwd'=>$val['C'],
                    'phone'=>$val['D'],
                    'lastOpTime'=>$val['E'],
                    'regTime'=>$val['F'],
                ];
            }
            // 入库
            // 启动事务
            Db::startTrans();
            try {
                $result = Db::name('jason_user')->insertAll($newData);
                if (!$result) {
                    throw new \Exception('插入数据失败!');
                }
                // 提交事务
                Db::commit();
                return json(['msg'=>'文件上传成功,已经导入'.$result.'条数据','status'=>200]);
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                return json(['msg'=>'导入数据失败,'.$e->getMessage(),'status'=>400]);
            }
        }
    

  4. 导出:控制器调用上面的封装好的方法
     

        /**
         * 导出
         *
         */
        public function export()
        {
            $data=Db::table('jason_user')->select()->toArray();
            //此处说明:解决数字太长尾数变000的问题
            //由于数字超过15位,会被显示成0或者加小数点处理。造成这种情况是由于Excel内置的数值有效范围是15位。超过15位,如果要显示的话,就需要转换成非数字格式。比如文本格式。
            foreach ($data as $key => $value) {
                $data[$key]['uid'] = "\t".$value['uid']."\t";
                $data[$key]['name'] = "\t".$value['name']."\t";
                $data[$key]['pwd'] = "\t".$value['pwd']."\t";
                $data[$key]['phone'] = "\t".$value['phone']."\t";
                $data[$key]['lastOpTime'] = "\t".$value['lastOpTime']."\t";
                $data[$key]['regTime'] = "\t".$value['regTime']."\t";
            }
            //这里规定列名
            return Excel::export('用户_'.time().'.xlsx',['id','用户名','密码','手机号','上次登陆时间戳','注册时间戳'],$data);
        }
    


    TP6实现导入导出,至此结束

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值