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​

ABCDE⋯L
1StatisticsNameJohn Doe0John Doe1John Doe2…John Doe9
2Number5.25.25.2…5.2
3NameJohn Doe0John Doe1John Doe2…John Doe9
4Number5.25.25.2…5.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.
ABCDE⋯L
1StatisticsNameJohn Doe0John Doe1John Doe2…John Doe9
2Number5.25.25.2…5.2
3NameJohn Doe0John Doe1John Doe2…John Doe9
4Number5.25.25.2…5.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