Не удается сгенерировать файл Excel правильно с помощью Spring Boot и Apache POI - PullRequest
0 голосов
/ 13 марта 2019

У меня есть очень простое приложение на основе SpringBoot и Thymeleaf, которое связано с Oracle DB.

Мое приложение в настоящее время читает из таблицы и отображает ее на странице с помощью шаблона пользовательского интерфейса Controller и Thymeleaf. У меня также есть ссылка внизу таблицы, в которой написано "Export to Excel", которая вызывает метод на уровне обслуживания, а также успешно генерирует и даже загружает этот .XLS документ.

Однако проблема в том, что генерируемый Excel является точной копией того, что находится на странице (с некоторыми дополнительными пустыми столбцами справа), даже если я создал лист вручную, написав код, который добавляет дополнительный столбец и другое название.

Не уверен, почему мой код не вызывается и почему данные моей таблицы HTML просто экспортируются в таблицу Excel как есть.

ExcelReportController.java

@Controller
@Log4j2
public class ExcelReportController {

    private static final String EXCEL_FILE_NAME = "applications.xls";
    @Autowired
    private LinkApplService linkApplService;

    @GetMapping("/excel")
    public ModelAndView showPage() {
        return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
    }

    @GetMapping("/download")
    public ModelAndView download(HttpServletResponse response) {
        response.setHeader("Content-disposition", "attachment; filename=" + EXCEL_FILE_NAME);
        return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
    }

}

ExcelBuilderService.java

@Service
public class ExcelBuilderService extends AbstractXlsView {

    @Override
    protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
                                      HttpServletResponse response) {
        Iterable<LinkAppl> linkAppls = (Iterable<LinkAppl>) model.get("linkAppls");
        //THIS SHEET WITH TITLE NOT GETTING SHOWN
        Sheet sheet = workbook.createSheet("All Applications List");
        Row header = sheet.createRow(0);
        header.createCell(0).setCellValue("ID");
        header.createCell(1).setCellValue("DESC");
        header.createCell(2).setCellValue("DESC");
        header.createCell(3).setCellValue("LINK_NOTES"); //THIS COLUMN NOT GETTING DISPLAYED
        int rowNum = 1;
        for (LinkAppl la : linkAppls) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(la.getApplId());
            row.createCell(1).setCellValue(la.getApplDeTx());
            row.createCell(2).setCellValue(la.getApplActvCd());
            row.createCell(3).setCellValue(la.getLinkNotesTx());
        }
    }

}

LinkAppl.java

@Entity
@Table(name = "LINK_APPL")
public class LinkAppl {
    private String applId;
    private String applDeTx;
    private String seqNbResetCd;
    private String intfMsgFrmtCd;
    private String sndRcvCd;
    private String applAcptMsgFrmtCd;
    private String applActvCd;
    private String sodEodIn;
    private String linkNotesTx;
    private String lastModByUsrId;
    private Timestamp lastModTs;
    private String sndCnctStsCd;
    private Long maxSeqNb;
    private String batIntfIn;
    private String gfpSrcSiteCd;
    private String rcvRterAckmentIn;
    private String rcvMqCodIn;
    private String fxApplIn;
    private String rcvEodpAckmentIn;

    //getters and setters go here

}

applications.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title>Link Statistics Report</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
        <h4>Excel Generation Demo</h4>
        <table border="1">
            <thead>
                <tr>
                    <td>App ID</td>
                    <td>Name</td>
                    <td>Active</td>
                </tr>
            </thead>
            <tbody>
                <tr th:each="a : ${linkAppls}">
                    <td th:text="${a.applId}">App ID</td>
                    <td th:text="${a.getApplDeTx()}">Description</td>
                    <td th:text="${a.applActvCd}">Active</td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="7">
                        <a href="/download">Export to Excel</a>
                    </td>
                </tr>
            </tfoot>
        </table>
    </body>
</html>

pom.xml

<!-- for handling .xls files (older format) -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.0.1</version>
</dependency>
<!-- for handling .xlsx files (newer format) -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.0.1</version>
</dependency>

enter image description here

Ответы [ 2 ]

1 голос
/ 13 марта 2019

Два ModelAndViews в ваших контроллерах абсолютно одинаковы.

return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());

точно так же в контроллере загрузки:

return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());

Настройка content-disposition не меняетсяSpring обрабатывает ваш запрос, и если вы откроете applications.xls в текстовом редакторе, вы обнаружите, что только что загрузили html-страницу, переименованную в .xls файл.Вам необходимо выяснить, как правильно подключиться и использовать созданный вами AbstractXlsView.


Загрузка файла:

@GetMapping("/download")
public void download(HttpServletResponse response) throws Exception {
    Iterable<LinkAppl> linkAppls = linkApplService.getAllLinkAppls();

    Workbook workbook = new HSSFWorkbook();
    Sheet sheet = workbook.createSheet("All Applications List");
    Row header = sheet.createRow(0);
    header.createCell(0).setCellValue("ID");
    header.createCell(1).setCellValue("DESC");
    header.createCell(2).setCellValue("DESC");
    header.createCell(3).setCellValue("LINK_NOTES");
    int rowNum = 1;
    for (LinkAppl la : linkAppls) {
        Row row = sheet.createRow(rowNum++);
        row.createCell(0).setCellValue(la.getApplId());
        row.createCell(1).setCellValue(la.getApplDeTx());
        row.createCell(2).setCellValue(la.getApplActvCd());
        row.createCell(3).setCellValue(la.getLinkNotesTx());
    }

    response.setHeader("Content-disposition", "attachment; filename=" + EXCEL_FILE_NAME);
    workbook.write(response.getOutputStream());
}
0 голосов
/ 14 марта 2019

Итак, наконец, с огромной помощью @Metroids я смог загрузить файл Excel через контроллер.Я также экспериментировал с загрузкой существующего файла, расположенного в папке src / main / resources.Вот исходный код для лучшего понимания.

application.html

 <a href="/download">Export to Excel</a>&nbsp;
 <a href="/buildNDownload">Export to Excel 2</a>

ExcelReportController.java

@Controller
@Log4j2
public class ExcelReportController {

    private static final String EXCEL_FILE_NAME = "applications.xls";
    @Autowired
    private LinkApplService linkApplService;

    @GetMapping("/excel")
    public ModelAndView showPage() {
        return new ModelAndView("applications", "linkAppls", linkApplService.getAllLinkAppls());
    }

    @GetMapping(value = "/download")
    public void download(HttpServletResponse response) {
        response.addHeader("Content-Disposition", "attachment; filename=" + EXCEL_FILE_NAME);
        try {
            //download an existing file located in src/main/resources folder
            File file = ResourceUtils.getFile("classpath:" + EXCEL_FILE_NAME);
            InputStream inputStream = new FileInputStream(file);
            IOUtils.copy(inputStream, response.getOutputStream());
            response.flushBuffer();
            inputStream.close();
        } catch (IOException e) {
            log.error("Error while locating file", e);
        }
    }

    @GetMapping(value = "/buildNDownload")
    public void buildNDownload(HttpServletResponse response) throws IOException {
        response.setHeader("Content-disposition", "attachment; filename=applications_new.xlsx");
        Iterable<LinkAppl> linkAppls = linkApplService.getAllLinkAppls();
        //build a file from scratch and then download
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("All Applications List");
        Row header = sheet.createRow(0);
        header.createCell(0).setCellValue("ID");
        header.createCell(1).setCellValue("DESC");
        header.createCell(2).setCellValue("ACTIVE");
        header.createCell(3).setCellValue("LINK_NOTES");
        int rowNum = 1;
        for (LinkAppl la : linkAppls) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(la.getApplId());
            row.createCell(1).setCellValue(la.getApplDeTx());
            row.createCell(2).setCellValue(la.getApplActvCd());
            row.createCell(3).setCellValue(la.getLinkNotesTx());
        }
        workbook.write(response.getOutputStream());
    }

}

pom.xml

<!-- for handling .xls files (older format) -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.0.1</version>
</dependency>
<!-- for handling .xlsx files (newer format) -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
...