
PhpSpreadsheet实战教程:如何在Excel中插入图片,完整代码与避坑指南
在日常的Web开发工作中,将数据导出为Excel文件是非常常见的需求。很多时候,我们不仅需要导出普通的文本数据,还希望能在Excel的指定单元格中插入图片,比如商品列表中的产品缩略图、员工信息表中的证件照,或者是报表模板中的公司Logo。PhpSpreadsheet作为PHP社区中处理Excel文件的利器,提供了完善的图片插入接口。本文将从零开始,详细讲解如何使用PhpSpreadsheet在Excel中插入图片,并分享一些实用的技巧和常见问题的解决方案。
一、准备工作:安装PhpSpreadsheet
在开始编写代码之前,我们需要先确保项目中已经引入了PhpSpreadsheet库。如果你还没有安装,可以通过Composer来快速完成。
打开命令行工具,进入你的项目根目录,然后执行以下命令:
composer require phpoffice/phpspreadsheet这条命令会自动下载PhpSpreadsheet及其所有依赖包。安装完成后,你会在项目目录下看到一个vendor文件夹,里面包含了所有第三方库文件。后续使用时,只需要在PHP脚本开头引入自动加载文件即可。
如果你的项目没有使用Composer管理依赖,建议先配置好Composer环境,因为PhpSpreadsheet的安装和更新都依赖于它。
二、核心代码实现:一步步在Excel中插入图片
下面我们通过一个完整的例子,演示如何创建一个新的Excel文件,并在指定单元格中插入一张图片。这个例子会模拟一个简单的产品清单导出功能,包含产品名称、价格和对应的产品图片。
第一步:引入自动加载并创建Spreadsheet对象
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
// 创建一个新的Spreadsheet对象
$spreadsheet = new Spreadsheet();
// 获取当前活动的工作表
$sheet = $spreadsheet->getActiveSheet();这里需要注意的是,require 'vendor/autoload.php'这行代码必须放在文件最前面,它负责加载所有通过Composer安装的类库。之后我们通过use关键字引入了三个关键的类:Spreadsheet用于创建工作簿,Drawing用于处理图片,Writer\Xlsx用于将工作簿保存为Excel文件。
第二步:添加文本数据作为表格基础
在插入图片之前,我们先往单元格里写入一些文本内容,这样生成的Excel看起来才像一个完整的表格。
// 设置表头
$sheet->setCellValue('A1', '产品图片');
$sheet->setCellValue('B1', '产品名称');
$sheet->setCellValue('C1', '价格');
// 填充一行示例数据
$sheet->setCellValue('B2', '高性能笔记本电脑');
$sheet->setCellValue('C2', '7999.00');这段代码在Excel的第一行写入了三个列标题,然后在第二行的B列和C列分别写入了产品名称和价格。接下来我们要做的,就是在A2单元格的位置插入一张产品图片。
第三步:创建绘图对象并加载图片
这是插入图片的核心步骤。我们需要创建一个Drawing对象,然后通过它的各种方法来设置图片的属性。
// 创建绘图对象
$drawing = new Drawing();
$drawing->setName('产品图片'); // 设置图片名称(在Excel中可见)
$drawing->setDescription('产品缩略图'); // 设置图片描述
// 指定图片文件路径
$imagePath = './images/product.jpg';
// 检查图片是否存在,避免程序崩溃
if (!file_exists($imagePath)) {
die('错误:图片文件不存在,请检查路径是否正确!');
}
$drawing->setPath($imagePath);这里有一个非常重要的细节:一定要在调用setPath()之前检查图片文件是否存在。因为如果图片路径错误或者文件缺失,PhpSpreadsheet会直接抛出异常,导致整个程序中断。使用file_exists()进行前置检查,可以让我们及时发现问题并给出友好的提示。
关于图片路径的写法,有几点需要注意:
- 相对路径是相对于当前PHP脚本的执行目录,而不是脚本文件所在目录。如果不确定,建议使用绝对路径。
- 在Windows系统下,路径分隔符可以使用反斜杠,但为了跨平台兼容,最好统一使用正斜杠。
- 如果图片存储在远程服务器上,需要先下载到本地临时目录再插入,因为PhpSpreadsheet不支持直接插入网络图片。
第四步:设置图片插入位置和偏移量
图片加载完成后,我们需要告诉程序这张图片要放到哪个单元格里。
// 设置图片插入的目标单元格
$drawing->setCoordinates('A2');
// 设置图片在单元格内的偏移量(单位:像素)
$drawing->setOffsetX(10); // 水平方向向右偏移10像素
$drawing->setOffsetY(10); // 垂直方向向下偏移10像素setCoordinates()方法接受一个单元格地址,比如'A2'表示将图片放置在A列第2行的位置。但这里要注意,图片并不是严格嵌入到单元格内部的,而是浮动在单元格上方的一个独立对象。所以即使你设置了坐标,图片的左上角默认是对齐到单元格的左上角。
为了让图片在单元格内看起来更居中或者更美观,我们可以使用setOffsetX()和setOffsetY()来微调图片的位置。这两个方法的单位是像素,正数表示向右或向下偏移,负数则向左或向上偏移。不过在实际使用中,负数偏移可能会导致图片超出单元格边界,所以建议尽量使用正值。
第五步:调整图片尺寸
图片插入后的默认尺寸可能不符合我们的要求,因此需要手动设置宽高。
// 设置图片宽度为100像素(高度会自动等比缩放)
$drawing->setWidth(100);
// 注意:不建议同时设置宽度和高度,否则可能导致图片变形
// $drawing->setHeight(100); // 这行注释掉了这里有一个非常容易踩的坑:如果同时调用setWidth()和setHeight(),PhpSpreadsheet会严格按照你设定的数值去拉伸或压缩图片,而不考虑原始宽高比。结果就是图片看起来扁了或者长了,非常不专业。
正确的做法是:只设置宽度或者只设置高度,让程序自动根据原始比例计算出另一个维度。比如你只想让图片宽度为100像素,那就只调用setWidth(100),高度会自动适配。反过来也是一样,只设置高度也可以。
如果你确实需要精确控制图片的显示尺寸,可以先计算出目标宽高比,然后手动调整。例如原图是800x600,你想显示成100x75,那就可以同时设置宽高,因为这个比例与原图一致。
第六步:将图片添加到工作表
所有属性设置完毕后,最后一步是把图片对象真正挂载到工作表上。
// 将图片添加到当前工作表
$drawing->setWorksheet($sheet);这一步非常重要,如果没有调用setWorksheet(),图片就不会出现在最终的Excel文件中。
第七步:调整单元格大小以适应图片
由于图片是浮动在单元格上方的,它不会自动撑大单元格。如果我们希望单元格刚好能容纳图片,就需要手动调整列宽和行高。
// 调整A列的宽度为15个字符宽度
$sheet->getColumnDimension('A')->setWidth(15);
// 调整第2行的行高为80像素
$sheet->getRowDimension('2')->setRowHeight(80);这里的列宽单位是字符宽度,行高单位是磅值。一般来说,要让100像素宽的图片完整显示,列宽设置在15左右比较合适,行高设置在80左右。你可以根据实际图片尺寸进行调整,多试几次就能找到最佳值。
第八步:保存Excel文件
最后一步,将工作簿保存为Excel文件。
// 创建写入器
$writer = new Xlsx($spreadsheet);
// 设置文件名
$filename = 'product_list.xlsx';
try {
// 保存文件到服务器
$writer->save($filename);
echo 'Excel文件生成成功,文件名:' . $filename;
} catch (Exception $e) {
echo '保存失败,错误信息:' . $e->getMessage();
}这里使用了try-catch结构来捕获可能的异常,比如磁盘空间不足、目录权限不够等情况。如果保存成功,会在当前目录下生成一个名为product_list.xlsx的文件。
如果你想直接在浏览器中触发下载而不是保存到服务器,可以使用php://output流并配合HTTP头信息来实现。这部分属于进阶用法,后面我们会单独介绍。
三、常见问题与解决方案
在实际开发中,很多人会遇到各种各样的问题,下面总结了一些最常见的踩坑点和解决方法。
图片路径问题
问题表现:程序报错说找不到图片文件,或者生成的Excel里图片显示为红叉。
原因分析:路径写错了。相对路径是相对于当前工作目录,而不是脚本文件所在的目录。比如你的脚本在/www/project/src/export.php,但你在脚本里写了./images/pic.jpg,那么程序会在/www/project/images/下找图片,而不是在/www/project/src/images/下找。
解决方案:
- 使用绝对路径,比如
/var/www/html/images/pic.jpg - 或者在插入前用
realpath()函数将相对路径转换为绝对路径 - 始终在调用
setPath()之前用file_exists()做检查
图片变形问题
问题表现:图片在Excel中显示时被拉长或压扁,比例失调。
原因分析:同时设置了setWidth()和setHeight(),而且设置的宽高比与原图不一致。
解决方案:只设置宽度或只设置高度,让程序自动等比缩放。如果非要同时设置,请确保宽高比与原图相同。
图片位置不对
问题表现:图片没有出现在预期的单元格位置,而是跑到了其他地方。
原因分析:setCoordinates()设置的单元格地址写错了,或者单元格行列索引搞混了。
解决方案:仔细检查单元格地址的写法,比如'A2'表示第一列第二行。如果图片需要放在合并单元格中,坐标要指向合并区域左上角的单元格。
图片不显示或显示不全
问题表现:Excel文件打开了,但图片区域是空白或者只显示了一部分。
原因分析:单元格的行高或列宽太小,无法容纳图片的全部内容。
解决方案:根据图片的实际尺寸,适当增大行高和列宽。可以先设大一点,然后再慢慢调整到合适的值。
内存溢出问题
问题表现:当插入大量高清图片时,PHP报出内存耗尽错误。
原因分析:每张高清图片都需要占用大量内存来加载和处理,如果一次性插入几十上百张图片,很容易超出PHP默认的内存限制。
解决方案:
- 在插入前先用GD库或Imagick库压缩图片,降低分辨率
- 在
php.ini中适当调高memory_limit的值,比如改为256M或512M - 考虑分批生成Excel文件,而不是一次性全部插入
四、进阶技巧:批量插入多张图片
在实际项目中,我们往往需要在一个Excel中插入多张图片,比如导出一整页的产品列表,每行都有一张产品缩略图。下面是一个批量插入的例子。
// 假设有一个产品数组
$products = [
['name' => '笔记本', 'price' => '7999', 'image' => './images/laptop.jpg'],
['name' => '手机', 'price' => '4999', 'image' => './images/phone.jpg'],
['name' => '耳机', 'price' => '999', 'image' => './images/earphone.jpg'],
];
// 从第2行开始逐行插入
$row = 2;
foreach ($products as $product) {
// 写入文本数据
$sheet->setCellValue('B' . $row, $product['name']);
$sheet->setCellValue('C' . $row, $product['price']);
// 插入图片
if (file_exists($product['image'])) {
$drawing = new Drawing();
$drawing->setName($product['name']);
$drawing->setPath($product['image']);
$drawing->setCoordinates('A' . $row);
$drawing->setWidth(80);
$drawing->setOffsetX(5);
$drawing->setOffsetY(5);
$drawing->setWorksheet($sheet);
}
// 调整行高
$sheet->getRowDimension($row)->setRowHeight(70);
$row++;
}在这个例子中,我们遍历产品数组,每循环一次就新建一个Drawing对象,然后设置对应的属性和坐标。注意,每个图片对象都是独立的,不能复用同一个对象。
五、总结
使用PhpSpreadsheet在Excel中插入图片并不复杂,核心就是掌握Drawing对象的几个关键方法:setPath()加载图片、setCoordinates()定位单元格、setWidth()或setHeight()控制尺寸、setOffsetX()和setOffsetY()微调位置。同时要注意图片路径的正确性、宽高比例的保持以及单元格大小的适配。
掌握了这些基础知识后,你就可以灵活地在Excel中插入任意数量的图片,无论是制作产品目录、员工相册还是报表模板,都能轻松应对。如果在实际开发中遇到其他问题,建议查阅PhpSpreadsheet的官方文档,那里有更详尽的API说明和示例代码。
PhpSpreadsheetExcel图片插入PHP代码示例Excel导出图片处理修改时间:2026-08-01 21:04:48