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

 

posted @ 2021-09-04 14:47  方达达  阅读(710)  评论(0编辑  收藏  举报