Skip to main content

Fill

This section explains how to use Fesod to fill data into files.

Placeholder Syntax

A template marks the cells to fill with {} placeholders. What sits inside the braces decides how the cell is filled:

PlaceholderMeaningFilled by
{name}a single variabledoFill(object), doFill(map)
{.name}the name property of every item of a listdoFill(list), fill(list, ...)
{data1.name}the same, for the list named data1fill(new FillWrapper("data1", list), ...)
\{name\}escaped with \, never parsednothing

The leading . is what makes a cell repeat once per item - downwards by default, or across the columns with FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL). The text before the . names which list the items come from, so one template can hold several lists side by side.

A cell may mix several placeholders with ordinary text, as in {name} is {number} years old this year. A placeholder the fill does not supply is cleared rather than left in the sheet: filling a list against {name}, or an object against {.name}, empties the cell and keeps only the text around it.

Escaping stops the braces from being parsed, but the \ characters are only removed when the same cell also holds a real placeholder. In a cell that contains nothing else, \{name\} is written out exactly as typed, backslashes included.

Simple Fill

Overview

Fill data into spreadsheet based on a template file using objects or Map.

POJO Class

@Getter
@Setter
@EqualsAndHashCode
public class FillData {
private String name;
private double number;
private Date date;
}

Data List

private List<FillData> data() {
List<FillData> list = ListUtils.newArrayList();
for (int i = 0; i < 10; i++) {
FillData fillData = new FillData();
fillData.setName("John Doe" + i);
fillData.setNumber(5.2);
fillData.setDate(new Date());
list.add(fillData);
}
return list;
}

Code Example

@Test
public void simpleFill() {
String templateFileName = "path/to/simple.xlsx";

// Approach 1: Fill based on object
FillData fillData = new FillData();
fillData.setName("John Doe");
fillData.setNumber(5.2);
FesodSheet.write("simpleFill.xlsx")
.withTemplate(templateFileName)
.sheet()
.doFill(fillData);

// Approach 2: Fill based on Map
Map<String, Object> map = new HashMap<>();
map.put("name", "John Doe");
map.put("number", 5.2);
FesodSheet.write("simpleFillMap.xlsx")
.withTemplate(templateFileName)
.sheet()
.doFill(map);
}

Template

ABCDE
1NameNumberComplexIgnoredEmpty
2{name}{number}{name} is {number} years old\{name\} ignored, {name}Empty{.empty}

Result

ABCDE
1NameNumberComplexIgnoredEmpty
2John Doe5.2John Doe is 5.2 years old{name} ignored, John DoeEmpty

Fill List

Overview

Fill multiple data items into a template list, supporting in-memory batch operations and file cache batch filling.

Code Example

@Test
public void listFill() {
String templateFileName = "path/to/list.xlsx";

// Approach 1: Fill all data at once
FesodSheet.write("listFill.xlsx")
.withTemplate(templateFileName)
.sheet()
.doFill(data());

// Approach 2: Batch filling
try (ExcelWriter writer = FesodSheet.write("listFillBatch.xlsx").withTemplate(templateFileName).build()) {
WriteSheet writeSheet = FesodSheet.writerSheet().build();
writer.fill(data(), writeSheet);
writer.fill(data(), writeSheet);
}
}

Template

ABC
1NameNumberDate
2{.name}{.number}{.date}

Result

Approach 1:

ABC
1NameNumberDate
2John Doe05.22026-07-31 19:55:44
3John Doe15.22026-07-31 19:55:44
4John Doe25.22026-07-31 19:55:44
11John Doe95.22026-07-31 19:55:44

Approach 2:

ABC
1NameNumberDate
2John Doe05.22026-07-31 19:55:44
11John Doe95.22026-07-31 19:55:44
12John Doe05.22026-07-31 19:55:44
21John Doe95.22026-07-31 19:55:44

Complex Fill

Overview

Fill various data types in a template, including lists and regular variables.

Code Example

@Test
public void complexFill() {
String templateFileName = "path/to/complex.xlsx";

try (ExcelWriter writer = FesodSheet.write("complexFill.xlsx").withTemplate(templateFileName).build()) {
WriteSheet writeSheet = FesodSheet.writerSheet().build();

// Fill list data, with forceNewRow enabled
FillConfig config = FillConfig.builder().forceNewRow(true).build();
writer.fill(data(), config, writeSheet);

// Fill regular variables
Map<String, Object> map = new HashMap<>();
map.put("date", "November 20, 2024");
map.put("total", 1000);
writer.fill(map, writeSheet);
}
}

Template

ABCD
1Statistics
2Time: {date}
3NameNumberNameNumber
4{.name}{.number}{.name}{.number}
5Total:{total}

Result

ABCD
1Statistics
2Time: November 20, 2024
3NameNumberNameNumber
4John Doe05.2John Doe05.2
5John Doe15.2John Doe15.2
6John Doe25.2John Doe25.2
13John Doe95.2John Doe95.2
14Total:1000

Complex Fill with Large Data

Overview

Optimize performance for filling large data, ensuring the template list is at the last row, and subsequent data is filled using WriteTable.

Code Example

@Test
public void complexFillWithTable() {
String templateFileName = "path/to/complexFillWithTable.xlsx";

try (ExcelWriter writer = FesodSheet.write("complexFillWithTable.xlsx").withTemplate(templateFileName).build()) {
WriteSheet writeSheet = FesodSheet.writerSheet().build();

// Fill list data
writer.fill(data(), writeSheet);

// Fill list data
Map<String, Object> map = new HashMap<>();
map.put("date", "November 20, 2024");
writer.fill(map, writeSheet);

// Fill statistical information
List<List<String>> totalList = new ArrayList<>();
totalList.add(Arrays.asList(null, null, null, "Total: 1000"));
writer.write(totalList, writeSheet);
}
}

Template

ABCD
1Statistics
2Time: {date}
3NameNumberNameNumber
4{.name}{.number}{.name}{.number}

Result

The file comes out the same as Complex Fill above. What changes is how it gets there. The template stops at the list row instead of reserving a row for {total}, and the total is appended afterwards with writer.write(...), so the list can grow to any length without rows below it to push down.

ABCD
1Statistics
2Time: November 20, 2024
3NameNumberNameNumber
4John Doe05.2John Doe05.2
5John Doe15.2John Doe15.2
6John Doe25.2John Doe25.2
13John Doe95.2John Doe95.2
14Total: 1000

Horizontal Fill

Overview

Fill list data horizontally, suitable for scenarios with dynamic column numbers.

Code Example

@Test
public void horizontalFill() {
String templateFileName = "path/to/horizontal.xlsx";

try (ExcelWriter writer = FesodSheet.write("horizontalFill.xlsx").withTemplate(templateFileName).build()) {
WriteSheet writeSheet = FesodSheet.writerSheet().build();

FillConfig config = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
writer.fill(data(), config, writeSheet);

Map<String, Object> map = new HashMap<>();
map.put("date", "November 20, 2024");
writer.fill(map, writeSheet);
}
}

Template

ABC
1StatisticsName{.name}
2Number{.number}
3Name{.name}
4Number{.number}
5Time: {date}

Result

ABCDEL
1StatisticsNameJohn Doe0John Doe1John Doe2John Doe9
2Number5.25.25.25.2
3NameJohn Doe0John Doe1John Doe2John Doe9
4Number5.25.25.25.2
5Time: November 20, 2024

Fill Multiple Lists Together

Overview

Support filling multiple lists simultaneously, with prefixes to differentiate between lists.

Code Example

@Test
public void compositeFill() {
String templateFileName = "path/to/composite.xlsx";

try (ExcelWriter writer = FesodSheet.write("compositeFill.xlsx").withTemplate(templateFileName).build()) {
WriteSheet writeSheet = FesodSheet.writerSheet().build();

// Use FillWrapper for filling multiple lists
// data1 is laid out across the columns, so it is filled horizontally
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
writer.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
writer.fill(new FillWrapper("data2", data()), writeSheet);
writer.fill(new FillWrapper("data3", data()), writeSheet);

Map<String, Object> map = new HashMap<>();
map.put("date", new Date());
writer.fill(map, writeSheet);
}
}

Template

ABCDE
1StatisticsName{data1.name}
2Number{data1.number}
3Name{data1.name}
4Number{data1.number}
5Time: {date}
6
7
8NameNumber
9{data2.name}{data2.number}
10NameNumber
11{data3.name}{data3.number}

Result

  • data1 is filled horizontally, so its ten items run across the columns from C to L on each of the four template rows.
  • data2 and data3 are filled downwards instead, occupying A/B in rows 9 to 18 and D/E in rows 11 to 20.
  • Calling fill again with the same list name appends to it, as in Fill List.
ABCDEL
1StatisticsNameJohn Doe0John Doe1John Doe2John Doe9
2Number5.25.25.25.2
3NameJohn Doe0John Doe1John Doe2John Doe9
4Number5.25.25.25.2
5Time: 2026-07-31 20:04:59
6
7
8NameNumber
9John Doe05.2
10John Doe15.2NameNumber
11John Doe25.2John Doe05.2
12John Doe35.2John Doe15.2
18John Doe95.2John Doe75.2
19John Doe85.2
20John Doe95.2