本章介绍基于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