web-dev-qa-db-ja.com

Excel JSFおよびPrimeFacesへのエクスポート

JDK 1.6、JSF 2.1、PrimeFaces 2.2.1、POI 3.2、およびApache Tomcat 7の使用

ユーザーの選択に基づいてExcelファイルをダウンロードできるようにサーブレットをセットアップしようとしています。 Excelドキュメントは実行時に作成されます。

エラーはなく、コードはサーブレットに入ります。

ボタンをクリックしても何も起こりません。 Excelドキュメントのデータで並べ替えとカスタムの書式設定を行う必要があるため、PrimeFacesが使用するデータテーブルエクスポートを使用していません。

ExportExcelReports.Java

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {       
    response.setContentType("application/vnd.ms-Excel");
    response.setHeader("Content-Disposition", "attachment; filename=\"my.xls\"");                

    HSSFWorkbook workbook = new HSSFWorkbook();

    HSSFSheet sheet = workbook.createSheet();
    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = row.createCell(0);
    cell.setCellValue(0.0);

    FileOutputStream out = new FileOutputStream("my.xls");
    workbook.write(out);
    out.close();
}

ProjectReportBean.Java

public void getReportData() {
    try {
        FacesContext ctx = FacesContext.getCurrentInstance();
        ExternalContext ectx = ctx.getExternalContext();
        HttpServletRequest request = (HttpServletRequest) ectx.getRequest();
        HttpServletResponse response = (HttpServletResponse) ectx.getResponse();
        RequestDispatcher dispatcher = request.getRequestDispatcher("/ExportExcelReports");
        dispatcher.forward(request, response);
        ctx.responseComplete();
    } catch (Exception e) {}
}

index.xhtml

<h:form id="reportsForm">
    <h:outputLabel for="report" value="Reports" /><br />
    <h:selectOneMenu id="report" value="#{projectReportBean.selectedReport}" required="true" requiredMessage="Select Report">
        <f:selectItem itemLabel="---" noSelectionOption="true" />
        <f:selectItems value="#{projectReportBean.reports}" />
    </h:selectOneMenu>

    <p:commandButton action="#{projectReportBean.getReportData}" value="Export" update="revgrid" />                      
</h:form>
16
Berek Bryan

2つの問題があります。

最初の問題は、_<p:commandButton>_がデフォルトでAjaxリクエストを送信することです。このリクエストはJavaScriptコードによって発生します。ただし、JavaScriptはファイルのダウンロードを含む応答では何もできません。セキュリティ上の制限により、JavaScriptはSave Asダイアログなどを生成できません。応答は基本的に完全に無視されます。

_ajax="false"_を_<p:commandButton>_に追加してajaxをオフにしてボタンが通常の同期HTTPリクエストを起動するようにするか、標準の_<h:commandButton>_に置き換える必要があります。

_<p:commandButton ajax="false" ... />
_

または

_<h:commandButton ... />
_

2番目の問題は、サーブレットがExcelファイルを応答にまったく書き込まず、サーバーの作業ディレクトリに保存されているローカルファイルに書き込むことです。基本的に、HTTP応答にはnothingが含まれます。 HttpServletResponse#getOutputStream()WorkBook#write()メソッドに渡す必要があります。

_workbook.write(response.getOutputStream());
_

無関係なことに、ここでサーブレットがどのように役立つのか疑問に思います。 JSF外で再利用しますか?そうでない場合は、必ずしもサーブレットにディスパッチする必要はなく、Beanのアクションメソッドで同じコードを実行するだけです。その空のcatchブロックもまた素敵ではありません。メソッドでthrowsとして宣言するか、少なくともnew FacesException(e)として再スローします。


pdateコメントどおり、サーブレットにまったく興味がないようです。次に、JSFアクションメソッドでプログラム的にExcelファイルを送信する方法を簡単に書き直します。

_public void getReportData() throws IOException {
    HSSFWorkbook workbook = new HSSFWorkbook();
    HSSFSheet sheet = workbook.createSheet();
    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = row.createCell(0);
    cell.setCellValue(0.0);

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    externalContext.setResponseContentType("application/vnd.ms-Excel");
    externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"my.xls\"");

    workbook.write(externalContext.getResponseOutputStream());
    facesContext.responseComplete();
}
_
26
BalusC

ここに私が前に書いたものと作業ケースがあります。

xhtml;

<h:panelGrid id="viewCommand" style="float:right;" >
                        <p:commandButton value="Export Excel" icon="ui-icon-document"
                            ajax="false" actionListener="#{xxx.export2Excel}"
                            rendered="#{xxx.showTable}">
                            <p:fileDownload value="#{xxx.exportFile}"
                                contentDisposition="attachment" />
                        </p:commandButton></h:panelGrid>

Javaサイド(POIあり);

protected void lOBExport2Excel(List table) throws Throwable {
    Row row = null;
    Cell cell = null;
    try {

        Workbook wb = new HSSFWorkbook();
        HSSFCellStyle styleHeader = (HSSFCellStyle) wb.createCellStyle();
        HSSFFont fontHeader = (HSSFFont) wb.createFont();
        fontHeader.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        styleHeader.setFont(fontHeader);
        Sheet sheet = wb.createSheet("sheet");
        row = sheet.createRow((short) 0);

        for (int i = 0; i < columnNames.size(); i++) {
            cell = row.createCell(i);
            cell.setCellValue(columnNames.get(i));
            cell.setCellStyle(styleHeader);
        }

        int j = 1;

        for (DBData[] temp : tabularData) {
            row = sheet.createRow((short) j);
            for (int k = 0; k < temp.length; k++) {
                HSSFCellStyle styleRow = (HSSFCellStyle) wb.createCellStyle();
                HSSFFont fontRow = (HSSFFont) wb.createFont();
                fontRow.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
                styleRow.setFont(fontRow);
                cell = row.createCell(k);
                setStyleFormat(temp[k].getDataType(), styleRow, wb);
                cell.setCellValue(temp[k].toFullString());
                cell.setCellStyle(styleRow);
            }

            j++;
        }

        String excelFileName = getFileName("xls");

        FileOutputStream fos = new FileOutputStream(excelFileName);
        wb.write(fos);
        fos.flush();
        fos.close();

        InputStream stream = new BufferedInputStream(new FileInputStream(excelFileName));
        exportFile = new DefaultStreamedContent(stream, "application/xls", excelFileName);


    } catch (Exception e) {
        catchError(e);
    }

}
1
newuserua

PrimeFaces FileDownloadの使用も検討することをお勧めします。あなたの構造に応じて、これは非常に簡単になります。 ContentStreamを提供できるマネージドBeanだけをサーブレットに作成する必要はありません。

ただし、サーブレットはすでに作成されているため、変更する必要はありません。

0
Rob V