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
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值