一、说明
1.需要安装Spreadsheet,如未安装自行composer安装即可
2.定义导出表格的表头(及键值)
3.数据内容需要与定义的表头一致
二、核心代码
try {
// 获取表格数据
$list = (new Activity())->select()->toArray();
if (!empty($list)) {
// 设置key
$key = [
['key' => 'index', 'title' => '序号'],
['key' => 'activity_name', 'title' => '名称'],
['key' => 'student_name', 'title' => '学生姓名'],
];
$sheet = new Spreadsheet();
$activeSheet = new ExcelLogic($sheet);
// 计算总列数
$allColumn = count($key);
// 计算总行数
$allRow = count($list);
// 重制表格数据,与键值对应
$newArr = [];
foreach ($list as $k => $v) {
$newArr[$k]['index'] = $k + 1;
$newArr[$k]['activity_name'] = $v['activity']['title'];
$newArr[$k]['student_name'] = $v['student']['name'];
}
// 添加表内容
for ($i = 0; $i < $allColumn; $i++) {
// 设置标题
$activeSheet->setCellsValue(1, $i + 1, $key[$i]['title'])
->setAlign(1, $i + 1)
->setrgBgColor(1, $i + 1, 1, '7f89e6')
->setFont(1, $i + 1, 1, 'ffffff')
->setBorder(1, $i + 1)
->setRowAndCol(1, $i + 1, 24, strlen($key[$i]['title']));
// 设置内容
for ($j = 0; $j < $allRow; $j++) {
$rowData = $newArr[$j][$key[$i]['key']];
$activeSheet->setCellsValue($j + 2, $i + 1, strval($rowData))
->setAlign($j + 2, $i + 1)
->setBorder($j + 2, $i + 1);
}
}
// 导出表格
$writer = IOFactory::createWriter($sheet, 'Xlsx');
//创建excel文件
$exportCache = new ExportCache();
$src = $exportCache->getSrc();
if (!file_exists($src)) {
mkdir($src, 0775, true);
}
$filename = '报名列表数据导出_' . date('YmdH') . '.xlsx';
$writer->save($src . $filename);
// 返回下载地址
}
return $this->success('', ['url' => ''], 2);
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
三、ExcelLogic类
<?php
namespace app\common\logic;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
/**
* @note Excel处理
*/
class ExcelLogic
{
// 定义sheet
private object $sheet;
// 定义当前操作工作表
private object $currentSheet;
/**
* @note 初始化
* @param object $sheet
* @param int $sheetIndex
*/
public function __construct(object $sheet, int $sheetIndex = 0)
{
$this->sheet = $sheet;
// $this->sheet = new Spreadsheet();
$this->currentSheet = $this->sheet->getActiveSheet($sheetIndex);
}
/**
* @notes 设置工作表名
* @param string $title 表名
* @return ExcelLogic
*/
public function setTitle(string $title = '模板'): ExcelLogic
{
$this->currentSheet->setTitle($title);
return $this;
}
/**
* @notes 设置字体样式
* @param int $row 行
* @param int $col 列
* @param string $fontName 字体名称
* @param string $fontSize 字体大小
* @param bool $isBold 是否加粗
* @param string $fontColor 字体颜色
* @param bool $isWrap 是否自动换行
* @param int $colSpan 列跨度
* @return ExcelLogic
*/
public function setFont(
int $row = 1,
int $col = 1,
int $colSpan = 1,
string $fontColor = '000000',
bool $isBold = false,
string $fontName = '宋体',
string $fontSize = '14',
bool $isWrap = true,
): ExcelLogic
{
$this->currentSheet->getStyleByColumnAndRow($col, $row, $col + $colSpan - 1, $row)->getFont()
->setName($fontName)
->setSize($fontSize)
->setBold($isBold)
->setColor(new Color($fontColor));
// 自动换行
$this->currentSheet->getStyleByColumnAndRow($col, $row, $col + $colSpan - 1, $row)->getAlignment()->setWrapText($isWrap);
return $this;
}
/**
* @notes 设置文字对齐方式
* @param int $row 行
* @param int $col 列
* @param string $alignHorizontal 水平对齐方式
* @param string $alignVertical 垂直对齐方式
* @return ExcelLogic
*/
public function setAlign(int $row = 1, int $col = 1, string $alignHorizontal = 'center', string $alignVertical = 'center'): ExcelLogic
{
// 水平居中
$this->currentSheet->getStyleByColumnAndRow($col, $row)->getAlignment()->setHorizontal($alignHorizontal);
// 垂直居中
$this->currentSheet->getStyleByColumnAndRow($col, $row)->getAlignment()->setVertical($alignVertical);
return $this;
}
/**
* @notes 行高及列宽
* @param int $row 行
* @param int $col 列
* @param int $rowHeight 行高
* @param int $colWidth 列宽
* @return ExcelLogic
*/
public function setRowAndCol(int $row = 1, int $col = 1, int $rowHeight = 24, int $colWidth = 20): ExcelLogic
{
// 设置行高
$this->currentSheet->getRowDimension($row)->setRowHeight($rowHeight);
$this->currentSheet->getColumnDimensionByColumn($col)->setWidth($colWidth);
return $this;
}
/**
* @notes 设置边框
* @param int $row 开始行
* @param int $col 开始列
* @param int $colSpan 列合并数
* @param string $borderStyle 边框样式
* @param string $borderColor 边框颜色
* @return ExcelLogic
*/
public function setBorder(
int $row = 1,
int $col = 1,
int $colSpan = 1,
string $borderStyle = 'thin',
string $borderColor = '000000'
): ExcelLogic
{
// 设置边框样式
$this->currentSheet->getStyleByColumnAndRow($col, $row, $col + $colSpan - 1, $row)->getBorders()
->getallBorders()
->setBorderStyle($borderStyle)->setColor(new Color($borderColor));
return $this;
}
/**
* @notes 设置背景色
* @param int $row 开始行
* @param int $col 开始列
* @param int $colSpan 列合并数
* @param string $bgColor 背景色
* @return ExcelLogic
*/
public function setrgBgColor(int $row = 1, int $col = 1, int $colSpan = 1, string $bgColor = 'ffffff'): ExcelLogic
{
// 设置背景色
$this->currentSheet->getStyleByColumnAndRow($col, $row, $col + $colSpan - 1, $row)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB($bgColor);
return $this;
}
/**
* @notes 设置单元格内容
* @param int $row 行
* @param int $col 列
* @param string $title 表头名称
* @param int $dataRow 内容
* @param string|int $data 内容
* @return ExcelLogic
*/
public function setCellValue(
int $row = 1,
int $col = 1,
string $title = '序号',
string|int $data = '',
int $dataRow = 0,
): ExcelLogic
{
// 设置表头
$this->currentSheet->setCellValueByColumnAndRow($col, $row, $title);
// 设置内容
if ($dataRow == 0) $dataRow = $row + 1;
$this->currentSheet->setCellValueByColumnAndRow($col, $dataRow, $data);
return $this;
}
/**
* @notes 设置单元格内容
* @param int $row 行
* @param int $col 列
* @param string $data 内容
* @return ExcelLogic
*/
public function setCellsValue(
int $row = 1,
int $col = 1,
string $data = '',
): ExcelLogic
{
// 设置内容
$this->currentSheet->setCellValueByColumnAndRow($col, $row, $data);
return $this;
}
/**
* @notes 合并列并设置内容
* @param string $val 单元格内容
* @param int $col 开始列
* @param int $colSpan 列合并数
* @param int $row 合并行
* @param string $bgColor 背景色
* @param string $align 文字对齐
* @param string $fontColor 字体颜色
* @param string $fontSize 字体大小
* @param bool $isBold 字体粗细
* @param string $fontName 字体名称
* @param bool $isWrap 是否自动换行
* @param float $rowHeight 行高
* @return ExcelLogic
*/
public
function mergeCell(
string $val,
int $col = 1,
int $colSpan = 1,
int $row = 1,
string $bgColor = 'FFFFFF',
string $align = 'left',
string $fontColor = 'ff4040',
string $fontSize = '14',
bool $isBold = true,
string $fontName = '宋体',
bool $isWrap = true,
float $rowHeight = 60
): ExcelLogic
{
$this->currentSheet->mergeCellsByColumnAndRow($col, $row, $col + $colSpan - 1, $row);
$this->currentSheet->setCellValueByColumnAndRow($col, $row, $val);
$this->setFont($row, $col, $colSpan, $fontColor, $isBold, $fontName, $fontSize, $isWrap);
$this->setAlign($row, $col, $align);
$this->setRowAndCol($row, $col, $rowHeight);
$this->setBorder($row, $col, $colSpan);
$this->setrgBgColor($row, $col, $colSpan, $bgColor);
return $this;
}
/**
* @notes 新建工作表
* @param string $title 工作表名称
* @param int $sheetIndex 工作表序号
* @param array $tableArr 表头数组
* @param array $keys 键值数组
* @param array $dataArr 数据数组
* @return ExcelLogic
*/
public function createSheet(string $title = 'sheet1', int $sheetIndex = 1, array $tableArr = [], array $keys = [], array $dataArr = []): ExcelLogic
{
// 新建工作表
$newSheet = new Worksheet($this->sheet, $title);
$this->sheet->addSheet($newSheet, $sheetIndex);
// 计算总列数
$totalCol = count($tableArr);
$colArr = $this->getColumn($totalCol);
// 添加数据内容
for ($i = 0; $i < $totalCol; $i++) {
// 设置表头
$newSheet->setCellValue($colArr[$i] . 1, $tableArr[$i]);
for ($j = 0; $j < count($dataArr); $j++) {
// 设置内容
$newSheet->setCellValue($colArr[$i] . $j + 2, $dataArr[$j][$keys[$i]]);
}
}
return $this;
}
/**
* @notes 自动计算列数
* @param string $col
*/
public
function getColumn(int $colNumber = 1)
{
// 生成A-Z的数组
$arr = range('A', 'Z');
// 计算循环次数
$no = ceil($colNumber / count($arr));
// 定义数组
$data = [];
if ($no <= 1) {
for ($i = 0; $i < $colNumber; $i++) {
$data[] = $arr[$i];
}
} else {
for ($i = 0; $i < count($arr); $i++) {
$data[] = $arr[$i];
}
for ($i = 0; $i < $colNumber - count($arr); $i++) {
$list = (($i + count($arr)) % count($arr));
$data[] = $arr[ceil(($i + 1) / count($arr)) - 1] . $arr[$list];
}
}
return $data;
}
}