- Published on
Laravel处理 excel/pdf/word 的导入导出
- Authors
- Name
- Darwin Stone
- @dustred233
背景
最近用 Laravel 处理了 Excel 的导入导出,PDF 和 Word 的导出,记录一下。
Ubuntu 20.04
Laravel 9.*
PHP 8.1
1. 导入excel
常见方案是使用 maatwebsite/excel
包,基于以前的使用经验,处理大的excel略慢,所以寻求更好的方案,找到了 xlswriter 一个PHP C 扩展。
xlswriter 安装
# 是否已安装xlswriter
php -m | grep xlswriter
# 安装pear
apt install php-pear
pecl channel-update pecl.php.net
apt install php8.1-dev
pecl install xlswriter
php --ini
vim /etc/php/8.1/cli/php.ini # 写入 extension=xlswriter.so
systemctl restart php8.1-fpm.service
#验证
php -m | grep xlswriter
xlswriter 使用
composer require viest/php-ext-xlswriter-ide-helper:dev-master
$excel = new \Vtiful\Kernel\Excel([
"path" => storage_path("/excel_folder"),
]);
$excel->openFile("your_excel_file_name.xlsx");
$excel->openSheet(); // 默认 sheet1, 解析 sheet2 则传入 sheet2名称
$excel->setSkipRows(1); // 跳过一行
$row = $excel->nextRow(); // 读取数据
// 处理数据...
2. 导出excel
需要导出的数据不多,直接使用 maatwebsite/excel。
maatwebsite/excel 安装及使用
composer require maatwebsite/excel
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
php artisan make:export YourExcelExport
生成的文件 app\Exports\YourExcelExport.php
默认 implements FromCollection
, 我习惯使用 implements FromView
, 可以自定义样式。
具体CSS属性见:https://docs.laravel-excel.com/3.1/exports/from-view.html
// 调试:调整excel样式
return view('excel_blade_name', ['data' => $data]);
// 导出
$fileName = 'export_excel_name' . date('YmdHis') . '.xlsx';
return Excel::download(new YourExcelExport($data), $fileName);
// 保存
$filePath = public_path($fileName);
Excel::store(new YourExcelExport($data), $filePath, 'local');
3. 导出pdf
3种方案:
dompdf 性能较差
spatie的 laravel-pdf要求版本较高,在本项目去适配或升级太费事
laravel-snappy 和 dompdf 是同一个作者,基于 wkhtmltopdf实现,性能较好
安装 snappy
# 安装 wkhtmltopdf
apt install wkhtmltopdf
# 注意 wkhtmltopdf 路径,不同系统可能不一样
which wkhtmltopdf
# 检查字体安装,主要是中文字体,如果未安装的话就会导致 pdf 乱码
fc-list
# 安装 dejavu
apt-get install fonts-dejavu
composer require barryvdh/laravel-snappy
php artisan vendor:publish --provider="Barryvdh\Snappy\ServiceProvider"
在 config/snappy.php
中确认 pdf.binary 的路径是否正确。
snappy使用
编辑 pdf 的模板文件
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">
* {
margin: 0;
padding: 0;
}
.pdf {
font-family: DejaVu Sans, sans-serif;
/* 设置字体 */
font-size: 12px;
/* 设置字号 */
}
</style>
<!-- CSS -->
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css">
</head>
<body>
<div class="pdf">
<table class="table table-borderless">
<!-- YOUR_TABLE_CODE -->
</table>
</div>
</body>
</html>
controller 中调用
// 调试
return view('pdf_blade_name', ['data' => $data]);
// 导出
$pdf = SnappyPdf::loadView('pdf_blade_name', ['data' => $data]);
$fileName = 'export_pdf_name.pdf';
// 如果文件名存在中文的话,下面这行取消注释
// $fileName = rawurlencode($fileName);
return $pdf->download($fileName);
// 保存
$filePath = public_path($fileName);
$pdf->save($filePath);
4. 导出word
目前貌似只有 PHPWord 这一种方案。
composer require phpoffice/phpword
基于上面 PDF 已经实现过了,所以突发奇想,以上面 pdf 或者 excel 的模板作为html来导出 word 文件。
具体操作:
// 获取 html 代码
$html_data = view('blade_view_name', ['data' => $this->data])->render();
// 转换为html
$objectWriter = IOFactory::createWriter($html_data, "HTML");
// 保存
$objectWriter->save($filePath);
// 导出
return response()->download($filePath);
// pdf 模板解析失败
// excel 模板成功导出 word 文件,但是失去了 table 样式
所以还是得自己写样式,因为有了excel处理的逻辑,就直接一格一格的填充table,没有(用模板文件的方式)[https://learnku.com/articles/42951]。
$phpWord = new PhpWord();
$section = $phpWord->addSection();
// 表格
$table = $section->addTable(['borderColor' => '666666', 'borderSize' => 6, 'cellMargin' => 50]);
// 第一行
$table->addRow();
$table->addCell(2000)->addText('cell1');
$table->addCell(3000, ['gridSpan' => 5])->addText('cell2');
$table->addCell(2000)->addText('cell3');
$table->addCell(3000, ['gridSpan' => 5])->addText('cell4');
// 合并单元格,垂直居中,首行样式
// $table->addCell(null, ['vMerge' => 'restart', 'valign' => 'center']);
// 剩余行
// $table->addCell(null, ['vMerge' => 'continue']);
5. 总结
处理 excel 最简单,word 最费事。