Рассказывает автор блога javarevisited.blogspot.ru
Из этой статьи вы сможете узнать о записи и чтении данных из Excel файлов в Java (будет рассмотрен как XLS
, так и XLSX
формат). Мы будем использовать библиотеку Apache POI и сосредоточимся на работе с типами String
и Date
, работа с последним происходит достаточно хитро. Напомню, что работу с числами мы уже рассмотрели в другой статье.
Библиотеку poi-XX.jar
вы можете использовать для всех старых (xls
, doc
, ppt
) файлов Microsoft Office, для новых (xlsx
, docx
, pptx
) вам понадобится poi-ooxml-XX.jar
. Очень важно понимать, что к чему относится, т.к. используемые классы тоже разные — для старых расширений это HSSFWorkbook
, а для новых — XSSFWorkbook
.
Подготовка: загрузка библиотек и зависимостей
Конечно, существует достаточно много открытых библиотек, которые позволяют работать с Excel файлами в Java, например, JXL, но мы будем использовать имеющую самый обширный API и самую популярную — Apache POI. Чтобы её использовать, вам нужно скачать jar
файлы и добавить их через Eclipse вручную, или вы можете предоставить это Maven.
Во втором случае вам нужно просто добавить следующие две зависимости:
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.12</version>
</dependency>
</dependencies>
Самое удобное в Maven — что он загрузит не только указанные poi.jar
и poi-ooxml.jar
, но и все jar файлы, которые используются внутри, то есть xmlbeans-2.6.0.jar
, stax-api-1.0.1.jar
, poi-ooxml-schemas-3.12.jar
и commons-codec-1.9.jar
.
Если вы будете добавлять библиотеки вручную — не забудьте о вышеназванных файлах. Скачать всё можно отсюда. Помните — если вы загрузите только poi-XX.jar
, то ваш код скомпилируется без ошибок, но потом упадёт с java.lang.NoClassDefFoundError: org/apache/xmlbeans/XmlObject
, так как внутри будет вызываться xmlbeans.jar
.
Запись
В этом примере мы запишем в xls
файл следующие данные: в первую ячейку — строку с именем, а во вторую — дату рождения. Вот пошаговая инструкция:
- Создаём объект
HSSFWorkBook
; - Создаём лист, используя на объекте, созданном в предыдущем шаге,
createSheet()
; - Создаём на листе строку, используя
createRow()
; - Создаём в строке ячейку —
createCell()
; - Задаём значение ячейки через
setCellValue();
- Записываем
workbook
вFile
черезFileOutputStream
; - Закрываем
workbook
, вызываяclose()
.
Для записи строк или чисел этого вполне достаточно, но чтобы записать дату, нам понадобится сделать ещё кое-что:
- Создать
DateFormat
; - Создать
CellStyle
; - Записать
DateFormat
вCellStyle
; - Записать
CellStyle
в ячейку; - Теперь в эту ячейку можно записать объект
Date
через всё тот жеsetCellValue
; - Чтобы дата поместилась в ячейку, нам нужно добавить столбцу свойство автоматически менять размер:
sheet.autoSizeColumn(1)
.
Всё вместе это будет выглядеть так:
@SuppressWarnings("deprecation")
public static void writeIntoExcel(String file) throws FileNotFoundException, IOException{
Workbook book = new HSSFWorkbook();
Sheet sheet = book.createSheet("Birthdays");
// Нумерация начинается с нуля
Row row = sheet.createRow(0);
// Мы запишем имя и дату в два столбца
// имя будет String, а дата рождения --- Date,
// формата dd.mm.yyyy
Cell name = row.createCell(0);
name.setCellValue("John");
Cell birthdate = row.createCell(1);
DataFormat format = book.createDataFormat();
CellStyle dateStyle = book.createCellStyle();
dateStyle.setDataFormat(format.getFormat("dd.mm.yyyy"));
birthdate.setCellStyle(dateStyle);
// Нумерация лет начинается с 1900-го
birthdate.setCellValue(new Date(110, 10, 10));
// Меняем размер столбца
sheet.autoSizeColumn(1);
// Записываем всё в файл
book.write(new FileOutputStream(file));
book.close();
}
Чтение
Теперь мы считаем из только что созданного файла то, что мы туда записали.
- Для начала создадим
HSSFWorkBook
, передав в конструкторFileInputStream
; - Получаем лист, передавая в
getSheet()
его номер или название; - Получаем строку, используя
getRow()
; - Получаем ячейку, используя
getCell()
; - Узнаём тип ячейки, используя на ней
getCellType()
; - В зависимости от типа ячейки, читаем её значения, используя
getStringCellValue()
,getNumericCellValue()
илиgetDateCellValue()
; - Закрываем
workbook
используяclose()
.
Напомню, что дату Excel хранит как числа, т.е. тип ячейки всё равно будет CELL_TYPE_NUMERIC
.
В виде кода это будет выглядеть следующим образом:
public static void readFromExcel(String file) throws IOException{
HSSFWorkbook myExcelBook = new HSSFWorkbook(new FileInputStream(file));
HSSFSheet myExcelSheet = myExcelBook.getSheet("Birthdays");
HSSFRow row = myExcelSheet.getRow(0);
if(row.getCell(0).getCellType() == HSSFCell.CELL_TYPE_STRING){
String name = row.getCell(0).getStringCellValue();
System.out.println("name : " + name);
}
if(row.getCell(1).getCellType() == HSSFCell.CELL_TYPE_NUMERIC){
Date birthdate = row.getCell(1).getDateCellValue();
System.out.println("birthdate :" + birthdate);
}
myExcelBook.close();
}
В заключение
Как уже упомналось выше, чтение из xlsx
файлов ничем принципиально не отличается — нужно только вместо HSSFWorkBook
, HSSFSheet
, HSSFRow
(и прочих) из poi-XX.jar
использовать XSSFWorkBook
, XSSFSheet
, XSSFRow
из poi-ooxml-XX.jar
. Это всё, что вам нужно знать для чтения и записи в файлы Excel. Разумеется, с помощью библиотеки Apache POI вы можете сделать гораздо больше, но эта статья должна помочь вам быстрее в ней освоиться.
Перевод статьи «How to Read Write Excel file in Java — POI Example»
The Excel file is a spreadsheet file format created by Microsoft for use with Microsoft Excel. You can use the file to create, view, edit, analyse data, charts, budgets and more. In this tutorial, I will show you how to use Spring Boot to download Excel file from a table in MySQL Database using Apache POI.
Related Posts:
– Spring Boot: Upload/Import Excel file data into MySQL Database
– Spring Boot Multipart File upload example
– How to upload multiple files in Java Spring Boot
– Upload/Import CSV file to MySQL Database in Spring Boot
CSV file instead:
Spring Boot Download CSV file from Database example
Deployment:
– Deploy Spring Boot App on AWS – Elastic Beanstalk
– Docker Compose: Spring Boot and MySQL example
Contents
- Spring Boot Rest API: Download Excel File
- Technology
- Project Structure
- Setup Spring Boot Download Excel File project
- Configure Spring Datasource, JPA, Hibernate
- Define Data Model
- Create Data Repository for working with Database
- Implement Excel Helper Class
- Create Excel File Service
- Create Controller for Excel File Download
- Run the Spring Boot Download Excel File App
- Conclusion
- Further Reading
- Source Code
Assume that we have a tutorials table in MySQL database like this:
We’re gonna create a Spring Boot Application that provides APIs for downloading MySQL table data as Excel file with following content:
If you send request to /api/excel/download
, the server will return a response with an Excel file tutorials.xlsx that contains data in MySQL table:
How to do this?
You need to set the HTTP header:
"Content-disposition" : "attachment; filename=[yourFileName]"
"Content-Type" : "application/vnd.ms-excel"
We’re gonna apply the information above later in this tutorial.
You can also find how to upload Excel File to the Spring Server & store data in MySQL Database in the post:
Spring Boot: Upload/Import Excel file data into MySQL Database
Technology
- Java 8
- Spring Boot 2 (with Spring Web MVC)
- Maven 3.6.1
- Apache POI 4.1.2
Project Structure
This is the project directory that we’re gonna build:
– ExcelHelper
provides functions to write to Excel file.
– Tutorial
data model class corresponds to entity and table tutorials.
– TutorialRepository
is an interface that extends JpaRepository
for persisting data.
– ExcelService
uses ExcelHelper
and TutorialRepository
methods load data to Excel file.
– ExcelController
calls ExcelService
methods and export Rest API for downloading Excel files.
– application.properties contains configuration for Spring Data.
– pom.xml for Spring Boot, MySQL connector, Apache POI dependencies.
Setup Spring Boot Download Excel File project
Use Spring web tool or your development tool (Spring Tool Suite, Eclipse, Intellij) to create a Spring Boot project.
Then open pom.xml and add these dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
Configure Spring Datasource, JPA, Hibernate
Under src/main/resources folder, open application.properties and write these lines.
spring.datasource.url= jdbc:mysql://localhost:3306/testdb?useSSL=false
spring.datasource.username= root
spring.datasource.password= 123456
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto= update
spring.datasource.username
&spring.datasource.password
properties are the same as your database installation.- Spring Boot uses Hibernate for JPA implementation, we configure
MySQL5InnoDBDialect
for MySQL database spring.jpa.hibernate.ddl-auto
is used for database initialization. We set the value toupdate
value so that a table will be created in the database automatically corresponding to defined data model. Any change to the model will also trigger an update to the table. For production, this property should bevalidate
.
Define Data Model
Our Data model is Tutorial with four fields: id, title, description, published.
In model package, we define Tutorial
class.
model/Tutorial.java
package com.bezkoder.spring.files.excel.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "tutorials")
public class Tutorial {
@Id
@Column(name = "id")
private long id;
@Column(name = "title")
private String title;
@Column(name = "description")
private String description;
@Column(name = "published")
private boolean published;
public Tutorial() {
}
public Tutorial(String title, String description, boolean published) {
this.title = title;
this.description = description;
this.published = published;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isPublished() {
return published;
}
public void setPublished(boolean isPublished) {
this.published = isPublished;
}
@Override
public String toString() {
return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]";
}
}
– @Entity
annotation indicates that the class is a persistent Java class.
– @Table
annotation provides the table that maps this entity.
– @Id
annotation is for the primary key.
– @Column
annotation is used to define the column in database that maps annotated field.
Create Data Repository for working with Database
Let’s create a repository to interact with Tutorials from the database.
In repository package, create TutorialRepository
interface that extends JpaRepository
.
repository/TutorialRepository.java
package com.bezkoder.spring.files.excel.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.bezkoder.spring.files.excel.model.Tutorial;
public interface TutorialRepository extends JpaRepository<Tutorial, Long> {
}
Now we can use JpaRepository’s methods: save()
, findOne()
, findById()
, findAll()
, count()
, delete()
, deleteById()
… without implementing these methods.
The quantity of rows in Excel file (also tutorials table) could be large, so you may want to get only several at once by modifying this Repository to work with Pagination, the instruction can be found at:
Spring Boot Pagination & Filter example | Spring JPA, Pageable
Implement Excel Helper Class
We’re gonna use Apache POI classes such as: Workbook
, Sheet
, Row
, Cell
.
Let me summarize the steps for writing to Excel file:
- create a new
Workbook
- create a new
Sheet
usingWorkbook.createSheet()
- iterate over
tutorials
list - for each
Tutorial
, create aRow
usingSheet.createRow()
- create
Cell
usingRow.createCell()
, then useCell.setCellValue()
- use
Workbook.write()
to write outByteArrayOutputStream
Workbook workbook = new XSSFWorkbook();
Sheet sheet = Workbook.createSheet(SHEET);
for (Tutorial tutorial : tutorials) {
Row row = sheet.createRow(rowIdx++);
row.createCell(0).setCellValue(tutorial.getId());
row.createCell(1).setCellValue(tutorial.getTitle());
row.createCell(2).setCellValue(tutorial.getDescription());
row.createCell(3).setCellValue(tutorial.isPublished());
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
workbook.write(out);
return new ByteArrayInputStream(out.toByteArray());
Under helper package, we create ExcepHelper
class with tutorialsToExcel()
method which processes a list of Tutorials, return a ByteArrayInputStream
for Excel file later.
Here is full code of helper/ExcelHelper.java:
package com.bezkoder.spring.files.excel.helper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.bezkoder.spring.files.excel.model.Tutorial;
public class ExcelHelper {
public static String TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
static String[] HEADERs = { "Id", "Title", "Description", "Published" };
static String SHEET = "Tutorials";
public static ByteArrayInputStream tutorialsToExcel(List<Tutorial> tutorials) {
try (Workbook workbook = new XSSFWorkbook(); ByteArrayOutputStream out = new ByteArrayOutputStream();) {
Sheet sheet = workbook.createSheet(SHEET);
// Header
Row headerRow = sheet.createRow(0);
for (int col = 0; col < HEADERs.length; col++) {
Cell cell = headerRow.createCell(col);
cell.setCellValue(HEADERs[col]);
}
int rowIdx = 1;
for (Tutorial tutorial : tutorials) {
Row row = sheet.createRow(rowIdx++);
row.createCell(0).setCellValue(tutorial.getId());
row.createCell(1).setCellValue(tutorial.getTitle());
row.createCell(2).setCellValue(tutorial.getDescription());
row.createCell(3).setCellValue(tutorial.isPublished());
}
workbook.write(out);
return new ByteArrayInputStream(out.toByteArray());
} catch (IOException e) {
throw new RuntimeException("fail to import data to Excel file: " + e.getMessage());
}
}
}
Create Excel File Service
ExcelService
class will be annotated with @Service
annotation, it uses ExcelHelper
and TutorialRepository
in load()
method which read data from database and return ByteArrayInputStream
.
service/ExcelService.java
package com.bezkoder.spring.files.excel.service;
import java.io.ByteArrayInputStream;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bezkoder.spring.files.excel.helper.ExcelHelper;
import com.bezkoder.spring.files.excel.model.Tutorial;
import com.bezkoder.spring.files.excel.repository.TutorialRepository;
@Service
public class ExcelService {
@Autowired
TutorialRepository repository;
public ByteArrayInputStream load() {
List<Tutorial> tutorials = repository.findAll();
ByteArrayInputStream in = ExcelHelper.tutorialsToExcel(tutorials);
return in;
}
}
Create Controller for Excel File Download
In controller package, we create ExcelController
class for Rest Apis.
– @CrossOrigin
is for configuring allowed origins.
– @Controller
annotation indicates that this is a controller.
– @GetMapping
getFile() method.
– We also use @Autowired
to inject implementation of ExcelService
bean to local variable.
controller/ExcelController.java
package com.bezkoder.spring.files.excel.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.bezkoder.spring.files.excel.service.ExcelService;
@CrossOrigin("http://localhost:8081")
@Controller
@RequestMapping("/api/excel")
public class ExcelController {
@Autowired
ExcelService fileService;
@GetMapping("/download")
public ResponseEntity<Resource> getFile() {
String filename = "tutorials.xlsx";
InputStreamResource file = new InputStreamResource(fileService.load());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename)
.contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
.body(file);
}
}
Run the Spring Boot Download Excel File App
Run Spring Boot application with command: mvn spring-boot:run
.
Conclusion
Today we’ve built a Rest API using Spring Boot to download Excel file that contains table data in MySQL database.
We also see how to use Apache POI to write data to Excel Sheet, JpaRepository
to retrieve items in database table without need of boilerplate code.
If you want to add Pagination to this Spring project, you can find the instruction at:
Spring Boot Pagination & Filter example | Spring JPA, Pageable
You can also find how to upload Excel File to the Spring Server & store data in MySQL Database in the post:
Spring Boot: Upload/Import Excel file data into MySQL Database
For CSV file instead:
Spring Boot Download CSV file from Database example
Happy learning! See you again.
Further Reading
- Spring Data JPA Reference Documentation
- https://github.com/apache/poi
Deployment:
– Deploy Spring Boot App on AWS – Elastic Beanstalk
– Docker Compose: Spring Boot and MySQL example
Source Code
You can find the complete source code for this tutorial on Github.
5.1. Books
Create Book
POJO:
src/main/java/example/micronaut/Book.java
package example.micronaut;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Introspected;
import javax.validation.constraints.NotBlank;
@Introspected
public class Book {
@NonNull
@NotBlank
private final String isbn;
@NonNull
@NotBlank
private final String name;
public Book(@NonNull @NotBlank String isbn, @NonNull @NotBlank String name) {
this.isbn = isbn;
this.name = name;
}
@NonNull
public String getIsbn() {
return isbn;
}
@NonNull
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
if (!isbn.equals(book.isbn)) return false;
return name.equals(book.name);
}
@Override
public int hashCode() {
int result = isbn.hashCode();
result = 31 * result + name.hashCode();
return result;
}
}
Create an interface to encapsulate Book retrieval.
src/main/java/example/micronaut/BookRepository.java
package example.micronaut;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.context.annotation.DefaultImplementation;
import java.util.List;
@DefaultImplementation(BookRepositoryImpl.class)
public interface BookRepository {
@NonNull
List<Book> findAll();
}
Create a bean which implements the previous interface:
src/main/java/example/micronaut/BookRepositoryImpl.java
package example.micronaut;
import io.micronaut.core.annotation.NonNull;
import jakarta.inject.Singleton;
import java.util.Arrays;
import java.util.List;
@Singleton (1)
public class BookRepositoryImpl implements BookRepository {
@NonNull
@Override
public List<Book> findAll() {
return Arrays.asList(
new Book("1491950358", "Building Microservices"),
new Book("1680502395", "Release It!"),
new Book("0321601912", "Continuous Delivery:"));
}
}
1 | Use jakarta.inject.Singleton to designate a class as a singleton. |
5.2. Spreadsheet Builder
Spreadsheet builder provides convenient way how to read and create MS Excel OfficeOpenXML Documents (XSLX) focus not only on content side but also on easy styling.
pom.xml
<dependency>
<groupId>builders.dsl</groupId>
<artifactId>spreadsheet-builder-poi:2.2.1</artifactId>
<scope>compile</scope>
</dependency>
5.3. Excel Creation
Create a interface to encapsulate Excel generation:
src/main/java/example/micronaut/BookExcelService.java
package example.micronaut;
import java.util.List;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.context.annotation.DefaultImplementation;
import io.micronaut.http.server.types.files.SystemFile;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@DefaultImplementation(BookExcelServiceImpl.class)
public interface BookExcelService {
String SHEET_NAME = "Books";
String HEADER_ISBN = "Isbn";
String HEADER_NAME = "Name";
String HEADER_EXCEL_FILE_SUFIX = ".xlsx";
String HEADER_EXCEL_FILE_PREFIX = "books";
String HEADER_EXCEL_FILENAME = HEADER_EXCEL_FILE_PREFIX + HEADER_EXCEL_FILE_SUFIX;
@NonNull
SystemFile excelFileFromBooks(@NonNull @NotNull List<@Valid Book> bookList); (1)
}
1 | SystemFile is specified as the return type of a route execution to indicate the given file should be downloaded by the client instead of displayed. |
Externalize your styles configuration into a class implementing builders.dsl.spreadsheet.builder.api.Stylesheet
interface to maximize code reuse.
src/main/java/example/micronaut/BookExcelStylesheet.java
package example.micronaut;
import builders.dsl.spreadsheet.api.FontStyle;
import builders.dsl.spreadsheet.builder.api.CanDefineStyle;
import builders.dsl.spreadsheet.builder.api.Stylesheet;
public class BookExcelStylesheet implements Stylesheet {
public static final String STYLE_HEADER = "header";
@Override
public void declareStyles(CanDefineStyle stylable) {
stylable.style(STYLE_HEADER, st -> {
st.font(f -> f.style(FontStyle.BOLD));
});
}
}
Create a bean which generates the Excel file.
src/main/java/example/micronaut/BookExcelServiceImpl.java
package example.micronaut;
import builders.dsl.spreadsheet.builder.poi.PoiSpreadsheetBuilder;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.exceptions.HttpStatusException;
import io.micronaut.http.server.types.files.SystemFile;
import jakarta.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Stream;
@Singleton (1)
public class BookExcelServiceImpl implements BookExcelService {
private static final Logger LOG = LoggerFactory.getLogger(BookExcelServiceImpl.class);
@NonNull
public SystemFile excelFileFromBooks(@NonNull @NotNull List<@Valid Book> bookList) {
try {
File file = File.createTempFile(HEADER_EXCEL_FILE_PREFIX, HEADER_EXCEL_FILE_SUFIX);
PoiSpreadsheetBuilder.create(file).build(w -> {
w.apply(BookExcelStylesheet.class);
w.sheet(SHEET_NAME, s -> {
s.row(r -> Stream.of(HEADER_ISBN, HEADER_NAME)
.forEach(header -> r.cell(cd -> {
cd.value(header);
cd.style(BookExcelStylesheet.STYLE_HEADER);
})
));
for (Book book : bookList) {
s.row(r -> {
r.cell(book.getIsbn());
r.cell(book.getName());
});
}
});
});
return new SystemFile(file).attach(HEADER_EXCEL_FILENAME);
} catch (IOException e) {
LOG.error("File not found exception raised when generating excel file");
}
throw new HttpStatusException(HttpStatus.SERVICE_UNAVAILABLE, "error generating excel file");
}
}
1 | Use jakarta.inject.Singleton to designate a class as a singleton. |
5.4. Controller
5.5. Views
Although the Micronaut framework is primarily designed around message encoding / decoding, there are occasions where it is convenient to render a view on the server side.
To use the Thymeleaf Java template engine to render views in a Micronaut application, add the following dependency on your classpath.
pom.xml
<dependency>
<groupId>io.micronaut.views</groupId>
<artifactId>micronaut-views-thymeleaf</artifactId>
<scope>compile</scope>
</dependency>
Create a controller:
src/main/java/example/micronaut/HomeController.java
package example.micronaut;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
import io.micronaut.http.server.types.files.SystemFile;
import io.micronaut.views.View;
import java.util.HashMap;
import java.util.Map;
@Controller (1)
public class HomeController {
private final BookRepository bookRepository;
private final BookExcelService bookExcelService;
public HomeController(BookRepository bookRepository, (2)
BookExcelService bookExcelService) {
this.bookRepository = bookRepository;
this.bookExcelService = bookExcelService;
}
@View("index") (3)
@Get
public Map<String, String> index() {
return new HashMap<>();
}
@Produces(value = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
@Get("/excel") (4)
public SystemFile excel() { (5)
return bookExcelService.excelFileFromBooks(bookRepository.findAll());
}
}
1 | The class is defined as a controller with the @Controller annotation mapped to the path / . |
2 | Constructor injection |
3 | Use @View annotation to specify which template to use to render the response. |
4 | You can specify the HTTP verb that a controller action responds to. To respond to a GET request, use io.micronaut.http.annotation.Get |
5 | SystemFile is specified as the return type of a route execution to indicate the given file should be downloaded by the client instead of displayed. |
The previous controller index method renders a simple view with a link to download the Excel file:
src/main/resources/views/index.html
<!DOCTYPE html>
<html>
<head>
<title>Micronaut</title>
</head>
<body>
<p><a href="/excel">Excel</a></p>
</body>
</html>
5.6. Tests
Often, file transfers remain untested in many applications. In this section, you will see how easy is to test that the
file downloads but also that the downloaded file contents match our expectations.
Create a test to verify the Excel file is downloaded and the content matches our expectations.
src/test/java/example/micronaut/DownloadExcelTest.java
package example.micronaut;
import builders.dsl.spreadsheet.query.api.SpreadsheetCriteria;
import builders.dsl.spreadsheet.query.api.SpreadsheetCriteriaResult;
import builders.dsl.spreadsheet.query.poi.PoiSpreadsheetCriteria;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.client.HttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import jakarta.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import static org.junit.jupiter.api.Assertions.assertEquals;
@MicronautTest (1)
class DownloadExcelTest {
@Inject
@Client("/")
HttpClient client; (2)
@Test
public void booksCanBeDownloadedAsAnExcelFile() throws FileNotFoundException {
HttpRequest<?> request = HttpRequest.GET("/excel")
.accept("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); (3)
HttpResponse<byte[]> response = client.toBlocking().exchange(request, byte[].class);
assertEquals(HttpStatus.OK, response.getStatus());
InputStream inputStream = new ByteArrayInputStream(response.body()); (4)
SpreadsheetCriteria query = PoiSpreadsheetCriteria.FACTORY.forStream(inputStream);
SpreadsheetCriteriaResult result = query.query(workbookCriterion -> {
workbookCriterion.sheet(BookExcelService.SHEET_NAME, sheetCriterion ->
sheetCriterion.row(rowCriterion ->
rowCriterion.cell(cellCriterion -> cellCriterion.value("Building Microservices"))));
});
assertEquals(1, result.getCells().size());
}
}
1 | Annotate the class with @MicronautTest so the Micronaut framework will initialize the application context and the embedded server. More info. |
2 | Inject the HttpClient bean and point it to the embedded server. |
3 | Creating HTTP Requests is easy thanks to the Micronaut framework fluid API. |
4 | Use .body() to retrieve the excel bytes. |
Learn to read excel, write excel, evaluate formula cells and apply custom formatting to the generated excel files using Apache POI library with examples.
If we are building software for the HR or Finance domain, there is usually a requirement for generating excel reports across management levels. Apart from reports, we can also expect some input data for the applications coming in the form of excel sheets and the application is expected to support this requirement.
Apache POI is a well-trusted library among many other open-source libraries to handle such usecases involving excel files. Please note that, in addition, we can read and write MS Word and MS PowerPoint files also using the Apache POI library.
This Apache POI tutorial will discuss some everyday excel operations in real-life applications.
- 1. Maven Dependency
- 2. Important Classes in POI Library
- 3. Writing an Excel File
- 4. Reading an Excel File
- 5. Add and Evaluate Formula Cells
- 6. Formatting the Cells
- 7. Conclusion
1. Maven Dependency
If we are working on a maven project, we can include the Apache POI dependencies in pom.xml
file using this:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.2</version>
</dependency>
2. Important Classes in POI Library
-
HSSF, XSSF and XSSF classes
Apache POI main classes usually start with either HSSF, XSSF or SXSSF.
- HSSF – is the POI Project’s pure Java implementation of the Excel 97(-2007) file format. e.g., HSSFWorkbook, HSSFSheet.
- XSSF – is the POI Project’s pure Java implementation of the Excel 2007 OOXML (.xlsx) file format. e.g., XSSFWorkbook, XSSFSheet.
- SXSSF (since 3.8-beta3) – is an API-compatible streaming extension of XSSF to be used when huge spreadsheets have to be produced and heap space is limited. e.g., SXSSFWorkbook, SXSSFSheet. SXSSF achieves its low memory footprint by limiting access to the rows within a sliding window, while XSSF gives access to all rows in the document.
-
Row and Cell
Apart from the above classes, Row and Cell interact with a particular row and a particular cell in an excel sheet.
-
Styling Related Classes
A wide range of classes like CellStyle, BuiltinFormats, ComparisonOperator, ConditionalFormattingRule, FontFormatting, IndexedColors, PatternFormatting, SheetConditionalFormatting etc. are used when you have to add formatting to a sheet, primarily based on some rules.
-
FormulaEvaluator
Another helpful class FormulaEvaluator is used to evaluate the formula cells in an excel sheet.
3. Writing an Excel File
I am taking this example first so we can reuse the excel sheet created by this code in further examples.
Writing excel using POI is very simple and involves the following steps:
- Create a workbook
- Create a sheet in workbook
- Create a row in sheet
- Add cells to sheet
- Repeat steps 3 and 4 to write more data
It seems very simple, right? Let’s have a look at the code doing these steps.
Java program to write an excel file using Apache POI library.
package com.howtodoinjava.demo.poi;
//import statements
public class WriteExcelDemo
{
public static void main(String[] args)
{
//Blank workbook
XSSFWorkbook workbook = new XSSFWorkbook();
//Create a blank sheet
XSSFSheet sheet = workbook.createSheet("Employee Data");
//This data needs to be written (Object[])
Map<String, Object[]> data = new TreeMap<String, Object[]>();
data.put("1", new Object[] {"ID", "NAME", "LASTNAME"});
data.put("2", new Object[] {1, "Amit", "Shukla"});
data.put("3", new Object[] {2, "Lokesh", "Gupta"});
data.put("4", new Object[] {3, "John", "Adwards"});
data.put("5", new Object[] {4, "Brian", "Schultz"});
//Iterate over data and write to sheet
Set<String> keyset = data.keySet();
int rownum = 0;
for (String key : keyset)
{
Row row = sheet.createRow(rownum++);
Object [] objArr = data.get(key);
int cellnum = 0;
for (Object obj : objArr)
{
Cell cell = row.createCell(cellnum++);
if(obj instanceof String)
cell.setCellValue((String)obj);
else if(obj instanceof Integer)
cell.setCellValue((Integer)obj);
}
}
try
{
//Write the workbook in file system
FileOutputStream out = new FileOutputStream(new File("howtodoinjava_demo.xlsx"));
workbook.write(out);
out.close();
System.out.println("howtodoinjava_demo.xlsx written successfully on disk.");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
See Also: Appending Rows to Excel
4. Reading an Excel File
Reading an excel file using POI is also very simple if we divide this into steps.
- Create workbook instance from an excel sheet
- Get to the desired sheet
- Increment row number
- iterate over all cells in a row
- repeat steps 3 and 4 until all data is read
Let’s see all the above steps in code. I am writing the code to read the excel file created in the above example. It will read all the column names and the values in it – cell by cell.
Java program to read an excel file using Apache POI library.
package com.howtodoinjava.demo.poi;
//import statements
public class ReadExcelDemo
{
public static void main(String[] args)
{
try
{
FileInputStream file = new FileInputStream(new File("howtodoinjava_demo.xlsx"));
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
//Check the cell type and format accordingly
switch (cell.getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "t");
break;
}
}
System.out.println("");
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Program Output:
ID NAME LASTNAME
1.0 Amit Shukla
2.0 Lokesh Gupta
3.0 John Adwards
4.0 Brian Schultz
See Also: Apache POI – Read an Excel File using SAX Parser
5. Add and Evaluate Formula Cells
When working on complex excel sheets, we encounter many cells with formulas to calculate their values. These are formula cells. Apache POI also has excellent support for adding formula cells and evaluating already present formula cells.
Let’s see one example of how to add formula cells in excel?
The sheet has four cells in a row and the fourth one in the multiplication of all the previous 3 rows. So the formula will be: A2*B2*C2 (in the second row)
Java program to add formula in an excel file using Apache POI library.
public static void main(String[] args)
{
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Calculate Simple Interest");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("Pricipal");
header.createCell(1).setCellValue("RoI");
header.createCell(2).setCellValue("T");
header.createCell(3).setCellValue("Interest (P r t)");
Row dataRow = sheet.createRow(1);
dataRow.createCell(0).setCellValue(14500d);
dataRow.createCell(1).setCellValue(9.25);
dataRow.createCell(2).setCellValue(3d);
dataRow.createCell(3).setCellFormula("A2*B2*C2");
try {
FileOutputStream out = new FileOutputStream(new File("formulaDemo.xlsx"));
workbook.write(out);
out.close();
System.out.println("Excel with foumula cells written successfully");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Similarly, we want to read a file with formula cells and use the following logic to evaluate formula cells.
Java program to evaluate formula in an excel file using Apache POI library.
public static void readSheetWithFormula()
{
try
{
FileInputStream file = new FileInputStream(new File("formulaDemo.xlsx"));
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
//Check the cell type after eveluating formulae
//If it is formula cell, it will be evaluated otherwise no change will happen
switch (evaluator.evaluateInCell(cell).getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "tt");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "tt");
break;
case Cell.CELL_TYPE_FORMULA:
//Not again
break;
}
}
System.out.println("");
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
Program Output:
Pricipal RoI T Interest (P r t)
14500.0 9.25 3.0 402375.0
6. Formatting the Cells
So far we have seen examples of reading/writing and excel files using Apache POI. But, when creating a report in an excel file, it is essential to add formatting on cells that fit into any pre-determined criteria.
This formatting can be a different coloring based on a specific value range, expiry date limit etc.
In the below examples, we are taking a couple of such cell formatting examples for various purposes.
6.1. Cell value in a specific range
This code will color any cell in a range whose value is between a configured range. [e.g., between 50 and 70]
static void basedOnValue(Sheet sheet)
{
//Creating some random values
sheet.createRow(0).createCell(0).setCellValue(84);
sheet.createRow(1).createCell(0).setCellValue(74);
sheet.createRow(2).createCell(0).setCellValue(50);
sheet.createRow(3).createCell(0).setCellValue(51);
sheet.createRow(4).createCell(0).setCellValue(49);
sheet.createRow(5).createCell(0).setCellValue(41);
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
//Condition 1: Cell Value Is greater than 70 (Blue Fill)
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(ComparisonOperator.GT, "70");
PatternFormatting fill1 = rule1.createPatternFormatting();
fill1.setFillBackgroundColor(IndexedColors.BLUE.index);
fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
//Condition 2: Cell Value Is less than 50 (Green Fill)
ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.LT, "50");
PatternFormatting fill2 = rule2.createPatternFormatting();
fill2.setFillBackgroundColor(IndexedColors.GREEN.index);
fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A1:A6")
};
sheetCF.addConditionalFormatting(regions, rule1, rule2);
}
6.2. Highlight Duplicate Values
Highlight all cells which have duplicate values in observed cells.
static void formatDuplicates(Sheet sheet) {
sheet.createRow(0).createCell(0).setCellValue("Code");
sheet.createRow(1).createCell(0).setCellValue(4);
sheet.createRow(2).createCell(0).setCellValue(3);
sheet.createRow(3).createCell(0).setCellValue(6);
sheet.createRow(4).createCell(0).setCellValue(3);
sheet.createRow(5).createCell(0).setCellValue(5);
sheet.createRow(6).createCell(0).setCellValue(8);
sheet.createRow(7).createCell(0).setCellValue(0);
sheet.createRow(8).createCell(0).setCellValue(2);
sheet.createRow(9).createCell(0).setCellValue(8);
sheet.createRow(10).createCell(0).setCellValue(6);
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
// Condition 1: Formula Is =A2=A1 (White Font)
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($A$2:$A$11,A2)>1");
FontFormatting font = rule1.createFontFormatting();
font.setFontStyle(false, true);
font.setFontColorIndex(IndexedColors.BLUE.index);
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A2:A11")
};
sheetCF.addConditionalFormatting(regions, rule1);
sheet.getRow(2).createCell(1).setCellValue("<== Duplicates numbers in the column are highlighted. " +
"Condition: Formula Is =COUNTIF($A$2:$A$11,A2)>1 (Blue Font)");
}
6.3. Alternate Color Rows in Different Colors
A simple code to color each alternate row in a different color.
static void shadeAlt(Sheet sheet) {
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
// Condition 1: Formula Is =A2=A1 (White Font)
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),2)");
PatternFormatting fill1 = rule1.createPatternFormatting();
fill1.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.index);
fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A1:Z100")
};
sheetCF.addConditionalFormatting(regions, rule1);
sheet.createRow(0).createCell(1).setCellValue("Shade Alternating Rows");
sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),2) (Light Green Fill)");
}
6.4. Color amounts that are going to expire in the next 30 days
A handy code for financial projects which keeps track of deadlines.
static void expiryInNext30Days(Sheet sheet)
{
CellStyle style = sheet.getWorkbook().createCellStyle();
style.setDataFormat((short)BuiltinFormats.getBuiltinFormat("d-mmm"));
sheet.createRow(0).createCell(0).setCellValue("Date");
sheet.createRow(1).createCell(0).setCellFormula("TODAY()+29");
sheet.createRow(2).createCell(0).setCellFormula("A2+1");
sheet.createRow(3).createCell(0).setCellFormula("A3+1");
for(int rownum = 1; rownum <= 3; rownum++) sheet.getRow(rownum).getCell(0).setCellStyle(style);
SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
// Condition 1: Formula Is =A2=A1 (White Font)
ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("AND(A2-TODAY()>=0,A2-TODAY()<=30)");
FontFormatting font = rule1.createFontFormatting();
font.setFontStyle(false, true);
font.setFontColorIndex(IndexedColors.BLUE.index);
CellRangeAddress[] regions = {
CellRangeAddress.valueOf("A2:A4")
};
sheetCF.addConditionalFormatting(regions, rule1);
sheet.getRow(0).createCell(1).setCellValue("Dates within the next 30 days are highlighted");
}
I am ending this apache poi tutorial here to keep the post within a limit.
7. Conclusion
In this tutorial, we learned to read excel, write excel, set and evaluate formula cells, and format the cells with color codings using the Apache POI library.
Happy Learning !!
Source Code on Github
- Details
- Written by
- Last Updated on 30 May 2019 | Print Email
In this tutorial, I will share with you how to read Excel files programmatically using Java.
You know, Excel is the very popular file format created by Microsoft. Although it is not an opened file format, Java applications can still read and write Excel files using the Apache POI — the Java API for Microsoft Documents, because the development team uses reverse-engineering to understand the Excel file format. Hence the name POI stands for Poor Obfuscation Implementation.
This tutorial shows you how simple and easy it is to read Excel files using Apache POI’s API.
1. Getting Apache POI library
Apache POI is the pure Java API for reading and writing Excel files in both formats XLS (Excel 2003 and earlier) and XLSX (Excel 2007 and later). To use Apache POI in your Java project:
- For non-Maven projects:
- Download the latest release of the library here: Apache POI — Download Release ArtifactsExtract the zip file and add the appropriate JAR files to your project’s classpath:- If you are reading and writing only Excel 2003 format, only the file poi-VERSION.jar is enough.- If you are reading and writing Excel 2007 format, you have to include the following files:
- poi-ooxml-VERSION.jar
- poi-ooxml-schemas-VERSION.jar
- xmlbeans-VERSION.jar
- Download the latest release of the library here: Apache POI — Download Release ArtifactsExtract the zip file and add the appropriate JAR files to your project’s classpath:- If you are reading and writing only Excel 2003 format, only the file poi-VERSION.jar is enough.- If you are reading and writing Excel 2007 format, you have to include the following files:
- For Maven projects: Add the following dependency to your project’s pom.xml file:
- For Excel 2003 format only:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>VERSION</version> </dependency>
- For Excel 2007 format:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>VERSION</version> </dependency>
The latest stable version of Apache POI is 3.11 (at the time of writing this tutorial).
- For Excel 2003 format only:
2. The Apache POI API Basics
There are two main prefixes which you will encounter when working with Apache POI:
- HSSF: denotes the API is for working with Excel 2003 and earlier.
- XSSF: denotes the API is for working with Excel 2007 and later.
And to get started the Apache POI API, you just need to understand and use the following 4 interfaces:
- Workbook: high level representation of an Excel workbook. Concrete implementations are: HSSFWorkbookand XSSFWorkbook.
- Sheet: high level representation of an Excel worksheet. Typical implementing classes are HSSFSheetand XSSFSheet.
- Row: high level representation of a row in a spreadsheet. HSSFRowand XSSFRoware two concrete classes.
- Cell: high level representation of a cell in a row. HSSFCelland XSSFCellare the typical implementing classes.
Now, let’s walk through some real-life examples.
3. Reading from Excel File Examples
Suppose you want to read an Excel file whose content looks like the following screenshot:
This spreadsheet contains information about books (title, author and price).
A Simple Example to Read Excel File in Java
Here’s a dirty example that reads every cell in the first sheet of the workbook and prints out values in every cell, row by row:
package net.codejava.excel; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Iterator; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * A dirty simple program that reads an Excel file. * @author www.codejava.net * */ public class SimpleExcelReaderExample { public static void main(String[] args) throws IOException { String excelFilePath = "Books.xlsx"; FileInputStream inputStream = new FileInputStream(new File(excelFilePath)); Workbook workbook = new XSSFWorkbook(inputStream); Sheet firstSheet = workbook.getSheetAt(0); Iterator<Row> iterator = firstSheet.iterator(); while (iterator.hasNext()) { Row nextRow = iterator.next(); Iterator<Cell> cellIterator = nextRow.cellIterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: System.out.print(cell.getStringCellValue()); break; case Cell.CELL_TYPE_BOOLEAN: System.out.print(cell.getBooleanCellValue()); break; case Cell.CELL_TYPE_NUMERIC: System.out.print(cell.getNumericCellValue()); break; } System.out.print(" - "); } System.out.println(); } workbook.close(); inputStream.close(); } }
Output:
Head First Java - Kathy Serria - 79.0 - Effective Java - Joshua Bloch - 36.0 - Clean Code - Robert Martin - 42.0 - Thinking in Java - Bruce Eckel - 35.0 -
A More Object-Oriented Example to read Excel File
For nicer and more object-oriented program, let’s create a model class (Book.java) with the following code:
package net.codejava.excel; public class Book { private String title; private String author; private float price; public Book() { } public String toString() { return String.format("%s - %s - %f", title, author, price); } // getters and setters }
Write a method that reads value of a cell as following:
private Object getCellValue(Cell cell) { switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: return cell.getStringCellValue(); case Cell.CELL_TYPE_BOOLEAN: return cell.getBooleanCellValue(); case Cell.CELL_TYPE_NUMERIC: return cell.getNumericCellValue(); } return null; }
Next, implement a method that reads an Excel file and returns a list of books:
public List<Book> readBooksFromExcelFile(String excelFilePath) throws IOException { List<Book> listBooks = new ArrayList<>(); FileInputStream inputStream = new FileInputStream(new File(excelFilePath)); Workbook workbook = new XSSFWorkbook(inputStream); Sheet firstSheet = workbook.getSheetAt(0); Iterator<Row> iterator = firstSheet.iterator(); while (iterator.hasNext()) { Row nextRow = iterator.next(); Iterator<Cell> cellIterator = nextRow.cellIterator(); Book aBook = new Book(); while (cellIterator.hasNext()) { Cell nextCell = cellIterator.next(); int columnIndex = nextCell.getColumnIndex(); switch (columnIndex) { case 1: aBook.setTitle((String) getCellValue(nextCell)); break; case 2: aBook.setAuthor((String) getCellValue(nextCell)); break; case 3: aBook.setPrice((double) getCellValue(nextCell)); break; } } listBooks.add(aBook); } workbook.close(); inputStream.close(); return listBooks; }
And here is the testing code:
public static void main(String[] args) throws IOException { String excelFilePath = "Books.xlsx"; ExcelReaderExample2 reader = new ExcelReaderExample2(); List<Book> listBooks = reader.readBooksFromExcelFile(excelFilePath); System.out.println(listBooks); }
Output:
[Head First Java - Kathy Serria - 79.000000, Effective Java - Joshua Bloch - 36.000000, Clean Code - Robert Martin - 42.000000, Thinking in Java - Bruce Eckel - 35.000000]
How to Read both Excel 2003 and 2007 format in Java
For better supporting both users using Excel 2003 and 2007, it’s recommended to write a separate factory method that returns an XSSFWorkbookor HSSFWorkbookdepending on the file extension of the file (.xls or .xlsx):
private Workbook getWorkbook(FileInputStream inputStream, String excelFilePath) throws IOException { Workbook workbook = null; if (excelFilePath.endsWith("xlsx")) { workbook = new XSSFWorkbook(inputStream); } else if (excelFilePath.endsWith("xls")) { workbook = new HSSFWorkbook(inputStream); } else { throw new IllegalArgumentException("The specified file is not Excel file"); } return workbook; }
And here’s a usage example of this factory method:
String excelFilePath = "Books.xlsx"; // can be .xls or .xlsx FileInputStream inputStream = new FileInputStream(new File(excelFilePath)); Workbook workbook = getWorkbook(inputStream, excelFilePath);
Reading Other Information
- Get a specific sheet:
Sheet thirdSheet = workbook.getSheetAt(2);
- Get sheet name:
String sheetName = sheet.getSheetName();
- Get total number of sheets in the workbook:
int numberOfSheets = workbook.getNumberOfSheets();
- Get all sheet names in the workbook:
int numberOfSheets = workbook.getNumberOfSheets(); for (int i = 0; i < numberOfSheets; i++) { Sheet aSheet = workbook.getSheetAt(i); System.out.println(aSheet.getSheetName()); }
- Get comment of a specific cell:
Comment cellComment = sheet.getCellComment(2, 2); System.out.println("comment: " + cellComment.getString());
For reading other information, see the getXXX() methods of the Workbook, Sheet, Row and Cell interfaces.
That’s how to read Excel files in Java programmatically. I recommend you to take this Java course to fully learn Java programming.
Related Java Excel Tutorials:
- How to Write Excel Files in Java using Apache POI
- Java Example to Read Password-protected Excel Files Using Apache POI
- Java Example to Update Existing Excel Files Using Apache POI
- Working with Formula Cells in Excel using Apache POI
References:
- Apache POI — the Java API for Microsoft Documents
- POI API Documentation (Javadocs)
- Apache POI Quick Guide
- Apache POI HOWTO
About the Author:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.