Simple, efficient Excel to POJO library for Java

Overview

ZeroCell

ZeroCell provides a simple API for loading data from Excel sheets into Plain Old Java Objects (POJOs) using annotations to map columns from an Excel sheet to fields in Java classes.

In case you don't fancy annotations or don't want to have to change your existing classes, you can map the columns to the fields without the annotations.

Why should I use this?

The library doesn't use the same approach that Apache POIs usermodel API and other POI based libraries use to process/store data loaded from the Excel file as a result it uses less resources as it doesn't process things such as Cell styles that take up memory. You also don't have to spend time setting data from cells to your Java objects, just define the mappings and let ZeroCell handle the rest.

What ZeroCell cannot do for you

  • Read or process excel workbook styles and other visual effects
  • Load data into complex object hierarchies
  • Write to excel files: The Apache POI library (which we use underneath) has a good API for writing to Excel files and provides the SXSSFWorkbook for writing large files in an efficient manner.

Usage

There are three ways to use zerocell: via annotations, the programmatic api and using the annotation processor.

First things first, add the following dependency to your pom.xml

<dependency>
    <groupId>com.creditdatamw.labs</groupId>
    <artifactId>zerocell-core</artifactId>
    <version>0.3.2</version>
</dependency>

Using Annotations

You create a class with @Column (and optionally @RowNumber) annotations to represent a row in an Excel sheet and then use the static methods on the Reader class to read the list of data from the file.

For example:

public class Person {
    @RowNumber
    private int rowNumber;
    
    @Column(index=0, name="FIRST_NAME")
    private String firstName;
    
    @Column(index=1, name="LAST_NAME")
    private String lastName;
    
    @Column(index=2, name="DATE_OF_BIRTH")
    private LocalDate dateOfBirth;
    
    // Getters and setters here ...
    
    public static void main(String... args) {
        // Then using the `Reader` class you can load 
        // a list from the excel file as follows:
        List<Person> people = Reader.of(Person.class)
                            .from(new File("people.xlsx"))
                            .sheet("Sheet 1")
                            .list();
        
        // You can also inspect the column names of 
        // the class using the static `columnsOf` method:
        String[] columns = Reader.columnsOf(Person.class);    
    }
}

Using the Programmatic API

If you don't want to use annotations you can still use ZeroCell to load from Excel sheet to your Java objects without too much work. The only difference with the annotation approach is that you have to define the column mappings via the Reader.using method.

For example:

public class Person {
    private int rowNo;
    
    private String id;
	
    private String firstName;
    
    private String middleName;
	
    private String lastName;
    
    private LocalDate dateOfBirth;
	
    private LocalDate dateOfRegistration;
    
    // Getters and setters here ...
    
    public static void main(String... args) {
        // Map the columns using, Reader.using method here
        List<Person> people = Reader.of(Person.class)
                            .from(new File("people.xlsx"))                            
                            .using(
                                new RowNumberInfo("rowNo", Integer.class),
                                new ColumnInfo("ID", "id", 0, String.class),
                                new ColumnInfo("FIRST_NAME", "firstName", 1, String.class),
                                new ColumnInfo("MIDDLE_NAME", "middleName", 2, String.class),
                                new ColumnInfo("LAST_NAME", "lastName", 3, String.class),
                                new ColumnInfo("DATE_OF_BIRTH", "dateOfBirth", 4, LocalDate.class),
                                new ColumnInfo("DATE_REGISTERED", "dateOfRegistration", 5, Date.class)
                            )
                            .sheet("Sheet 1")
                            .list();
         
        people.forEach(person -> {
            // Do something with person here    
        });    
    }
}

Using the Annotation Processor

ZeroCell provides an annotation processor to generate Reader classes to read records from Excel without Runtime reflection which makes the code amenable to better auditing and customization.

In order to use the functionality you will need to add the zerocell-processor dependency to your POM. This adds a compile-time annotation processor which generates the classes:

<dependency>
    <groupId>com.creditdatamw.labs</groupId>
    <artifactId>zerocell-processor</artifactId>
    <version>0.3.2</version>
    <scope>provided</scope>
</dependency>

Then, in your code use the @ZerocellReaderBuilder annotation on a class that contains ZeroCell @Column annotations.

Using a class defined as in the example shown below:

package com.example;

@ZerocellReaderBuilder
public class Person {
    @RowNumber
    private int rowNumber;
    
    @Column(index=0, name="FIRST_NAME")
    private String firstName;
    
    @Column(index=1, name="LAST_NAME")
    private String lastName;
    
    @Column(index=2, name="DATE_OF_BIRTH")
    private LocalDate dateOfBirth;
    
    public static void main(String... args) {
        File file = new File("people.xlsx");
        String sheet = "Sheet 1";
        ZeroCellReader<Person> reader = new com.example.PersonReader();
        List<Person> people = reader.read(file, sheet);
        people.forEach(person -> {
            // do something with person
        });
    }
}

Generates a class in the com.example package

package com.example;

public class PersonReader implements ZeroCellReader {
  // generated code here
}

Using Converters

Converters allow you to process the value loaded from an Excel Cell for a particular field, primarily converters enable you to transform String values to another data type. This allows you to load data into fields that have types other than the default supported types.

An example converter is shown below:

public class SimpleISOCurrency {
    public final String isoCurrency;
    public final double amount;

    public SimpleISOCurrency(String iso, double amount) {
        assert amount > 0.0;
        this.isoCurrency = iso;
        this.amount = amount;
    }
}

public class MalawiKwachaConverter implements Converter<SimpleISOCurrency> {
    @Override
    public SimpleISOCurrency convert(String value, String columnName, int row) {
        return new SimpleISOCurrency("MWK", Double.parseDouble(value));
    }
}

// Usage looks like this:

// ...
@Column(index=1, name="Balance (MWK)", converter=MalawiKwachaConverter.class)
private SimpleISOCurrency balance;
// ...

Using converters for pre-processing

You can also use converters as sort of pre-processing step where you operate on the String from the file before it's set on the field.

Below is a simple example:

/**
 * Simple Converter that prefixes values with ID-
 */
public class IdPrefixingConverter implements Converter<String> {
    @Override
    public String convert(String value, String columnName, int row) {
        return String.format("ID-%s", value);
    }
}

// Usage looks like this:

// ...
@Column(index=3, name="ID No.", converter=IdPrefixingConverter.class)
private String idNo;
// ...

Basic ISO LocalDate Converter

Below is a simple implementation of an converter for java.time.LocalDate that you can use.

Please note: that if you need to parse date times considering timezones you should implement your own converter and use a type like OffsetDateTime

public class BasicISOLocalDateConverter implements Converter<LocalDate> {
    /**
    * Basic ISO converter - attempts to parse a string that is formatted as an
    * ISO8601 date and convert it to a java.time.LocalDate instance.
    * 
    * @param value the value to convert
    * @param column the name of the current column
    * @param row the current row index
    * 
    * @throws ZeroCellException if the value cannot be parsed as an ISO date
    */
    @Override
    public LocalDate convert(String value, String column, int row) {
        if (value == null) return null;
        DateTimeFormatter formatter = DateTimeFormatter.BASIC_ISO_DATE;
        try {
            return LocalDate.parse(value, formatter);
        } catch (DateTimeParseException e) {
            throw new ZeroCellException(e);
        }
    }
}

Loading the Correct Sheet

If you do not specify the name of the sheet to load from, zerocell attempts to load data from the first Sheet in the Workbook. If the Sheet doesn't have matching columns as the defined model an exception will be thrown. In order to ensure the correct sheet is loaded it is recommended to always specify the sheet name.

Exception Handling

The API throws ZeroCellException if something goes wrong, e.g. sheet not found. It is an unchecked exception and may cause your code to stop executing if not handled. Typically ZeroCellException will wrap another exception, so it's worth peeking at the cause using Exception#getCause.

CONTRIBUTING

See the CONTRIBUTING.md file for more information.


Copyright (c) Credit Data CRB Ltd

Comments
  • GH-25: upgrade poi to 5.1.0

    GH-25: upgrade poi to 5.1.0

    Previous poi versions don't support Java 9+ modules, so when it comes to compilation in such projects, it fails. This update doesn't affect anything except the actual opportunity to use this library in modular applications.

    Relates to https://github.com/sskorol/test-data-supplier/issues/105

    Closes #25

    opened by sskorol 4
  • Dev

    Dev

    Implement the ability to parse any column from Excel file, not all of them, like it was previously. Also now parsing takes up less memory because it uses another method in the OPCPackage class. Added method which allows specify maximum number of rows.

    opened by DaNizz97 3
  • Upgrade poi to 5.1.0

    Upgrade poi to 5.1.0

    Hi @zikani03,

    I want to integrate your library into test-data-supplier I own. The main problem which prevents me from doing it is the poi dependency which doesn't support Java 9+ modules yet. The good news is that they have recently added such support in 5.1.0 version. Wondering if you can make a new release with poi 5.1.0?

    Note that I've already tested it locally. And it works as expected.

    opened by sskorol 2
  • New Feature: add java.io.InputStream support in Reader

    New Feature: add java.io.InputStream support in Reader

    1. modified:
    • Reader: add method com.creditdatamw.zerocell.Reader.ReaderBuilder#from(java.io.InputStream)
    • EntityHandler: add method com.creditdatamw.zerocell.handler.EntityHandler#process(java.io.InputStream)
    1. unit test:
    • add unit test: com.creditdatamw.zerocell.TestReader#testShouldReadFromInputStream
    opened by euclideanrn 2
  • Unable to read Locked Cells in the Sheet

    Unable to read Locked Cells in the Sheet

    Hi

    I have tried reading a sheet which is locked - I got following exception

    Exception :

    com.creditdatamw.zerocell.ZeroCellException: Failed to write value to field error_warning at row 1 at com.creditdatamw.zerocell.handler.EntityHandler$EntityExcelSheetHandler.writeColumnField(EntityHandler.java:261) at com.creditdatamw.zerocell.handler.EntityHandler$EntityExcelSheetHandler.cell(EntityHandler.java:226) at org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.endElement(XSSFSheetXMLHandler.java:380) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2967) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602) at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643) at com.creditdatamw.zerocell.ReaderUtil.process(ReaderUtil.java:56) at com.creditdatamw.zerocell.handler.EntityHandler.process(EntityHandler.java:132) at com.creditdatamw.zerocell.Reader$ReaderBuilder.list(Reader.java:68) at com.marksandspencer.ordering.servicetest.stepdefs.bulkcreate.template.BulkCreateOrderStepDefs.file_byte_array_should_be_returned_by_service(BulkCreateOrderStepDefs.java:197) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at cucumber.runtime.Utils$1.call(Utils.java:37) at cucumber.runtime.Timeout.timeout(Timeout.java:13) at cucumber.runtime.Utils.invoke(Utils.java:31) at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:38) at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37) at cucumber.runtime.Runtime.runStep(Runtime.java:299) at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44) at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39) at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:44) at cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.java:91) at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:63) at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:18) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at cucumber.runtime.junit.FeatureRunner.run(FeatureRunner.java:70) at cucumber.api.junit.Cucumber.runChild(Cucumber.java:93) at cucumber.api.junit.Cucumber.runChild(Cucumber.java:37) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at cucumber.api.junit.Cucumber.run(Cucumber.java:98) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

    opened by skgandikota 2
  • Add Fallback Strategy hint to `@Column` annotations

    Add Fallback Strategy hint to `@Column` annotations

    Proposal:

    Add Parse Failure Strategy Hints to @Column annotations

    Description:

    The library may fail to parse some values from Excel cells, the current default action right now is to return null values for most types as the converters use Boxed types for primitives (long, int, etc..), null for temporal types (Date, LocalDate, etc..), no-op for Strings - which means a null from the Excel will result in null String and Boolean.FALSE for Booleans.

    However, this may result in incorrect data and misinterpretations of data if not checked.

    This proposal introduces an optional annotation method onParseFail to specify explicitly how the library must behave should it fail to parse a value in the absence of a custom Converter class. Additionally, this proposal modifies the default strategy for handling parse failures.

    The following strategies are proposed:

    • LEGACY - this strategy will maintain the current sematics of the library, and will not be recommended.

    • DEFAULT - in order to maintain compatibility this will be the default strategy for the library, this will reduce noise in user code.

      The default strategy will behave in the following manner:

      • for temporal types (Date, LocalDateTime, etc..) default will result in an Exception being thrown,
      • for String types if the value is null the result will be an empty String (""),
      • for numeric types the result will be the respective MIN_VALUE of that type
      • for Booleans, an exception will be thrown if the Excel value is null
    • THROW_EXCEPTION - throw an exception if the value cannot be parsed/converted - the result of this is that the library will halt processing the input stream/file.

    • USE_MIN_VALUE - use <Type>.MIN_VALUE if the value cannot be parsed for the following types (long, double, byte, int, short)

    • DEFAULT_TO_ZERO - For all numeric types, default to zero (0) if the value cannot be parsed from the string.

    • DEFAULT_TO_TRUE - For booleans, default to true if the value cannot be parsed from Excel.

    • DEFAULT_TO_FALSE - For booleans, default to false if the value cannot be parsed from Excel.

    • DEFAULT_TO_NULL - For all Date, LocalDate, Timestamp, LocalDateTime and Strings types, return null if the value cannot be parsed from Excel or the value from Excel is already null (basically a no-op when the value is null from Excel).

    • DEFAULT_TO_EMPTY_STRING - When the mapped field is a string, default to an empty String if the value from the Excel cell is null.

    The use of the options would look as follows:

    
    public class Person {
    
      @Column(name="Age Default", index=0)
      private int ageDefault; // this will result in Integer.MIN_VALUE being set on failure to parse
    
      @Column(name="Age", index=0, onParseFail=ParseFailureStrategy.DEFAULT)
      private int age;  // this will result in Integer.MIN_VALUE being set on failure to parse
    
      @Column(name="Age 0", index=0, onParseFail=ParseFailureStrategy.THROW_EXCEPTION)
      private int ageZero;
      
      @Column(name="Age 1", index=1, onParseFail=ParseFailureStrategy.USE_MIN_VALUE)
      private int ageOne;
      
      @Column(name="Age 2", index=2, onParseFail=ParseFailureStrategy.DEFAULT_TO_ZERO)
      private int ageTwo;
      
      @Column(name="Age 3", index=2, onParseFail=ParseFailureStrategy.DEFAULT_TO_EMPTY_STRING)
      private String ageThree;
    }
    
    enhancement 
    opened by zikani03 1
  • Example file

    Example file

    Hi,

    I do not understand this line of code. Maybe the code is not up to date, or should I implement such reader class for myself as well? I didn't find it in the example folder.

        ZeroCellReader<Person> reader = new com.creditdatamw.zerocell.example.PersonExcelReader();
    

    Thanks

    opened by brobee 1
  • Bump logback-classic from 1.1.2 to 1.2.0

    Bump logback-classic from 1.1.2 to 1.2.0

    Bumps logback-classic from 1.1.2 to 1.2.0.

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Referencing removed Apache POI classes preventing Apache POI upgrade

    Referencing removed Apache POI classes preventing Apache POI upgrade

    Removed classes referenced: org.apache.poi.utils.SAXHelper org.apache.poi.hssf.util.CellReference

    SAXHelper: https://github.com/creditdatamw/zerocell/blob/69b02d0f5d37014595245e48c2ea81767a62eac0/core/src/main/java/com/creditdatamw/zerocell/ReaderUtil.java#L10

    CellReference: https://github.com/creditdatamw/zerocell/blob/62a6547a3b54b0dfedb8640170fefb20119783b4/processor/src/main/java/com/creditdatamw/zerocell/processor/spec/CellMethodSpec.java#L51

    org.apache.poi.utils.SAXHelper is used in ReaderUtil and prevents Apache POI to be upgraded beyond 3. SAXHelper is refactored in Apache POI 4.x to org.apache.poi.ooxml.util.SAXHelper and further removed in POI 5.0.
    Apache POI suggests to use org/apache/poi/util/XMLHelper instead.

    org.apache.poi.hssf.util.CellReference is refactored to org.apache.poi.ss.util.CellReference

    Apache POI deprecation info: https://poi.apache.org/apidocs/dev/deprecated-list.html#class

    opened by heiching 0
  • Bump junit from 4.12 to 4.13.1

    Bump junit from 4.12 to 4.13.1

    Bumps junit from 4.12 to 4.13.1.

    Release notes

    Sourced from junit's releases.

    JUnit 4.13.1

    Please refer to the release notes for details.

    JUnit 4.13

    Please refer to the release notes for details.

    JUnit 4.13 RC 2

    Please refer to the release notes for details.

    JUnit 4.13 RC 1

    Please refer to the release notes for details.

    JUnit 4.13 Beta 3

    Please refer to the release notes for details.

    JUnit 4.13 Beta 2

    Please refer to the release notes for details.

    JUnit 4.13 Beta 1

    Please refer to the release notes for details.

    Commits
    • 1b683f4 [maven-release-plugin] prepare release r4.13.1
    • ce6ce3a Draft 4.13.1 release notes
    • c29dd82 Change version to 4.13.1-SNAPSHOT
    • 1d17486 Add a link to assertThrows in exception testing
    • 543905d Use separate line for annotation in Javadoc
    • 510e906 Add sub headlines to class Javadoc
    • 610155b Merge pull request from GHSA-269g-pwp5-87pp
    • b6cfd1e Explicitly wrap float parameter for consistency (#1671)
    • a5d205c Fix GitHub link in FAQ (#1672)
    • 3a5c6b4 Deprecated since jdk9 replacing constructor instance of Double and Float (#1660)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • zerocell-core doesn't skip empty row

    zerocell-core doesn't skip empty row

    I have a spreadsheet with 3 rows data, but after reading this sheet to POJOs class, size of list POJOs is 999 instead of 3. Is there any way to skip the empty row?

    enhancement 
    opened by hungbang 0
  • Support for Java Stream API

    Support for Java Stream API

    Great work on this library! I've got one suggestion: It would be great if the library would support returning a Stream rather than the whole list in one go.

    enhancement 
    opened by sebastian-raubach 0
Owner
Credit Data CRB
Credit Data CRB 💚 Open Source
Credit Data CRB
Framework for serialization to Json, XML, Byte and Excel, therefore an oviparous wool milk sow J

NetworkParser Framework for serialization from Java objects to Json, XML and Byte. NetworkParser is a simple framework for serializing complex model s

Fujaba Tool Suite 4 Nov 18, 2020
A simple java JSON deserializer that can convert a JSON into a java object in an easy way

JSavON A simple java JSON deserializer that can convert a JSON into a java object in an easy way. This library also provide a strong object convertion

null 0 Mar 18, 2022
100% Java, Lambda Enabled, Lightweight Rules Engine with a Simple and Intuitive DSL

RuleBook » A Simple & Intuitive Rules Abstraction for Java 100% Java · Lambda Enabled · Simple, Intuitive DSL · Lightweight Why RuleBook? RuleBook rul

Delivered Technologies Labs 666 Dec 21, 2022
A simple java json configuration system built with gson.

Simple Configuration A simple json configuration system built with gson. Setup ?? Using Maven REPOSITORY <repositories> <repository> <id>j

Kacper Horbacz 2 Sep 24, 2022
A simple JAVA HTTP requests tool.

JAVA-HTTP Hello ?? I made this very simple tool to start studying HTTP requests in JAVA. You need JAVA 18 to be able to test it: Download JAVA Functio

Ghost 9 Oct 16, 2022
A Java serialization/deserialization library to convert Java Objects into JSON and back

Gson Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to a

Google 21.7k Jan 8, 2023
A universal types-preserving Java serialization library that can convert arbitrary Java Objects into JSON and back

A universal types-preserving Java serialization library that can convert arbitrary Java Objects into JSON and back, with a transparent support of any kind of self-references and with a full Java 9 compatibility.

Andrey Mogilev 9 Dec 30, 2021
Java with functions is a small java tools and utils library.

Java with functions is a small java tools and utils library.

null 4 Oct 14, 2022
a simple rating component

rn-rating-component A Simple react-native rating component. Installation Install rn-rating-component and its dependeices with npm npm install --save

Yuva raghav 3 Aug 20, 2021
✔️ Simple, pretty and powerful logger for android

Logger Simple, pretty and powerful logger for android Setup Download implementation 'com.orhanobut:logger:2.2.0' Initialize Logger.addLogAdapter(new A

Orhan Obut 13.5k Jan 5, 2023
Simple LaTeX filter for OmegaT

Simple LaTeX filter plugin for OmegaT What is it? This plugin implements a subset of LaTeX syntax as OmegaT file filter. Translated content is expecte

Lev Abashkin 4 May 24, 2022
A modern JSON library for Kotlin and Java.

Moshi Moshi is a modern JSON library for Android and Java. It makes it easy to parse JSON into Java objects: String json = ...; Moshi moshi = new Mos

Square 8.7k Dec 31, 2022
JSON to JSON transformation library written in Java.

Jolt JSON to JSON transformation library written in Java where the "specification" for the transform is itself a JSON document. Useful For Transformin

Bazaarvoice 1.3k Dec 30, 2022
Sawmill is a JSON transformation Java library

Update: June 25, 2020 The 2.0 release of Sawmill introduces a breaking change to the GeoIpProcessor to comply with the updated license of the MaxMind

Logz.io 100 Jan 1, 2023
Genson a fast & modular Java <> Json library

Genson Genson is a complete json <-> java conversion library, providing full databinding, streaming and much more. Gensons main strengths? Easy to use

null 212 Jan 3, 2023
Lean JSON Library for Java, with a compact, elegant API.

mJson is an extremely lightweight Java JSON library with a very concise API. The source code is a single Java file. The license is Apache 2.0. Because

Borislav Iordanov 77 Dec 25, 2022
A modern and lightweight library for working with email addresses in Java

JMail A modern, fast, zero-dependency library for working with email addresses and performing email address validation in Java. Built for Java 8 and u

Rohan Nagar 67 Dec 22, 2022
A wayfast raycast java library.

NOTE: Rayfast is still in development and is not completely stable api-wise. GridCasting likely will not change, however Area3d's may have some improv

EmortalMC 19 Dec 20, 2022
Java library to represent monetary amounts.

Joda-Money Joda-Money provides a library of classes to store amounts of money. Joda-Money does not provide, nor is it intended to provide, monetary al

Joda.org 599 Jan 4, 2023