php PhpOffice\PhpSpreadsheet 导出多sheet 文件
有期待,才有动力。
有时候,需求要求在导出excel 生成的xls文件同一个文件中,需要包含多个sheet 的excel文件,之前的都是一个sheet工作区间的,所以现在就花点时间来研究一下
例如
希望能给那些需要的伙伴点提示或者帮助
不多说,直接上代码了,都懂的,我是在Core/extend 里面进行生成了类文件
<?php namespace core\extend; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; /** * 导出扩展开发 * Class MyExcelExtend * @package core\extend * @author Dada * @time 20220516 */ class MyExcelExtend { /** * [举列子数据格式] * @author Dada * @time 2022-05-16 * @return [type] [description] */ public function test() { $data = [ [ 'sheet_name'=>'sheet_1', 'header_title' => ['测试1-1', '测试1-2'], 'data' => [ ], ], [ 'sheet_name'=>'sheet_2', 'header_title' => ['测试2-1', '测试2-2'], 'data' => [ ['11-11', '11-11'], ['22-11', '22-11'], ], ], ]; $this->myExport($data, 'my_test'); } /** * [导出方法] * @author Dada * @time 2022-05-16 * @param array $data [参照上面的test构造数据] * @param string $fileName [文件名] * @return [type] [description] */ public function myExport($data = [], $fileName = '') { if( empty($fileName) ) { $fileName = date('Y-m-d H:i:s'); } $spreadsheet = new Spreadsheet(); // 数据进行处理 foreach ($data as $key => $val) { $this->createSheet($spreadsheet,$key,$val); } // 输出头 header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx"'); header('Cache-Control: max-age=0'); $writer = new Xlsx($spreadsheet); $writer->save('php://output'); //删除清空 $spreadsheet->disconnectWorksheets(); unset($spreadsheet); exit; } /** * [编辑sheet] * @author Dada * @time 2022-05-16 * @param [type] $spreadsheet [spreadsheet对象] * @param [type] $sheetIndex [description] * @param array $data [数据] * @return [type] [description] */ public function createSheet($spreadsheet, $sheetIndex, $data = []) { $spreadsheet->createSheet();//创建sheet $objActSheet = $spreadsheet->setActiveSheetIndex($sheetIndex); //设置当前的活动sheet $headerCount = count($data['header_title']); //计算数据所占的列数 $infoStart = 2; // 输出从第二行开始 $cellName = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ']; // 设置sheet 名字 $sheet = $spreadsheet->getActiveSheet($sheetIndex)->setTitle($data['sheet_name']); //设置sheet的名称 for ($j=0; $j < $headerCount; $j++) { $spreadsheet->getActiveSheet($sheetIndex)->getStyle($cellName[$j])->getAlignment()->setHorizontal('center'); //居中 $spreadsheet->getActiveSheet($sheetIndex)->getColumnDimension($cellName[$j])->setWidth(20); // 宽度 } // 导出内容 foreach ($data['data'] as $key => $item) { //循环设置单元格 for ($i = 65; $i < $headerCount + 65; $i++) { //数字转字母从65开始: $sheet->setCellValue(strtoupper(chr($i)) . ($key+"$infoStart"), $item[$i - 65]); // $spreadsheet->getActiveSheet($sheetIndex)->getColumnDimension(strtoupper(chr($i)))->setWidth(20); //固定列宽 } } // 导出头部 foreach ($data['header_title'] as $key => $title) { $spreadsheet->getActiveSheet($sheetIndex)->setCellValue($cellName[$key].'1', $title); // $sheet->getActiveSheet($sheetIndex)->setWidth(20); } } }
第二版优化,之前只能针对从0开始的索引数组,进行了优化,也可以针对关联数组,你发现了吗?
<?php namespace core\extend; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; /** * 导出扩展开发 * Class MyExcelExtend * @package core\extend * @author Dada * @time 20220516 */ class MyExcelExtend { /** * [举列子数据格式] * @author Dada * @time 2022-05-16 * @return [type] [description] */ public function test() { $data = [ [ 'sheet_name'=>'sheet_1', 'header_title' => ['测试1-1', '测试1-2'], 'data' => [ ], ], [ 'sheet_name'=>'sheet_2', 'header_title' => ['测试2-1', '测试2-2'], 'data' => [ ['11-11', '11-11'], ['22-11', '22-11'], ], ], ]; $this->myExport($data, 'my_test'); } /** * [导出方法] * @author Dada * @time 2022-05-16 * @param array $data [参照上面的test构造数据] * @param string $fileName [文件名] * @return [type] [description] */ public function myExport($data = [], $fileName = '') { if( empty($fileName) ) { $fileName = date('Y-m-d H:i:s'); } $spreadsheet = new Spreadsheet(); // 数据进行处理 foreach ($data as $key => $val) { $this->createSheet($spreadsheet,$key,$val); } // 输出头 header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx"'); header('Cache-Control: max-age=0'); $writer = new Xlsx($spreadsheet); $writer->save('php://output'); //删除清空 $spreadsheet->disconnectWorksheets(); unset($spreadsheet); exit; } /** * [编辑sheet] * @author Dada * @time 2022-05-16 * @param [type] $spreadsheet [spreadsheet对象] * @param [type] $sheetIndex [description] * @param array $data [数据] * @return [type] [description] */ public function createSheet($spreadsheet, $sheetIndex, $data = []) { $spreadsheet->createSheet(); // 对象 $objActSheet = $spreadsheet->setActiveSheetIndex($sheetIndex); //设置当前的活动sheet $headerCount = count($data['header_title']); //计算数据所占的列数 $infoStart = 2; // 输出从第二行开始 $cellName = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ']; // 设置sheet 名字 $sheet = $spreadsheet->getActiveSheet($sheetIndex)->setTitle($data['sheet_name']); //设置sheet的名称 for ($j=0; $j < $headerCount; $j++) { $spreadsheet->getActiveSheet($sheetIndex)->getStyle($cellName[$j])->getAlignment()->setHorizontal('center'); //居中 $spreadsheet->getActiveSheet($sheetIndex)->getColumnDimension($cellName[$j])->setWidth(20); // 宽度 } // 导出内容 foreach ($data['data'] as $key => $item) { // 关联数据进行处理 - add if( array_keys($item) !== range(0, count($item) - 1) ) { $item = array_values($item); } //循环设置单元格 for ($i = 65; $i < $headerCount + 65; $i++) { //数字转字母从65开始: $sheet->setCellValue(strtoupper(chr($i)) . ($key+"$infoStart"), $item[$i - 65]); // $spreadsheet->getActiveSheet($sheetIndex)->getColumnDimension(strtoupper(chr($i)))->setWidth(20); //固定列宽 } } // 导出头部 foreach ($data['header_title'] as $key => $title) { $spreadsheet->getActiveSheet($sheetIndex)->setCellValue($cellName[$key].'1', $title); // $sheet->getActiveSheet($sheetIndex)->setWidth(20); } } }
第三版优化,在第二版代码运行的时候,如果导出的字段超过26个,就会出现问题,chr($i) 这个逻辑就有问题,所以进行了修改
<?php namespace core\extend; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; /** * 导出扩展开发 * Class MyExcelExtend * @package core\extend * @author Dada * @time 20220516 */ class MyExcelExtend { /** * [举列子数据格式] * @author Dada * @time 2022-05-16 * @return [type] [description] */ public function test() { $data = [ [ 'sheet_name'=>'sheet_1', 'header_title' => ['测试1-1', '测试1-2'], 'data' => [ ], ], [ 'sheet_name'=>'sheet_2', 'header_title' => ['测试2-1', '测试2-2'], 'data' => [ ['11-11', '11-11'], ['22-11', '22-11'], ], 'style' => [ 'C' => '@', ], ], ]; $this->myExport($data, 'my_test'); } /** * [导出方法] * @author Dada * @time 2022-05-16 * @param array $data [参照上面的test构造数据] * @param string $fileName [文件名] * @return [type] [description] */ public function myExport($data = [], $fileName = '') { if( empty($fileName) ) { $fileName = date('Y-m-d H:i:s'); } $spreadsheet = new Spreadsheet(); // 数据进行处理 foreach ($data as $key => $val) { $this->createSheet($spreadsheet,$key,$val); } // 输出头 header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx"'); header('Cache-Control: max-age=0'); $writer = new Xlsx($spreadsheet); $writer->save('php://output'); //删除清空 $spreadsheet->disconnectWorksheets(); unset($spreadsheet); exit; } /** * [编辑sheet] * @author Dada * @time 2022-05-16 * @param [type] $spreadsheet [spreadsheet对象] * @param [type] $sheetIndex [description] * @param array $data [数据] * @return [type] [description] */ public function createSheet($spreadsheet, $sheetIndex, $data = []) { $spreadsheet->createSheet(); // 对象 $objActSheet = $spreadsheet->setActiveSheetIndex($sheetIndex); //设置当前的活动sheet $headerCount = count($data['header_title']); //计算数据所占的列数 $infoStart = 2; // 输出从第二行开始 // 这个还可以动态生成 $cellName = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ']; // 设置sheet 名字 $sheet = $spreadsheet->getActiveSheet($sheetIndex)->setTitle($data['sheet_name']); //设置sheet的名称 $isStyle = false; if( isset($data['style']) ) { $isStyle = true; } for ($j=0; $j < $headerCount; $j++) { $rowIndex = $cellName[$j]; $spreadsheet->getActiveSheet($sheetIndex)->getStyle($rowIndex)->getAlignment()->setHorizontal('center'); //居中 $spreadsheet->getActiveSheet($sheetIndex)->getColumnDimension($rowIndex)->setWidth(20); // 宽度 // 如果存在样式 if( $isStyle && array_key_exists($rowIndex, $data['style']) ) { $spreadsheet->getActiveSheet($sheetIndex)->getStyle($rowIndex)->getNumberFormat()->setFormatCode($data['style'][$rowIndex]); } } $cellIndex = ''; // 导出内容 foreach ($data['data'] as $key => $item) { // 关联数据进行处理 - add if( array_keys($item) !== range(0, count($item) - 1) ) { $item = array_values($item); } //循环设置单元格 for ($i = 0; $i < $headerCount; $i++) { $cellIndex = $cellName[$i].($key+$infoStart); $sheet->setCellValue($cellIndex, $item[$i]); } } // 导出头部 foreach ($data['header_title'] as $key => $title) { $spreadsheet->getActiveSheet($sheetIndex)->setCellValue($cellName[$key].'1', $title); } } }
已经通过测试,如果在运行的时候遇到问题,可以联系我,一同在研究
部分结果展示
sheet_1
sheet_2