JAVA:将数据(从数据库)导出到Excel并将其发送到客户端

时间:2012-02-15 12:23:47

标签: java struts2 inputstream apache-poi

正如标题所示,我需要将一些数据(我从数据库中获取)放入Excel工作表,然后将其发送到客户端,以便用户可以保存,打开或取消操作。

我见过一些关于此的文章,最接近的文章是:How can I get the user to download my file? (Java, MVC, Excel, POI)。参考史蒂文斯提供的链接,我尝试了以下代码:

public String execute(){
    setContentDisposition("attachment; filename=\"" + ename + "\"");
    try{
        ServletContext servletContext = ServletActionContext.getServletContext();
        String filePath = servletContext.getRealPath("/WEB-INF/template/excel/mytemplate.xls");
        File file = new File(filePath);
        Workbook wb = WorkbookFactory.create(new FileInputStream(file));
        Sheet sheet = wb.getSheetAt(0);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        wb.write(baos);
        InputStream excelStream;
        excelStream = new ByteArrayInputStream(baos.toByteArray());
    }catch(Exception e){
        System.out.println(e.getMessage());
    }
    return SUCCESS;
}

首先,WorkbookFactory未定义。其次,我无法正确理解代码是如何工作的。

我还找到了这个链接:http://www.roseindia.net/answers/viewqa/Java-Beginners/14930-How-to-export-data-from-database-to-excel-sheet-by-using-java--in-standalone-project.html。但是这里excel文件保存在服务器上。我希望文件不应该保存在服务器端,它应该直接转到客户端

(如果有帮助)我正在使用:struts 2 framework,hibernate

我愿意使用其他东西,比如POI API,jQuery或任何其他好东西。

出于某种原因,我无法使用displayTag

Javascript将是我最后的手段(尽管我已经实现了它),因为它需要更改浏览器的一些默认安全设置(如果可以避免,我也可以使用javascript)。

请告知我现在应该怎么做。

谢谢!

编辑:

    <result-types>
        <result-type name="jsp" class="org.apache.struts2.views.jsp"/>
        <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
        <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
    </result-types>
    <action name="myActionName" class="package.myActionClass">
         <result type="stream">
            <param name="contentType">"application/vnd.ms-excel"</param>
            <param name="inputName">excelStream</param>
            <param name="contentDisposition">contentDisposition</param>
            <param name="bufferSize">1024</param>
         </result>
    </action>

执行操作时出错:

java.lang.reflect.InvocationTargetException

java.lang.IncompatibleClassChangeError: Class org.apache.poi.hssf.usermodel.HSSFWorkbook does not implement the requested interface org.apache.poi.ss.usermodel.Workbook

2 个答案:

答案 0 :(得分:10)

好。所以最后我完成了所有的障碍,并想出办法来做到这一点。

我意识到我遇到的问题不是创建excel文件,问题是将其发送到客户端,而且也没有在服务器上创建文件或临时文件。

所以这里是如何去做的(我已经从原始代码中删除了详细信息,以便您可以轻松理解它。)

在操作文件中,您首先必须创建HSSFWorkbook对象,将数据放在其上,然后不将其保存到服务器上的磁盘,使用输入流将其发送到客户端。

行动档案代码:

public String execute(){

    setContentDisposition("attachment; filename=\"" + ename + ".xls\"");

    try{
        HSSFWorkbook hwb=new HSSFWorkbook();
        HSSFSheet sheet =  hwb.createSheet("new sheet");

        //////You can repeat this part using for or while to create multiple rows//////
            HSSFRow row = sheet.createRow(rowNum);
            row.createCell(0).setValue("col0");
            row.createCell(1).setValue("col1");
            row.createCell(2).setValue("col2");
            row.createCell(3).setValue("col3");
            .
            .
            .
        ///////////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////////
        //////Now you are ready with the HSSFworkbook object to be sent to client//////
        ///////////////////////////////////////////////////////////////////////////////

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        hwb.write(baos);
        excelStream = new ByteArrayInputStream(baos.toByteArray());

        ///////////////////////////////////////////////////////////////////////////////
        ////Here HSSFWorkbook object is sent directly to client w/o saving on server///
        ///////////////////////////////////////////////////////////////////////////////
    }catch(Exception e){
        System.out.println(e.getMessage());
    }
    return SUCCESS;
}

现在在struts-config文件中写一下(注意excelStream&amp; contentDisposition已在动作本身设置,结果类型也是org.apache.struts2.dispatcher.StreamResult):

    <action name="actionName" class="actionClass">
        <result type="stream">
            <param name="contentType">"application/vnd.ms-excel"</param>
            <param name="inputName">excelStream</param>
            <param name="contentDisposition">contentDisposition</param>
            <param name="bufferSize">1024</param>
        </result>
    </action>

多数民众赞成。现在,当执行操作时,将提示用户保存或打开文件。

:)

答案 1 :(得分:2)

您的类路径中有两个不同的POI副本,一个旧的和一个新的。这就是为什么你得到异常 java.lang.IncompatibleClassChangeError:类org.apache.poi.hssf.usermodel.HSSFWorkbook没有实现所请求的接口org.apache.poi.ss.usermodel.Workbook - 你已经针对新副本进行了编译,但在运行时它正在寻找一些新的和一些旧的罐子。

POI FAQ中介绍了这一点。理想情况下,您应该能够查看设置中的所有罐子,然后消除旧的POI。如果没有,POI FAQ entry有一些示例代码可用于让JVM打印出从中加载POI类的位置。这将显示jar文件名,您可以删除旧文件名。