天天看點

批量html轉word 或者 pdf

代碼中用到了jacob首先要下載下傳相應版本的.dll放到jdk 和 jre 的bin目錄下面 可參考https://www.cnblogs.com/liudaihuablogs/p/9761297.html

maven 

<dependency>
			<groupId>cn.afterturn</groupId>
			<artifactId>easypoi-base</artifactId>
			<version>4.1.0</version>
		</dependency>
		<!-- easypoi-->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-scratchpad</artifactId>
			<version>3.14</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.14</version>
		</dependency>

		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>xdocreport</artifactId>
			<version>1.0.6</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.14</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>ooxml-schemas</artifactId>
			<version>1.3</version>
		</dependency>
		<dependency>
			<groupId>org.jsoup</groupId>
			<artifactId>jsoup</artifactId>
			<version>1.11.3</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.14</version>
		</dependency>
		<dependency>
			<groupId>net.sf.jacob-project</groupId>
			<artifactId>jacob</artifactId>
			<version>1.14.3</version>
		</dependency>
           
@Controller
public class TempController {

    @Autowired
    private TempService tempService;

    @RequestMapping("/baogao")
    public void execute() throws  Exception{
        // 拼接html
        List<InfoDetailResponse> report = tempService.getReport();
    }



}
           
package com.meadin.service.front.service.impl;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.meadin.common.module.response.InfoDetailResponse;
import com.meadin.service.front.dao.TempDao;
import com.meadin.service.front.service.TempService;
import com.meadin.service.front.util.CustomXWPFDocument;
import com.meadin.service.front.util.MSOfficeGeneratorUtils;
import com.meadin.service.front.util.OfficeUtil;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.util.HtmlUtils;

import javax.annotation.Resource;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description:
 * @Auther:
 * @Date: 2019/9/20 16:24
 * @version:
 */
@Service
public class TempServiceImpl implements TempService {
    @Resource
    private TempDao tempDao;

    public List<InfoDetailResponse> getReport(){
        List<InfoDetailResponse> report = tempDao.getReport();
        for (InfoDetailResponse info:report) {
            try {
                String html = getHtml(info.getTitle(), info.getMetaDescription(), info.getText());
                writeWordFile(html,info);
                String name=info.getTitle();
                String docFile="D:\\report\\"+name+".docx";
                String pdf="D:\\meadinPdf\\"+name+".pdf";
               // docToPdf(docFile,pdf);
            }catch (Exception e){
                e.printStackTrace();
            }

        }
        return report;
    }
    public String getHtml(String title,String mets,String text) throws Exception {
        String html1="<!DOCTYPE html>\n" +
                "<html>\n" +
                "  <head>\n" +
                "      <meta charset=\"utf-8\"/>\n" +
                "      <meta name=\"renderer\" content=\"webkit\" />\n" +
                "      <meta http-equiv=\"X-UA-Compatible\" content=\"IE=EDGE,chrome=1\" />\n" +
                "      <meta content=\"user-scalable=no, width=1200, initial-scale=1, maximum-scale=1.0\"  name=\"viewport\"/>\n" +
                "  </head>\n" +
                "  <body>\n" +
                "    <div class=\"box-body view-container\">\n" +
                "\t\t\t <h2 style=\"text-align:center;\"> ";
        String html2="</h2>\n" +
                "\t  \t<p  style=\"text-align:center;\" class=\"ext\">\n" +
                "\t  \t\t<font color=\"gray\">邁點研究院</font>\n" +
                "\t  \t</p>\t\t\n" +
                "\t\t<p> <font color=\"gray\">";

        String html3="</font></p>\n" +
                "\t  \t<div class=\"text\">";

        String html4="<div>\n" +
                "  </body>\n" +
                "</html>";
        String html = html1 + title + html2 + mets + html3 + text + html4;

        return html;
    }


    public   String writeWordFile(String content,InfoDetailResponse info) {
        int id=info.getId();
        String name=info.getTitle();
        String docFile="D:\\report\\"+name+".docx";
        String path = "D:/wordFile";
        Map<String, Object> param = new HashMap<String, Object>();

        if (!"".equals(path)) {
            File fileDir = new File(path);
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            content = HtmlUtils.htmlUnescape(content);
            List<HashMap<String, String>> imgs = getImgStr(content);
            int count = 0;
            for (HashMap<String, String> img : imgs) {
                count++;
                //處理替換以“/>”結尾的img标簽
                content = content.replace(img.get("img"), "${imgReplace" + count + "}");
                //處理替換以“>”結尾的img标簽
                content = content.replace(img.get("img1"), "${imgReplace" + count + "}");
                //處理替換以“ />”結尾的img标簽
                content = content.replace(img.get("img2"), "${imgReplace" + count + "}");
                Map<String, Object> header = new HashMap<String, Object>();

                try {
                    File filePath = new File(ResourceUtils.getURL("classpath:").getPath());
                    String imagePath = img.get("src");
                    //如果沒有寬高屬性,預設設定為400*300
                    int[] imgWH = getImgWH(imagePath);
                    int w= imgWH[0];
                    int h= imgWH[1];
                    if (w>500){
                        double a= 500d/w;
                        double h1= a*h;
                        h=(int)h1;
                        w=500;
                    }
                    header.put("width",w);
                    header.put("height",h);
                    header.put("type", "jpg");
                    header.put("content", OfficeUtil.inputStream2ByteArray(getImageStream(imagePath), true));
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                param.put("${imgReplace" + count + "}", header);
            }
            try {
                // 生成doc格式的word文檔,需要手動改為docx
                byte by[] = content.getBytes("UTF-8");
                ByteArrayInputStream bais = new ByteArrayInputStream(by);
                POIFSFileSystem poifs = new POIFSFileSystem();
                DirectoryEntry directory = poifs.getRoot();
                DocumentEntry documentEntry = directory.createDocument("WordDocument", bais);
                String pathTemp="D:\\wordFile\\"+name+"temp.doc";
                FileOutputStream ostream = new FileOutputStream(pathTemp);
                poifs.writeFilesystem(ostream);
                bais.close();
                ostream.close();
                getWord(name);
                String pathMod="D:\\wordFile\\"+name+"mod.doc";
                CustomXWPFDocument doc = OfficeUtil.generateWord(param, pathMod);
                //最終生成的帶圖檔的word檔案
                FileOutputStream fopts = new FileOutputStream(docFile);
                doc.write(fopts);
                fopts.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "D:/wordFile/final.docx";
    }

    public InputStream getImageStream(String url) {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setReadTimeout(50000);
            connection.setConnectTimeout(50000);
            connection.setRequestMethod("GET");
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                InputStream inputStream = connection.getInputStream();
                return inputStream;
            }
        } catch (IOException e) {
            System.out.println("擷取網絡圖檔出現異常,圖檔路徑為:" + url);
            e.printStackTrace();
        }
        return null;
    }


    //擷取html中的圖檔元素資訊
    public   List<HashMap<String, String>> getImgStr(String htmlStr) {
        List<HashMap<String, String>> pics = new ArrayList<HashMap<String, String>>();

        Document doc = Jsoup.parse(htmlStr);
        Elements imgs = doc.select("img");
        for (Element img : imgs) {
            HashMap<String, String> map = new HashMap<String, String>();
            if(!"".equals(img.attr("width"))) {
                map.put("width", img.attr("width").substring(0, img.attr("width").length() - 2));
            }
            if(!"".equals(img.attr("height"))) {
                map.put("height", img.attr("height").substring(0, img.attr("height").length() - 2));
            }
            map.put("img", img.toString().substring(0, img.toString().length() - 1) + "/>");
            map.put("img2", img.toString().substring(0, img.toString().length() - 1) + " />");
            map.put("img1", img.toString());
            map.put("src", img.attr("src"));
            pics.add(map);
        }
        return pics;
    }


    public  void getWord(String name) {
        // 複制空白文檔-粘貼到臨時文檔(相當于手動執行copy_paste)
        MSOfficeGeneratorUtils officeUtils = new MSOfficeGeneratorUtils(false);
        String path="D:\\wordFile\\"+name+"temp.doc";
        officeUtils.openDocument(path);
        officeUtils.copy(); // 拷貝整篇文檔
        officeUtils.close();
        officeUtils.createNewDocument();
        officeUtils.paste(); // 粘貼整篇文檔
        String pathMod="D:\\wordFile\\"+name+"mod.doc";
        officeUtils.saveAs(pathMod);
        officeUtils.close(); // 關閉Office Word建立的文檔
        officeUtils.quit(); // 退出Office Word程式
    }
    /**
     * 讀取遠端url圖檔,得到寬高
     * @param imgurl 圖檔路徑
     * @return [0] 寬  [1]高
     */
    public  int[] getImgWH(String imgurl) {
        boolean b = false;
        try {
            //執行個體化url
            URL url = new URL(imgurl);
            //載入圖檔到輸入流
            BufferedInputStream bis = new BufferedInputStream(url.openStream());
            //執行個體化存儲位元組數組
            byte[] bytes = new byte[100];
            //設定寫入路徑以及圖檔名稱
            OutputStream bos = new FileOutputStream(new File("pic.jpg"));
            int len;
            while ((len = bis.read(bytes)) > 0) {
                bos.write(bytes, 0, len);
            }
            bis.close();
            bos.flush();
            bos.close();
            //關閉輸出流
            b = true;
        } catch (Exception e) {
            //如果圖檔未找到
            b = false;
        }
        int[] a = new int[2];
        if (b) {//圖檔存在
            //得到檔案
            File file = new File("pic.jpg");
            BufferedImage bi = null;
            boolean imgwrong = false;
            try {
                //讀取圖檔
                bi = javax.imageio.ImageIO.read(file);
                try {
                    //判斷檔案圖檔是否能正常顯示,有些圖檔編碼不正确
                    int i = bi.getType();
                    imgwrong = true;
                } catch (Exception e) {
                    imgwrong = false;
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if (imgwrong) {
                a[0] = bi.getWidth(); //獲得 寬度
                a[1] = bi.getHeight(); //獲得 高度
            } else {
                a = null;
            }
            //删除檔案
            file.delete();
        } else {//圖檔不存在
            a = null;
        }
        return a;
    }


    public void docToPdf(String wordFile,String pdfFile) {
        ActiveXComponent app = null;
        System.out.println("開始轉換...");
        // 開始時間
        long start = System.currentTimeMillis();
        try {
            // 打開word
            app = new ActiveXComponent("Word.Application");
            Dispatch documents = app.getProperty("Documents").toDispatch();
            System.out.println("打開檔案: " + wordFile);
            // 打開文檔
            Dispatch document = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch();
            // 如果檔案存在的話,不會覆寫,會直接報錯,是以我們需要判斷檔案是否存在
            File target = new File(pdfFile);
            if (target.exists()) {
                target.delete();
            }
            System.out.println("另存為: " + pdfFile);
            // 另存為,将文檔報錯為pdf,其中word儲存為pdf的格式宏的值是17
            Dispatch.call(document, "SaveAs", pdfFile, 17);
            // 關閉文檔
            Dispatch.call(document, "Close", false);
            // 結束時間
            long end = System.currentTimeMillis();
            System.out.println("轉換成功,用時:" + (end - start) + "ms");
        }catch(Exception e) {
            System.out.println("轉換失敗"+e.getMessage());
        }finally {
            // 關閉office
            app.invoke("Quit", 0);
        }
    }

}
           
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;

import java.io.IOException;
import java.io.InputStream;

/**
 * 自定義 XWPFDocument,并重寫 createPicture()方法
 */
public class CustomXWPFDocument extends XWPFDocument {
    public CustomXWPFDocument(InputStream in) throws IOException {
        super(in);
    }

    public CustomXWPFDocument() {
        super();
    }

    public CustomXWPFDocument(OPCPackage pkg) throws IOException {
        super(pkg);
    }

    /**
     * @param ind
     * @param width 寬
     * @param height 高
     * @param paragraph  段落
     */
    public void createPicture(String blipId, int ind, int width, int height,XWPFParagraph paragraph) {
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();
        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=\""
                + ind
                + "\" 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>";

        inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try {
            xmlToken = XmlToken.Factory.parse(picXml);
        } catch (XmlException xe) {
            xe.printStackTrace();
        }
        inline.set(xmlToken);

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

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

        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(ind);
        docPr.setName("圖檔" + ind);
        docPr.setDescr("測試");
    }
}

           
package com.meadin.service.front.util;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

import java.util.List;

public class MSOfficeGeneratorUtils {
    /**
     * * Microsoft Office Word 程式對象
     */
    private ActiveXComponent word = null;

    /**
     * Word 活動文檔對象
     */
    private Dispatch document = null;

    /**
     * 所有 Word 文檔對象
     */
    private Dispatch documents = null;

    /**
     * *selection 代表目前活動文檔視窗中的所選内容。如果文檔中沒有選中任何内容,則此對象代表插入點(即光标所在位置)。<br/>
     * * 每個文檔視窗中隻能存在一個selection對象,并且在整個應用程式中,隻能存在一個活動的selection對象
     */
    private Dispatch selection = null;

    /**
     * * range 對象代表文檔中的一個連續的區域。每個range對象由一個起始字元位置與結束字元位置定義。<br/>
     * * range 對象獨立于所選内容。你可以定義和處理一個範圍而無需改變所選内容。還可以在文檔中定義多個範圍。但每個文檔中隻能有一個所選内容
     */
    private Dispatch range = null;

    /**
     * * PageSetup 對象包含文檔所有頁面的設定屬性(如紙張大小,左邊距,下邊距)
     */
    private Dispatch pageSetup = null;

    /**
     * * 文檔中的所有表格對象
     */
    private Dispatch tables = null;

    /** 單個表格對象 */
    private Dispatch table = null;

    /** 表格所有行對象 */
    private Dispatch rows = null;

    /** 表格所有列對象 */
    private Dispatch cols = null;

    /** 表格指定行對象 */
    private Dispatch row = null;

    /** 表格指定列對象 */
    private Dispatch col = null;

    /** 表格中指定的單元格 */
    private Dispatch cell = null;

    /** 字型 */
    private Dispatch font = null;

    /** 對齊方式 */
    private Dispatch alignment = null;

    /**
     * * 構造方法 * * @param visible * 設定在生成word文檔時,程式是否可見
     */
    public MSOfficeGeneratorUtils(boolean visible) {
        if (this.word == null) {
            // 初始化Microsoft Office Word 執行個體
            this.word = new ActiveXComponent("Word.Application");
            this.word.setProperty("Visible", new Variant(visible));
            // 禁用宏
            this.word.setProperty("AutomationSecurity", new Variant(3));
        }
        if (this.documents == null)
            this.documents = word.getProperty("Documents").toDispatch();
    }

    /**
     * * 設定頁面方向與頁邊距 * * @param orientation * 頁面方向 *
     * <ul>
     * *
     * <li>0 橫向</li> *
     * <li>1 縱向</li> *
     * </ul>
     * * @param leftMargin * 左邊距 * @param rightMargin * 右邊距 * @param topMargin * 上邊距
     * * @param buttomMargin * 下邊距
     */
    public void setPageSetup(int orientation, int leftMargin, int rightMargin, int topMargin, int buttomMargin) {
        if (this.pageSetup == null)
            this.getPageSetup();
        Dispatch.put(pageSetup, "Orientation", orientation);
        Dispatch.put(pageSetup, "LeftMargin", leftMargin);
        Dispatch.put(pageSetup, "RightMargin", rightMargin);
        Dispatch.put(pageSetup, "TopMargin", topMargin);
        Dispatch.put(pageSetup, "BottomMargin", buttomMargin);
    }

    /**
     * * 打開word文檔 * * @param docPath * word文檔路徑 * @return 打開的文檔對象
     */
    public Dispatch openDocument(String docPath) {
        this.document = Dispatch.call(documents, "Open", docPath).toDispatch();
        this.getSelection();
        this.getRange();
        this.getAlignment();
        this.getFont();
        this.getPageSetup();
        return this.document;
    }

    /**
     * * 建立一篇新文檔 * * @return 文檔對象
     */
    public Dispatch createNewDocument() {
        this.document = Dispatch.call(documents, "Add").toDispatch();
        this.getSelection();
        this.getRange();
        this.getPageSetup();
        this.getAlignment();
        this.getFont();
        return this.document;
    }

    /**
     * * 擷取標明的内容或插入點 * * @return selection
     */
    public Dispatch getSelection() {
        this.selection = word.getProperty("Selection").toDispatch();
        return this.selection;
    }

    /**
     * * 擷取目前文檔中可以修改的部分,前提是必須存在選中内容 * * @return range
     */
    public Dispatch getRange() {
        this.range = Dispatch.get(this.selection, "Range").toDispatch();
        return this.range;
    }

    /**
     * * 獲得目前文檔的頁面屬性
     */
    public Dispatch getPageSetup() {
        if (this.document == null)
            return this.pageSetup;
        this.pageSetup = Dispatch.get(this.document, "PageSetup").toDispatch();
        return this.pageSetup;
    }

    /**
     * * 把選中内容或插入點向上移動 * * @param count * 移動的距離
     */
    public void moveUp(int count) {
        for (int i = 0; i < count; i++)
            Dispatch.call(this.selection, "MoveUp");
    }

    /**
     * * 把選中内容或插入點向下移動 * * @param count * 移動的距離
     */
    public void moveDown(int count) {
        for (int i = 0; i < count; i++)
            Dispatch.call(this.selection, "MoveDown");
    }

    /**
     * * 把選中内容或插入點向左移動 * * @param count * 移動的距離
     */
    public void moveLeft(int count) {
        for (int i = 0; i < count; i++)
            Dispatch.call(this.selection, "MoveLeft");
    }

    /**
     * * 把選中内容或插入點向右移動 * * @param count * 移動的距離
     */
    public void moveRight(int count) {
        for (int i = 0; i < count; i++)
            Dispatch.call(this.selection, "MoveRight");
    }

    /**
     * * 執行硬換行(Enter鍵) * * @param count * 換行數
     */
    public void enterDown(int count) {
        for (int i = 0; i < count; i++)
            Dispatch.call(this.selection, "TypeParagraph");
    }

    /**
     * * 把插入點移動到檔案首位置
     */
    public void moveStart() {
        Dispatch.call(this.selection, "HomeKey", new Variant(6));
    }

    /**
     * * 把插入點移動到檔案末尾
     */
    public void moveEnd() {
        Dispatch.call(selection, "EndKey", new Variant(6));
    }

    /**
     * * 從標明内容或插入點開始查找文本 * * @param toFindText * 要查找的内容 * @return 查詢到的内容并選中
     */
    public boolean find(String toFindText) {
        // 從selection所在位置開始查詢
        Dispatch find = Dispatch.call(this.selection, "Find").toDispatch();
        // 設定要查找的?熱?br />
        Dispatch.put(find, "Text", toFindText);
        // 向前查找
        Dispatch.put(find, "Forward", "True");
        // 設定格式
        Dispatch.put(find, "Format", "True");
        // 大小寫比對
        Dispatch.put(find, "MatchCase", "True");
        // 全字比對
        Dispatch.put(find, "MatchWholeWord", "True");
        // 查找并選中
        return Dispatch.call(find, "Execute").getBoolean();
    }

    /**
     * * 替換標明的内容 * * @param newText * 要替換的内容
     */
    public void replace(String newText) {
        // 設定替換文本
        Dispatch.put(this.selection, "Text", newText);
    }

    /**
     * * 全局替換 * * @param oldText * 要替換的内容 * @param replaceObj * 被替換的内容
     */
    public void replaceAll(String oldText, Object replaceObj) {
        // 将插入點移到檔案開頭
        moveStart();
        // 表格替換方式
        String newText = (String) replaceObj;
        // 圖檔替換方式
        if (oldText.indexOf("image") != -1 || newText.lastIndexOf(".bmp") != -1 || newText.lastIndexOf(".jpg") != -1
                || newText.lastIndexOf(".gif") != -1) {
            while (find(oldText)) {
                insertImage(newText);
                Dispatch.call(this.selection, "MoveRight");
            }
            // 文本方式
        } else {
            while (find(oldText)) {
                replace(newText);
                Dispatch.call(this.selection, "MoveRight");
            }
        }
    }

    /**
     * * 将指定的内容替換成圖檔 * @param replaceText 指定的内容 * @param imgPath 圖檔路徑
     */
    public void replaceText2Image(String replaceText, String imgPath) {
        moveStart();
        while (find(replaceText)) {
            insertImage(imgPath);
            moveEnd();
            enterDown(1);
        }
    }

    /**
     * * 向目前插入點替換圖檔 * * @param imagePath * 圖檔的路徑
     */
    public void insertImage(String imagePath) {
        Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(), "AddPicture", imagePath);
    }

    /**
     * * 合并單元格 * * @param tableIndex * 表格下标,從1開始 * @param fstCellRowIdx * 開始行
     * * @param fstCellColIdx * 開始列 * @param secCellRowIdx * 結束行 * @param
     * secCellColIdx * 結束列
     */
    public void mergeCell(int tableIndex, int fstCellRowIdx, int fstCellColIdx, int secCellRowIdx, int secCellColIdx) {
        getTable(tableIndex);
        Dispatch fstCell = Dispatch.call(table, "Cell", new Variant(fstCellRowIdx), new Variant(fstCellColIdx))
                .toDispatch();
        Dispatch secCell = Dispatch.call(table, "Cell", new Variant(secCellRowIdx), new Variant(secCellColIdx))
                .toDispatch();
        Dispatch.call(fstCell, "Merge", secCell);
    }

    /**
     * * 拆分目前單元格 * * @param numRows * 拆分的行數,如果不想拆分行,請指定為1 * @param numColumns *
     * 拆分的列數,如果不想拆分列,請指定為1
     */
    public void splitCell(int numRows, int numColumns) {
        Dispatch.call(this.cell, "Split", new Variant(numRows), new Variant(numColumns));
    }

    /**
     * * 向表格中寫入内容 * * @param list * 要寫入的内容<br/>
     * * 注:list.size() 應該與表格的rows一緻,String數組的length屬性應與表格的columns一緻
     */
    public void insertToTable(List<String[]> list) {
        if (list == null || list.size() <= 0)
            return;
        if (this.table == null)
            return;
        for (int i = 0; i < list.size(); i++) {
            String[] strs = list.get(i);
            for (int j = 0; j < strs.length; j++) {
                // 周遊表格中每一??單元格,周遊次數所要填入的?熱菔?肯嗤?br /> Dispatch cell = this.getCell(i + 1, j
                // + 1);
                // 選中此單元格
                Dispatch.call(cell, "Select");
                // 寫入?熱莸醬說ピ?裰?br /> Dispatch.put(this.selection, "Text", strs[j]);
                // 将插入點移動至下一??位置
            }
            this.moveDown(1);
        }
        // 換行
        this.enterDown(1);
    }

    /**
     * * 向目前插入點插入文本内容 * * @param list * 要插入的内容,list.size()代表行數
     */
    public void insertToDocument(List<String> list) {
        if (list == null || list.size() <= 0)
            return;
        if (this.document == null)
            return;
        for (String str : list) {
            Dispatch.put(this.selection, "Text", str);
            this.moveDown(1);
            this.enterDown(1);
        }
    }

    /**
     * * 在目前插入點插入文本 * * @param insertText * 要插入的文本
     */
    public void insertToText(String insertText) {
        Dispatch.put(this.selection, "Text", insertText);
    }

    /**
     * *
     * 在目前插入點插入字元串,利用此方法插入一行text後,Word會預設選中它,如果再調用此方法,會将原來的内容覆寫掉,是以調用此方法後,記得調用moveRight,将偏移量向右邊移動一個位置
     * 。 * @param newText 要插入的新字元串
     */
    public void insertText(String newText) {
        Dispatch.put(selection, "Text", newText);
    }

    /**
     * * 建立新的表格 * * @param rowCount * 行 * @param colCount * 列 * @param width * 表格邊框
     * *
     * <ul>
     * *
     * <li>0 無邊框</li> *
     * <li>1 有邊框</li> *
     * </ul>
     * * @return 表格對象
     */
    public Dispatch createNewTable(int rowCount, int colCount, int width) {
        if (this.tables == null)
            this.getTables();
        this.getRange();
        if (rowCount > 0 && colCount > 0)
            this.table = Dispatch.call(this.tables, "Add", this.range, new Variant(rowCount), new Variant(colCount),
                    new Variant(width)).toDispatch();
        return this.table;
    }

    /**
     * * 擷取目前document對象中的所有表格對象 * * @return tables
     */
    public Dispatch getTables() {
        if (this.document == null)
            return this.tables;
        this.tables = Dispatch.get(this.document, "Tables").toDispatch();
        return this.tables;
    }

    /**
     * * 擷取目前文檔中的所有表格數量 * * @return 表格數量
     */
    public int getTablesCount() {
        if (this.tables == null)
            this.getTables();
        return Dispatch.get(tables, "Count").getInt();
    }

    /**
     * * 根據索引獲得table對象 * * @param tableIndex * 索引 * @return table
     */
    public Dispatch getTable(int tableIndex) {
        if (this.tables == null)
            this.getTables();
        if (tableIndex >= 0)
            this.table = Dispatch.call(this.tables, "Item", new Variant(tableIndex)).toDispatch();
        return this.table;
    }

    /**
     * * 在指定的單元格裡填寫資料 * * @param tableIndex * 表格索引 * @param cellRowIdx * 行索引
     * * @param cellColIdx * 列索引 * @param txt * 文本
     */
    public void putTxtToCell(int tableIndex, int cellRowIdx, int cellColIdx, String txt) {
        getTable(tableIndex);
        getCell(cellRowIdx, cellColIdx);
        Dispatch.call(this.cell, "Select");
        Dispatch.put(this.selection, "Text", txt);
    }

    /**
     * * 在目前文檔末尾拷貝來自另一個文檔中的段落 * * @param anotherDocPath * 另一個文檔的磁盤路徑 * @param
     * tableIndex * 被拷貝的段落在另一格文檔中的序号(從1開始)
     */
    public void copyParagraphFromAnotherDoc(String anotherDocPath, int paragraphIndex) {
        Dispatch wordContent = Dispatch.get(this.document, "Content").toDispatch(); // 取得目前文檔的内容
        Dispatch.call(wordContent, "InsertAfter", "$selection$");// 插入特殊符定位插入點
        copyParagraphFromAnotherDoc(anotherDocPath, paragraphIndex, "$selection$");
    }

    /**
     * * 在目前文檔指定的位置拷貝來自另一個文檔中的段落 * * @param anotherDocPath * 另一個文檔的磁盤路徑 * @param
     * tableIndex * 被拷貝的段落在另一格文檔中的序号(從1開始) * @param pos * 目前文檔指定的位置
     */
    public void copyParagraphFromAnotherDoc(String anotherDocPath, int paragraphIndex, String pos) {
        Dispatch doc2 = null;
        try {
            doc2 = Dispatch.call(documents, "Open", anotherDocPath).toDispatch();
            Dispatch paragraphs = Dispatch.get(doc2, "Paragraphs").toDispatch();
            Dispatch paragraph = Dispatch.call(paragraphs, "Item", new Variant(paragraphIndex)).toDispatch();
            Dispatch range = Dispatch.get(paragraph, "Range").toDispatch();
            Dispatch.call(range, "Copy");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (doc2 != null) {
                Dispatch.call(doc2, "Close", new Variant(true));
                doc2 = null;
            }
        }

    }

    /**
     * * 在目前文檔指定的位置拷貝來自另一個文檔中的表格 * * @param anotherDocPath * 另一個文檔的磁盤路徑 * @param
     * tableIndex * 被拷貝的表格在另一格文檔中的序号(從1開始) * @param pos * 目前文檔指定的位置
     */
    public void copyTableFromAnotherDoc(String anotherDocPath, int tableIndex, String pos) {
        Dispatch doc2 = null;
        try {
            doc2 = Dispatch.call(documents, "Open", anotherDocPath).toDispatch();
            Dispatch tables = Dispatch.get(doc2, "Tables").toDispatch();
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex)).toDispatch();
            Dispatch range = Dispatch.get(table, "Range").toDispatch();
            Dispatch.call(range, "Copy");
            if (this.find(pos)) {
                getRange();
                Dispatch.call(this.range, "Paste");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (doc2 != null) {
                Dispatch.call(doc2, "Close", new Variant(true));
                doc2 = null;
            }
        }
    }

    /**
     * * 在目前文檔指定的位置拷貝來自另一個文檔中的圖檔 * * @param anotherDocPath * 另一個文檔的磁盤路徑 * @param
     * shapeIndex * 被拷貝的圖檔在另一格文檔中的位置 * @param pos * 目前文檔指定的位置
     */
    public void copyImageFromAnotherDoc(String anotherDocPath, int shapeIndex, String pos) {
        Dispatch doc2 = null;
        try {
            doc2 = Dispatch.call(documents, "Open", anotherDocPath).toDispatch();
            Dispatch shapes = Dispatch.get(doc2, "InLineShapes").toDispatch();
            Dispatch shape = Dispatch.call(shapes, "Item", new Variant(shapeIndex)).toDispatch();
            Dispatch imageRange = Dispatch.get(shape, "Range").toDispatch();
            Dispatch.call(imageRange, "Copy");
            if (this.find(pos)) {
                getRange();
                Dispatch.call(this.range, "Paste");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (doc2 != null) {
                Dispatch.call(doc2, "Close", new Variant(true));
                doc2 = null;
            }
        }
    }

    /**
     * * 在指定的表格的指定行前面增加行 * * @param tableIndex * word檔案中的第N張表(從1開始) * @param
     * rowIndex * 指定行的序号(從1開始)
     */
    public void addTableRow(int tableIndex, int rowIndex) {
        getTable(tableIndex);
        getTableRows();
        getTableRow(rowIndex);
        Dispatch.call(this.rows, "Add", new Variant(this.row));
    }

    /**
     * * 在第1行前增加一行 * * @param tableIndex * word文檔中的第N張表(從1開始)
     */
    public void addFirstTableRow(int tableIndex) {
        getTable(tableIndex);
        getTableRows();
        Dispatch row = Dispatch.get(rows, "First").toDispatch();
        Dispatch.call(this.rows, "Add", new Variant(row));
    }

    /**
     * 在最後1行前增加一行 * * @param tableIndex * word文檔中的第N張表(從1開始)
     */
    public void addLastTableRow(int tableIndex) {
        getTable(tableIndex);
        getTableRows();
        Dispatch row = Dispatch.get(this.rows, "Last").toDispatch();
        Dispatch.call(this.rows, "Add", new Variant(row));
    }

    /**
     * * 增加一行 * * @param tableIndex * word文檔中的第N張表(從1開始)
     */
    public void addRow(int tableIndex) {
        getTable(tableIndex);
        getTableRows();
        Dispatch.call(this.rows, "Add");
    }

    /**
     * * 增加一列 * * @param tableIndex * word文檔中的第N張表(從1開始)
     */
    public void addCol(int tableIndex) {
        getTable(tableIndex);
        getTableColumns();
        Dispatch.call(this.cols, "Add").toDispatch();
        Dispatch.call(this.cols, "AutoFit");
    }

    /**
     * * 在指定列前面增加表格的列 * * @param tableIndex * word文檔中的第N張表(從1開始) * @param colIndex *
     * 指定列的序号 (從1開始)
     */
    public void addTableCol(int tableIndex, int colIndex) {
        getTable(tableIndex);
        getTableColumns();
        getTableColumn(colIndex);
        Dispatch.call(this.cols, "Add", this.col).toDispatch();
        Dispatch.call(this.cols, "AutoFit");
    }

    /**
     * * 在第1列前增加一列 * * @param tableIndex * word文檔中的第N張表(從1開始)
     */
    public void addFirstTableCol(int tableIndex) {
        getTable(tableIndex);
        Dispatch cols = getTableColumns();
        Dispatch col = Dispatch.get(cols, "First").toDispatch();
        Dispatch.call(cols, "Add", col).toDispatch();
        Dispatch.call(cols, "AutoFit");
    }

    /**
     * * 在最後一列前增加一列 * * @param tableIndex * word文檔中的第N張表(從1開始)
     */
    public void addLastTableCol(int tableIndex) {
        getTable(tableIndex);
        Dispatch cols = getTableColumns();
        Dispatch col = Dispatch.get(cols, "Last").toDispatch();
        Dispatch.call(cols, "Add", col).toDispatch();
        Dispatch.call(cols, "AutoFit");
    }

    /**
     * * 擷取目前表格的列數 * * @return 列總數
     */
    public int getTableColumnsCount() {
        if (this.table == null)
            return 0;
        return Dispatch.get(this.cols, "Count").getInt();
    }

    /**
     * * 擷取目前表格的行數 * * @return 行總數
     */
    public int getTableRowsCount() {
        if (this.table == null)
            return 0;
        return Dispatch.get(this.rows, "Count").getInt();
    }

    /**
     * * 擷取目前表格的所有列對象 * * @return cols
     */
    public Dispatch getTableColumns() {
        if (this.table == null)
            return this.cols;
        this.cols = Dispatch.get(this.table, "Columns").toDispatch();
        return this.cols;
    }

    /**
     * * 擷取目前表格的所有行對象 * * @return rows
     */
    public Dispatch getTableRows() {
        if (this.table == null)
            return this.rows;
        this.rows = Dispatch.get(this.table, "Rows").toDispatch();
        return this.rows;
    }

    /**
     * * 根據索引獲得目前表格的列對象 * * @param columnIndex * 列索引 * @return col
     */
    public Dispatch getTableColumn(int columnIndex) {
        if (this.cols == null)
            this.getTableColumns();
        if (columnIndex >= 0)
            this.col = Dispatch.call(this.cols, "Item", new Variant(columnIndex)).toDispatch();
        return this.col;
    }

    /**
     * * 根據索引獲得目前表格的行對象 * * @param rowIndex * 行索引 * @return row
     */
    public Dispatch getTableRow(int rowIndex) {
        if (this.rows == null)
            this.getTableRows();
        if (rowIndex >= 0)
            this.row = Dispatch.call(this.rows, "Item", new Variant(rowIndex)).toDispatch();
        return this.row;
    }

    /**
     * * 自動調整目前所有表格
     */
    public void autoFitTable() {
        int count = this.getTablesCount();
        for (int i = 0; i < count; i++) {
            Dispatch table = Dispatch.call(tables, "Item", new Variant(i + 1)).toDispatch();
            Dispatch cols = Dispatch.get(table, "Columns").toDispatch();
            Dispatch.call(cols, "AutoFit");
        }
    }

    /**
     * * 根據行索引與列索引擷取目前表格中的單元格 * * @param cellRowIdx * 行索引 * @param cellColIdx * 列索引
     * * @return cell對象
     */
    public Dispatch getCell(int cellRowIdx, int cellColIdx) {
        if (this.table == null)
            return this.cell;
        if (cellRowIdx >= 0 && cellColIdx >= 0)
            this.cell = Dispatch.call(this.table, "Cell", new Variant(cellRowIdx), new Variant(cellColIdx))
                    .toDispatch();
        return this.cell;
    }

    public void selectCell(int cellRowIdx, int cellColIdx) {
        if (this.table == null)
            return;
        getCell(cellRowIdx, cellColIdx);
        if (cellRowIdx >= 0 && cellColIdx >= 0)
            Dispatch.call(this.cell, "select");
    }

    /**
     * * 設定目前文檔的标題 * * @param title 标題 * @param alignmentType 對齊方式 * @see
     * setAlignment
     */
    public void setTitle(String title, int alignmentType) {
        if (title == null || "".equals(title))
            return;
        if (this.alignment == null)
            this.getAlignment();
        if (alignmentType != 0 && alignmentType != 1 && alignmentType != 2)
            alignmentType = 0;
        Dispatch.put(this.alignment, "Alignment", alignmentType);
        Dispatch.call(this.selection, "TypeText", title);
    }

    /**
     * * 設定目前表格邊框的粗細 * * @param width * 範圍:1 < w < 13, 如果是0,就代表?]有框<br/>
     *
     */
    public void setTableBorderWidth(int width) {
        if (this.table == null)
            return;
        /*
         * 設定表格線的粗細 1:代表最上邊一條線 2:代表最左邊一條線 3:最下邊一條線 4:最右邊一條線 5:除最上邊最下邊之外的所有橫線
         * 6:除最左邊最右邊之外的所有豎線 7:從左上角到右下角的斜線 8:從左下角到右上角的斜線
         */
        Dispatch borders = Dispatch.get(table, "Borders").toDispatch();
        Dispatch border = null;
        for (int i = 1; i < 7; i++) {
            border = Dispatch.call(borders, "Item", new Variant(i)).toDispatch();
            if (width != 0) {
                Dispatch.put(border, "LineWidth", new Variant(width));
                Dispatch.put(border, "Visible", new Variant(true));
            } else if (width == 0) {
                Dispatch.put(border, "Visible", new Variant(false));
            }
        }
    }

    /**
     * * 得到指定的表格指定的單元格中的值 * * @param tableIndex * 表格索引(從1開始) * @param rowIndex *
     * 行索引(從1開始) * @param colIndex * 列索引(從1開始) * @return
     */
    public String getTxtFromCell(int tableIndex, int rowIndex, int colIndex) {
        String value = "";
        // 設定為目前表格
        getTable(tableIndex);
        getCell(rowIndex, colIndex);
        if (cell != null) {
            Dispatch.call(cell, "Select");
            value = Dispatch.get(selection, "Text").toString();
            value = value.substring(0, value.length() - 2); // 去掉最後的回車符;
        }
        return value;
    }

    /**
     * * 對目前選中的内容設定項目符号與清單 * * @param tabIndex *
     * <ul>
     * *
     * <li>1.項目編号</li> *
     * <li>2.編号</li> *
     * <li>3.多級編号</li> *
     * <li>4.清單樣式</li> *
     * </ul>
     * * @param index * 0表示沒有,其它數字代表是該tab頁中的第幾項内容
     */
    public void applyListTemplate(int tabIndex, int index) {
        // 取得ListGalleries對象清單
        Dispatch listGalleries = Dispatch.get(this.word, "ListGalleries").toDispatch();
        // 取得清單中一個對象
        Dispatch listGallery = Dispatch.call(listGalleries, "Item", new Variant(tabIndex)).toDispatch();
        Dispatch listTemplates = Dispatch.get(listGallery, "ListTemplates").toDispatch();
        if (this.range == null)
            this.getRange();
        Dispatch listFormat = Dispatch.get(this.range, "ListFormat").toDispatch();
        Dispatch.call(listFormat, "ApplyListTemplate", Dispatch.call(listTemplates, "Item", new Variant(index)),
                new Variant(true), new Variant(1), new Variant(0));
    }

    /**
     * * 增加文檔目錄
     */
    public void addTablesOfContents() {
        // 取得ActiveDocument、TablesOfContents、range對象
        Dispatch ActiveDocument = word.getProperty("ActiveDocument").toDispatch();
        Dispatch TablesOfContents = Dispatch.get(ActiveDocument, "TablesOfContents").toDispatch();
        Dispatch range = Dispatch.get(this.selection, "Range").toDispatch();
        // 增加目錄
        Dispatch.call(TablesOfContents, "Add", range, new Variant(true), new Variant(1), new Variant(3),
                new Variant(true), new Variant(""), new Variant(true), new Variant(true));
    }

    /**
     * * 設定目前selection對齊方式 * * @param alignmentType *
     * <ul>
     * *
     * <li>0.居左</li> *
     * <li>1.居中</li> *
     * <li>2.居右</li> *
     * </ul>
     *
     */
    public void setAlignment(int alignmentType) {
        if (this.alignment == null)
            this.getAlignment();
        Dispatch.put(this.alignment, "Alignment", alignmentType);
    }

    /**
     * * 擷取目前selection的對齊方式 * * @return alignment
     */
    public Dispatch getAlignment() {
        if (this.selection == null)
            this.getSelection();
        this.alignment = Dispatch.get(this.selection, "ParagraphFormat").toDispatch();
        return this.alignment;
    }

    /**
     * * 擷取字型對象 * * @return font
     */
    public Dispatch getFont() {
        if (this.selection == null)
            this.getSelection();
        this.font = Dispatch.get(this.selection, "Font").toDispatch();
        return this.font;
    }

    /**
     * * 設定目前selection的字型 * * @param fontName * 字型名稱,如“微軟雅黑” * @param isBold * 是否粗體
     * * @param isItalic * 是否斜體 * @param isUnderline * 是否下劃線 * @param rgbColor *
     * 顔色值"1,1,1,1" * @param Scale * 字型間距 * @param fontSize * 字型大小
     */
    @Deprecated
    public void setFontScale(String fontName, boolean isBold, boolean isItalic, boolean isUnderline, String rgbColor,
                             int Scale, int fontSize) {
        Dispatch.put(this.font, "Name", fontName);
        Dispatch.put(this.font, "Bold", isBold);
        Dispatch.put(this.font, "Italic", isItalic);
        Dispatch.put(this.font, "Underline", isUnderline);
        Dispatch.put(this.font, "Color", rgbColor);
        Dispatch.put(this.font, "Scaling", Scale);
        Dispatch.put(this.font, "Size", fontSize);
    }

    /**
     * 設定目前標明内容的字型
     *
     * @param isBold
     *            是否為粗體
     * @param isItalic
     *            是否為斜體
     * @param isUnderLine
     *            是否帶下劃線
     * @param color
     *            rgb 字型顔色 例如:紅色 255,0,0
     * @param size
     *            字型大小 12:小四 16:三号
     * @param name
     *            字型名稱 例如:宋體,新宋體,楷體,隸書
     */

    public void setFont(boolean isBold, boolean isItalic, boolean isUnderLine, String color, String size, String name) {
        Dispatch font = Dispatch.get(getSelection(), "Font").toDispatch();
        Dispatch.put(font, "Name", new Variant(name));
        Dispatch.put(font, "Bold", new Variant(isBold));
        Dispatch.put(font, "Italic", new Variant(isItalic));
        Dispatch.put(font, "Underline", new Variant(isUnderLine));
        if (!"".equals(color))
            Dispatch.put(font, "Color", color);
        Dispatch.put(font, "Size", size);
    }

    /**
     * * 儲存檔案 * * @param outputPath * 儲存路徑
     */
    public void saveAs(String outputPath) {
        if (this.document == null)
            return;
        if (outputPath == null || "".equals(outputPath))
            return;
        Dispatch.call(this.document, "SaveAs", outputPath);
    }

    /**
     * * 另存為HTML内容 * * @param htmlFile * html檔案路徑
     */
    public void saveAsHtml(String htmlFile) {
        Dispatch.invoke(this.document, "SaveAs", Dispatch.Method, new Object[] { htmlFile, new Variant(8) },
                new int[1]);
    }

    /**
     * * saveFormat | Member name Description 0 | wdFormatDocument Microsoft Word *
     * format. 1 | wdFormatTemplate Microsoft Word template format. 2 | *
     * wdFormatText Microsoft Windows text format. 3 | wdFormatTextLineBreaks *
     * Microsoft Windows text format with line breaks preserved. 4 | *
     * wdFormatDOSText Microsoft DOS text format. 5 | wdFormatDOSTextLineBreaks *
     * Microsoft DOS text with line breaks preserved. 6 | wdFormatRTF Rich text *
     * format (RTF). 7 | wdFormatEncodedText Encoded text format. 7 | *
     * wdFormatUnicodeText Unicode text format. 8 | wdFormatHTML Standard HTML *
     * format. 9 | wdFormatWebArchive Web archive format. 10 | *
     * wdFormatFilteredHTML Filtered HTML format. 11 | wdFormatXML Extensible *
     * Markup Language (XML) format.
     */

    /**
     * * 關閉目前word文檔
     */

    public void close() {
        if (document == null)
            return;
        Dispatch.call(document, "Close", new Variant(0));
    }

    /**
     * * 執行目前文檔列印指令
     */
    public void printFile() {
        if (document == null)
            return;
        Dispatch.call(document, "PrintOut");
    }

    /**
     * * 退出Microsoft Office Word程式
     */
    public void quit() {
        word.invoke("Quit", new Variant[0]);
        ComThread.Release();
    }

    /**
     * * 選中整篇文檔
     */
    public void selectAllContent() {
        Dispatch.call(this.document, "select");
    }

    /**
     * * 複制整篇文檔 * @param target
     */
    public void copy() {
        Dispatch.call(this.document, "select");
        Dispatch.call(this.selection, "copy");
    }

    /**
     * * 在目前插入點位置粘貼選中的内容
     */
    public void paste() {
        Dispatch.call(this.selection, "paste");
    }

}
           
package com.meadin.service.front.util;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 适用于word 2007
 */
public class OfficeUtil {

    /**
     * 根據指定的參數值、模闆,生成 word 文檔
     * @param param 需要替換的變量
     * @param template 模闆
     */
    public static CustomXWPFDocument generateWord(Map<String, Object> param, String template) {
        CustomXWPFDocument doc = null;
        try {
            OPCPackage pack = POIXMLDocument.openPackage(template);
            doc = new CustomXWPFDocument(pack);
            if (param != null && param.size() > 0) {

                //處理段落
                List<XWPFParagraph> paragraphList = doc.getParagraphs();
                processParagraphs(paragraphList, param, doc);

                //處理表格
                Iterator<XWPFTable> it = doc.getTablesIterator();
                while (it.hasNext()) {
                    XWPFTable table = it.next();
                    List<XWPFTableRow> rows = table.getRows();
                    for (XWPFTableRow row : rows) {
                        List<XWPFTableCell> cells = row.getTableCells();
                        for (XWPFTableCell cell : cells) {
                            List<XWPFParagraph> paragraphListTable =  cell.getParagraphs();
                            processParagraphs(paragraphListTable, param, doc);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return doc;
    }
    /**
     * 處理段落
     * @param paragraphList
     */
    public static void processParagraphs(List<XWPFParagraph> paragraphList,Map<String, Object> param,CustomXWPFDocument doc){
        if(paragraphList != null && paragraphList.size() > 0){
            for(XWPFParagraph paragraph:paragraphList){
                //poi轉換過來的行間距過大,需要手動調整
                if(paragraph.getSpacingBefore() >= 1000 || paragraph.getSpacingAfter() > 1000) {
                    paragraph.setSpacingBefore(0);
                    paragraph.setSpacingAfter(0);
                }
                //設定word中左右間距
                paragraph.setIndentationLeft(0);
                paragraph.setIndentationRight(0);
                List<XWPFRun> runs = paragraph.getRuns();
                //加了圖檔,修改了paragraph的runs的size,是以循環不能使用runs
                List<XWPFRun> allRuns = new ArrayList<XWPFRun>(runs);
                for (XWPFRun run : allRuns) {
                    String text = run.getText(0);
                    if(text != null){
                        boolean isSetText = false;
                        for (Entry<String, Object> entry : param.entrySet()) {
                            String key = entry.getKey();
                            if(text.indexOf(key) != -1){
                                isSetText = true;
                                Object value = entry.getValue();
                                if (value instanceof String) {//文本替換
                                    text = text.replace(key, value.toString());
                                } else if (value instanceof Map) {//圖檔替換
                                    text = text.replace(key, "");
                                    Map pic = (Map)value;
                                    int width = Integer.parseInt(pic.get("width").toString());
                                    int height = Integer.parseInt(pic.get("height").toString());
                                    int picType = getPictureType(pic.get("type").toString());
                                    byte[] byteArray = (byte[]) pic.get("content");
                                    ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
                                    try {
                                        String blipId = doc.addPictureData(byteInputStream,picType);
                                        doc.createPicture(blipId,doc.getNextPicNameNumber(picType), width, height,paragraph);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                        if(isSetText){
                            run.setText(text,0);
                        }
                    }
                }
            }
        }
    }
    /**
     * 根據圖檔類型,取得對應的圖檔類型代碼
     * @param picType
     * @return int
     */
    private static int getPictureType(String picType){
        int res = CustomXWPFDocument.PICTURE_TYPE_PICT;
        if(picType != null){
            if(picType.equalsIgnoreCase("png")){
                res = CustomXWPFDocument.PICTURE_TYPE_PNG;
            }else if(picType.equalsIgnoreCase("dib")){
                res = CustomXWPFDocument.PICTURE_TYPE_DIB;
            }else if(picType.equalsIgnoreCase("emf")){
                res = CustomXWPFDocument.PICTURE_TYPE_EMF;
            }else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){
                res = CustomXWPFDocument.PICTURE_TYPE_JPEG;
            }else if(picType.equalsIgnoreCase("wmf")){
                res = CustomXWPFDocument.PICTURE_TYPE_WMF;
            }
        }
        return res;
    }
    /**
     * 将輸入流中的資料寫入位元組數組
     * @param in
     * @return
     */
    public static byte[] inputStream2ByteArray(InputStream in,boolean isClose){
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        try{

            byte[] buffer = new byte[1024];
            int len = -1;
            while((len = in.read(buffer)) != -1){
                outStream.write(buffer, 0, len);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(isClose){
                try {
                    outStream.close();
                    in.close();
                } catch (Exception e2) {
                    System.out.println("關閉流失敗");
                }
            }
        }
        return outStream.toByteArray();

//        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) {
//                    System.out.println("關閉流失敗");
//                }
//            }
//        }
//        return byteArray;
    }
}