SchoolPhysicalExamination/application/download/controller/Excel.php

223 lines
8.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\download\controller;
use think\Controller;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
class Excel extends Controller
{
// public function exportWithCustomStyle()
// {
// $data = [
// ['订单号', '客户名称', '订单金额', '下单日期', '状态'],
// ['ORD20230001', '张三', 1580.00, '2023-05-10', '已完成'],
// ['ORD20230002', '李四', 2399.00, '2023-05-11', '已发货'],
// ['ORD20230003', '王五', 899.00, '2023-05-12', '待付款'],
// ];
// $options = [
// 'sheet_title' => '五月订单', // 工作表名称
// 'header_style' => [
// 'font' => [
// 'bold' => true,
// 'color' => ['argb' => 'FFFFFFFF'] // 白色文字
// ],
// 'fill' => [
// 'fillType' => Fill::FILL_SOLID,
// 'startColor' => ['argb' => 'FF0070C0'] // 蓝色背景
// ],
// 'alignment' => [
// 'horizontal' => Alignment::HORIZONTAL_CENTER,
// ],
// ],
// 'stripe_color1' => 'FFE6F1FF', // 浅蓝色
// 'stripe_color2' => 'FFD6E6FF', // 稍深一点的蓝色
// ];
// $excel = new \app\download\controller\Excel();
// $excel->export($data, '五月订单报表', $options);
// }
/**
* 导出 Excel 文件(带斑马纹效果)
*
* @param array $data 要导出的数据,格式为二维数组,第一行为表头
* @param string $filename 下载的文件名(不带扩展名)
* @param array $options 可选配置项
* - 'sheet_title' => string 工作表标题
* - 'header_style' => array 自定义表头样式
* - 'content_style' => array 自定义内容样式
* - 'zebra_stripe' => bool 是否启用斑马纹效果默认true
* - 'stripe_color1' => string 斑马纹第一种颜色(默认白色)
* - 'stripe_color2' => string 斑马纹第二种颜色(默认浅灰色)
* - 'auto_width' => bool 是否自动调整列宽
* @return void
*/
public function export(array $data, string $filename = 'export', array $options = [])
{
// 验证数据
if (empty($data) || !is_array($data) || !is_array($data[0])) {
throw new \InvalidArgumentException('导出数据格式不正确,应为二维数组且第一行为表头');
}
// 默认配置
$defaultOptions = [
'sheet_title' => 'Sheet1',
'header_style' => [
'font' => ['bold' => true],
'fill' => [
'fillType' => Fill::FILL_SOLID,
'startColor' => ['argb' => Color::COLOR_YELLOW],
],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
'borders' => [
'outline' => ['borderStyle' => Border::BORDER_THIN],
'inside' => ['borderStyle' => Border::BORDER_THIN]
],
],
'content_style' => [
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
'borders' => [
'outline' => ['borderStyle' => Border::BORDER_THIN],
'inside' => ['borderStyle' => Border::BORDER_THIN]
],
],
'zebra_stripe' => true, // 默认启用斑马纹
'stripe_color1' => 'FFFFFFFF', // 白色
'stripe_color2' => 'FFEEEEEE', // 浅灰色
'auto_width' => true,
];
// 合并用户配置和默认配置
$options = array_merge($defaultOptions, $options);
// 创建 Spreadsheet 对象
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle($options['sheet_title']);
// 获取列数和行数
$columnCount = count($data[0]);
$rowCount = count($data);
// // 写入数据
// foreach ($data as $rowIndex => $rowData) {
// for ($colIndex = 0; $colIndex < $columnCount; $colIndex++) {
// $sheet->setCellValueByColumnAndRow($colIndex + 1, $rowIndex + 1, $rowData[$colIndex]);
// }
// }
// 修改后的代码(强制文本格式)
// use PhpOffice\PhpSpreadsheet\Cell\DataType; // 确保顶部已引入
foreach ($data as $rowIndex => $rowData) {
for ($colIndex = 0; $colIndex < $columnCount; $colIndex++) {
$cellValue = $rowData[$colIndex];
// 强制设置为文本格式
$sheet->setCellValueExplicitByColumnAndRow(
$colIndex + 1,
$rowIndex + 1,
(string)$cellValue,
DataType::TYPE_STRING
);
}
}
// 设置表头样式
$headerRange = 'A1:' . $this->getExcelColumnName($columnCount) . '1';
$sheet->getStyle($headerRange)->applyFromArray($options['header_style']);
// 设置内容样式
$contentRange = 'A2:' . $this->getExcelColumnName($columnCount) . $rowCount;
$sheet->getStyle($contentRange)->applyFromArray($options['content_style']);
// =============================================
// 重点:斑马纹效果实现
// =============================================
if ($options['zebra_stripe']) {
$this->applyZebraStripe(
$sheet,
$columnCount,
$rowCount,
$options['stripe_color1'],
$options['stripe_color2']
);
}
// 自动调整列宽
if ($options['auto_width']) {
for ($colIndex = 1; $colIndex <= $columnCount; $colIndex++) {
$sheet->getColumnDimensionByColumn($colIndex)->setAutoSize(true);
}
}
// 设置响应头以触发文件下载
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"');
header('Cache-Control: max-age=0');
// 保存并输出 Excel 文件
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
exit;
}
/**
* 应用斑马纹效果(核心实现)
*
* @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $sheet
* @param int $columnCount 总列数
* @param int $totalRows 总行数(包括表头)
* @param string $color1 第一种颜色
* @param string $color2 第二种颜色
*/
protected function applyZebraStripe($sheet, $columnCount, $totalRows, $color1, $color2)
{
// 从第二行开始应用斑马纹(跳过表头)
for ($rowIndex = 2; $rowIndex <= $totalRows; $rowIndex++) {
// 计算当前行应该使用哪种颜色
$color = ($rowIndex % 2 == 0) ? $color1 : $color2;
// 设置行样式
$rowStyle = [
'fill' => [
'fillType' => Fill::FILL_SOLID,
'startColor' => ['argb' => $color],
],
];
// 应用样式到整行
$range = 'A' . $rowIndex . ':' . $this->getExcelColumnName($columnCount) . $rowIndex;
$sheet->getStyle($range)->applyFromArray($rowStyle);
}
}
/**
* 获取 Excel 列名
*
* @param int $index 列索引从1开始
* @return string Excel 列名
*/
protected function getExcelColumnName($index)
{
$columnName = '';
while ($index > 0) {
$remainder = ($index - 1) % 26;
$columnName = chr(65 + $remainder) . $columnName;
$index = intval(($index - 1) / 26);
}
return $columnName;
}
}