1. 程式人生 > >javaUtil---匯出資料到word表格中後,下載word文件

javaUtil---匯出資料到word表格中後,下載word文件

為滿足將對應資料插入到word表格中並匯出word模板,下載word模板。
utils的 controller裡的方法:
1.利用ResponseEntity 實體進行檔案匯出,以解決匯出檔名稱自定,防止亂碼的效果。因為 ResponseEntity 可以對http協議的header進行設定來設定編碼格式。

public static final String TargetDir = "targetfile" + File.separator;
public static final String DownloadDir = "downloadfile" + File.separator;
public
static ResponseEntity<byte[]> fileDownload(File targetfile, String filename, HttpServletRequest request) { try { if (targetfile.exists() && targetfile.isFile()) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//設定header的contenttype為位元組流。
String userAgent = request.getHeader("User-Agent");//通過userAgent判斷瀏覽器型別 byte[] bytes = userAgent.contains("MSIE") ? filename.getBytes() : filename.getBytes("UTF-8"); // name.getBytes("UTF-8")處理safari的亂碼問題,解決檔名亂碼問題 String fileName = new
String(bytes, "ISO-8859-1"); headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");//設定CONTENT_DISPOSITION使瀏覽器開啟檔案下載對話方塊 byte[] readFileToByteArray = null; readFileToByteArray = FileUtils.readFileToByteArray(targetfile); return new ResponseEntity<byte[]>(readFileToByteArray, headers, HttpStatus.OK); } } catch (IOException e) { e.printStackTrace(); } return new ResponseEntity<byte[]>(HttpStatus.INTERNAL_SERVER_ERROR) }

2.獲取模板檔案路徑
//params是一個數據map集合,此資料集合用於將資料插入對應模板的對應位置。然後利用XWPFDocument相關技術操作word文件。

public static String getDocxPath(HttpServletRequest request, String type,
            Map<String, String> params) {
        Map<String, Object> params1 = new HashMap<String, Object>();

        for (Entry<String, String> entry : params.entrySet()) {
            params1.put(entry.getKey(), entry.getValue());
        }

        return getDocxPathIncludePic(request, type, params1);
    }
public static String getDocxPathIncludePic(HttpServletRequest request,
            String type, Map<String, Object> params) {

        Map<String, String> docxMapping = SpringContextHolder
                .getBean("docxMapping");
        String fileTargetPath = docxMapping.get(type);//此tape為配置檔案裡的key值。通過key值獲得對應模板的名字
        String tf = null;
        if (fileTargetPath != null) {
            File dir = new File(request.getSession().getServletContext()
                    .getRealPath("/")
                    + DownloadDir + UserUtils.getUser().getId());//替換後文件暫存資料夾
            if (!dir.exists())
                dir.mkdirs(); // 如果目標資料夾不存在則建立新的資料夾
            InputStream is = null;
            OutputStream os = null;

            try {
                is = new FileInputStream(request.getSession()
                        .getServletContext().getRealPath("/")
                        + TargetDir + fileTargetPath);//獲取模板word檔案地址
                XWPFDocument doc = new XWPFDocument(is);
                replaceInTable(doc, params, "");//呼叫函式替換word文件中的內容
                tf = dir.getPath()
                        + File.separator
                        + UUID.randomUUID().toString().replace("-", "")
                                .concat(".docx");
                os = new FileOutputStream(tf);
                doc.write(os);//生成新的word檔案

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (os != null) {
                        os.close();
                    }
                    if (is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return tf;
    }

3.context配置檔案中設定docxMapping bean

<bean id="docxMapping" class="java.util.HashMap">
        <constructor-arg>
            <map>
                <entry>
                    <key>
                        <value><![CDATA[test]]></value>
                    </key>
                    <value><![CDATA[test.docx]]></value>
                </entry>
        </map>
        </constructor-arg>
</bean>

4.替換word模板內容的方法

private static void replaceInTable(XWPFDocument doc,
            Map<String, Object> params, String destFilePath) {
        Iterator<XWPFTable> iterator = doc.getTablesIterator();//獲取word文件中的表格集合
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        List<XWPFParagraph> paras;
        while (iterator.hasNext()) {
            table = iterator.next();
            rows = table.getRows();
            for (XWPFTableRow row : rows) {
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    paras = cell.getParagraphs();//獲取單元格中的段落
                    for (XWPFParagraph para : paras) {
                        replaceInPara(para, params, destFilePath, doc, cell);//呼叫方法替換單元格內的一個段落
                    }
                }
            }
        }
        Iterator<XWPFParagraph> itPara = doc.getParagraphsIterator();
        XWPFParagraph paragraph;
        while (itPara.hasNext()) {
            paragraph = (XWPFParagraph) itPara.next();
            replaceInPara(paragraph, params, destFilePath, doc, null);
        }
    }

4.替換單元格內的資料方法
替換原理:在模板檔案中需要填寫內容的單元格寫一些key,通過傳入map的key與模板中的key對應,將單元格中的key替換成應該填入的內容。

private static void replaceInPara(XWPFParagraph para,
            Map<String, Object> params, String destFilePath, XWPFDocument doc,
            XWPFTableCell cell) {
        List<XWPFRun> runs = para.getRuns();//獲取段落中的文字
        for (int i = 0; i < runs.size(); i++) {
            XWPFRun run = runs.get(i);
            String runText = run.toString();
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                String key = entry.getKey();
                if (key.equals(runText.trim())) {
                    Object value = entry.getValue();
                    if (value == null) {
                        para.removeRun(i);
                    }
                    // 文字替換
                    else if (value instanceof String) {
                        String ff = run.getFontFamily();
                        int fs = run.getFontSize();
                        para.removeRun(i);
                        XWPFRun newrun = para.insertNewRun(i);
                        newrun.setText(value.toString());
                        newrun.setFontFamily(ff);
                        newrun.setFontSize(fs);
                    }
                    // 圖片替換
                    else if (value instanceof Map) {
                        para.removeRun(i);
                        XWPFRun newrun = para.insertNewRun(i);
                        Map<String, Object> pic = (Map<String, Object>) value;
                        // byte[] byteArray = (byte[]) pic.get("content");
                        // ByteArrayInputStream byteInputStream = new
                        // ByteArrayInputStream(
                        // byteArray);
                        if (pic != null) {
                            try {
                                createPicture(doc, newrun, pic, para);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } else {
                    continue;
                }
            }
        }
    }

5.輔助方法:

/**
     * 將輸入流中的資料寫入位元組陣列
     * 
     * @param in
     * @return
     */
    public static byte[] inputStream2ByteArray(InputStream in, boolean isClose) {
        byte[] byteArray = null;
        try {
            int total = in.available();
            byteArray = new byte[total];
            in.read(byteArray);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (isClose) {
                try {
                    in.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
        return byteArray;
    }

    /**
     * 根據圖片型別,取得對應的圖片型別程式碼
     * 
     * @param picType
     * @return int
     */
    private static int getPictureType(String picType) {
        int res = XWPFDocument.PICTURE_TYPE_PICT;
        if (picType != null) {
            if (picType.equalsIgnoreCase("png")) {
                res = XWPFDocument.PICTURE_TYPE_PNG;
            } else if (picType.equalsIgnoreCase("dib")) {
                res = XWPFDocument.PICTURE_TYPE_DIB;
            } else if (picType.equalsIgnoreCase("emf")) {
                res = XWPFDocument.PICTURE_TYPE_EMF;
            } else if (picType.equalsIgnoreCase("jpg")
                    || picType.equalsIgnoreCase("jpeg")) {
                res = XWPFDocument.PICTURE_TYPE_JPEG;
            } else if (picType.equalsIgnoreCase("wmf")) {
                res = XWPFDocument.PICTURE_TYPE_WMF;
            }
        }
        return res;
    }

    /**
     * 獲取圖片的param引數
     * 
     * @param width
     *            寬度
     * @param height
     *            高度
     * @param imgType
     *            圖片型別 現在只支援 png,dib,emf,jpg,jpeg,wmf
     * @param fileUrl
     *            檔案url路徑
     * @return
     */
    public static Map<String, Object> getPictureParam(int width, int height,
            String imgType, String fileUrl) {
        Map<String, Object> header = new HashMap<String, Object>();
        header.put("width", width);
        header.put("height", height);
        header.put("type", imgType);
        header.put("fileUrl", fileUrl);
        // try {
        // header.put("content",
        // inputStream2ByteArray(new FileInputStream(fileUrl), true));
        // } catch (FileNotFoundException e) {
        // e.printStackTrace();
        // }
        return header;
    }

    /**
     * @param id
     * @param width
     *            寬
     * @param height
     *            高
     * @param paragraph
     *            段落
     */
    private static void createPicture(XWPFDocument doc, XWPFRun run,
            Map<String, Object> pic, XWPFParagraph paragraph) {
        FileInputStream fileInputStream = null;
        int width = Integer.parseInt(pic.get("width").toString());
        int height = Integer.parseInt(pic.get("height").toString());
        int picType = getPictureType(pic.get("type").toString());
        String fileUrl = pic.get("fileUrl").toString();
        int id = 0;
        try {
            id = doc.getNextPicNameNumber(picType);
        } catch (InvalidFormatException e1) {
            e1.printStackTrace();
        }

        try {
            fileInputStream = new FileInputStream(fileUrl);
            final String blipId = run.getDocument().addPictureData(
                    fileInputStream, picType);

            final int EMU = 9525;
            width *= EMU;
            height *= EMU;
            // String blipId =
            // getAllPictures().get(id).getPackageRelationship().getId();

            final CTInline inline = run.getCTR().addNewDrawing().addNewInline();

            final String picXml = ""
                    + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
                    + "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
                    + "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
                    + "         <pic:nvPicPr>" + "            <pic:cNvPr id=\""
                    + id
                    + "\" name=\"Generated\"/>"
                    + "            <pic:cNvPicPr/>"
                    + "         </pic:nvPicPr>"
                    + "         <pic:blipFill>"
                    + "            <a:blip r:embed=\""
                    + blipId
                    + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
                    + "            <a:stretch>"
                    + "               <a:fillRect/>"
                    + "            </a:stretch>"
                    + "         </pic:blipFill>"
                    + "         <pic:spPr>"
                    + "            <a:xfrm>"
                    + "               <a:off x=\"0\" y=\"0\"/>"
                    + "               <a:ext cx=\""
                    + width
                    + "\" cy=\""
                    + height
                    + "\"/>"
                    + "            </a:xfrm>"
                    + "            <a:prstGeom prst=\"rect\">"
                    + "               <a:avLst/>"
                    + "            </a:prstGeom>"
                    + "         </pic:spPr>"
                    + "      </pic:pic>"
                    + "   </a:graphicData>" + "</a:graphic>";

            // CTGraphicalObjectData graphicData =
            // inline.addNewGraphic().addNewGraphicData();
            XmlToken xmlToken = null;
            xmlToken = XmlToken.Factory.parse(picXml);
            inline.set(xmlToken);
            // graphicData.set(xmlToken);

            inline.setDistT(0);
            inline.setDistB(0);
            inline.setDistL(0);
            inline.setDistR(0);

            final CTPositiveSize2D extent = inline.addNewExtent();
            extent.setCx(width);
            extent.setCy(height);

            final CTNonVisualDrawingProps docPr = inline.addNewDocPr();
            docPr.setId(id);
            docPr.setName("Picture " + id);
            docPr.setDescr("Generated");
        } catch (final Exception e) {
            run.setText("圖片路徑有誤或者非標準格式圖片,請到網站下載自行插入");
            run.setColor("FF0000");
        } finally {
            // close streams
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (final IOException ioEx) {
                    // can be ignored
                }
            }
        }
    }