Java - poi和itext将Excel转化为PDF(支持图片)

需求:将Excel转化为PDF,支持图片,只单个sheet

要求:1、开源免费;2、支持跨平台

设计:1. 采用POI读取Excel文件;2. 采用itext生成PDF文件。

注:如果费用许可的情况下,建议使用Aspose(可跨平台,收费,不开源)。

开发难点:

1. 将POI标准转化为Itext标准,包括单元格内容,字体,样式,单元格的合并等;

2. Excel文件x轴可以滚动,而PDF文件宽度是固定的,转化后的PDF内容可能会出现挤压的情况。

思路:1. 先将poi对转化为标准对象,如将POI的颜色转化为RGB;2. 将标准对象转化为itext对象。

转换事项:

1. 单元格类型:常规、数值、文本等。

2. 对齐方式:水平对齐只支持左对齐、居中、右对齐,默认左对齐;垂直对齐方式只顶端对齐、垂直居中、底端对齐,默认底端对齐。

3. 文本的字体(暂不支持,目前固定为STSong-Light)、颜色(支持)、大小(支持)、是否加粗(支持),是否倾斜(支持),是否有下划线(支持),是否自动换行(支持)

4. 框线:下框线、上框线、左框线、右框线(仅设置边框颜色和边框宽度)

5. 填充色(背景色):支持。

6. 单元格的高度和宽度

遗留问题(后续改善):

1. excel不支持黑色背景。

2. excel相邻单元格都有边框时,PDF文件边框变粗。

3. 当excel单元格处在图片区域,PDF中该单元格无文本。

4. 当excel文件存在多张图片有重合区域时,PDF只有其中的一张图片(起始单元格最靠前的图片)。

5. excel单元格字体加粗、倾斜、下划线,pdf只有加粗、下划线,缺少倾斜。

6. 部分情况pdf样式失真。

7.目前该文主要是验证excel转pdf,后期会更新优化后方案。

示例(excel2003文件转化为pdf)

excel2003文件:

转化后的PDF文件:

 

测试代码:

// poi和itext将Excel转化为PDF(支持图片)
String pdf = "F:/Users/zyj/Desktop/2019-09-27 自由报表/插件测试/excel2pdf_new.pdf";
Xls2Pdf xls2Pdf = new Xls2Pdf(xls, 0);
xls2Pdf.savePdf(pdf);

poi读取xls文件,生成PDF的代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * Excel2003文件转化为PDF文件
 * 
 * @author zyj
 * @date 2019-10-18
 */
public class Xls2Pdf {
	private HSSFWorkbook _wb = null;
	private int _sheetIndex = 0;
	private HSSFSheet _sheet = null;
	// 文本中的合并单元格
	private List<CellRangeAddress> _ranges = null;
	// 单个Sheet中所有的图片信息
	private Map<String, HSSFPictureData> _pics = null;
	// 图片中的最后一个单元格位置
	private Integer[] _lastCell = null;

	/**
	 * 构造函数
	 * 
	 * @param excel      excel2003文件的全路径
	 * @param sheetindex sheet索引
	 * @throws IOException
	 */
	public Xls2Pdf(String excel, int sheetIndex) throws IOException {
		InputStream input = new FileInputStream(excel);
		HSSFWorkbook wb = new HSSFWorkbook(input);
		this._wb = wb;
		this._sheetIndex = sheetIndex;
	}

	/**
	 * 构造函数
	 * 
	 * @param wb         excel工作薄
	 * @param sheetIndex sheet索引
	 */
	public Xls2Pdf(HSSFWorkbook wb, int sheetIndex) {
		this._wb = wb;
		this._sheetIndex = sheetIndex;
	}

	/**
	 * 保存为pdf文件
	 * 
	 * @param pdf pdf文件的全路径
	 * @throws IOException
	 * @throws BadElementException
	 * @throws DocumentException
	 */
	public void savePdf(String pdf) throws IOException, BadElementException, DocumentException {
		PdfPTable table = this.genPdfPTable();
		// Step 1 — Create a Document
		Document document = new Document();
		// Step 2 — Get a PdfWriter instance
		FileOutputStream output = new FileOutputStream(pdf);
		PdfWriter.getInstance(document, output);
		// Step 3 — Open the Document
		document.open();
		// Step 4 — Add content.
		document.add(table);
		// Step 5 — Close the Document
		document.close();
	}

	/**
	 * 将sheet转化为PdfPTable
	 * 
	 * @return PdfPTable对象
	 * @throws IOException
	 * @throws BadElementException
	 * @throws DocumentException
	 */
	public PdfPTable genPdfPTable() throws IOException, BadElementException, DocumentException {
		if (this._wb == null) {
			return null;
		}
		this._sheet = this._wb.getSheetAt(this._sheetIndex);
		if (this._sheet == null) {
			return null;
		}
		// 文本中的合并单元格
		this._ranges = this._sheet.getMergedRegions();
		// sheet中所有图片信息
		this._pics = XlsHelper.getPictrues(this._wb, this._sheetIndex);
		// sheet中最后一个单元格位置
		this._lastCell = this.getLastCell();
		PdfPTable table = new PdfPTable(this._lastCell[1] + 1);
		// 遍历Sheet中的所有行
		for (int i = 0; 
<think>好的,我现在需要帮助用户在SpringBoot中实现将ExcelWord文件换为图片PDF的功能。首先,我得考虑用户的具体需求。他们可能需要在后端处理这些文档换,比如生成报告或者预览文件。接下来,我需要找出适合的Java库,考虑如何集成到Spring Boot项目中。首先,对于WordPDF图片,常见的库有ApachePOIdocx4j。Apache POI功能强大,但处理复杂格式可能会有问题。docx4j更适合处理.docx文件,支持换为PDF,但可能需要依赖XSLTFOP。另外,LibreOffice或OpenOffice的无头模式也是一个选项,但需要安装软件,可能增加部署复杂度。然后是ExcelPDF图片。同样,ApachePOI可以读取Excel文件,但生成图片可能需要借助其他库如ApacheBatik或Thymeleaf将表格渲染为HTML再图片。JExcelApi也是一个选择,但可能不如POI流行。对于PDF换,iText或Flying Saucer结合POI可能有效。用户可能关心这些库的易用性、许可协议以及性能。例如,LibreOffice换质量高,但需要调用外部进程,可能影响性能。而纯Java库如docx4j可能更易于集成,但处理复杂文档时可能有局限。 接着,我需要考虑具体实现步骤。例如,使用docx4j将WordPDF,可能需要添加依赖,编写换代码。对于Excel,可能需要用POI读取数据,再用iText生成PDF表格。或者,使用Thymeleaf模板生成HTML,再通过wkhtmltopdfPDF,这样处理样式更灵活。 另外,用户可能需要处理大文件或高发,这时候要考虑异步处理资源管理。例如,使用Spring的异步功能,或者缓存换结果。最后,生成相关问题,帮助用户深入了解各个方案的优缺点,以及如何处理特定格式或性能优化。例如,比较不同库的换质量,如何处理图表,或者如何提高换速度。</think>在Spring Boot中实现Excel/Word图片PDF,可采用以下主流方案: ### 一、Word文档换方案 1. **Apache POI + PDFBox** ```java // 换Word到PDF XWPFDocument doc = new XWPFDocument(new FileInputStream("input.docx")); PdfOptions options = PdfOptions.create(); PdfConverter.getInstance().convert(doc, new FileOutputStream("output.pdf"), options); ``` 支持.docx格式换,但复杂样式可能失真[^1] 2. **docx4j** ```xml <dependency> <groupId>org.docx4j</groupId> <artifactId>docx4j</artifactId> <version>11.4.4</version> </dependency> ``` 通过XSL-FO实现高质量PDF换,支持目录、页眉页脚等复杂元素[^2] 3. **LibreOffice无头模式** ```bash soffice --headless --convert-to pdf test.docx ``` 通过JNA调用实现,换质量最佳但需要安装LibreOffice[^3] ### 二、Excel换方案 1. **Apache POI + iText** ```java // 读取Excel生成PDF表格 XSSFWorkbook workbook = new XSSFWorkbook(new File("input.xlsx")); PdfPTable table = new PdfPTable(sheet.getRow(0).getLastCellNum()); sheet.forEach(row -> row.forEach(cell -> table.addCell(cell.toString()))); document.add(table); ``` 适合简单表格换,但图表无法保留[^4] 2. **Aspose.Cells** ```java Workbook workbook = new Workbook("input.xlsx"); workbook.save("output.pdf", SaveFormat.PDF); ``` 商业库支持完整格式保留,但需付费授权[^5] 3. **HTML中间件方案** 使用Thymeleaf生成HTML模板后,通过wkhtmltopdf换: ```java @Autowired private SpringTemplateEngine templateEngine; Context context = new Context(); String html = templateEngine.process("excel-template", context); new WkHtmlToPdf().convert(html, outputStream); ``` 支持复杂样式自定义,但需维护HTML模板[^6] ### 三、通用图片生成方案 1. **Java截图方案** ```java // 使用awt生成图片 Dimension size = table.getPreferredSize(); BufferedImage image = new BufferedImage(size.width, size.height, TYPE_INT_ARGB); Graphics2D graphics = image.createGraphics(); table.print(graphics); ImageIO.write(image, "PNG", new File("output.png")); ``` 适合简单内容截取,分辨率有限 2. **PDF图片** ```java PDDocument document = PDDocument.load(new File("input.pdf")); PDFRenderer renderer = new PDFRenderer(document); BufferedImage image = renderer.renderImage(0, 3.0f); // 300DPI ``` 需先换为PDF后再生成图片 ### 四、性能优化建议 - 使用`@Async`实现异步- 对重复文档启用缓存 - 限制换任务数量 - 使用临时文件替代内存操作
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值