Master EasyPOI: Design Complex Excel Templates and Export Images Efficiently
This article explains how to use EasyPOI for Excel template design, covering version compatibility, Maven configuration, template creation for simple and complex reports, expression syntax, image export pitfalls, and Java code examples to render data into templates without common pitfalls.
Version and Dependency Notes
EasyPOI 4.0.0 and later depend on Apache POI 4.0.0+, so Maven versions must match. Apache POI 4.0.0 introduces breaking changes; if your existing code relies on older APIs, stay on earlier versions. For compatibility with JEECG 3.7 (which uses POI 3.9), the author chose EasyPOI 3.3.0 with POI 3.15.
<properties>
<poi.version>3.15</poi.version>
<easypoi.version>3.3.0</easypoi.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>${easypoi.version}</version>
</dependency>
</dependencies>Excel Template Design
Use EasyPOI's template export to avoid manual coding of Excel styles. First, design the template, distinguishing fixed header sections from repeatable data rows. EasyPOI provides its own expression language; refer to the official docs for details.
Simple Excel Report Template
Below are example screenshots of a simple report and its template.
Complex Excel Report Template
The following complex template separates a static header from a repeatable product detail section. The expression syntax is explained below.
{{!fe: list t.id ‘库别:’ t.bin 换行 ‘商品名称:’ t.name 换行 ‘商品编号:’ t.code t.barcode 换行 ‘生产日期:’ t.proDate 换行 ‘进货日期:’ t.recvDate}}
Key expression components:
!fe: Iterate data without creating a new row (the row is created by fe:).
list – the collection name retrieved from a Map<String, Object>.
t – placeholder for each element in the list; must remain consistent throughout the template.
]] – line‑break marker; must appear in the last column of each row.
‘’ – denotes a constant string value.
Preparing Template Data
Create a Map<String, Object> where the key is list and the value is a List<Map<String, Object>>. Example code:
Map<String, Object> total = new HashMap<>();
List<Map<String, Object>> mapList = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
Map<String, Object> map = new HashMap<>();
map.put("id", i + "");
map.put("bin", "001 1000千克");
map.put("name", "商品" + i);
map.put("code", "goods" + i);
map.put("proDate", "2019-05-30");
map.put("recvDate", "2019-07-07");
// Insert image
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
BufferedImage bufferImg = ImageIO.read(BarcodeUtil.generateToStream("001"));
ImageIO.write(bufferImg, "jpg", byteArrayOut);
ImageEntity imageEntity = new ImageEntity(byteArrayOut.toByteArray(), 200, 1000);
map.put("barcode", imageEntity);
mapList.add(map);
}
total.put("list", mapList);Image Export Details
EasyPOI supports image export via URL or byte[]. In this example, barcodes are generated dynamically and exported as byte[]. The built‑in ImageEntity bean sets width, height, and span. Note that RowSpan/ColumnSpan affect height handling; the image height should be set explicitly because merged cells do not inherit the span.
//BaseExportService.java
ClientAnchor anchor;
if (type.equals(ExcelType.HSSF)) {
anchor = new HSSFClientAnchor(0, 0, 0, 0,
(short) cell.getColumnIndex(), cell.getRow().getRowNum(),
(short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
} else {
anchor = new XSSFClientAnchor(0, 0, 0, 0,
(short) cell.getColumnIndex(), cell.getRow().getRowNum(),
(short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
} //ExcelExportOfTemplateUtil.java
if (img.getRowspan() > 1 || img.getColspan() > 1) {
img.setHeight(0);
PoiMergeCellUtil.addMergedRegion(cell.getSheet(), cell.getRowIndex(),
cell.getRowIndex() + img.getRowspan() - 1,
cell.getColumnIndex(), cell.getColumnIndex() + img.getColspan() - 1);
}Exporting Data to the Template
After preparing the template and data, render them with the following utility method:
public static void exportByTemplate(String templateName, Map<String, Object> data, OutputStream fileOut) {
TemplateExportParams params = new TemplateExportParams("export/template/" + templateName, true);
try {
Workbook workbook = ExcelExportUtil.exportExcel(params, data);
workbook.write(fileOut);
} catch (Exception e) {
LogUtil.error("", e);
}
}Conclusion
Most EasyPOI tutorials only cover basic row insertion, but real‑world Excel templates can be far more complex. This article introduced key concepts, expression syntax, image export pitfalls, and provided practical code to help developers avoid common mistakes and boost productivity.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
