使用 Apache POI 對整行套用粗體文字樣式
一、簡介
在本快速教學中,我們將探索使用 Apache POI 庫將粗體字體樣式套用至 Excel 工作表中的整行的有效方法。透過簡單的範例和有價值的見解,我們將了解每種方法的細微差別。
2. 依賴關係
讓我們從編寫和載入 Excel 檔案所需的依賴項poi開始:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
3. 場景和輔助方法
我們的場景涉及建立一個帶有標題行和一些資料行的工作表。然後,我們將為標題行中使用的字體定義粗體樣式。最終,我們將創建一些方法來設定這種大膽的風格。最重要的是,我們會明白為什麼我們需要多個來做到這一點,因為明顯的選擇( setRowStyle()
)不能按預期工作。
為了促進工作表創建,我們將從 utils 類別開始。讓我們編寫一些方法來建立單元格和包含單元格的行:
public class PoiUtils {
private static void newCell(Row row, String value) {
short cellNum = row.getLastCellNum();
if (cellNum == -1)
cellNum = 0;
Cell cell = row.createCell(cellNum);
cell.setCellValue(value);
}
public static Row newRow(Sheet sheet, String... rowValues) {
Row row = sheet.createRow(sheet.getLastRowNum() + 1);
for (String value : rowValues) {
newCell(row, value);
}
return row;
}
// ...
}
然後,要建立粗體字體樣式,我們先從Workbook
建立字體,然後呼叫setBold(true)
。其次,我們將建立一個使用粗體字體的CellStyle
:
public static CellStyle boldFontStyle(Workbook workbook) {
Font boldFont = workbook.createFont();
boldFont.setBold(true);
CellStyle boldStyle = workbook.createCellStyle();
boldStyle.setFont(boldFont);
return boldStyle;
}
最後,要將工作表寫入文件,我們需要在Workbook
上呼叫write()
:
public static void write(Workbook workbook, Path path)
throws IOException {
try (FileOutputStream fileOut = new FileOutputStream(path.toFile())) {
workbook.write(fileOut);
}
}
4. 使用setRowStyle()
的注意事項
在查看 POI API 時,我們的任務最明顯的選擇是Row.setRowStyle()
。不幸的是,這種方法不能可靠地工作,而且目前存在一個錯誤。**問題似乎是 Microsoft Office 渲染忽略行樣式而只關心單元格樣式。**
另一方面,它可以與 OpenOffice 一起使用,但前提是我們使用SXSSFWorkbook
實現,該實現適用於大檔案。為了測試這一點,我們將從範例表方法開始:
private void writeSampleSheet(Path destination, Workbook workbook)
throws IOException {
Sheet sheet = workbook.createSheet();
CellStyle boldStyle = PoiUtils.boldFontStyle(workbook);
Row header = PoiUtils.newRow(sheet, "Name", "Value", "Details");
header.setRowStyle(boldStyle);
PoiUtils.newRow(sheet, "Albert", "A", "First");
PoiUtils.newRow(sheet, "Jane", "B", "Second");
PoiUtils.write(workbook, destination);
}
然後,使用斷言方法檢查第一行和第二行的樣式。首先,我們斷言第一Row
具有粗體字體樣式。然後,對於其中的每個單元格,我們斷言預設樣式與我們為第一Row
設定的樣式不同。這斷言我們的行樣式具有優先權。最後,我們斷言第二Row
不包含任何應用程式的樣式:
private void assertRowStyleAppliedAndDefaultCellStylesDontMatch(Path sheetFile)
throws IOException, InvalidFormatException {
try (Workbook workbook = new XSSFWorkbook(sheetFile.toFile())) {
Sheet sheet = workbook.getSheetAt(0);
Row row0 = sheet.getRow(0);
XSSFCellStyle rowStyle = (XSSFCellStyle) row0.getRowStyle();
assertTrue(rowStyle.getFont().getBold());
row0.forEach(cell -> {
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
assertNotEquals(rowStyle, style);
});
Row row1 = sheet.getRow(1);
XSSFCellStyle row1Style = (XSSFCellStyle) row1.getRowStyle();
assertNull(row1Style);
Files.delete(sheetFile);
}
}
最終,我們的測試包括將工作表寫入臨時文件,然後讀回。我們確保應用了我們的樣式,測試第一行和第二行中的樣式,然後刪除該檔案:
@Test
void givenXssfWorkbook_whenSetRowStyle1stRow_thenOnly1stRowStyled()
throws IOException, InvalidFormatException {
Path sheetFile = Files.createTempFile("xssf-row-style", ".xlsx");
try (Workbook workbook = new XSSFWorkbook()) {
writeSampleSheet(sheetFile, workbook);
}
assertRowStyleAppliedAndDefaultCellStylesDontMatch(sheetFile);
}
在執行此測試時,我們現在可以檢查是否僅在第一行獲得粗體樣式,這正是我們的預期。
5. 使用setCellStyle()
行中的儲存格
考慮到setRowStyle()
的問題,我們只剩下setCellStyle()
。我們需要它來為要套用粗體樣式的行中的每個儲存格設定樣式。因此,讓我們透過迭代標題中的每一行並使用粗體樣式呼叫setCellStyle()
來修改原始內容:
@Test
void givenXssfWorkbook_whenSetCellStyleForEachRow_thenAllCellsContainStyle()
throws IOException, InvalidFormatException {
Path sheetFile = Files.createTempFile("xssf-cell-style", ".xlsx");
try (Workbook workbook = new XSSFWorkbook()) {
Sheet sheet = workbook.createSheet();
CellStyle boldStyle = PoiUtils.boldFontStyle(workbook);
Row header = PoiUtils.newRow(sheet, "Name", "Value", "Details");
header.forEach(cell -> cell.setCellStyle(boldStyle));
PoiUtils.newRow(sheet, "Albert", "A", "First");
PoiUtils.write(workbook, sheetFile);
}
// ...
}
這樣,我們就可以保證我們的風格在不同格式和平台上一致應用。讓我們透過斷言未設定行樣式並且第一行中的每個單元格都包含粗體字體樣式來完成我們的測試:
try (Workbook workbook = new XSSFWorkbook(sheetFile.toFile())) {
Sheet sheet = workbook.getSheetAt(0);
Row row0 = sheet.getRow(0);
XSSFCellStyle rowStyle = (XSSFCellStyle) row0.getRowStyle();
assertNull(rowStyle);
row0.forEach(cell -> {
XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle();
assertTrue(style.getFont().getBold());
});
Row row1 = sheet.getRow(1);
rowStyle = (XSSFCellStyle) row1.getRowStyle();
assertNull(rowStyle);
Files.delete(sheetFile);
}
請注意,為了方便起見,我們在這裡使用XSSFWorkbook
。此方法在所有Workbook
實作中一致有效。
六,結論
在本文中,我們了解到雖然setRowStyle()
可能無法可靠地實現我們的目標,但我們發現了使用setCellStyle()
的強大替代方案。現在,我們可以自信地設定 Excel 工作表中的行格式,確保在不同平台上獲得一致且具有視覺影響力的結果。
與往常一樣,原始碼可以在 GitHub 上取得。