使用Apache POI XMLSlideShow,如何在段落中嵌入用户头像并搭配文字?
实现PPT中重复生成带头像的用户信息条目(支持跨幻灯片)
核心思路
用表格布局实现头像与文本的对齐是最稳妥的方案,表格能轻松控制每个用户条目的排版,同时方便计算剩余空间,实现跨幻灯片的自动延伸:
- 每个用户条目对应表格的一行,左侧单元格放置头像图片,右侧单元格放置姓名、地址等文本
- 预先计算单张幻灯片可容纳的条目数,当当前幻灯片剩余空间不足时,自动创建新幻灯片继续添加条目
完整实现代码
import org.apache.poi.sl.usermodel.*; import org.apache.poi.xslf.usermodel.*; import org.apache.commons.io.IOUtils; import java.io.FileInputStream; import java.io.FileOutputStream; import java.awt.*; import java.util.ArrayList; import java.util.List; public class UserProfilePPTGenerator { // 用户数据模型 static class User { String name; String address; String avatarPath; User(String name, String address, String avatarPath) { this.name = name; this.address = address; this.avatarPath = avatarPath; } } public static void main(String[] args) throws Exception { XMLSlideShow ppt = new XMLSlideShow(); Dimension pageSize = ppt.getPageSize(); // 模拟用户数据 List<User> users = new ArrayList<>(); users.add(new User("张三", "北京市朝阳区XX街道123号", "avatar1.png")); users.add(new User("李四", "上海市浦东新区XX路456号", "avatar2.png")); users.add(new User("王五", "广州市天河区XX大道789号", "avatar3.png")); // 可添加更多用户... // 配置条目参数:每个用户条目的高度、头像大小、表格边距 int entryHeight = 120; int avatarSize = 100; int tableMargin = 40; int tableWidth = pageSize.width - 2 * tableMargin; int maxEntriesPerSlide = (pageSize.height - 2 * tableMargin) / entryHeight; XSLFSlide currentSlide = ppt.createSlide(); XSLFTable table = currentSlide.createTable(); // 设置表格样式:无边框,全宽 table.setStyle(XSLFTableStyle.NONE); table.setAnchor(new Rectangle(tableMargin, tableMargin, tableWidth, 0)); int currentEntryCount = 0; for (User user : users) { // 如果当前幻灯片已满,创建新幻灯片和新表格 if (currentEntryCount >= maxEntriesPerSlide) { currentSlide = ppt.createSlide(); table = currentSlide.createTable(); table.setStyle(XSLFTableStyle.NONE); table.setAnchor(new Rectangle(tableMargin, tableMargin, tableWidth, 0)); currentEntryCount = 0; } // 创建表格行 XSLFTableRow row = table.addRow(); row.setHeight(entryHeight); // 左侧单元格:放置头像 XSLFTableCell avatarCell = row.addCell(); avatarCell.setWidth(avatarSize + 20); // 预留小边距 byte[] avatarData = IOUtils.toByteArray(new FileInputStream(user.avatarPath)); XSLFPictureData pictureData = ppt.addPicture(avatarData, PictureData.PictureType.PNG); XSLFPictureShape avatar = avatarCell.createPicture(pictureData); // 让头像在单元格中居中 avatar.setAnchor(new Rectangle(10, 10, avatarSize, avatarSize)); // 右侧单元格:放置用户信息 XSLFTableCell infoCell = row.addCell(); infoCell.setWidth(tableWidth - avatarSize - 20); // 姓名段落 XSLFParagraph namePara = infoCell.addNewParagraph(); XSLFRun nameRun = namePara.createRun(); nameRun.setText("姓名:" + user.name); nameRun.setFontSize(14); nameRun.setBold(true); // 地址段落 XSLFParagraph addrPara = infoCell.addNewParagraph(); XSLFRun addrRun = addrPara.createRun(); addrRun.setText("地址:" + user.address); addrRun.setFontSize(12); currentEntryCount++; } // 保存PPT try (FileOutputStream out = new FileOutputStream("user_profiles.pptx")) { ppt.write(out); } ppt.close(); } }
关键细节说明
- 表格布局:用无边框表格消除视觉干扰,同时保证头像和文本的精准对齐
- 跨幻灯片处理:通过计算单页可容纳的条目数,在条目数达到上限时自动新建幻灯片和表格
- 头像居中:通过设置图片的anchor偏移,让头像在单元格内居中显示
- 文本排版:用不同的段落和Run对象区分姓名(加粗放大)和地址,提升可读性
内容的提问来源于stack exchange,提问作者Mahesh
相关产品推荐
相关产品推荐

