家明故事

PHP常用Excel库及用法详解

家明 0 0

PHP 处理 Excel 文件有很多成熟的库,它们各有特点,能满足从简单导出到复杂数据处理的不同需求。下面我将为你介绍几个主流且实用的 PHP Excel 库,并提供详细的用法说明。

🧰 一、主流 PHP Excel 库对比

以下是几个主流的 PHP Excel 库的对比,帮助你根据项目需求进行选择。

库名称主要特点支持格式适用场景维护状态
PhpSpreadsheet功能全面,支持单元格操作、样式、公式、图表、图片等,是 PHPExcel 的现代继承者.xls, .xlsx, .csv, .ods, HTML复杂报表生成、数据导入导出、模板填充、公式计算活跃维护
PHPExcel曾经的主流选择,功能丰富(支持图片、图表、公式、多工作表等),但已停止更新,被 PhpSpreadsheet 取代.xls, .xlsx, .csv, .ods, PDF老项目维护,或需要兼容旧代码的情况停止维护
Laravel Excel专为 Laravel 设计的包,封装了 PhpSpreadsheet,提供优雅的语法和便捷的集成.xls, .xlsx, .csvLaravel 项目中的 Excel 导入导出活跃维护
Excel Writer (XML)支持公式、图片、多工作表、格式,可直接从 MySQL 查询导出数据生成 Microsoft Office 2003 XML 格式需要生成 Office 2003 XML 格式的场景较少更新

🔔 选择建议

  • 对于新项目,强烈推荐使用 PhpSpreadsheet,它功能强大且持续更新。

  • 如果你的项目基于 LaravelLaravel Excel 能极大提升开发效率。

  • PHPExcel 仅建议用于维护旧项目。

📦 二、PhpSpreadsheet 详细用法

PhpSpreadsheet 是目前最推荐使用的 PHP 电子表格处理库,功能非常强大。

1. 安装与引入

通过 Composer 安装:

bash
composer require phpoffice/phpspreadsheet

在脚本中引入自动加载文件:

php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\IOFactory;

2. 创建 Excel 并写入数据

php
// 创建一个新的 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 数据

php
// 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 支持复杂的操作,如公式、图片和图表

php
// 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。

php
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. 安装与配置

bash
composer require maatwebsite/excel

发布配置文件:

bash
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"

2. 创建导出类

bash
php artisan make:export UsersExport --model=User

在 app/Exports/UsersExport.php 中定义导出:

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. 在控制器中调用导出

php
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 数据

创建导入类:

bash
php artisan make:import UsersImport --model=User

在 app/Imports/UsersImport.php 中定义导入规则:

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',
        ];
    }
}

在控制器中处理上传和导入:

php
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', '用户导入成功!');
    }
}

💡 五、实用技巧与常见问题

  1. 性能优化
    处理大量数据(如上万行)时,注意可能的内存消耗。可以使用 WithChunkReading concern(在 Laravel Excel 中)来分块读取数据,或者考虑使用 CSV 格式代替 XLSX 进行导出。

  2. 常见问题

    • 中文乱码:确保文件编码和输出头部正确。早期版本或 CSV 文件可能需要注意 UTF-8 BOM 头(\xEF\xBB\xBF)来解决中文乱码问题。

    • 文件无法打开:确保服务器有写入权限,并且输出到浏览器前没有额外的空格或输出。

    • 样式不生效:检查样式数组的格式是否正确。

  3. 复杂表格
    对于非常复杂的、带有固定样式的报表,可以考虑先制作一个 Excel 模板文件,然后使用 PhpSpreadsheet 加载这个模板,只需在特定位置填充数据即可,这样可以省去用代码设置样式的麻烦

六、总结

PHP 处理 Excel 的首选是现代且功能强大的 PhpSpreadsheet 库。对于 Laravel 项目,使用 Laravel Excel 封装包可以让开发流程更加高效和优雅

选择哪个库取决于你的具体需求、项目框架以及对功能的要求。从简单的数据导出到复杂的、带有样式和公式的报表生成,这些工具都能很好地胜任。

希望以上信息能帮助你有效地在 PHP 项目中处理 Excel 文件!

标签:PHP  Excel  

打赏

发表评论