PHP 处理 Excel 文件有很多成熟的库,它们各有特点,能满足从简单导出到复杂数据处理的不同需求。下面我将为你介绍几个主流且实用的 PHP Excel 库,并提供详细的用法说明。
🧰 一、主流 PHP Excel 库对比
以下是几个主流的 PHP Excel 库的对比,帮助你根据项目需求进行选择。
🔔 选择建议:
对于新项目,强烈推荐使用 PhpSpreadsheet,它功能强大且持续更新。
如果你的项目基于 Laravel,Laravel Excel 能极大提升开发效率。
PHPExcel 仅建议用于维护旧项目。
📦 二、PhpSpreadsheet 详细用法
PhpSpreadsheet 是目前最推荐使用的 PHP 电子表格处理库,功能非常强大。
1. 安装与引入
通过 Composer 安装:
composer require phpoffice/phpspreadsheet
在脚本中引入自动加载文件:
require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\IOFactory;
2. 创建 Excel 并写入数据
// 创建一个新的 Spreadsheet 对象 $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); // 获取活动工作表 // 1. 直接设置单元格数据 $sheet->setCellValue('A1', 'Hello World!'); $sheet->setCellValue('A2', 123); $sheet->setCellValue('B2', 456); // 2. 设置一整组数据(数组) $data = [ ['姓名', '年龄', '邮箱'], ['张三', 20, 'zhangsan@example.com'], ['李四', 25, 'lisi@example.com'], ['王五', 30, 'wangwu@example.com'], ]; $sheet->fromArray($data, null, 'A4'); // 从 A4 单元格开始插入数据 // 3. 合并单元格 $sheet->mergeCells('C1:D2'); // 4. 设置单元格样式 $styleArray = [ 'font' => [ 'bold' => true, 'color' => ['rgb' => 'FF0000'], ], 'alignment' => [ 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, ], 'borders' => [ 'top' => [ 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, ], ], 'fill' => [ 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_GRADIENT_LINEAR, 'rotation' => 90, 'startColor' => [ 'argb' => 'FFA0A0A0', ], 'endColor' => [ 'argb' => 'FFFFFFFF', ], ], ]; $sheet->getStyle('A1:C1')->applyFromArray($styleArray); // 将样式应用于 A1 到 C1 的区域 // 5. 设置列宽 $sheet->getColumnDimension('A')->setWidth(20); $sheet->getColumnDimension('B')->setAutoSize(true); // 自动调整列宽 // 保存文件 $writer = new Xlsx($spreadsheet); $writer->save('hello_world.xlsx'); // 或者直接输出到浏览器下载 header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="hello_world.xlsx"'); header('Cache-Control: max-age=0'); $writer->save('php://output'); exit;
3. 读取 Excel 数据
// 1. 加载已存在的 Excel 文件 $spreadsheet = IOFactory::load('example.xlsx'); // 2. 获取工作表数量、名称 $sheetCount = $spreadsheet->getSheetCount(); $sheetNames = $spreadsheet->getSheetNames(); // 3. 获取第一个工作表 (索引 0) $worksheet = $spreadsheet->getSheet(0); // 或者通过名称获取工作表 // $worksheet = $spreadsheet->getSheetByName('Sheet1'); // 4. 获取单元格数据 $cellValue = $worksheet->getCell('A1')->getValue(); $calculatedValue = $worksheet->getCell('A1')->getCalculatedValue(); // 获取计算公式的计算结果 // 5. 获取最高行和列 $highestRow = $worksheet->getHighestRow(); $highestColumn = $worksheet->getHighestColumn(); // 6. 循环读取所有数据(逐行) $data = []; for ($row = 1; $row <= $highestRow; $row++) { $rowData = []; // 假设我们读取到第 Z 列 for ($col = 'A'; $col <= 'Z'; $col++) { $cell = $worksheet->getCell($col . $row); $rowData[] = $cell->getValue(); } $data[] = $rowData; } // 7. 或者使用更方便的方法转换为数组(注意空单元格) $data = $worksheet->toArray(); // 打印读取的数据 print_r($data);
4. 处理公式、图片和图表
PhpSpreadsheet 支持复杂的操作,如公式、图片和图表。
// 1. 设置公式 $sheet->setCellValue('D2', '=SUM(B2:C2)'); // 在 D2 单元格设置求和公式 // 2. 添加图片 $drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing(); $drawing->setName('Logo'); $drawing->setDescription('Logo'); $drawing->setPath('./path/to/logo.jpg'); // 图片路径 $drawing->setHeight(36); $drawing->setCoordinates('C1'); // 将图片放置在 C1 单元格附近 $drawing->setWorksheet($sheet); // 3. 创建图表(示例:柱状图) $dataSeriesLabels = [ new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues('String', 'Worksheet!$B$1', null, 1), // 标签 ]; $xAxisTickValues = [ new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues('String', 'Worksheet!$A$2:$A$5', null, 4), // X轴数据 ]; $dataSeriesValues = [ new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues('Number', 'Worksheet!$B$2:$B$5', null, 4), // Y轴数据 ]; $series = new \PhpOffice\PhpSpreadsheet\Chart\DataSeries( \PhpOffice\PhpSpreadsheet\Chart\DataSeries::TYPE_BARCHART, // 图表类型 null, // 绘制类型 range(0, count($dataSeriesValues) - 1), // 数据系列顺序 $dataSeriesLabels, // 标签 $xAxisTickValues, // X轴数据 $dataSeriesValues // Y轴数据 ); $chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart( 'chart1', // 图表名称 new \PhpOffice\PhpSpreadsheet\Chart\Title('My Chart'), // 标题 null, // X轴标题 null, // Y轴标题 null, // 布局 null, // 图例 null, // X轴 null, // Y轴 null // 网格线 ); $chart->addSeries($series); // 将图表添加到工作表 $sheet->addChart($chart);
🛠️ 三、从数据库生成 Excel
一个常见的场景是将数据库中的数据导出到 Excel。
require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // 1. 连接数据库 (使用 PDO 示例) $dbhost = 'localhost'; $dbname = 'your_database'; $dbuser = 'username'; $dbpass = 'password'; try { $pdo = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("数据库连接失败: " . $e->getMessage()); } // 2. 查询数据 $stmt = $pdo->query('SELECT name, age, email FROM users'); $users = $stmt->fetchAll(PDO::FETCH_ASSOC); // 3. 创建 PhpSpreadsheet 对象并填充数据 $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); // 设置表头 $sheet->setCellValue('A1', '姓名'); $sheet->setCellValue('B1', '年龄'); $sheet->setCellValue('C1', '邮箱'); // 设置表头样式 $headerStyle = [ 'font' => ['bold' => true], 'fill' => [ 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['argb' => 'FFDDDDDD'] ] ]; $sheet->getStyle('A1:C1')->applyFromArray($headerStyle); // 填充数据行 $rowIndex = 2; foreach ($users as $user) { $sheet->setCellValue('A' . $rowIndex, $user['name']); $sheet->setCellValue('B' . $rowIndex, $user['age']); $sheet->setCellValue('C' . $rowIndex, $user['email']); $rowIndex++; } // 自动调整列宽 foreach (range('A', 'C') as $col) { $sheet->getColumnDimension($col)->setAutoSize(true); } // 4. 保存并输出 $writer = new Xlsx($spreadsheet); header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="users_export.xlsx"'); header('Cache-Control: max-age=0'); $writer->save('php://output'); exit;
🔧 四、Laravel Excel 用法
在 Laravel 中使用 maatwebsite/excel
包可以非常优雅地处理导入导出。
1. 安装与配置
composer require maatwebsite/excel
发布配置文件:
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"
2. 创建导出类
php artisan make:export UsersExport --model=User
在 app/Exports/UsersExport.php
中定义导出:
namespace App\Exports; use App\Models\User; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithHeadings; use Maatwebsite\Excel\Concerns\WithMapping; use Maatwebsite\Excel\Concerns\WithStyles; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; class UsersExport implements FromCollection, WithHeadings, WithMapping, WithStyles { public function collection() { // 从这里返回要导出的数据集合 return User::all(); // 也可以自定义查询 // return User::select('name', 'email', 'created_at')->get(); } // 定义 Excel 的表头 public function headings(): array { return [ 'ID', '姓名', '邮箱', '注册时间' ]; } // 定义每行数据的映射关系 public function map($user): array { return [ $user->id, $user->name, $user->email, $user->created_at->format('Y-m-d H:i:s'), // 格式化日期 ]; } // 可选:设置样式 public function styles(Worksheet $sheet) { return [ // 表头行加粗 1 => ['font' => ['bold' => true]], ]; } }
3. 在控制器中调用导出
namespace App\Http\Controllers; use App\Exports\UsersExport; use Maatwebsite\Excel\Facades\Excel; class ExportController extends Controller { public function exportUsers() { // 导出为 xlsx 文件并下载 return Excel::download(new UsersExport, 'users.xlsx'); // 或者导出为 CSV // return Excel::download(new UsersExport, 'users.csv', \Maatwebsite\Excel\Excel::CSV); // 存储到服务器 // Excel::store(new UsersExport, 'exports/users.xlsx'); } }
4. 导入 Excel 数据
创建导入类:
php artisan make:import UsersImport --model=User
在 app/Imports/UsersImport.php
中定义导入规则:
namespace App\Imports; use App\Models\User; use Illuminate\Support\Facades\Hash; use Maatwebsite\Excel\Concerns\ToModel; use Maatwebsite\Excel\Concerns\WithHeadingRow; // 如果有表头行 use Maatwebsite\Excel\Concerns\WithValidation; // 如果需要验证 class UsersImport implements ToModel, WithHeadingRow, WithValidation { // 使用表头行(默认第一行是表头) public function headingRow(): int { return 1; } public function model(array $row) { // 假设 Excel 表头是 'name', 'email' return new User([ 'name' => $row['name'], 'email' => $row['email'], 'password' => Hash::make('default_password'), // 设置默认密码 ]); } public function rules(): array { // 定义验证规则 return [ '*.email' => 'required|email|unique:users,email', '*.name' => 'required|string|max:255', ]; } }
在控制器中处理上传和导入:
namespace App\Http\Controllers; use App\Imports\UsersImport; use Maatwebsite\Excel\Facades\Excel; use Illuminate\Http\Request; class ImportController extends Controller { public function showImportForm() { return view('import'); } public function importUsers(Request $request) { $request->validate([ 'file' => 'required|file|mimes:xlsx,csv' ]); // 导入 Excel 文件 Excel::import(new UsersImport, $request->file('file')); return back()->with('success', '用户导入成功!'); } }
💡 五、实用技巧与常见问题
性能优化:
处理大量数据(如上万行)时,注意可能的内存消耗。可以使用WithChunkReading
concern(在 Laravel Excel 中)来分块读取数据,或者考虑使用 CSV 格式代替 XLSX 进行导出。常见问题:
中文乱码:确保文件编码和输出头部正确。早期版本或 CSV 文件可能需要注意 UTF-8 BOM 头(
\xEF\xBB\xBF
)来解决中文乱码问题。文件无法打开:确保服务器有写入权限,并且输出到浏览器前没有额外的空格或输出。
样式不生效:检查样式数组的格式是否正确。
复杂表格:
对于非常复杂的、带有固定样式的报表,可以考虑先制作一个 Excel 模板文件,然后使用 PhpSpreadsheet 加载这个模板,只需在特定位置填充数据即可,这样可以省去用代码设置样式的麻烦。
六、总结
PHP 处理 Excel 的首选是现代且功能强大的 PhpSpreadsheet 库。对于 Laravel 项目,使用 Laravel Excel 封装包可以让开发流程更加高效和优雅。
选择哪个库取决于你的具体需求、项目框架以及对功能的要求。从简单的数据导出到复杂的、带有样式和公式的报表生成,这些工具都能很好地胜任。
希望以上信息能帮助你有效地在 PHP 项目中处理 Excel 文件!
发表评论