Java:POI之Excel導出

在使用kendoui的Grid導出Excel報表的過程中出現的幾個問題:
1、在打開下載好的文檔時會出現警告



2、打開Excel時,發現Excel的列是緊湊的,不能保證正常的表格的寬度



目前上述問題,我還沒找到問題是如何發生的,且沒有合適的解決辦法(猜測是由于JsZip庫導致的該類型問題)
因此,我希望能將Excel報表的導出放到服務器上去完成!

POI:Apache旗下的一個開源函式庫,提供了 API 給 Java 對 Microsoft Office 格式檔案讀和寫的功能;

結構:

對應POI文檔:http://tool.oschina.net/apidocs/apidoc?api=apache-POI (咳咳。我這里不知道為什么官網進不去!所以只提供鏡像鏈接!官網傳送門)
接下來以xlsx文件為例展示來做一個輸出的流程;


因為要在通過瀏覽器端和服務端交互做導出表格的工作,那么就應該是在瀏覽器端發送請求后,服務器做出響應,在響應中增加要導出報表的相關信息;
因為還有其他需求可能會用到這些部分,我將創建導出xlsx文件的操作包裝成了一個根據類,具體請參照代碼;
其中要特別注意火狐瀏覽器,火狐瀏覽器的編碼規則不同與其他瀏覽器的編解碼規則,火狐要求必須使用iso-8859-1進行傳輸信息,直接使用utf8會出現亂碼問題。

import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

public class ReportUtil {
   /**
     * 根據傳入的請求和文件名,創建一個輸出流
     * @param request 瀏覽器請求,如果請求來判斷當前瀏覽器類型,進行轉碼工作
     * @param httpServletResponse 服務端響應,通過響應中的輸出流導出文件
     * @param fileName 文件名
     * @return 一個響應輸出流
     * @throws IOException 在編碼過程中會出現IO異常
     */
    public static ServletOutputStream createOutputStream(HttpServletRequest request,HttpServletResponse httpServletResponse, String fileName) throws IOException {

        // 通常解決漢字亂碼方法用URLEncoder.encode(...)
        String fileNameDisplay = URLEncoder.encode(fileName, "UTF-8") + ".xlsx";
        if ("FF".equals(getBrowser(request))) {
            // 針對火狐瀏覽器處理方式不一樣了
            fileNameDisplay = new String(fileName.getBytes("UTF-8"),
                    "iso-8859-1") + ".xlsx";
        }

        httpServletResponse.addHeader("Content-Disposition", "attachment;filename=" + fileNameDisplay);
       // httpServletResponse.addHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(fileName + ".xlsx", "UTF-8") + "\"");
        httpServletResponse.setContentType("application/vnd.ms-excel;charset=UTF-8");
        httpServletResponse.setHeader("Accept-Ranges", "bytes");
        ServletOutputStream outputStream = httpServletResponse.getOutputStream();
        return outputStream;
    }
    /**
     * 工作流寫入workbook并關閉當前管控的對應的workbook和輸出流
     * @param wb 當前服務器管控的workbook對象,用于輸出的excel
     * @param outputStream 需要寫入對應的workbook中的輸出流
     * @throws IOException 在寫入workbook時可能會拋出的異常,此異常提交到上一層解決
     */
    public static void streamWriteAndClose(XSSFWorkbook wb,ServletOutputStream outputStream) throws IOException{
        try{
            wb.write(outputStream);
        }catch (OpenXML4JRuntimeException e){
            System.err.println(e.getMessage());
        }
        finally {//包裝到finally中保證關閉操作必執行
            //關閉流
            try{
                outputStream.close();
            }catch (Exception ose){
                System.err.println(ose.getMessage());
            }
            try{
                wb.close();
            }
            catch (Exception wbe){
                System.err.println(wbe.getMessage());
            }
        }
    }

    // 以下為服務器端判斷客戶端瀏覽器類型的方法
    private  static String getBrowser(HttpServletRequest request) {
        String UserAgent = request.getHeader("USER-AGENT").toLowerCase();
        if (UserAgent != null) {
            if (UserAgent.indexOf("msie") >= 0)
                return "IE";
            if (UserAgent.indexOf("firefox") >= 0)
                return "FF";
            if (UserAgent.indexOf("safari") >= 0)
                return "SF";
        }
        return null;
    }

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容