Excel utility for Java to read and write data in declarative way.

Overview

Data Excel Exporter

Maven Central

A Java wrapper using Apache POI to read and write Excel file in declarative fashion.

Installation

ExcelUtil is using Apache POI version 5.0.0

<dependency>
    <groupId>io.github.nambach</groupId>
    <artifactId>ExcelUtil</artifactId>
    <version>2.3.0</version>
</dependency>

Quick Guides

Write Excel

A very simple usage

The core building block to write data is DataTemplate<T>. It holds mapping rules of the DTO class you need to export Excel.

public class Main {

    static final DataTemplate<Book> BOOK_TEMPLATE = DataTemplate
            .fromClass(Book.class)
            .includeAllFields();

    public static void main(String[] args) {
        InputStream stream = BOOK_TEMPLATE.writeData(books);

        FileUtil.writeToDisk(".../books.xlsx", stream, true);
    }
}

Your DTO class should follow camelCase convention, so that the generated titles would be correct.

Customize Styles

The next building block is Style, which is pretty much the same as what you can configure with normal Excel.

static final Style BASED_STYLE = Style
        .builder()
        .fontName("Calibri")
        .fontSize((short) 12)
        .build();

static final Style HEADER_STYLE = Style
        .builder(BASED_STYLE)     // it is able to accumulate previous style
        .fontColorInHex("#ffffff")
        .backgroundColorInHex("#191970")
        .border(BorderSide.FULL)
        .horizontalAlignment(HorizontalAlignment.LEFT)
        .build();

Since Apache POI has some limitations regarding to stylings, it is recommended to pre-define your styles as static constant for optimization and further reuse.

Below is an example to apply styles conditionally.

public class Main {
    static final Style DATA_STYLE = ...
    static final Style HIGH_RATE = ...
    static final Style FAVORITE_ONE = ...

    static final DataTemplate<Book> BOOK_TEMPLATE = DataTemplate
            .fromClass(Book.class)
            .column(c -> c.field("isbn").title("ISBN"))  // customize column title
            .includeFields("title", "author")
            .column(c -> c.title("Category")
                          .transform(book -> book.getCategory().getName()))  // derive new column
            .column(c -> c.field("rating")
                          .conditionalStyle(book -> book.getRating() > 4 ?  // styles with conditions
                                                    HIGH_RATE : null))
            .config(cf -> cf.startAtCell("A2")
                            .autoSizeColumns(true)
                            .headerStyle(HEADER_STYLE)
                            .dataStyle(DATA_STYLE)
                            .conditionalRowStyle(book -> book.getTitle() // selective styling
                                            .contains("Harry Potter") ? FAVORITE_ONE : null));

    public static void main(String[] args) {
        InputStream stream = BOOK_TEMPLATE.writeData(books);

        FileUtil.writeToDisk(".../books.xlsx", stream, true);
    }
}

Result

Result

Merge rows

You can merge your data rows, either based on same cell values or a particular value that you specify.

Before doing so, you might want to sort your data so that the merging process can perform correctly.

books.sort(Comparator
     .comparing((Book book) -> book.getCategory().getId())
     .thenComparing(comparing(Book::getSubCategory).reversed())
     .thenComparing(Book::getTitle));

Here is example of how to configure merge rows.

static final Style VCENTER = Style.builder().verticalAlignment(VerticalAlignment.CENTER).build();

static final DataTemplate<Book> BOOK_TEMPLATE = DataTemplate
        .fromClass(Book.class)
        .includeFields("title")
        .column(c -> c.field("subCategory")
                      .style(VCENTER)
                      .mergeOnValue(true))  // merge cells with the same value consecutively
        .column(c -> c.title("Category")
                      .style(VCENTER)
                      .transform(book -> book.getCategory().getName())
                      .mergeOnId(book -> book.getCategory().getId()))  // merge on derived value
        .config(cf -> cf.startAtCell("A2")
                        .autoSizeColumns(true));

Result

Result

Read Excel

The building block to read data is ReaderConfig<T>.

ReaderConfig<Book> BOOK_READER = ReaderConfig
        .fromClass(Book.class)
        .titleAtRow(0)
        .dataFromRow(1)
        .column(0, "ibsn")
        .column(1, "title")
        .column(2, "author")
        .column(3, "category");

You can directly retrieve the config from your already defined DataTemplate<T>.

ReaderConfig<Book> BOOK_READER = BOOK_TEMPLATE.getReaderConfig();

InputStream stream = FileUtil.readFromDisk(".../book.xlsx");
List<Book> books = BOOK_READER.readSheet(stream);

For more flexible process while reading data, use built-in callback handler as below.

ReaderConfig<Book> READER_CONFIG = ReaderConfig
    .fromClass(Book.class)
    .titleAtRow(0)
    .dataFromRow(1)
    .column(0, "ibsn")
    .column(1, "title")
    .handler(set -> set.atColumn(2)
                       .handle((book, cell) -> {
                           String value = cell.readString();
                           book.getCategory().setName(value);
                       }))
    .handler(set -> set.fromColumn(3)
                       .handle((book, cell) -> {
                           String title = cell.getColumnTitle();
                           if (title.contains("Rating in")) {
                               String year = title.substring(10);
                               Double rating = cell.readDouble();
                               book.getRatingMap().put(year, rating);
                           }
                       }));

Documentation

Documentation can be found here.

Notes

  • Minimum JDK version: 1.8
  • Support Excel version:
    • 97-2003 (.xls)
    • 2007+ (.xlsx)

License

Released under Apache-2.0 License.

Comments
  • SequentialWriter does not reset cell pointer when creating new sheets

    SequentialWriter does not reset cell pointer when creating new sheets

    I use the SequentialWriter in one of my applications. After upgrading to ExelUtil 2.4.0 and POI 5.1 the behavior of the SequentialWriter has changed. After creating a new sheet, the cursor now sticks in the position it had in the previous sheet. New content will then typically be added in the next row beyond the last row of the content added last to the previous sheet. Thus, if you iteratively create new sheets and add content, you end up with an increased number of empty rows leading the actual content. In previous versions, content in new sheets was always added starting from the top row. This seems to be a bug.

    Example code (entires contains a HashMap of filled data templates):

    SequentialWriter writer = new SequentialWriter(); for( String sheet : entries.keySet() ) { writer.createNewSheet(sheet); writer.writeData(REPORT_TEMPLATE, entries.get(sheet)); } InputStream stream = writer.exportToFile(); FileUtil.writeToDisk(filename, stream, true);

    bug 
    opened by prof-thies-pfeiffer 3
  • excludeFields() seems to actually perform an

    excludeFields() seems to actually perform an "includeOnlyThis"

    Current condition in ColumnTemplate#excludeFields is removeIf(m -> !fields.contains(m.getField()) which means it removes all fields that are not in the list of removed fields. This is the wrong way around as far as I see.

    bug 
    opened by centic9 3
  • feat: add readSheetOrThrow methods to ReaderConfig

    feat: add readSheetOrThrow methods to ReaderConfig

    To support the following situations:

    List<Book> books = readerConfig.readSheetOrThrow(stream, rowErrors -> new BusinessException("Ignore error detail."))
                                   .stream()
                                   .filter(...)
                                   .collect(toList());
    
    List<Book> books = readerConfig.readSheetOrThrow(stream, rowErrors -> new BusinessException("Failed, " + rowErrors.size() + " errors!"))
                                   .stream()
                                   .filter(...)
                                   .collect(toList());
    
    opened by JustAnotherID 2
  • Please add documentation for extending / customizing the Validation framework

    Please add documentation for extending / customizing the Validation framework

    I noticed the WIKI has a link https://github.com/nambach/ExcelUtil/wiki/Reading-Validation But that page does not exist. I'm trying to create a custom validator but can't get it to work. Adding that page might help. (In particular I'm trying to create a validator that either allows null or empty cells or a valid integer.)

    documentation 
    opened by fvanwesterop 2
  • Handler ignores empty cells

    Handler ignores empty cells

    When iterating through each header to get row data it ignores all the empty cells and only get data from the first cell that have value .handler(set -> set.fromColumn(5)

    opened by VnVentX 1
  • Replace System.out/err in favor of Logger

    Replace System.out/err in favor of Logger

    Hi,

    It would be useful to replace all occurrences of System.out/err with a Logger and get rid of the "printStackTrace" methods or ignored exceptions.

    enhancement 
    opened by Nawrok 1
  • [Snyk] Upgrade org.apache.poi:poi-ooxml from 5.1.0 to 5.2.0

    [Snyk] Upgrade org.apache.poi:poi-ooxml from 5.1.0 to 5.2.0

    Snyk has created this PR to upgrade org.apache.poi:poi-ooxml from 5.1.0 to 5.2.0.

    :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.


    • The recommended version is 1 version ahead of your current version.
    • The recommended version was released 22 days ago, on 2022-01-06.

    Note: You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.

    For more information:

    ๐Ÿง View latest project report

    ๐Ÿ›  Adjust upgrade PR settings

    ๐Ÿ”• Ignore this dependency or unsubscribe from future upgrade PRs

    opened by snyk-bot 1
  • Use getters if available instead of accessing the field directly

    Use getters if available instead of accessing the field directly

    Other frameworks use the getter if it is available and only fall back to the field-value if no getter is available. This allows to "process" the value in the gettter.

    E.g. the following leads to empty column-values instead of "default":

    private String value;
    
    public String getValue() {
        if (value == null) {
            return "default";
        }
        return value;
    }
    
    opened by centic9 1
  • [Snyk] Upgrade org.apache.logging.log4j:log4j-api from 2.17.2 to 2.18.0

    [Snyk] Upgrade org.apache.logging.log4j:log4j-api from 2.17.2 to 2.18.0

    Snyk has created this PR to upgrade org.apache.logging.log4j:log4j-api from 2.17.2 to 2.18.0.

    :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.


    • The recommended version is 1 version ahead of your current version.
    • The recommended version was released 22 days ago, on 2022-06-28.

    Note: You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.

    For more information:

    ๐Ÿง View latest project report

    ๐Ÿ›  Adjust upgrade PR settings

    ๐Ÿ”• Ignore this dependency or unsubscribe from future upgrade PRs

    opened by snyk-bot 0
  • [Snyk] Upgrade org.projectlombok:lombok from 1.18.22 to 1.18.24

    [Snyk] Upgrade org.projectlombok:lombok from 1.18.22 to 1.18.24

    This PR was automatically created by Snyk using the credentials of a real user.


    Snyk has created this PR to upgrade org.projectlombok:lombok from 1.18.22 to 1.18.24.

    :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.


    • The recommended version is 1 version ahead of your current version.
    • The recommended version was released 24 days ago, on 2022-04-18.

    Note: You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.

    For more information:

    ๐Ÿง View latest project report

    ๐Ÿ›  Adjust upgrade PR settings

    ๐Ÿ”• Ignore this dependency or unsubscribe from future upgrade PRs

    opened by nambach 0
  • [Snyk] Upgrade org.apache.poi:poi from 5.2.1 to 5.2.2

    [Snyk] Upgrade org.apache.poi:poi from 5.2.1 to 5.2.2

    This PR was automatically created by Snyk using the credentials of a real user.


    Snyk has created this PR to upgrade org.apache.poi:poi from 5.2.1 to 5.2.2.

    :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.


    • The recommended version is 1 version ahead of your current version.
    • The recommended version was released a month ago, on 2022-03-12.

    Note: You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.

    For more information:

    ๐Ÿง View latest project report

    ๐Ÿ›  Adjust upgrade PR settings

    ๐Ÿ”• Ignore this dependency or unsubscribe from future upgrade PRs

    opened by nambach 0
  • [Snyk] Upgrade org.apache.logging.log4j:log4j-api from 2.18.0 to 2.19.0

    [Snyk] Upgrade org.apache.logging.log4j:log4j-api from 2.18.0 to 2.19.0

    This PR was automatically created by Snyk using the credentials of a real user.


    Snyk has created this PR to upgrade org.apache.logging.log4j:log4j-api from 2.18.0 to 2.19.0.

    :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.


    • The recommended version is 1 version ahead of your current version.
    • The recommended version was released 22 days ago, on 2022-09-13.

    Note: You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.

    For more information:

    ๐Ÿง View latest project report

    ๐Ÿ›  Adjust upgrade PR settings

    ๐Ÿ”• Ignore this dependency or unsubscribe from future upgrade PRs

    opened by nambach 0
  • [Snyk] Upgrade org.apache.poi:poi-ooxml from 5.2.2 to 5.2.3

    [Snyk] Upgrade org.apache.poi:poi-ooxml from 5.2.2 to 5.2.3

    Snyk has created this PR to upgrade org.apache.poi:poi-ooxml from 5.2.2 to 5.2.3.

    :information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.


    • The recommended version is 1 version ahead of your current version.
    • The recommended version was released 22 days ago, on 2022-09-09.

    Note: You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.

    For more information:

    ๐Ÿง View latest project report

    ๐Ÿ›  Adjust upgrade PR settings

    ๐Ÿ”• Ignore this dependency or unsubscribe from future upgrade PRs

    opened by snyk-bot 0
Releases(v2.5.0)
Library that makes it possible to read, edit and write CSV files

AdaptiveTableLayout Welcome the new CSV Library AdaptiveTableLayout for Android by Cleveroad Pay your attention to our new library that makes it possi

Cleveroad 1.9k Jan 6, 2023
A small companion library to Mixin, designed to help you write your Mixins in a more expressive and compatible way.

MixinExtras A small companion library to Mixin, designed to help you write your Mixins in a more expressive and compatible way. More information about

null 97 Jan 7, 2023
JAXB-based Java library for Word docx, Powerpoint pptx, and Excel xlsx files

README What is docx4j? docx4j is an open source (Apache v2) library for creating, editing, and saving OpenXML "packages", including docx, pptx, and xs

Jason Harrop 1.9k Jan 2, 2023
Fun little program to generate worlds in Excel

Basic world generation for Excel! How to use (For windows): Download the latest release from Releases run java -jar WorldGenExcelVersion.jar "path_to_

Steven Zhu 1 Feb 12, 2022
A library to create, read and validate ZUGFeRD compliant invoices. Available for Java and .NET

Konik ZUGFeRD Library Is an easy to use open source implementation of the ZUGFeRD data model including various enhancements. Features Easy and underst

Konik 42 Dec 20, 2022
High Performance data structures and utility methods for Java

Agrona Agrona provides a library of data structures and utility methods that are a common need when building high-performance applications in Java. Ma

Real Logic 2.5k Jan 7, 2023
Flutter plugin for notification read & reply

Reflex Flutter plugin for notification read & reply. Compatibility โœ… Android โŒ iOS (active issue: iOS support for reflex) Show some โค๏ธ and โญ the repo

Devs On Flutter 14 Dec 20, 2022
An Auction website. Users can Put up items for sale, bid on currently active auctions and write reviews for items that they have won in the auctions.

Auction-Project An Auction website. Users can Put up items for sale, bid on currently active auctions and write reviews for items that they have won i

Nika Salia 3 Sep 7, 2021
a proxy for http & https ,write by java,no dependences for other tech

็”ณๆ˜Ž ๆœฌ้กน็›ฎๅชๆ˜ฏไฝœ่€…่ฎฐๅฝ•ๅ’Œๅˆ†ไบซJava็ฝ‘็ปœ็ผ–็จ‹ๅญฆไน ๅฟƒๅพ—๏ผŒ่ฏทๅ‹ฟ็”จไบŽ้žๆณ•็”จ้€”๏ผŒๅฆๅˆ™ๅŽๆžœ่‡ช่ดŸ! ๅŽŸ็†ไป‹็ปๅšๅฎข๏ผš https://blog.csdn.net/wang382758656/article/details/123098032 https://juejin.cn/post/706921880022

Sand 58 May 3, 2022
@FengG0d 's Client, but he leave, I am the new owner, but, I don't know how to write Java, I need your help.

IKUN Client Help me I need help! The original Author was leave, but I don't know how to write a good client, I need Your help! to make a good IKun Cli

Chenken520 2 Sep 4, 2022
Write enterprise Bitcoin applications with Spring Boot.

Write enterprise Bitcoin applications with Spring Boot. Starter projects with multiple Bitcoin related modules that you can include in your application Google Colab

DE MINING 3 Dec 11, 2022
Cadence is a distributed, scalable, durable, and highly available orchestration engine to execute asynchronous long-running business logic in a scalable and resilient way.

Cadence This repo contains the source code of the Cadence server and other tooling including CLI, schema tools, bench and canary. You can implement yo

Uber Open Source 6.5k Jan 4, 2023
Android Auto Apps Downloader (AAAD) is an app for Android Phones that downloads popular Android Auto 3rd party apps and installs them in the correct way to have them in Android Auto.

Android Auto Apps Downloader (AAAD) is an app for Android Phones that downloads popular Android Auto 3rd party apps and installs them in the correct way to have them in Android Auto.

Gabriele Rizzo 865 Jan 2, 2023
Conway's Game Of Life, but made by me in a very inefficient and unpractical way. Still, I am proud!

Conway's Game Of Life, but made by me in a very ugly and inefficient way. Still, I am proud! I want to share my appreciation to cellular automata with anyone who comes across this repo.

UlaลŸ Dilek 6 May 25, 2022
A fun way to learn Camunda and win a small price

Camunda-Coding-Challenge A fun way to learn about Camunda and win a small prize. The coding challenge is designed for the Camunda Code Studio. Results

null 3 Oct 2, 2021
Java utilities to throw checked exceptions in a "sneaky" way.

Sneaky Java Java utilities to throw checked exceptions in a "sneaky" way. If you're tired of checked exceptions in lambdas, then this library is made

Semyon Kirekov 24 Dec 3, 2022
Shitty, yet simple way to get someone's token right at their discord client's startup.

discord-token-stealer Shitty, yet simple discord injector to add a little spice to their discord client Disclaimer: This is for educational purposes o

Gavin 3 Sep 26, 2022
Some anti afk bot which prevents you from getting punished for going afk in games. Way of stopping the bot is slightly flawed but we'll ignore that.

AntiAFK Some anti afk bot which prevents you from getting punished for going afk in games. Gui mode coming soon... Installation Install Java 17. Downl

flasky 1 Jan 13, 2022
This sample shows how to implement two-way text chat over Bluetooth between two Android devices, using all the fundamental Bluetooth API capabilities.

Zenitsu-Bluetooth Chat Application This sample shows how to implement two-way text chat over Bluetooth between two Android devices, using all the fund

Gururaj Koni 1 Jan 16, 2022