使用 Java 將 Excel 檔案轉換為 PDF
一、簡介
在本文中,我們將探討如何使用 Apache POI 和 iText 函式庫在 Java 中將 Excel 檔案轉換為 PDF。 Apache POI 處理 Excel 檔案解析和資料擷取,而 iText 負責 PDF 文件建立和格式化。透過利用它們的優勢,我們可以有效地轉換 Excel 數據,同時保留其原始格式和樣式。
2.添加依賴
在開始實施之前,我們需要將 Apache POI 和 iText 庫新增到我們的專案中。在pom.xml
檔中加入以下依賴項:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
</dependency>
可以從 Maven Central 下載最新版本的Apache POI和iText庫。
3. 載入Excel文件
庫就位後,讓我們使用 Apache POI 載入目標 Excel 檔案。我們首先使用FileInputStream
開啟 Excel 檔案並建立一個代表載入的工作簿的XSSFWorkbook
物件:
FileInputStream inputStream = new FileInputStream(excelFilePath);
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
我們將使用此物件來存取各個工作表及其資料。
4. 建立 PDF 文檔
接下來,我們將利用 iText 建立一個新的 PDF 文件:
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath));
document.open();
這將建立一個新的Document
物件並將其與負責寫入 PDF 內容的PDFWriter
實例關聯起來。最後,我們透過FileOutputStream
指定 PDF 所需的輸出位置。
5. 解析Excel數據
文件準備就緒後,我們將迭代工作表中的每一行以提取單元格值:
void addTableData(PdfPTable table) throws DocumentException, IOException {
XSSFSheet worksheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = worksheet.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
if (row.getRowNum() == 0) {
continue;
}
for (int i = 0; i < row.getPhysicalNumberOfCells(); i++) {
Cell cell = row.getCell(i);
String cellValue;
switch (cell.getCellType()) {
case STRING:
cellValue = cell.getStringCellValue();
break;
case NUMERIC:
cellValue = String.valueOf(BigDecimal.valueOf(cell.getNumericCellValue()));
break;
case BLANK:
default:
cellValue = "";
break;
}
PdfPCell cellPdf = new PdfPCell(new Phrase(cellValue));
table.addCell(cellPdf);
}
}
}
程式碼首先建立一個與工作表第一行中的列數相符的PdfTable
物件。然後,迭代工作表中的每一行,提取單元格值並將它們編織到 PDF 表格中。但是,目前不支援 Excel 公式,並且將傳回空字串。
對於每個提取的單元格值,我們使用包含提取的資料的Phrase
來建立一個新的PdfPCell
物件。 Phrase
是一個 iText 元素,表示格式化的文字字串。
6. 保留 Excel 樣式
使用 Apache POI 和 iText 的主要優勢之一是能夠保留原始 Excel 檔案的格式和樣式。這包括字體樣式、顏色和對齊方式。
透過從 Apache POI 存取相關的單元格樣式信息,我們可以使用 iText 將其應用到 PDF 文件中的相應元素。但是,需要注意的是,這種方法在保留格式和樣式的同時,可能無法複製直接從 Excel 匯出或使用印表機驅動程式列印的 PDF 的確切外觀和風格。對於更複雜的格式需求,可能需要額外的調整。
6.1.字體樣式
我們將建立一個專用的getCellStyle(Cell cell)
方法,從與每個單元格關聯的CellStyle
物件中提取字體、顏色等樣式資訊:
Font getCellStyle(Cell cell) throws DocumentException, IOException {
Font font = new Font();
CellStyle cellStyle = cell.getCellStyle();
org.apache.poi.ss.usermodel.Font cellFont = cell.getSheet()
.getWorkbook()
.getFontAt(cellStyle.getFontIndexAsInt());
if (cellFont.getItalic()) {
font.setStyle(Font.ITALIC);
}
if (cellFont.getStrikeout()) {
font.setStyle(Font.STRIKETHRU);
}
if (cellFont.getUnderline() == 1) {
font.setStyle(Font.UNDERLINE);
}
short fontSize = cellFont.getFontHeightInPoints();
font.setSize(fontSize);
if (cellFont.getBold()) {
font.setStyle(Font.BOLD);
}
String fontName = cellFont.getFontName();
if (FontFactory.isRegistered(fontName)) {
font.setFamily(fontName);
} else {
logger.warn("Unsupported font type: {}", fontName);
font.setFamily("Helvetica");
}
return font;
}
Phrase
物件可以接受單元格值和Front
物件作為其建構函數的參數:
PdfPCell cellPdf = new PdfPCell(new Phrase(cellValue, getCellStyle(cell));
這使我們能夠控制 PDF 單元格中文字的內容和格式。請注意,iText 的內建字型僅限於 Courier、Helvetica 和 TimesRoman。因此,在直接應用之前,我們應該檢查 iText 是否支援提取的單元格的字體系列。如果 Excel 檔案使用不同的字體系列,則不會反映在 PDF 輸出中。
6.2.背景顏色樣式
除了保留字體樣式之外,我們還希望確保 Excel 文件中單元格的背景顏色準確反映在生成的 PDF 中。為此,我們將建立一個新方法setBackgroundColor(),
以從 Excel 儲存格中提取背景顏色資訊並將其套用到對應的 PDF 儲存格。
void setBackgroundColor(Cell cell, PdfPCell cellPdf) {
short bgColorIndex = cell.getCellStyle()
.getFillForegroundColor();
if (bgColorIndex != IndexedColors.AUTOMATIC.getIndex()) {
XSSFColor bgColor = (XSSFColor) cell.getCellStyle()
.getFillForegroundColorColor();
if (bgColor != null) {
byte[] rgb = bgColor.getRGB();
if (rgb != null && rgb.length == 3) {
cellPdf.setBackgroundColor(new BaseColor(rgb[0] & 0xFF, rgb[1] & 0xFF, rgb[2] & 0xFF));
}
}
}
}
6.3.對齊樣式
Apache POI 在 CellStyle 物件上提供getAlignment()
方法。這將傳回一個表示對齊方式的常數值。一旦我們有了映射的 iText 對齊常數,我們就可以使用setHorizontalAlignment()
方法在PdfPCell
物件上設定它。
以下是如何合併對齊提取和應用的範例:
void setCellAlignment(Cell cell, PdfPCell cellPdf) {
CellStyle cellStyle = cell.getCellStyle();
HorizontalAlignment horizontalAlignment = cellStyle.getAlignment();
switch (horizontalAlignment) {
case LEFT:
cellPdf.setHorizontalAlignment(Element.ALIGN_LEFT);
break;
case CENTER:
cellPdf.setHorizontalAlignment(Element.ALIGN_CENTER);
break;
case JUSTIFY:
case FILL:
cellPdf.setVerticalAlignment(Element.ALIGN_JUSTIFIED);
break;
case RIGHT:
cellPdf.setHorizontalAlignment(Element.ALIGN_RIGHT);
break;
}
}
現在,讓我們更新現有程式碼,在其中迭代單元格以包含字體和背景顏色樣式:
PdfPCell cellPdf = new PdfPCell(new Phrase(cellValue, getCellStyle(cell)));
setBackgroundColor(cell, cellPdf);
setCellAlignment(cell, cellPdf);
請注意,產生的 Excel 看起來與從 Excel 匯出的 PDF(或透過印表機驅動程式列印的 PDF)不同。
7. 儲存PDF文檔
最後,我們可以將產生的PDF文件儲存到所需的位置。這涉及關閉 PDF 文件物件並確保正確釋放所有資源:
document.add(table);
document.close();
workbook.close();
八、結論
我們學習了使用 Apache POI 和 iText 在 Java 中將 Excel 檔案轉換為 PDF。透過結合用於 Excel 處理的 Apache POI 和用於 PDF 產生的 iText 功能,我們可以無縫地保留格式並將樣式從 Excel 應用於 PDF。
本文中的程式碼範例可以在 GitHub 上基於 Maven 的專案中找到。