简体   繁体   English

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

[英]JAVA : Exporting Data (from database) to excel and sending it to client side

As the title suggest, I need to put some data (which I have got from database) into an excel sheet, and then send it to client side so that user can save , open or cancel the action. 正如标题所示,我需要将一些数据(我从数据库中获取)放入Excel工作表,然后将其发送到客户端,以便用户可以保存,打开或取消操作。

I have seen some articles regarding this, the closest one being : How can I get the user to download my file? 我见过一些关于此的文章,最接近的是: 我怎样才能让用户下载我的文件? (Java, MVC, Excel, POI) . (Java,MVC,Excel,POI) Referring to links provided by Stevens I tried out the following code : 参考Stevens提供的链接,我尝试了以下代码:

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;
}

Here firstly WorkbookFactory is not defined. 这里首先没有定义WorkbookFactory Secondly, I could not understand properly how the code is working. 其次,我无法正确理解代码是如何工作的。

I also found this link : 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 . 我也找到了这个链接: 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 But here the excel file gets saved on the server. 但是这里excel文件保存在服务器上。 I want that the file should not be saved on the server side, it should directly go to client side 我希望文件不应该保存在服务器端,它应该直接转到客户端

(If it helps) I am using : struts 2 framework, hibernate (如果有帮助)我正在使用:struts 2框架,hibernate

I am open to using other things like POI API, jQuery or any other good stuff. 我愿意使用其他东西,如POI API,jQuery或任何其他好东西。

I can not use displayTag for some reason. 我出于某种原因无法使用displayTag

Javascript would be my last resort (although I have implemented with it) because it requires changing some default security settings of the browser (If this can be avoided I am open to javascript as well). Javascript将是我的最后一招(尽管我已经实现了它)因为它需要更改浏览器的一些默认安全设置(如果可以避免这种情况我也可以使用javascript)。

Please advise how should I go about this now. 请告知我现在应该怎么做。

Thanks!! 谢谢!!

EDIT : 编辑:

    <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>

The error while executing 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

Okay. 好的。 So finally I am through with all the roadblocks and have figured out a way to do this. 所以最后我完成了所有的障碍,并找到了一种方法来做到这一点。

I realized that the problem I was facing was not in creating the excel file, the problem was sending it to client side, and that too without creating a file or temporary file on the server. 我意识到我遇到的问题不是创建excel文件,问题是将其发送到客户端,而且也没有在服务器上创建文件或临时文件。

So here is how to go about it (I have ripped off details from my original code so that you can easily understand it). 所以这里是如何去做的(我已经从原始代码中删除了细节,以便您可以轻松理解它)。

In the action file you first have to create a HSSFWorkbook object, put data on it and then without saving it to disk on server, send it to client using inputstream. 在操作文件中,您首先必须创建HSSFWorkbook对象,将数据放在其上,然后不将其保存到服务器上的磁盘,使用inputstream将其发送到客户端。

Action File code : 动作文件代码:

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;
}

Now in the struts-config file just write (note that excelStream & contentDisposition has been set in the action itself also the result-type here is org.apache.struts2.dispatcher.StreamResult ): 现在在struts-config文件中只写(注意excelStream&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>

Thats it. 而已。 Now when the action is executed, the user will be prompted to save or open the file. 现在,当执行操作时,将提示用户保存或打开文件。

:) :)

You have two different copies of POI on your classpath, one old and one new. 您在类路径中有两个不同的POI副本,一个旧的和一个新的。 That's why you're getting the exception java.lang.IncompatibleClassChangeError: Class org.apache.poi.hssf.usermodel.HSSFWorkbook does not implement the requested interface org.apache.poi.ss.usermodel.Workbook - you've compiled against the new copy, but at runtime it's finding some new and some old jars. 这就是为什么你得到异常java.lang.IncompatibleClassChangeError:类org.apache.poi.hssf.usermodel.HSSFWorkbook没有实现所请求的接口org.apache.poi.ss.usermodel.Workbook - 你已经编译了新的副本,但在运行时它发现了一些新的和一些旧的罐子。

This is covered in the POI FAQ . POI常见问题解答中对此进行了介绍。 Ideally you should just be able to look at all the jars in your setup, and zap the old POI one. 理想情况下,您应该能够查看设置中的所有罐子,然后消除旧的POI。 If not, the POI FAQ entry has some sample code you can use to get the JVM to print out where it has loaded POI classes from. 如果没有, POI FAQ条目有一些示例代码,您可以使用它们来打印JVM从哪里加载POI类。 That will show you the jar file name, and you can remove the old one. 这将显示jar文件名,您可以删除旧文件名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM