[film YT na dole wpisu]

Cześć, tym razem postanowiłem napisać kreatora plików Excel na bazie biblioteki Apache POI.

Moim zamiarem było stworzenie uniwersalnego narzędzia, które może się przydać, gdy będziemy chcieli zapisać jakąś kolekcję do pliku .xls.

W projekcie użyłem refleksji.

Struktura projektu to bazowy projekt Maven. Zrezygnowałem z biblioteki Lombok, aby uprościć ten przykład maksymalnie.

Poniżej plik pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>devlab</groupId>
    <artifactId>xlsCreator</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

    </dependencies>

</project>

Oczywiście wrzucam screen ze strukturą projektu.

W tym przykładzie nie ma znaczenia, gdzie umieścimy klasy i czy w ogóle zrobimy sobie oddzielne paczki na klasy.

Poniżej modelowa klasa Person.

Z założenia kreator plików XLS ma działać z każdą klasą modelową. Dzięki refleksji znaczenie mają dla mnie tylko metody ‚get’, bo na nich opieram poprawne działanie kreatora.

Poniżej klasa Person:


package model;

public class Person {
    private String name;
    private String lastName;
    private int age;

    public Person(String name, String lastName, int age) {
        this.name = name;
        this.lastName = lastName;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

No i wreszcie mój kreator plików. Zawiera jedną metodę, która przyjmuje kolekcję oraz ścieżkę zapisu pliku i nazwę pliku.


package commons;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class XlsFileCreator<T> {

    private Class<T> clazz;

    public XlsFileCreator(Class<T> clazz) {
        this.clazz = clazz;
    }

    public void createFile(List<T> series, String path, String fileName)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {

        //tworzę plik excel
        HSSFWorkbook workbook = new HSSFWorkbook();

        // tworzę arkusz w pliku
        HSSFSheet sheet = workbook.createSheet(fileName);

        //ustawiam czcionki
        Font headerFont = workbook.createFont();
        headerFont.setBold(true);
        headerFont.setFontHeightInPoints((short) 10);
        headerFont.setColor(IndexedColors.BLACK.getIndex());

        //zapisuję styl czcionki do arkusza
        CellStyle headerCellStyle = workbook.createCellStyle();
        headerCellStyle.setFont(headerFont);

        //kolekcja nazw kolumn w arkuszu
        List<String> columns = new ArrayList<>();

        //iteracja po klasie przekazanej do pola 'clazz'. Odczytuję wszystkie zadeklarowane pola.
        for (Field f : clazz.getDeclaredFields()) {
            columns.add(f.getName());
        }

        //zapisuję do struktury pliku excel odczytane powyżej pola klasy jako nagłówki kolumn.
        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < columns.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(columns.get(i));
            cell.setCellStyle(headerCellStyle);
        }

        // test odczytu metod zaczynających się na 'get'. Tylko test.
        columns.forEach(t -> System.out.println("get" + t.substring(0, 1).toUpperCase() + t.substring(1)));

        //zapis danych i wywoływanie metod 'get'.
        for (int i = 0; i < series.size(); i++) {

            //plus 1, ponieważ pierwszy wiersz, czyli index 0 w dokumencie zarezerwowany na nagłówki.
            HSSFRow row = sheet.createRow(i + 1);

            for (int j = 0; j < columns.size(); j++) {

                HSSFCell cell = row.createCell(j);
                Method method = series.get(i)
                        .getClass()
                        .getMethod("get" + columns.get(j)
                                .substring(0, 1)
                                .toUpperCase() + columns.get(j)
                                .substring(1));

                //wywolywanie wszystkich dostępnych metod 'get' na obiekcie i zapis do arkusza.
                Object result = method.invoke(series.get(i));
                cell.setCellValue(String.valueOf(result));
            }
        }

        //stylizacja arkusza - ustawianie auto szerokości kolumn.
        for (int i = 0; i < columns.size(); i++) {
            sheet.autoSizeColumn(i);
        }

        //dodawanie unikalnej nazwy do pliku. Przykład: persons_12948573628.xls
        long mills = System.currentTimeMillis();
        String file = path + fileName + "_" + mills + ".xls";

        //zapis pliku
        workbook.write(new File(file));
        workbook.close();
    }

}

Jeszcze klasa Main, gdzie tworzę przykładową kolekcję i odpalam program:


import commons.XlsFileCreator;
import model.Person;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {

        XlsFileCreator<Person> xlsFileCreator = new XlsFileCreator<>(Person.class);

        List<Person> persons = Arrays.asList(
                new Person("Adam", "Kowalski", 25),
                new Person("Maria", "Kowalska", 22));

        try {
            xlsFileCreator.createFile(persons, "src/main/resources/", "persons");

        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | IOException e) {
            e.printStackTrace();
        }

    }
}

Po odpaleniu otrzymałem taki plik:

Zachęcam Cię do polubienia mojego funpage’a

Jeśli masz jakiś ciekawy pomysł, jak mógłbym ulepszyć ten kod, albo zrobiłeś coś podobnego, lub chciałbyś to rozwinąć, to daj mi znać na fejsie 🙂

Cały kod dostępny tutaj.

Dodaj komentarz

Twój adres email nie zostanie opublikowany.