Java操做Word

Poi工具

Apache的POI,是Apache軟件基金會的開放源碼函式庫,POI提供API給Java程序對Microsoft Office格式檔案讀和寫的功能。POI讀寫Excel功能強大、操做簡單。可是POI操做時,通常只用它讀取word文檔,POI只能可以建立簡單的word文檔,相對而言POI操做時的功能太少。java

添加Poi依賴

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.15</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>3.15</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.15</version>
</dependency>
複製代碼

導出

1)導出語句以下git

public void upload() throws IOException {
XWPFDocument doc = new XWPFDocument();// 建立Word文件
    XWPFParagraph p = doc.createParagraph();// 新建一個段落
    p.setAlignment(ParagraphAlignment.CENTER);// 設置段落的對齊方式
    p.setBorderBottom(Borders.DOUBLE);//設置下邊框
    p.setBorderTop(Borders.DOUBLE);//設置上邊框
    p.setBorderRight(Borders.DOUBLE);//設置右邊框
    p.setBorderLeft(Borders.DOUBLE);//設置左邊框
    XWPFRun r = p.createRun();//建立段落文本
    r.setText("POI建立的Word段落文本");
    r.setBold(true);//設置爲粗體
    r.setColor("FF0000");//設置顏色
    p = doc.createParagraph();// 新建一個段落
    r = p.createRun();
    r.setText("POI讀寫Excel功能強大、操做簡單。");
    XWPFTable table= doc.createTable(3, 3);//建立一個表格
    table.getRow(0).getCell(0).setText("表格1");
    table.getRow(1).getCell(1).setText("表格2");
    table.getRow(2).getCell(2).setText("表格3");
    FileOutputStream out = new FileOutputStream("D:\\記事本\\公司\\word\\sample.doc");
    doc.write(out);
    out.close();
}
複製代碼

2)調用接口。導出後的word以下。github

導入

1)導入語句以下。web

public void importWord(@RequestParam("file") MultipartFile file) throws IOException {
if (file == null) {
        System.out.println("文件不能爲空");
    }
    // 建立Word文件
    XWPFDocument doc = new XWPFDocument(file.getInputStream());
    //遍歷段落
    for (XWPFParagraph p : doc.getParagraphs())
    {
        System.out.println(p.getParagraphText());
    }
    //遍歷表格
    for (XWPFTable table : doc.getTables())
    {
        for (XWPFTableRow row : table.getRows()) {
            for (XWPFTableCell cell : row.getTableCells()) {
                System.out.println(cell.getText());
            }
        }
    }
}
複製代碼

2)調用接口,導入以前導出的word文本。導入後的控制檯輸出以下。spring

使用Freemarker模板進行生成

優勢:採用FreeMarker是導出Word的最佳實現,很是的靈活,可以按照本身指定的樣式設置並輸出內容,操做簡單方便,代碼實現也容易。代碼量少,樣式、內容容易控制,打印不變形,徹底符合office標準。apache

**缺點:**須要提早設計好word模板,把須要替換的地方用特殊標記標出來。編程

添加freemarker依賴

<!--引入freemarker 模板依賴-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
複製代碼

導出

1)準備要導出的word模板小程序

2)製做基本樣式以後,另存爲.xml格式文檔app

3)打開.xml文件,在相應的地方填入${content}表達式編輯器

4)使用文本編輯器sublime打開

5)複製黏貼至項目文件中,後綴名更改成.ftl

6)編寫導出類

package com.lamarsan.word_demo.freemarker;

import freemarker.template.*;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/** * className: ExportMyWord * description: TODO * * @author hasee * @version 1.0 * @date 2019/7/15 14:54 */
public class ExportMyWord {
    private Logger log = Logger.getLogger(ExportMyWord.class.toString());
    private Configuration config = null;

    public ExportMyWord() {
        config = new Configuration();
        config.setDefaultEncoding("utf-8");
    }

    /** * FreeMarker生成Word * @param dataMap 數據 * @param templateName 目標名 * @param saveFilePath 保存文件路徑的全路徑名(路徑+文件名) * @Author Huang Xiaocong 2018年12月15日 下午10:19:03 */
    public void createWord(Map<String, Object> dataMap, String templateName, String saveFilePath) {
        //加載模板(路徑)數據
        config.setClassForTemplateLoading(this.getClass(), "/templates");
        //設置異常處理器 這樣的話 即便沒有屬性也不會出錯 如:${list.name}...不會報錯
        config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        Template template = null;
        if(templateName.endsWith(".ftl")) {
            templateName = templateName.substring(0, templateName.indexOf(".ftl"));
        }
        try {
            template = config.getTemplate(templateName + ".ftl");
        } catch (TemplateNotFoundException e) {
            log.info("模板文件未找到");
            e.printStackTrace();
        } catch (MalformedTemplateNameException e) {
            log.info("模板類型不正確");
            e.printStackTrace();
        } catch (IOException e) {
            log.info("IO讀取失敗");
            e.printStackTrace();
        }
        File outFile = new File(saveFilePath);
        if(!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }
        Writer out = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outFile);
        } catch (FileNotFoundException e) {
            log.info("輸出文件時未找到文件");
            e.printStackTrace();
        }
        out = new BufferedWriter(new OutputStreamWriter(fos));
        //將模板中的預先的代碼替換爲數據
        try {
            template.process(dataMap, out);
        } catch (TemplateException e) {
            log.info("填充模板時異常");
            e.printStackTrace();
        } catch (IOException e) {
            log.info("IO讀取時異常");
            e.printStackTrace();
        }
        log.info("由模板文件:" + templateName + ".ftl" + " 生成文件 :" + saveFilePath + " 成功!!");
        try {
            out.close();//web項目不可關閉
        } catch (IOException e) {
            log.info("關閉Write對象出錯");
            e.printStackTrace();
        }
    }
    /** * 得到圖片的Base64編碼 * @param imgFile * @return * @Author Huang Xiaocong 2018年12月15日 下午10:15:10 */
    public String getImageStr(String imgFile) {
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(imgFile);
        } catch (FileNotFoundException e) {
            log.info("加載圖片未找到");
            e.printStackTrace();
        }
        try {
            data = new byte[in.available()];
            //注:FileInputStream.available()方法能夠從輸入流中阻斷由下一個方法調用這個輸入流中讀取的剩餘字節數
            in.read(data);
            in.close();
        } catch (IOException e) {
            log.info("IO操做圖片錯誤");
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);

    }

}
複製代碼

須要注意的是,在加載config.setClassForTemplateLoading(this.getClass(), "/templates");時,須要指定存放freemarker文件的文件目錄地址,即templates,否則會報org.springframework.beans.factory.BeanCreationException: Error creating bean with...錯誤,即找不到模板文件。

7)編寫main方法

public static void main(String[] args) {
ExportMyWord emw = new ExportMyWord();
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("name", "傅澤鵬");
    dataMap.put("age", 20);
    dataMap.put("sex", "男");
    dataMap.put("imgheader", emw.getImageStr("D:\\圖片\\130.png"));
    dataMap.put("phoneNum", "13588097790");
    dataMap.put("project", "計算機");
    dataMap.put("address", "杭州");
    dataMap.put("natureWork", "全職");
    dataMap.put("industry", "IT");
    dataMap.put("application", "Java開發");
    dataMap.put("time", "2017年-2021年");
    dataMap.put("schoolname", "浙江科技學院");
    dataMap.put("education", "本科");
    dataMap.put("projectExperience", "辯論小程序開發");
    dataMap.put("introduce", "喜歡二次元,編程的大學生");
    emw.createWord(dataMap, "information.ftl", "D:\\記事本\\公司\\簡歷.docx");
}
複製代碼

8)修改ftl文件的圖片代碼

若是立馬點擊生成docx文件,會發現圖片變成了一堆超級長的代碼。因此能夠判斷是ftl處的代碼有誤。進入ftl代碼,查找${imgheader},修改<w:p>標籤以下。

<w:p>
<w:pPr>
        <w:widowControl w:val="off"/>
        <w:jc w:val="center"/>
        <w:rPr>
            <w:rFonts w:hint="default"/>
            <w:b w:val="off"/>
            <w:sz w:val="24"/>
            <w:sz-cs w:val="32"/>
            <w:vertAlign w:val="baseline"/>
            <w:lang w:val="EN-US" w:fareast="ZH-CN"/>
        </w:rPr>
    </w:pPr>
    <w:r>
        <w:rPr>
            <w:rFonts w:hint="fareast"/>
            <w:b w:val="off"/>
            <w:sz w:val="24"/>
            <w:sz-cs w:val="32"/>
            <w:vertAlign w:val="baseline"/>
            <w:lang w:val="EN-US" w:fareast="ZH-CN"/>
        </w:rPr>
        <w:pict>
            <w:binData w:name="wordml://1.png">${imgheader}</w:binData>
            <v:shape id="_x0000_s1026" o:spt="75" alt="" type="#_x0000_t75"
                     style="height:119.8pt;width:74.65pt;" filled="f" o:preferrelative="t"
                     stroked="f" coordsize="21600,21600">
                <v:path/>
                <v:fill on="f" focussize="0,0"/>
                <v:stroke on="f"/>
                <v:imagedata src="wordml://1.png" o:title="140"/>
                <o:lock v:ext="edit" aspectratio="t"/>
                <w10:wrap type="none"/>
                <w10:anchorlock/>
            </v:shape>
        </w:pict>
    </w:r>
</w:p>
複製代碼

9)最終效果圖

補充循環操做

若是須要多重循環能夠用list來實現。

1)目標模板以下:

2)查找字段,在<w:tr>前加入<#list list as list>,</w:tr>後加入</#list>。第一個list 不能變,第二個list 爲變量名,第三個list 爲別名。

3)將time改爲list.time,schoolname改爲list.schoolname,education改爲list.eduxcation。

4)運行代碼以下:

public static void main(String[] args) {
    ExportMyWord emw = new ExportMyWord();
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("name", "傅澤鵬");
    dataMap.put("age", 20);
    dataMap.put("sex", "男");
    dataMap.put("imgheader", emw.getImageStr("D:\\圖片\\130.png"));
    dataMap.put("phoneNum", "13588097790");
    dataMap.put("project", "計算機");
    dataMap.put("address", "杭州");
    dataMap.put("natureWork", "全職");
    dataMap.put("industry", "IT");
    dataMap.put("application", "Java開發");
    List<Map<String, Object>> newsList = new ArrayList<Map<String, Object>>();
    Map<String, Object> map = new HashMap<String, Object>();
    Map<String, Object> map2 = new HashMap<String, Object>();
    Map<String, Object> map3 = new HashMap<String, Object>();
    map.put("time", "2017年-2021年");
    map.put("schoolname", "浙江科技學院");
    map.put("education", "本科");
    map2.put("time", "2014年-2017年");
    map2.put("schoolname", "瑞安四中");
    map2.put("education", "高中");
    map3.put("time", "2011年-2014年");
    map3.put("schoolname", "莘塍一中");
    map3.put("education", "初中");
    newsList.add(map);
    newsList.add(map2);
    newsList.add(map3);
    //注意list 的名字
    dataMap.put("list", newsList);
    dataMap.put("projectExperience", "辯論小程序開發");
    dataMap.put("introduce", "喜歡二次元,編程的大學生");
    emw.createWord(dataMap, "information_list.ftl", "D:\\記事本\\公司\\簡歷2.docx");
}
複製代碼

6)最終結果圖:

項目github地址:github.com/lamarsan/wo…

相關文章
相關標籤/搜索