Sharecs.net
  • Trang chủ
  • Thủ Thuật
    • Thủ thuật máy tính
      • Windows
      • MacOS
      • Linux
    • Thủ thuật internet
    • Thủ thuật phần mềm
  • Phần Mềm
  • Lỗi máy tính
    • Lỗi internet
    • Lỗi windows
    • Lỗi phần mềm
  • Lập Trình
    • Lập Trình Java
    • Lập trình Python
    • Lập Trình React Native
    • Code Hay
  • Linh Tinh
    • PhotoShop
    • Tải Video Wallpaper
    • Kho Tools
      • Cân Bằng Phương Trình Hóa Học
      • Custom Css Scrollbar – Render Code
      • Tạo Kí Tự Đặc Biệt Online
      • Tạo Deep Link
    • Tài Liệu – Luận Văn – Báo Cáo
    • Kho Theme Website WordPress
No Result
View All Result
  • Trang chủ
  • Thủ Thuật
    • Thủ thuật máy tính
      • Windows
      • MacOS
      • Linux
    • Thủ thuật internet
    • Thủ thuật phần mềm
  • Phần Mềm
  • Lỗi máy tính
    • Lỗi internet
    • Lỗi windows
    • Lỗi phần mềm
  • Lập Trình
    • Lập Trình Java
    • Lập trình Python
    • Lập Trình React Native
    • Code Hay
  • Linh Tinh
    • PhotoShop
    • Tải Video Wallpaper
    • Kho Tools
      • Cân Bằng Phương Trình Hóa Học
      • Custom Css Scrollbar – Render Code
      • Tạo Kí Tự Đặc Biệt Online
      • Tạo Deep Link
    • Tài Liệu – Luận Văn – Báo Cáo
    • Kho Theme Website WordPress
No Result
View All Result
Sharecs.net
No Result
View All Result
Home Lập Trình Lập Trình Java

How To Import Excel Spring Boot – Trả Lỗi Trong File

Nguyễn Tuấn by Nguyễn Tuấn
30/11/2022
0
0
SHARES
39
VIEWS

Ở bài trước mình có hướng dẫn các bạn làm thế nào để excel data ra file excel một cách dễ dàng và đơn giản, các bạn có thể xem lại tại đây.

Mục Lục

  • 1 Giới thiệu Import Excel Spring Boot
  • 2 Thư viện import excel trong java
  • 3 Import Excel Spring Boot
    • 3.1 Code abstract class và validator dùng chung
      • 3.1.1 Xử lý đọc data từ file excel
      • 3.1.2 Xử lý validate trong DTO
      • 3.1.3 Xử lý validate không phải trong DTO
      • 3.1.4 Xuất Dữ Liệu Ra File Excel Trong Java
    • 3.2 Áp dụng Abstract class vào Import excel

Giới thiệu Import Excel Spring Boot

Trong bài viết này mình sẽ hướng dẫn các bạn import excel spring boot. Mục tiêu mình đăt ra là:

  • Import data từ excel vào csdl
  • Khi dữ liệu bị lỗi thì tự động trả lại file excel và bôi đỏ dòng bị lỗi
  • Comment nội dung bị lỗi để người dùng biết
  • Code tối ưu
Import Excel Spring Boot
Import Excel Spring Boot

Thư viện import excel trong java

Các bạn thêm thư viện vào project của mình, bên cạnh đó các bạn có thể tìm thư viện trên trang mvnrepository.com

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

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

        <dependency>
            <groupId>com.github.ozlerhakan</groupId>
            <artifactId>poiji</artifactId>
            <version>3.1.9</version>
        </dependency>

Hai thư viện đầu tiên thì hẳn các bạn cũng đã biết nhiều, thư viện thứ 3 mình dùng để xử lý đọc file excel to object. Thư viện Poiji cũng có các hướng dẫn về cách sử dụng các bạn xem tại đây nhé.

Import Excel Spring Boot

Vì import excel mình dùng ở rất nhiều nơi nên mình sẽ chia tiếp thành 2 phần, đầu tiên sẽ code setup những thứ dùng chung. Làm sao có thể tái sử dụng và tùy biến được nhiều nhất có thể, phần tiếp theo là áp dụng các abstract class mình đã viết như thế nào cho api.

Code abstract class và validator dùng chung

Đầu tiên chúng ta hình dung những cái gì mình sẽ hay dùng chung? Các bạn liệt kê thử xem. Như mình thấy thì có: đọc file excel, 1 phần của validate lỗi, xuất file excel, ghi lỗi vào cell, xóa comment đã ghi nếu file đã có, xử lý lỗi trả về cho nhiều ngôn ngữ khác nhau…

Vậy nên mình sẽ tạo 1 file abstract class tại các module nào cần api import excel thì mình extends lôi ra dùng.

Abstract class sẽ nhận 2 Object làExcelImportDTO ( là dto của các trường có trong file import excel) và Object Entity.

@Getter
@Slf4j
public abstract class ImportExcelValidator<S, T> {

} 

@Getter và @Slf4j cho bạn nào chưa biết là mình dùng lombok các bạn tra google rồi đọc thêm nhé. Cái này có nhiều rồi, cũng dễ thôi.

Tiếp theo chúng ta cần xác định sẽ khai bảo những gì. Mình xác định cái căn bản trước, quá trình làm mà thiếu thì thêm.

@Getter
@Slf4j
public abstract class ImportExcelValidator<S, T> {

    private final List<S> sourceObjects;

    private final List<T> destinationObjects;

    private final MultipartFile multipartFile;

    private final int headerStart;

    private final Locale locale;

    private final int lastCellNum;

    private final List<ErrorDetail> errorsDetail;

} 

Chúng ta có thể thấy:

  1. sourceObjects là DTO của file excel nhận dữ liệu .
  2. destinationObjects là object entity đây là kết quả cuối cùng mình nhận được để saveAll.
  3. multipartFile thằng này sẽ nhận file mình tải lên
  4. headerStart là số dòng bắt đầu trong excel
  5. locale dùng để xác định loại ngôn ngữ mà lỗi sẽ trả về ghi vào file
  6. lastCellNum là số cột kết thúc trong excel
  7. errorsDetail là object sẽ thể hiện số dòng bị lỗi và thông tin lỗi
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ErrorDetail {

    private int index;

    private String message;

}
Xử lý đọc data từ file excel

TrongImportExcelValidator.class chúng ta xử lý đọc excel bằng thư viện poiji như sau:

    public ImportExcelValidator(MultipartFile file, int headerStart, Locale locale, int lastCellNum) {
        // Convert Excel to Object
        PoijiOptions options = PoijiOptions.PoijiOptionsBuilder.settings().rawData(true).trimCellValue(true).headerStart(headerStart).dateFormatter(DateTimeFormatter.ofPattern(Constants.PRINT_DATE_FORMAT)).build();

        try {
            Class<S> sourceType = (Class<S>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            this.sourceObjects = Poiji.fromExcel(file.getInputStream(), PoijiExcelType.XLSX, sourceType, options);
        } catch (IOException e) {
            // add return lỗi
        }

        this.errorsDetail = new ArrayList<>();
        this.destinationObjects = new ArrayList<>();
        this.multipartFile = file;
        this.headerStart = headerStart;
        this.locale = locale;
        this.lastCellNum = lastCellNum;
    }

Mình sử dụng thư viện Poiji nên các bạn vào link trên để đọc thêm nhé. Nếu các bạn muốn check xem định dạng ngày tháng đã đúng hay chưa thì có thể tìm hiểu thêm, code trong phần withCasting của Poiji.

    public abstract ImportExcelValidator<S, T> validate();

    /**
     *  Xử lý data khi đã pass qua hết tất cả các validate
     * @return
     */
    public abstract List<T> thenMappingAndReturnDestinationObjects();

Hàm trên mình để validate cho từng object import excel khác nhau.

Xử lý validate trong DTO

Trong DTO chúng ta thường có các validate như: @NotBank, @NotNull, @Size, @Digits … hay là một Annotation mà bạn tự viết. Annotation hay lắm các bạn thử học viết 1 số cái đơn giản xem, rất tiện khi dung luôn. Ở bài viết khác mình sẽ hướng dẫn các bạn viết 1 số Annotation đơn giản mà rất hay sử dụng trong import excel, các bạn theo dõi tại đây nhé.

Ví dụ một dto import excel như này:

@Data
@NoArgsConstructor
@AllArgsConstructor
@ExcelCheckDuplication
public class ExcelDTO {

    public ExcelDTO (String code, String name) {
        this.code = code;
        this.name = name;
    }

    @ExcelCell(0)
    @NotBlank(message = "name_empty")
    @Size(max = 200, message = "name_validation_size")
    public String name;

    @ExcelCell(1)
    @NotBlank(message = "code_not_empty")
    @Size(max = 255, message = "code_validation_size")
    public String code;

    @ExcelCell(2)
    @NotNull(message = "max_value_empty")
    @Digits(integer = 9, fraction = 2, message = "max_value_invalid")
    public BigDecimal maxValue;

}

Một số điểm đáng chú ý:

  1. @ExcelCheckDuplication là annotation mình tự viết để check duplication
  2. @ExcelCell(0) : là Annotation của poiji dùng để xác định vị trí cột trong excel ( bạn cũng có thể xác định bằng tên, poiji có hỗ trợ hết)
  3. message : là nội dung lỗi sẽ trả về nếu data không pass qua được. Hiện tại các lỗi này mình đang set là key ví dụ: code_validation_size key này có thể dịch sang nhiều ngôn ngữ khác nhau. Nội dung key sẽ lấy từ resources/i18n trong project spring boot của bạn.

Tiếp theo mình sẽ viết hàm xử lý chung cho tất cả các phần này. Sau mình chỉ việc bắt validate trong dto, nếu còn sót cái nào thì mình kế thừa lại validate() trong ImportExcelValidator.class mình đã viết để xử lý.

    /**
     *
     * @return
     */
    public ImportExcelValidator<S, T> validatePre() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        ReloadableResourceBundleMessageSource messageSource = messageSource();

        int temp = 0;

        for (S dto: this.getSourceObjects()) {
            ErrorDetail errorDetail = new ErrorDetail();
            List<String> comments = new ArrayList<>();
            temp++;

            // Pre validation
            Set<ConstraintViolation<S>> violations = validator.validate(dto);

            if (violations.size() > 0) {

                for (ConstraintViolation<S> violation: violations) {
                    comments.add(messageSource.getMessage(violation.getMessage(), null, locale));
                }

                errorDetail.setIndex(temp);
                errorDetail.setMessage(String.join(", ", comments));
                errorsDetail.add(errorDetail);
            }
        }

        return this;
    }


    private static ReloadableResourceBundleMessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();

        messageSource.setBasename("classpath:i18n/messages");
        messageSource.setFallbackToSystemLocale(false);
        messageSource.setDefaultEncoding(String.valueOf(StandardCharsets.UTF_8));
        messageSource.setCacheSeconds(0);

        return messageSource;
    }

Để có thể kiểm tra xem data có pass qua các annotation đã check và lấy ra message không thì mình dùng ValidatorFactory ( bạn có thể xem thêm tại baeldung.com ).

entityErrorsDetail mình cũng đã khai báo rồi giờ mình chỉ việc add số dong bị lỗi và message vào list nữa thôi. ReloadableResourceBundleMessageSource mình dùng để xử lý đa ngôn ngữ nhé.

Vậy là chúng ta đã xong phần đọc file excel trong java và 1 nửa của validate dữ liệu. Vì sao validate data mới được 1 nửa, tại mỗi api import excel thì sẽ có những validate đặc thù riêng như lấy data từ database check tồn tại, các thứ nữa rất nhiều. Nên tới đây mình chỉ xong được 1 nửa validate thôi.

Xử lý validate không phải trong DTO

Khi mình kế thừa class ImportExcelValidator.class thì mình cũng kế thừa lại hàm validate() để sử dụng. Kết quả hàm này trả về là gì?

Hàm validate() sẽ return 1 List<String> keyComments lỗi và số dòng bị lỗi. Công việc tiếp theo chúng ta chỉ cần add vào errorsDetail.

/**
     * @param keyComments key messenger error
     * @param temp row error
     * @return
     */
    public void errorMessengers(List<String> keyComments, int temp) {
        List<String> comments = new ArrayList<>();
        ReloadableResourceBundleMessageSource messageSource = messageSource();

        for (String str: keyComments) {
            comments.add(messageSource.getMessage(str, null, locale));
        }

        String comment = String.join(", ", comments);

        if (!ObjectUtils.isEmpty(comment)) {
            ErrorDetail errorDetail = new ErrorDetail(temp, comment);
            this.getErrorsDetail().add(errorDetail);
        }
    }
Xuất Dữ Liệu Ra File Excel Trong Java

Ý tưởng của mình là lấy luôn data từ HttpServletResponse response mình sẽ chỉ xóa comment và style đang có trong file. Sau đó set comment và style mới vào là được.

/**
     * @param sheet workbook
     * @return
     */
    public void removeComment(XSSFSheet sheet) {
        // Get comment exists
        Map<CellAddress, XSSFComment> oldComments = sheet.getCellComments();
        Cell cell;

        for (Map.Entry<CellAddress, XSSFComment> oldComment: oldComments.entrySet()) {
            cell = sheet.getRow(oldComment.getKey().getRow()).getCell(oldComment.getKey().getColumn());
            cell.removeCellComment();

            cell.getCellStyle().setFillForegroundColor(IndexedColors.WHITE.getIndex());
        }
    }

    public void setCommentStyle(XSSFWorkbook workbook, XSSFSheet sheet, Map<Integer, String> mapErrorDetail) {
        Row row; Cell cell; Comment comment;

        CellStyle cellStyle = workbook.getCellStyleAt(0);
        cellStyle.setFillForegroundColor(IndexedColors.CORAL.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);

        CreationHelper factory = workbook.getCreationHelper();
        ClientAnchor anchor = factory.createClientAnchor();

        for (Map.Entry<Integer, String> errorDetail: mapErrorDetail.entrySet()) {
            int rowNumber = errorDetail.getKey() + headerStart;
            row = sheet.getRow(rowNumber);
            int lastColumn = Math.max(row.getLastCellNum(), lastCellNum);
            RichTextString errorMessenger = factory.createRichTextString(errorDetail.getValue());

            for (int i = 0; i < lastColumn; i++) {
                cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                cell.setCellStyle(cellStyle);

                comment = sheet.createDrawingPatriarch().createCellComment(anchor);
                comment.setString(errorMessenger);
                cell.setCellComment(comment);
            }
        }
    }

Trên là delete comment in file excel và set lại background cho ô, tiếp theo là mình ghi lại ra file excel và trả về cho người dùng.

    /**
     *
     * @param response
     * @return
     */
    public ImportExcelValidator<S, T> thenReturnExcelIfError(HttpServletResponse response) {
        if (!ObjectUtils.isEmpty(errorsDetail)) {

            try {
                XSSFWorkbook workbook = new XSSFWorkbook(multipartFile.getInputStream());
                XSSFSheet sheet = workbook.getSheetAt(0);

                // remove comment
                this.removeComment(sheet);
                // map row index and message error
                Map<Integer, String> mapErrorDetail = errorsDetail.stream().collect(Collectors.toMap(ErrorDetail::getIndex, ErrorDetail::getMessage));
                // Set comment and style in sheet
                this.setCommentStyle(workbook, sheet, mapErrorDetail);

                response.setHeader("Content-Disposition", "attachment; filename=" + multipartFile.getOriginalFilename() + ".xlsx");
                ServletOutputStream out = response.getOutputStream();

                workbook.write(out);
                out.flush();
                out.close();
            } catch (IOException e) {
                // add return Error when create new file excel
            }
            // add return validate error
        }

        return this;
    }

Áp dụng Abstract class vào Import excel

Do bài này cũng hơi dài nên mình sẽ tách thành 2 bài nhé. Phần 2 Áp dụng Abstract class

Cảm ơn các bạn đã ghé thăm. Chúc các bạn thành công!

5/5 - (1 bình chọn)
Tags: excel in javaimport exceljava
ShareSendTweetShare

Cùng chuyên mục

Annotations @Controller and @RestController Trong Spring

Annotations @Controller and @RestController Trong Spring

05/02/2023
9
How to Convert String to XML in Java ?

How to Convert String to XML in Java ?

19/01/2023
6
Đồ Án Tốt Nghiệp Quản Lý Trang Thiết Bị && Full Báo Cáo

Đồ Án Tốt Nghiệp Quản Lý Trang Thiết Bị && Full Báo Cáo

11/12/2022
25
How To Import Excel Spring Boot – Trả Lỗi Trong File

Import Excel Spring Boot – Đọc dữ liệu từ file Excel và lưu vào Database – P2

06/12/2022
18
Subscribe
Notify of
guest

guest

0 Comments
Inline Feedbacks
View all comments

Tài nguyên

Cân bằng phương trình phản ứng hóa

Tạo deep link

Custom Css Scrollbar – Render Code

Bài Viết Nổi Bật

  • Hatsune Miku Anime Wallpaper Video 4k

    Hatsune Miku Anime Wallpaper Video 4k

    0 shares
    Share 0 Tweet 0
  • Bài Tập Code Python Đơn Giản Có Lời Giải – Phần 1

    1 shares
    Share 0 Tweet 0
  • Thư viện đồ họa trong Python – Vẽ doraemon

    0 shares
    Share 0 Tweet 0
  • Download Video Wallpaper Agatsuma Zenitsu – Anime Kimetsu No Yaiba

    45 shares
    Share 0 Tweet 0
  • Thư viện đồ họa trong Python – Vẽ Pikachu

    0 shares
    Share 0 Tweet 0
  • Trending
  • Comments
  • Latest
Hatsune Miku Anime Wallpaper Video 4k

Hatsune Miku Anime Wallpaper Video 4k

30/01/2023
Bài Tập Code Python Đơn Giản Có Lời Giải – Phần 1

Bài Tập Code Python Đơn Giản Có Lời Giải – Phần 1

31/08/2020
Download Video Wallpaper Agatsuma Zenitsu – Anime Kimetsu No Yaiba

Download Video Wallpaper Agatsuma Zenitsu – Anime Kimetsu No Yaiba

16/12/2022
Bài Tập Code Python Đơn Giản Có Lời Giải – Phần 1

Thư viện đồ họa trong Python – Vẽ doraemon

09/12/2020
Cách Kích Hoạt Key Win 11 Bản Quyền –Active Win 11 – Win 10 Free

Cách Kích Hoạt Key Win 11 Bản Quyền –Active Win 11 – Win 10 Free

1
Annotations @Controller and @RestController Trong Spring

Annotations @Controller and @RestController Trong Spring

05/02/2023
Sự Cố Năm 2038 – Lỗi Đồng Hồ Trên Máy Tính

Sự Cố Năm 2038 – Lỗi Đồng Hồ Trên Máy Tính

05/02/2023
5 cách mà máy ảnh sẽ phát triển vào năm 2023 – Tốt và Xấu

5 cách mà máy ảnh sẽ phát triển vào năm 2023 – Tốt và Xấu

22/01/2023
Tòa án Ấn Độ bác bỏ yêu cầu của Google để chặn phán quyết chống độc quyền Android

Tòa án Ấn Độ bác bỏ yêu cầu của Google để chặn phán quyết chống độc quyền Android

21/01/2023

Phản hồi gần đây

  • Crom trong Cách Kích Hoạt Key Win 11 Bản Quyền –Active Win 11 – Win 10 Free
  • ngu trong Anime Wallpaper Video 4k – Anime Kanao Tsuyuri Kimetsu no Yaiba
  • thiem trong Share Phôi Chứng Minh Nhân Dân PSD
  • Nguyễn Tuấn trong Ứng Dụng Thuật Toán Hồi Quy Tuyến Tính Để Chẩn Đoán Xơ Vữa Động Mạch 2021

Donate

Mời Share’cs ly Cafe 

Liên hệ quảng cáo

Email: Sharecs.net@gmail.com

Hợp tác nội dung: Sharecs rất vinh dự được mời các bạn đóng góp những sản phẩm thiết kế, thủ thuật hay những chia sẻ hữu ích… để cùng chia sẻ rộng rãi tới mọi người!

Giới Thiệu

Sharecs.net là một website/blog cá nhân, chuyên chia sẻ những kiến thức xoay quanh công nghệ như máy tính, internet, phần mềm, lập trình,... Mình hi vọng, Sharecs sẽ mang lại những kiến thức mà bạn chưa từng được học trên ghế nhà trường!

  • Giới Thiệu & Liên Hệ
  • Chính Sách Bảo Mật

CopyRight By Sharecs.net DMCA.com Protection Status

No Result
View All Result
  • Trang chủ
  • Thủ Thuật
    • Thủ thuật máy tính
      • Windows
      • MacOS
      • Linux
    • Thủ thuật internet
    • Thủ thuật phần mềm
  • Phần Mềm
  • Lỗi máy tính
    • Lỗi internet
    • Lỗi windows
    • Lỗi phần mềm
  • Lập Trình
    • Lập Trình Java
    • Lập trình Python
    • Lập Trình React Native
    • Code Hay
  • Linh Tinh
    • PhotoShop
    • Tải Video Wallpaper
    • Kho Tools
      • Cân Bằng Phương Trình Hóa Học
      • Custom Css Scrollbar – Render Code
      • Tạo Kí Tự Đặc Biệt Online
      • Tạo Deep Link
    • Tài Liệu – Luận Văn – Báo Cáo
    • Kho Theme Website WordPress

CopyRight By Sharecs.net DMCA.com Protection Status