think PHP导入导出excel

本地环境

think PHP5,PhpOffice/PhpSpreadsheet,composer
PHP版本7.4,这个插件的最低版本要求7.2
配置PhpSpreadsheet
官网:https://phpspreadsheet.readthedocs.io/en/stable/

composer require phpoffice/phpspreadsheet

数据库与excel表

在这里插入图片描述
在这里插入图片描述

导入文件

思路:首先读取excel文件数据,将他存放在缓存中,然后按照数据库的插入指令,插入数据

测试

public function upexceltest()
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setCellValue('A1', 'Welcome to Helloweba.');
        $writer = new Xlsx($spreadsheet);
        $path = ROOT_PATH.'public'.DS.'uploads'.DS.'excel';
        $writer->save($path.'/'.'hello.xlsx');//默认保存文件到public
        dump($writer);

    }

这段代码会产生一个excel文件

存缓存

新建phpspreadsheet实例

use think\Db;
use think\Request;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

获取数据,移动获取到的excel文件到本地目录

//正式使用excel上传
    //读取excel数据然后将数据组装成sql语句,传递进mysql中
    //第一步,读取excel信息,将数据中需要的预处理提取出来
    //第二部,将预处理数据进行封装成sql数据,使用模型传入数据库
    public function upexcel(Request $request)
    {
        // 判断请求类型是否为POST
        if ($request->isPost()) {
            // 获取上传的文件信息
            $file = $request->file('file');
            if (empty($file)) {
                $this->error('请选择要上传的文件!');
            }
            // 移动到框架应用根目录/public/uploads/ 目录下
            $info = $file->move(ROOT_PATH . 'public' . DS . 'uploads'.'/excel');
            if ($info) {
                // 获取文件路径
                $filePath = $info->getSaveName();

开始实例化导入

try {
                    // 使用PHPSpreadsheet读取Excel文件
                    $reader = IOFactory::createReader('Xlsx');
                    $reader->setReadDataOnly(true);
                    $spreadsheet = $reader->load(ROOT_PATH . 'public' . DS . 'uploads'.'/excel' . DS . $filePath);
                    $worksheet = $spreadsheet->getActiveSheet();//获取excel中的活动表
                    $highestRow = $worksheet->getHighestRow(); // 总行数
                    $highestColumn = $worksheet->getHighestColumn(); // 总列数
                    $highestColumnIndex = Coordinate::columnIndexFromString($highestColumn); // 转换为数字索引
                    $lines = $highestRow - 1; // 减1是因为Excel的行号从1开始,实际数据行应从第2行开始计算
                    if ($lines <= 0) {
                        $this->error('Excel表格中没有数据!');
                    } else {

将数据提取出来成数组

$rowData = []; // 初始化二维数组,在外部循环之前定义

                        for ($row = 2; $row <= $highestRow; ++$row) {
                            // 为每一行初始化一个新的数据数组
                            $currentRowData = [];

                            for ($col = 1; $col <= $highestColumnIndex; ++$col) {
                                // 使用较新的 getCell() 方法,但首先确认您的PhpSpreadsheet版本
                                $cellAddress = Coordinate::stringFromColumnIndex($col) . $row; // 转换列索引为列字母
                                $cell = $worksheet->getCell($cellAddress);
                                $currentRowData[] = $cell->getValue(); // 将当前单元格的值添加到该行数据中
                            }
                            // 将当前行的所有数据作为一个数组添加到 rowData
                            $rowData[] = $currentRowData;
                        }
                        // 现在,$rowData 是一个二维数组,每个内部数组代表一行的数据
//                        return json_encode($rowData); // 打印出来检查结果
                        //将二维数组转换为键值对的数据,姓名:mmm,语文:23
//                        foreach($rowData as $key=>$value){
//                            foreach ($rowData[])
//                        }

将数组提取出来组合成sql需要的数组批量导入数据库

$newData = [];
                        foreach($rowData as $row){
                            $newRow = ['name' => $row[0], 'chinese' => $row[1],'math'=>$row[2],'english'=>$row[3]];
                            $newData[] = $newRow;
                        }
                        $data = model('student')->insertAll($newData);
                        if ($data){
                            return json_encode(['code'=>200,'msg'=>'Excel数据导入成功!']);
                        }
                    }
                } catch (\Exception $e) {
                    return "导入失败";
                };
            }
        }
    }

完整代码

//正式使用excel上传
    //读取excel数据然后将数据组装成sql语句,传递进mysql中
    //第一步,读取excel信息,将数据中需要的预处理提取出来
    //第二部,将预处理数据进行封装成sql数据,使用模型传入数据库
    public function upexcel(Request $request)
    {
        // 判断请求类型是否为POST
        if ($request->isPost()) {
            // 获取上传的文件信息
            $file = $request->file('file');
            if (empty($file)) {
                $this->error('请选择要上传的文件!');
            }
            // 移动到框架应用根目录/public/uploads/ 目录下
            $info = $file->move(ROOT_PATH . 'public' . DS . 'uploads'.'/excel');
            if ($info) {
                // 获取文件路径
                $filePath = $info->getSaveName();

                try {
                    // 使用PHPSpreadsheet读取Excel文件
                    $reader = IOFactory::createReader('Xlsx');
                    $reader->setReadDataOnly(true);
                    $spreadsheet = $reader->load(ROOT_PATH . 'public' . DS . 'uploads'.'/excel' . DS . $filePath);
                    $worksheet = $spreadsheet->getActiveSheet();//获取excel中的活动表
                    $highestRow = $worksheet->getHighestRow(); // 总行数
                    $highestColumn = $worksheet->getHighestColumn(); // 总列数
                    $highestColumnIndex = Coordinate::columnIndexFromString($highestColumn); // 转换为数字索引
                    $lines = $highestRow - 1; // 减1是因为Excel的行号从1开始,实际数据行应从第2行开始计算
                    if ($lines <= 0) {
                        $this->error('Excel表格中没有数据!');
                    } else {
                        // 这里可以添加读取每行数据的逻辑,例如:
                        $rowData = []; // 初始化二维数组,在外部循环之前定义

                        for ($row = 2; $row <= $highestRow; ++$row) {
                            // 为每一行初始化一个新的数据数组
                            $currentRowData = [];

                            for ($col = 1; $col <= $highestColumnIndex; ++$col) {
                                // 使用较新的 getCell() 方法,但首先确认您的PhpSpreadsheet版本
                                $cellAddress = Coordinate::stringFromColumnIndex($col) . $row; // 转换列索引为列字母
                                $cell = $worksheet->getCell($cellAddress);
                                $currentRowData[] = $cell->getValue(); // 将当前单元格的值添加到该行数据中
                            }
                            // 将当前行的所有数据作为一个数组添加到 rowData
                            $rowData[] = $currentRowData;
                        }
                        // 现在,$rowData 是一个二维数组,每个内部数组代表一行的数据
//                        return json_encode($rowData); // 打印出来检查结果
                        //将二维数组转换为键值对的数据,姓名:mmm,语文:23
//                        foreach($rowData as $key=>$value){
//                            foreach ($rowData[])
//                        }
                        $newData = [];
                        foreach($rowData as $row){
                            $newRow = ['name' => $row[0], 'chinese' => $row[1],'math'=>$row[2],'english'=>$row[3]];
                            $newData[] = $newRow;
                        }
                        $data = model('student')->insertAll($newData);
                        if ($data){
                            return json_encode(['code'=>200,'msg'=>'Excel数据导入成功!']);
                        }
                    }
                } catch (\Exception $e) {
                    return "导入失败";
                };
            }
        }
    }

导出数据

从数据库导出数据
思路:通过sql语句查询数据,转化成二维数组,二维数组之后按照foreach循环将数据按照要求传入excel表

实例化excel表格

//导出数据,第一步,导出数据库,第二部通过数据库导出成excel数据
    public function downexcel()
    {

        //设置表数据
        $spreadsheet = new Spreadsheet();
        $worksheet = $spreadsheet->getActiveSheet();
        //设置工作表标题名称
        $worksheet->setTitle('学生成绩表');
        //将其存入excel表
        //表头
        设置单元格内容
        $worksheet->setCellValue('A1',  '学生成绩表');
        $worksheet->setCellValue('A2','姓名');
        $worksheet->setCellValue('B2',  '语文');
        $worksheet->setCellValue('C2',  '数学');
        $worksheet->setCellValue('D2', '外语');
        $worksheet->setCellValue('E2',  '总分');
        //合并单元格
        $worksheet->mergeCells('A1:E1');

        $styleArray = [
            'font' => [
                'bold' => true
            ],
            'alignment' => [
                'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
            ],
        ];
        //设置单元格样式
        $worksheet->getStyle('A1')->applyFromArray($styleArray)->getFont()->setSize(28);
        $worksheet->getStyle('A2:E2')->applyFromArray($styleArray)->getFont()->setSize(14);

查询数据库数据,并按要求写入数据库

$db = Db::query('select id,name,chinese,math,english from fa_student');
     $len = count($db);
     $j = 0;
     for($i=0;$i<$len;$i++){
         $j = $i+3;//从第三行开始
         $data = $db[$i];
         $worksheet->setCellValue('A'.$j,$data['name']);//A3,第一行
         $worksheet->setCellValue('B'.$j,$data['chinese']);//A3,第一行
         $worksheet->setCellValue('C'.$j,$data['math']);//A3,第一行
         $worksheet->setCellValue('D'.$j,$data['english']);//A3,第一行
         $worksheet->setCellValue('E'.$j,$data['chinese'] + $data['math'] + $data['english']);//
     }

设置excel格的式

 //设置外边框
      $styleArrayBody = [
          'borders' => [
              'allBorders' => [
                  'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
                  'color' => ['argb' => '666666'],
              ],
          ],
          'alignment' => [
              'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
          ],
      ];
      $total_rows = $len + 2;
//添加所有边框/居中
      $worksheet->getStyle('A1:E'.$total_rows)->applyFromArray($styleArrayBody);

打印数据

       //保存数据并使用浏览器打印出来
//        $filename = '成绩表.xlsx';
//        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
//        header('Content-Disposition: attachment;filename="'.$filename.'"');
//        header('Cache-Control: max-age=0');
//        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
        //这行代码会将生成的Excel文件内容直接输出到HTTP响应体中,这意味着它将作为下载的形式提供给客户端(比如浏览器),或者如果是在命令行脚本中运行,则会输出到标准输出流。
//        $writer->save('php://output');//如果不需要浏览器打开就保存excel文件的话,请注释掉这行代码

        //保存数据直接保存为excel,好像没啥区别
        $filename = '成绩表.xlsx';
        header('Content-Type: application/vnd.ms-excel');
        header('Content-Disposition: attachment;filename="'.$filename.'"');
        header('Cache-Control: max-age=0');
        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save('php://output');
    }

完整代码

    //导出数据,第一步,导出数据库,第二部通过数据库导出成excel数据
    public function downexcel()
    {

        //设置表数据
        $spreadsheet = new Spreadsheet();
        $worksheet = $spreadsheet->getActiveSheet();
        //设置工作表标题名称
        $worksheet->setTitle('学生成绩表');
        //将其存入excel表
        //表头
        设置单元格内容
        $worksheet->setCellValue('A1',  '学生成绩表');
        $worksheet->setCellValue('A2','姓名');
        $worksheet->setCellValue('B2',  '语文');
        $worksheet->setCellValue('C2',  '数学');
        $worksheet->setCellValue('D2', '外语');
        $worksheet->setCellValue('E2',  '总分');
        //合并单元格
        $worksheet->mergeCells('A1:E1');

        $styleArray = [
            'font' => [
                'bold' => true
            ],
            'alignment' => [
                'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
            ],
        ];
        //设置单元格样式
        $worksheet->getStyle('A1')->applyFromArray($styleArray)->getFont()->setSize(28);
        $worksheet->getStyle('A2:E2')->applyFromArray($styleArray)->getFont()->setSize(14);
        $db = Db::query('select id,name,chinese,math,english from fa_student');
        $len = count($db);
        $j = 0;
        for($i=0;$i<$len;$i++){
            $j = $i+3;//从第三行开始
            $data = $db[$i];
            $worksheet->setCellValue('A'.$j,$data['name']);//A3,第一行
            $worksheet->setCellValue('B'.$j,$data['chinese']);//A3,第一行
            $worksheet->setCellValue('C'.$j,$data['math']);//A3,第一行
            $worksheet->setCellValue('D'.$j,$data['english']);//A3,第一行
            $worksheet->setCellValue('E'.$j,$data['chinese'] + $data['math'] + $data['english']);//
        }

        //设置外边框
        $styleArrayBody = [
            'borders' => [
                'allBorders' => [
                    'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
                    'color' => ['argb' => '666666'],
                ],
            ],
            'alignment' => [
                'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
            ],
        ];
        $total_rows = $len + 2;
//添加所有边框/居中
        $worksheet->getStyle('A1:E'.$total_rows)->applyFromArray($styleArrayBody);

        //保存数据并使用浏览器打印出来
//        $filename = '成绩表.xlsx';
//        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
//        header('Content-Disposition: attachment;filename="'.$filename.'"');
//        header('Cache-Control: max-age=0');
//        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
        //这行代码会将生成的Excel文件内容直接输出到HTTP响应体中,这意味着它将作为下载的形式提供给客户端(比如浏览器),或者如果是在命令行脚本中运行,则会输出到标准输出流。
//        $writer->save('php://output');//如果不需要浏览器打开就保存excel文件的话,请注释掉这行代码

        //保存数据直接保存为excel,好像没啥区别
        $filename = '成绩表.xlsx';
        header('Content-Type: application/vnd.ms-excel');
        header('Content-Disposition: attachment;filename="'.$filename.'"');
        header('Cache-Control: max-age=0');
        $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save('php://output');
    }

原作者连接
https://blog.youkuaiyun.com/ice_mocha/article/details/116460057
更详细

<think>我们参考了提供的引用内容,特别是引用[1]到[5],这些引用主要讨论了在Yii2框架中使用不同的扩展(如PHPExcelPhpSpreadsheet)来实现Excel导入导出功能,并提到了处理大量数据时可能遇到的内存问题以及解决方案。用户需求:使用Yii2框架实现Excel文件的批量导入和导出功能。根据引用内容,我们可以总结出两种主要的实现方式:1.使用moonlandsoft/yii2-phpexcel扩展(基于PHPExcel,但注意PHPExcel已不再维护,推荐使用PhpSpreadsheet替代)2.使用PhpSpreadsheet(PHPExcel的升级版)结合Yii2。考虑到PHPExcel已经停止更新,而PhpSpreadsheet是当前活跃维护的项目,我们推荐使用PhpSpreadsheet。实现步骤:一、安装PhpSpreadsheet可以通过Composer安装PhpSpreadsheet:``` composerrequire phpoffice/phpspreadsheet```二、导入Excel文件1.创建一个模型(例如UploadForm)来处理文件上传。2.在控制器中编写导入逻辑,使用PhpSpreadsheet读取上传的Excel文件,解析数据并处理(如存入数据库)。3.注意:对于大量数据的导入,应该采用分批次读取和写入数据库的方式,避免内存溢出。三、导出Excel文件1.在控制器中编写导出逻辑,使用PhpSpreadsheet创建Excel文件,将数据写入。2.对于大量数据的导出,同样需要考虑内存问题。解决方案可以是分批从数据库读取数据并写入Excel,或者使用缓存(如CSV格式)然后提供下载。四、处理大量数据引用[3]提到,使用yii的batch方法(例如batch()或each())来分批处理数据,避免一次性加载所有数据到内存。下面我们分别给出导入和导出的示例代码:导入示例(假设我们有一个模型`Item`,需要将Excel中的数据导入到item表中):1.创建上传表单模型(UploadForm):```phpnamespace app\models; useyii\base\Model; useyii\web\UploadedFile;class UploadForm extendsModel{/*** @var UploadedFile*/public $file;publicfunction rules(){return [[['file'], 'file','skipOnEmpty' =>false,'extensions'=> 'xlsx, xls'],];}} ```2.在控制器中编写导入动作: ```phpuse app\models\UploadForm;use PhpOffice\PhpSpreadsheet\IOFactory; useyii\web\UploadedFile;use Yii;public functionactionImport() {$model =new UploadForm();if(Yii::$app->request->isPost){$model->file= UploadedFile::getInstance($model,'file');if ($model->validate()){$inputFileName =$model->file->tempName;$spreadsheet =IOFactory::load($inputFileName);$sheetData= $spreadsheet->getActiveSheet()->toArray(null,true,true,true);//假设第一行是标题,从第二行开始读取数据for ($i =2; $i <=count($sheetData); $i++){$row= $sheetData[$i];//这里根据你的表格结构解析$row,例如:$item =new Item();$item->name= $row['A'];$item->price =$row['B'];// ...其他属性赋值$item->save();}Yii::$app->session->setFlash('success', '导入成功!');return$this->redirect(['index']);}}return$this->render('import', ['model'=> $model]);} ```注意:上面的导入示例是简单的一次性导入,对于大量数据,我们不应该在一个请求中处理所有行,而应该使用队列或者分步导入(例如每次处理100行,然后刷新页面继续处理下一批)。但是,更好的做法是使用命令行后台任务来处理大量数据导入。导出示例(导出所有Item数据到Excel): ```phpuse PhpOffice\PhpSpreadsheet\Spreadsheet; usePhpOffice\PhpSpreadsheet\Writer\Xlsx;use yii\data\ActiveDataProvider; publicfunction actionExport(){$dataProvider =new ActiveDataProvider(['query' =>Item::find(),'pagination'=> false, //导出所有数据,不分页]);$spreadsheet =new Spreadsheet();$sheet =$spreadsheet->getActiveSheet();//设置标题行$sheet->setCellValue('A1', 'ID');$sheet->setCellValue('B1', '名称');$sheet->setCellValue('C1', '价格');//...其他标题$row=2;foreach($dataProvider->getModels() as$item) {$sheet->setCellValue('A'. $row,$item->id);$sheet->setCellValue('B' .$row, $item->name);$sheet->setCellValue('C'. $row,$item->price);// ...其他列$row++;}$writer =new Xlsx($spreadsheet);$filename ='items_export_'. date('YmdHis') .'.xlsx';header('Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');header('Content-Disposition:attachment;filename="' .$filename. '"');header('Cache-Control: max-age=0');$writer->save('php://output');exit; }```但是,如果数据量非常大,上面的导出代码可能会导致内存不足。我们可以采用分批写入的方式,或者使用PhpSpreadsheet的缓存功能(例如使用SQLite或Memcache)来减少内存占用。另外,也可以考虑将数据导出为CSV格式,因为CSV是文本格式,占用内存少。大量数据导出优化(使用分批查询):```phppublicfunction actionExport(){//设置脚本执行时间和内存set_time_limit(0);ini_set('memory_limit','512M');$spreadsheet =new Spreadsheet();$sheet =$spreadsheet->getActiveSheet();//设置标题行$sheet->setCellValue('A1', 'ID');$sheet->setCellValue('B1', '名称');$sheet->setCellValue('C1', '价格');$row=2;//分批获取数据,每次1000条$batchSize =1000;$query =Item::find();$count =$query->count();$totalBatches =ceil($count /$batchSize);for($batch=0;$batch< $totalBatches;$batch++) {$items =$query->offset($batch* $batchSize)->limit($batchSize)->all();foreach($itemsas $item){$sheet->setCellValue('A' .$row, $item->id);$sheet->setCellValue('B'. $row,$item->name);$sheet->setCellValue('C' .$row, $item->price);$row++;}//每处理完一批,可以释放内存(但注意PhpSpreadsheet内部可能已经缓存了数据)unset($items);}//输出$writer =new Xlsx($spreadsheet);$filename ='items_export_' .date('YmdHis'). '.xlsx';header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');header('Content-Disposition: attachment;filename="'. $filename .'"');header('Cache-Control:max-age=0');$writer->save('php://output');exit;} ```另外,引用[3]提到使用yii的batch方法,我们也可以这样写(使用each()): ```php$query= Item::find(); $row=2;foreach ($query->each(1000) as$item) {$sheet->setCellValue('A'. $row,$item->id);$sheet->setCellValue('B' .$row, $item->name);$sheet->setCellValue('C'. $row,$item->price);$row++; }```这样each方法会每次从数据库取1000条,然后逐条处理,处理完一批再取下一批,内存中只保持1000条记录。总结:1.导入:使用PhpSpreadsheet读取上传的Excel文件,然后分批将数据存入数据库。2.导出:使用PhpSpreadsheet创建Excel文件,分批从数据库读取数据并写入Excel,最后输出文件。注意事项:-文件上传时注意服务器临时目录的权限和大小限制。 -处理大量数据时,建议使用命令行任务或队列,避免Web请求超时。-导出大量数据时,除了分批读取,还可以考虑使用CSV格式,因为CSV格式更节省内存。以上就是在Yii2中实现Excel批量导入导出的基本方法。根据用户需求,我们生成了以下相关问题:§§相关问题§§1.在Yii2中如何处理Excel导入时的数据验证?2.如何优化Yii2中大量数据导出到Excel的性能? 3.除了PhpSpreadsheet,Yii2还有哪些常用的Excel处理扩展?4.在Yii2中如何实现Excel模板的导出(例如带有样式和公式的模板)?5.如何将Excel导入的数据与Yii2模型中的关联关系(如一对多)一起保存?</think>### Yii2 实现 Excel 批量导入导出方法 在 Yii2 中实现 Excel 批量导入导出功能,推荐使用 **PhpSpreadsheet**(PHPExcel 的现代替代品),以下是完整实现方案: --- ### 一、环境准备 1. **安装扩展**(通过 Composer): ```bash composer require phpoffice/phpspreadsheet composer require yiisoft/yii2-httpclient # 可选,用于优化大文件处理 ``` 2. **配置模型**(示例模型): ```php // models/ImportForm.php namespace app\models; use yii\base\Model; use yii\web\UploadedFile; class ImportForm extends Model { public $excelFile; public function rules() { return [ [['excelFile'], 'file', 'extensions' => 'xlsx, xls', 'maxSize' => 1024*1024*10], // 10MB限制 ]; } } ``` --- ### 二、批量导入实现 #### 控制器代码 ```php // controllers/ExcelController.php use app\models\ImportForm; use PhpOffice\PhpSpreadsheet\IOFactory; public function actionImport() { $model = new ImportForm(); if (Yii::$app->request->isPost) { $model->excelFile = UploadedFile::getInstance($model, 'excelFile'); if ($model->validate()) { $inputFileName = $model->excelFile->tempName; $spreadsheet = IOFactory::load($inputFileName); $sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true); // 批量处理数据(示例) $batchSize = 100; // 每批处理100条 $rows = array_slice($sheetData, 1); // 跳过标题行 foreach (array_chunk($rows, $batchSize) as $batch) { $transaction = Yii::$app->db->beginTransaction(); try { foreach ($batch as $row) { // 创建模型并保存(示例) $item = new Item(); $item->name = $row['A']; $item->price = $row['B']; $item->save(); } $transaction->commit(); } catch (\Exception $e) { $transaction->rollBack(); Yii::$app->session->setFlash('error', '导入失败: '.$e->getMessage()); } } Yii::$app->session->setFlash('success', '成功导入 '.count($rows).' 条数据'); } } return $this->render('import', ['model' => $model]); } ``` #### 视图文件 ```php // views/excel/import.php <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?> <?= $form->field($model, 'excelFile')->fileInput() ?> <button>批量导入</button> <?php ActiveForm::end() ?> ``` --- ### 三、批量导出实现 #### 控制器代码(支持大数据量) ```php public function actionExport() { $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); // 设置标题行 $sheet->setCellValue('A1', 'ID'); $sheet->setCellValue('B1', '产品名称'); $sheet->setCellValue('C1', '价格'); // 分批获取数据(避免内存溢出) $query = Item::find(); $rowIndex = 2; foreach ($query->batch(500) as $items) { foreach ($items as $item) { $sheet->setCellValue('A'.$rowIndex, $item->id); $sheet->setCellValue('B'.$rowIndex, $item->name); $sheet->setCellValue('C'.$rowIndex, $item->price); $rowIndex++; } // 每批处理后释放内存 unset($items); } // 生成文件 header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="products_'.date('Ymd').'.xlsx"'); $writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); $writer->save('php://output'); exit; } ``` --- ### 四、性能优化技巧 1. **内存优化**: ```php // 在导出前添加 \PhpOffice\PhpSpreadsheet\Settings::setCache(new \PhpOffice\PhpSpreadsheet\Cache\FilesystemPool()); ``` 2. **大文件处理**: - 导入:使用 `$spreadsheet->getSheet(0)->getRowIterator()` 逐行读取 - 导出:使用 `chunk()` 或 `batch()` 分批查询数据库 3. **队列处理**(超大数据量): ```php // 将导入任务推入队列 Yii::$app->queue->push(new ImportJob([ 'filePath' => '/tmp/import.xlsx' ])); ``` --- ### 五、常见问题解决 1. **内存溢出**: - 修改 `php.ini`:`memory_limit = 512M` - 使用 `batch()` 分批处理数据 2. **中文乱码**: ```php // 导出前设置编码 $sheet->setCellValue('A1', mb_convert_encoding('产品名称', 'UTF-8', 'auto')); ``` 3. **超时处理**: ```php set_time_limit(0); // 取消脚本执行时间限制 ``` > **提示**:对于超过 10 万行的数据集,建议导出为 CSV 格式,效率更高[^3][^5]。 --- ### 六、扩展推荐 1. [moonlandsoft/yii2-phpexcel](https://github.com/moonlandsoft/yii2-phpexcel) - 简化操作的扩展包 2. [yii2tech/spreadsheet](https://github.com/yii2tech/spreadsheet) - 专业数据导入导出解决方案 --- ### 示例文件结构 ``` controllers/ ExcelController.php models/ ImportForm.php Item.php views/ excel/ import.php config/ web.php (添加路由规则) ``` 在 `config/web.php` 中添加: ```php 'components' => [ // ... ], 'params' => [...], ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值