PHP基于xlswriter支持无限表头层级Excel导出

本章介绍基于PHP扩展xlswriter的Vtiful\Kernel\Excel类可以支持无限层级的复杂表头导出!
废了九牛二虎之力,终于把这个功能类写完了…后续会持续更新优化

准备xlswriter扩展
windows系统:
到PECL网站下载符合自己本地PHP环境的ddl文件下载地址,并复制到PHP的扩展目录ext文件夹下,修改php.ini文件,加上这行

 

extension=xlswriter

打开phpinfo()验证扩展是否安装成功

Linux系统:
 

pecl install xlswriter

 php配置文件添加
 

extension = xlswriter.so

重启php nginx

composer下载phpoffice/phpexcel

因为有用到单元格相关函数,所以需要执行下列命令

composer require phpoffice/phpexcel 1.8

封装导出类文件(重点来了)

  • 支持多层表头
  • 支持多Sheet
  • 支持过滤选项
  • 支持单元格格式
  • 支持单元格公式
  • 支持表头加粗
  • 支持表头斜体
  • 支持冻结表头
  • 支持插入图片
  • 支持表头居中
  • 支持锁定保护
  • 支持数据合并
  • 支持数据背景颜色
<?php
use PHPExcel_Cell;

class MultiFloorXlsWriterService
{
    // 默认宽度
    private $defaultWidth = 16;
    // 默认高度
    private $defaultHeight = 15;
    // 默认导出格式
    private $exportType = '.xlsx';
    // 表头最大层级
    private $maxHeight  = 1;
    // 文件名
    private $fileName = null;
    // 默认公式行距离数据间隔
    private $defaultFormulaTop = 2;
    // 数据占用截至行
    private $maxDataLine = 2;
    // 默认的单元格格式,常规
    private $defaultCellFormat = 'general';
    // 支持的单元格格式,可扩充
    private $allowCellFormat = [
        'general' => \PHPExcel_Style_NumberFormat::FORMAT_GENERAL,
        'text' => \PHPExcel_Style_NumberFormat::FORMAT_TEXT,
    ];
    // 支持的单元列操作-数据合并
    const CELL_ACT_MERGE = 'merge';
    // 支持的单元列操作-背景颜色
    const CELL_ACT_BACKGROUND = 'background';
    // 数据合并开始标识
    const ACT_MERGE_START = 'start';
    // 数据合并结束标识
    const ACT_MERGE_END = 'end';
    private $allowCellActs = [
        self::CELL_ACT_MERGE,
        self::CELL_ACT_BACKGROUND,
    ];
    // 单元格操作集合
    private $cellActs = [];

    private $xlsObj;
    private $fileObject;
    private $format;
    private $boldIStyle;
    private $colManage;
    private $lastColumnCode;

    public function __construct()
    {
        // 文件默认输出地址
        $path = base_path().'/storage/logs';
        $config = [
            'path' => $path
        ];

        $this->xlsObj = (new \Vtiful\Kernel\Excel($config));
    }

    /**
     * 设置文件名
     * @param string $fileName 文件名
     * @param string $sheetName 第一个sheet名
     */
    public function setFileName(string $fileName = '', string $sheetName = 'Sheet1')
    {
        $fileName = empty($fileName) ? (string)time() : $fileName;
        $fileName .= $this->exportType;

        $this->fileName = $fileName;

        $this->fileObject = $this->xlsObj->fileName($fileName, $sheetName);
        $this->format     = (new \Vtiful\Kernel\Format($this->fileObject->getHandle()));
    }

    /**
     * 设置表头
     * @param array $header
     * @throws \Exception
     */
    public function setHeader(array $header)
    {
        if (empty($header)) {
            throw new \Exception('表头数据不能为空');
        }

        if (is_null($this->fileName)) {
            self::setFileName(time());
        }

        // 获取单元格合并需要的信息
        $colManage = self::setHeaderNeedManage($header);

        // 完善单元格合并信息
        $this->colManage = self::completeColMerge($colManage);

        // 设置最后单元格标识
        $this->lastColumnCode = self::getColumn(end($this->colManage)['cursorEnd']) . $this->maxHeight;

        // 合并单元格
        self::queryMergeColumn();
    }

    /**
     * 填充文件数据
     * @param array $data
     * @throws \Exception
     */
    public function setData(array $data)
    {
        // 起始行
        $indexRow = $this->maxHeight + 1;
        // 起始列
        $indexCol = 0;
        foreach ($data as $row => $datum) {
            foreach ($datum as $column => $value) {
                // 列值为数组,说明有额外操作
                if (is_array($value)) {
                    $val = $value[0];
                    $act = $value[1];
                    $pos = self::getColumn($indexCol) . $indexRow;
                    // 有效行为
                    $availableActs = array_intersect($this->allowCellActs, array_keys($act));
                    foreach ($availableActs as $availableAct) {
                        switch ($availableAct) {
                            case self::CELL_ACT_MERGE:
                                // 数据合并
                                $this->cellActs[$indexCol][self::CELL_ACT_MERGE][$act[$availableAct]] = $pos;
                                $this->cellActs[$indexCol][self::CELL_ACT_MERGE]['val'] = $val;
                                break;
                            case self::CELL_ACT_BACKGROUND:
                                // 背景颜色
                                $this->cellActs[$indexCol][self::CELL_ACT_BACKGROUND][] = [
                                    'row'    => $row,
                                    'column' => $column,
                                    'color'  => $act[$availableAct],
                                    'val'    => $val
                                ];
                                break;
                            default:
                                throw new \Exception('不支持的单元格操作['. $availableAct .']');
                        }
                    }
                } else {
                    $this->fileObject->insertText($row + $this->maxHeight, $column, $value);
                }
                $indexCol++;
            }
            $indexRow++;
            $indexCol = 0;
        }
        // 执行单元格操作
        self::queryCellActs();
        $this
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值