PhpSpreadsheet安装
composer require phpoffice/phpspreadsheet
使用composer安装时一定要下载php对应的版本,下载之前使用php -v检查当前php版本
简单使用
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
// 创建Spreadsheet对象
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 动态表头
$headers = ['ID', '姓名', '性别', '职业', '新增字段', '新增字段2', '新增字段3', '新增字段4', '新增字段5', '新增字段6', '新增字段7', '新增字段8', '新增字段9', '新增字段10', '新增字段11', '新增字段12', '新增字段13', '新增字段14', '新增字段15', '新增字段16', '新增字段17', '新增字段18', '新增字段19', '新增字段20', '新增字段21', '新增字段22', '新增字段23', '新增字段24', '新增字段25', '新增字段26', '新增字段27', '新增字段28', '新增字段29', '新增字段30'];
// 动态数据
$data = [
[1, '李云龙', '男', '军人', '1427141544485854854485', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
[2, '苏乞儿', '男', '乞丐', '值2', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
[3, '周星驰', '男', '导演', '值3', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
[4, '林允儿', '女', '演员', '值4', '字段1', '字段2', '字段3', '字段4', '字段5', '字段6', '字段7', '字段8', '字段9', '字段10', '字段11', '字段12', '字段13', '字段14', '字段15', '字段16', '字段17', '字段18', '字段19', '字段20', '字段21', '字段22', '字段23', '字段24', '字段25', '字段26', '字段27', '字段28', '字段29', '字段30'],
];
// 设置表头和数据
$allData = array_merge([$headers], $data);
$sheet->fromArray($allData, null, 'A1');
// 设置表头样式
$styleArray = [
'alignment' => [
'horizontal' => 'center',
'vertical' => 'center',
],
'font' => [
'name' => '宋体',
// 'bold' => true,
// 'size' => 22
]
];
$headerRange = 'A1:' . chr(ord('A') + count($headers) - 1) . '1';
$sheet->getStyle($headerRange)
->getNumberFormat() // 先获取NumberFormat对象
->setFormatCode(NumberFormat::FORMAT_TEXT)
->applyFromArray($styleArray);
// 保存文件
$writer = new Xlsx($spreadsheet);
$writer->save('dynamic_example.xlsx');
?>
在thinkphp项目中使用
// 如果将该扩展直接安装到thinkphp6项目中提示找不到Class 'PhpOffice\\PhpSpreadsheet\\Spreadsheet' not found,将该扩展放置项目根目录的extend文件夹中(参考下图),随后打开下行代码
// require_once app()->getRootPath() . 'extend/PhpSpreadsheet/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
public function export_data($data){
// 获取所有要查询的字段和名称
$header_arr = [];
$fields_arr = [];
foreach($data['export_data'] as $key=>$val){
array_push($header_arr, $val['label']);
array_push($fields_arr, $val['field']);
}
// 文件存储目录
$public = app()->getRootPath().'public/';
$path = 'uploads/export_data/';
if(!file_exists($path)){
mkdir($path, 0777);
}
// 文件名
$res_file = $file_name . '_all.xlsx';
$finalFile = $public . $path . $res_file;
$currentRow = 1; // 当前写入行
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// 3. 计算列范围 - 安全方法
$lastColumn = Coordinate::stringFromColumnIndex(count($header_arr));
$headerRange = 'A:' . $lastColumn;
// $sheet->setTitle('Sheet1');
// 如果是第一次运行,创建新文件并写入头部
if (!file_exists($finalFile)) {
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->getStyle($headerRange)
->getNumberFormat()
->setFormatCode(NumberFormat::FORMAT_TEXT);
// 写入头部
$sheet->fromArray([$header_arr], null, 'A1');
$currentRow = 2;
// 设置表头样式
$styleArray = [
'alignment' => [
'horizontal' => 'center',
'vertical' => 'center',
],
// 'font' => [
// 'name' => '宋体',
// 'bold' => true,
// 'size' => 22
// ]
];
// $headerRange = 'A1:' . chr(ord('A') + count($header_arr) - 1) . '1';
$sheet->getStyle($headerRange)->applyFromArray($styleArray);
// 保存文件
$writer = new Xlsx($spreadsheet);
$writer->save($finalFile);
// echo "创建新文件并写入头部\n";
}
// 分批导出并追加数据
$totalBatches = 3; // 假设总共3批
for ($batch = 1; $batch <= $totalBatches; $batch++) {
// 加载现有文件
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($finalFile);
$sheet = $spreadsheet->getActiveSheet();
// 获取当前最后一行
$currentRow = $sheet->getHighestRow() + 1;
// 生成测试数据 - 实际应用中从数据库获取
$data = [];
$perBatch = 10000;
$start = ($batch - 1) * $perBatch + 1;
$end = $batch * $perBatch;
for ($i = $start; $i <= $end; $i++) {
$data[] = [
$i,
"姓名{$i}",
($i % 2) ? '男' : '女',
"职业{$i}"
];
}
// 追加数据
$stringContent = array_map(function($row) use ($sheet, $currentRow) {
return array_map(function($cell) {
return (string)$cell; // 只返回值,不返回类型
}, $row);
}, $data);
// 先设置数据
$sheet->fromArray($stringContent, null, "A{$currentRow}");
// 部分列强制文本格式
$forceTextColumns = ['CI', 'AQ', 'AH']; // 需要强制文本的列
for ($row = $currentRow; $row <= $highestRow; $row++) {
foreach ($forceTextColumns as $col) {
$cell = $sheet->getCell($col.$row);
$cell->setValueExplicit(
$cell->getValue(),
DataType::TYPE_STRING
);
$sheet->getStyle($col.$row)->getNumberFormat()->setFormatCode('@');
}
}
// 保存文件
$writer = new Xlsx($spreadsheet);
$writer->save($finalFile);
echo "批次 {$batch} 数据已追加到 {$finalFile} (行 {$currentRow}-" . ($currentRow + count($data) - 1) . ")\n";
}
echo "所有数据已导出到 {$finalFile}\n";
}