编程知识 cdmana.com

How to export word with java code

Preface :

export word In fact, there are still many places to use in daily work , So I want to write an article to record it , Before exporting , Need to know about how browsers handle servlet Background data for . We can learn more about it http Communication download behavior in servlet The implementation of the .

== The exported tool class code comes from the network , If there is infringement, please contact me to delete the article ==

personal use ==ftl== As word Export template engine , There are many template engines to choose from , The individual found that ftl It's used a lot , So choose this one

<!-- more -->

Code cloud address :

The article involves more code , If you want to see the operation, you can check my own code cloud address :

https://gitee.com/lazyTimes/i...

Effect demonstration :

Gave a test page , I wrote some scripts on the spot , As a reference ( It will be posted later Html Code in )

Click on the submit , Export content , export word The report

After export , open word The content is :

Implementation steps - Make word Templates

First step newly build word, Make a prototype of the results

Will need to export word The content of , Paste it to a new one first word In the document

The second step Transfer format -> xml

Select File “ Save as ”, Set the format to xml Format

The third step Format file

Put the document in idea Or support formatting software , format , preservation :

Pay attention to the place holder

Step four : Template data replacement placeholder

stay word Where the page will need to import data , Replace placeholders

When you need to pay attention to content processing : ${ filename} It can be cut into parts , We need to cut multiple parts , Change it to the following style

Remember that after all the changes , Open it now xml Format word, Make sure it's not broken

The above steps are completed , There is one word The template is ready

Step five : Make ftl file ,word Template forming

Create a new one in the project ftl file , At the same time, you need to configure , At the same time to do a good job in the operation of the station sign xml Put the content in

Code implementation - Export code

  1. The configuration of the tool class is as follows :

WordGeneratorUtil.java

/**
     *  Template constant class configuration 
     */
public static final class FreemarkerTemplate {
    public static final String REPORT = "report";
    public static final String REC_RECOMMEND = "recRecommend";
    //  Add your template file name :

}

In a static block of code , You need to inject the corresponding template configuration

//  Note that the corresponding template should be loaded during initialization 
allTemplates.put(FreemarkerTemplate.REPORT, configuration.getTemplate(FreemarkerTemplate.REPORT + ".ftl"));
allTemplates.put(FreemarkerTemplate.REC_RECOMMEND,configuration.getTemplate(FreemarkerTemplate.REC_RECOMMEND + ".ftl"));
  1. After configuration , When exporting, you can find the corresponding file
  2. Establish a general export method :
/**
     *  establish doc  file 
     * dataMap  data , A place holder for the corresponding template is required , Otherwise it will go wrong 
     * @param dataMap  data 
     * @param wordName  word  The name of the report 
     * @param freemarkerTemplateName   Specify which freemarker Templates 
     * @return
     */
public static File createDoc(String freemarkerTemplateName, String wordName, Map<String, String> dataMap) {
    try {
        File f = new File(wordName);
        Template t = allTemplates.get(freemarkerTemplateName);
        //  This place can't be used FileWriter Because you need to specify the encoding type, otherwise generated Word The document cannot be opened because of an unrecognized encoding 
        Writer w = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8);
        t.process(dataMap, w);
        w.close();
        return f;
    } catch (Exception ex) {
        ex.printStackTrace();
        throw new RuntimeException(" Generate word Document failed ");
    }
}

Tool class complete code :

package com.zxd.interview.export;


import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *  A tool class found on the Internet according to information 
 *  Mainly with freemarker  For the core template generation word Document tool class 
 *  Fixed path is configured by default 
 *  You need to get the corresponding template according to the path 
 *  The request parameter needs to set the corresponding template name 
 * @author 
 * @className: WordGeneratorUtils
 * @description:  Document generation tool class 
 * </p>
 * version: V1.0.0
 */
public final class WordGeneratorUtil {
    private static Configuration configuration = null;
    private static Map<String, Template> allTemplates = null;
    private static final String TEMPLATE_URL = "/templates";

    /**
     *  Template constant class configuration 
     */
    public static final class FreemarkerTemplate {
        public static final String Test = "test";
        public static final String REPORT = "report";
        public static final String REC_RECOMMEND = "recRecommend";

    }

    static {
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(WordGeneratorUtil.class, TEMPLATE_URL);
        allTemplates = new HashMap(4);
        try {
            //  Note that the corresponding template should be loaded during initialization 
            allTemplates.put(FreemarkerTemplate.Test, configuration.getTemplate(FreemarkerTemplate.Test + ".ftl"));
            allTemplates.put(FreemarkerTemplate.REPORT, configuration.getTemplate(FreemarkerTemplate.REPORT + ".ftl"));
            allTemplates.put(FreemarkerTemplate.REC_RECOMMEND, configuration.getTemplate(FreemarkerTemplate.REC_RECOMMEND + ".ftl"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private WordGeneratorUtil() {
        throw new AssertionError();
    }

    /**
     *  establish doc  file 
     * dataMap  data , A place holder for the corresponding template is required , Otherwise it will go wrong 
     * @param dataMap  data 
     * @param wordName  word  The name of the report 
     * @param freemarkerTemplateName   Specify which freemarker Templates 
     * @return
     */
    public static File createDoc(String freemarkerTemplateName, String wordName, Map<String, String> dataMap) {
        try {
            File f = new File(wordName);
            Template t = allTemplates.get(freemarkerTemplateName);
            //  This place can't be used FileWriter Because you need to specify the encoding type, otherwise generated Word The document cannot be opened because of an unrecognized encoding 
            Writer w = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8);
            t.process(dataMap, w);
            w.close();
            return f;
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(" Generate word Document failed ");
        }
    }


}

Call layer :

  1. At the business level , Will need to export the data , According to the place holder i Information assignment , Be careful not to miss , Otherwise, the exported file will not open
@Override
public File exportQualityStep4Word(WordReportDTO exportWordRequest) {
    Map<String, String> datas = new HashMap(QualityConstants.HASH_MAP_INIT_VALUE);
    // Main title 
    datas.put("schoolName", exportWordRequest.getSchoolName());
    datas.put("title1", exportWordRequest.getBaseSituation());
    datas.put("title2", exportWordRequest.getLearningEnvRec());
    datas.put("title3", exportWordRequest.getLearningEnvPro());
    datas.put("title4", exportWordRequest.getDayLifeRec());
    datas.put("title5", exportWordRequest.getDayLifePro());
    datas.put("title6", exportWordRequest.getLearningActivityRec());
    datas.put("title7", exportWordRequest.getLearningActivityPro());
    datas.put("title8", exportWordRequest.getDevRecommend());

    datas.put("base64_1", exportWordRequest.getBase64_1());
    datas.put("base64_2", exportWordRequest.getBase64_2());
    datas.put("base64_3", exportWordRequest.getBase64_3());
    datas.put("base64_4", exportWordRequest.getBase64_4());
    datas.put("base64_5", exportWordRequest.getBase64_5());
    datas.put("base64_6", exportWordRequest.getBase64_6());


    // export 
    return WordGeneratorUtil.createDoc(WordGeneratorUtil.FreemarkerTemplate.REPORT,
                                       exportWordRequest.getWordName(),
                                       datas);
}
  1. The following is the basic operation of generating report export , You can copy the past changes where they are used
/**
 *  Export report operation for generating report 
 *
 * @param request           request
 * @param response           The response data 
 * @param exportWordRequest  export dto
 */
@PostMapping("/quality/exportword")
@ResponseBody
public void povertyExportWord(HttpServletRequest request, HttpServletResponse response,
                              WordReportDTO exportWordRequest) {

    File file = qualityReportService.exportQualityStep4Word(exportWordRequest);

    InputStream fin = null;
    OutputStream out = null;
    try {
        //  Call the tool class WordGeneratorUtils Of createDoc Method generation Word file 
        fin = new FileInputStream(file);

        response.setCharacterEncoding(QualityConstants.UTF_8);
        response.setContentType(QualityConstants.CONTENT_TYPE_WORD);
        //  Set up the browser to process the file as a download 
        //  Set the file name encoding to solve the problem of file name garbled 
        // Get the... In the request header User-Agent
        String filename = exportWordRequest.getWordName();
        String agent = request.getHeader(QualityConstants.USER_AGENT);
        String filenameEncoder = "";
        //  Make different judgments according to different browsers 
        if (agent.contains(QualityConstants.MSIE)) {
            // IE browser 
            filenameEncoder = URLEncoder.encode(filename, QualityConstants.UTF_8);
            filenameEncoder = filenameEncoder.replace("+", " ");
        } else if (agent.contains(QualityConstants.FIREFOX)) {
            //  Firefox 
            BASE64Encoder base64Encoder = new BASE64Encoder();
            filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes(QualityConstants.UTF_8)) + "?=";
        } else {
            //  Other browsers 
            filenameEncoder = URLEncoder.encode(filename, QualityConstants.UTF_8);
        }
        response.setHeader(QualityConstants.ACCESS_CONTROL_ALLOW_ORIGIN, "*");// All domains can span 
        response.setHeader(QualityConstants.CONTENT_TYPE, QualityConstants.CONTENT_TYPE_STEAM);// Binary system    Streaming files 
        response.setHeader(QualityConstants.CONTENT_DISPOSITION, "attachment;filename=" + filenameEncoder + ".doc");// Download and its file name 
        response.setHeader(QualityConstants.CONNECTION, QualityConstants.CLOSE);// Request to close the connection head 
        // Set the file to open or download in the browser 
        response.setContentType(QualityConstants.CONTENT_TYPE_DOWNLOAD);
        out = response.getOutputStream();
        byte[] buffer = new byte[QualityConstants.BYTE_512];
        int bytesToRead = QualityConstants.NUM_MINUS_1;
        //  Will read in... Through the loop Word The contents of the file are output to the browser 
        while ((bytesToRead = fin.read(buffer)) != QualityConstants.NUM_MINUS_1) {
            out.write(buffer, QualityConstants.NUM_ZERO, bytesToRead);
        }

    } catch (Exception e) {
        throw new RuntimeException(QualityConstants.FARIURE_EXPORT, e);
    } finally {
        try {
            if (fin != null) {
                fin.close();
            }
            if (out != null) {
                out.close();
            }
            if (file != null) {
                file.delete();
            }
        } catch (IOException e) {
            throw new RuntimeException(QualityConstants.FARIURE_EXPORT, e);
        }
    }

}

Export entities dto

Here's an exported entity dto, Entity objects can be customized :

package com.zxd.interview.dto;

/**
 *  Test using dto, Used to encapsulate exports word The object of 
 *
 * @author zhaoxudong
 * @version 1.0
 * @date 2020/11/7 23:37
 */
public class TestReportDTO {

    /**
     *  test 
     */
    private String test0;

    /**
     *  test 
     */
    private String test1;

    /**
     *  test 
     */
    private String test2;

    /**
     *  test 
     */
    private String test4;

    /**
     *  test 
     */
    private String test5;

    /**
     *  test 
     */
    private String test6;

    /**
     *  Report name 
     */
    private String wordName;

    public String getTest0() {
        return test0;
    }

    public void setTest0(String test0) {
        this.test0 = test0;
    }

    public String getTest1() {
        return test1;
    }

    public void setTest1(String test1) {
        this.test1 = test1;
    }

    public String getTest2() {
        return test2;
    }

    public void setTest2(String test2) {
        this.test2 = test2;
    }

    public String getTest4() {
        return test4;
    }

    public void setTest4(String test4) {
        this.test4 = test4;
    }

    public String getTest5() {
        return test5;
    }

    public void setTest5(String test5) {
        this.test5 = test5;
    }

    public String getTest6() {
        return test6;
    }

    public void setTest6(String test6) {
        this.test6 = test6;
    }

    public String getWordName() {
        return wordName;
    }

    public void setWordName(String wordName) {
        this.wordName = wordName;
    }


    @Override
    public String toString() {
        return "TestReportDTO{" +
                "test0='" + test0 + '\'' +
                ", test1='" + test1 + '\'' +
                ", test2='" + test2 + '\'' +
                ", test4='" + test4 + '\'' +
                ", test5='" + test5 + '\'' +
                ", test6='" + test6 + '\'' +
                '}';
    }
}

Constant configuration module :

I don't like hard coding , Ugly and ugly , So a lot of things will be replaced by immutable objects .

package com.zxd.interview.constant;

/**
 *  Constant configuration class 
 *
 * @author zhouhui
 */
public class QualityConstants {

    /**
     *  Quality inspection   Supervision of the project id
     */
    public static final int EVENTID = 12;

    /**
     *  Numbers 0
     */
    public static final int NUM_ZERO = 0;
    /**
     *  Numbers 1
     */
    public static final int NUM_ONE = 1;

    /**
     *  Numbers 2
     */
    public static final int NUM_TWO = 2;
    /**
     *  Numbers -1
     */
    public static final int NUM_MINUS_1 = -1;
    /**
     *  Byte size 512
     */
    public static final int BYTE_512 = 512;
    /**
     * 500 Error code 
     */
    public static final int CODE_500 = 500;
    /**
     * 500 Error message  -  Illegal state 
     */
    public static final String CODE_500_MSG_1 = " Illegal state !";
    /**
     * 500 Error message  -  Unsupervised users are not allowed to view quality inspection records 
     */
    public static final String CODE_500_MSG_2 = " Unsupervised users are not allowed to view quality inspection records !";
    /**
     * 500 Error message  -  This quality monitoring has been completed ! Can't modify 
     */
    public static final String CODE_500_MSG_3 = " This quality monitoring has been completed ! Can't modify !";
    /**
     * 500 Error message  -  Submit failed , Material upload cannot be empty 
     */
    public static final String CODE_500_MSG_4 = " Submit failed , Material upload cannot be empty ";
    /**
     * 500 Error message  -  Submit failed , Please try again later or contact the Administrator 
     */
    public static final String CODE_500_MSG_5 = " Submit failed , Please try again later or contact the Administrator !";
    /**
     * 500 Error message  -  Submit failed , Feedback cannot be empty 
     */
    public static final String CODE_500_MSG_6 = " Submit failed , Feedback cannot be empty !";
    /**
     * 405 Error code 
     */
    public static final int CODE_405 = 405;
    /**
     * 405 Error message  -  This information can only be viewed by the supervisor 
     */
    public static final String CODE_405_MSG_1 = " This information can only be viewed by the supervisor !";
    /**
     * 200 Successfully coded 
     */
    public static final int CODE_200 = 200;
    /**
     * 200 Success message  -  This information can only be viewed by the supervisor 
     */
    public static final String CODE_200_MSG_1 = " Submit successfully !";

    /**
     *  Error message  -  No record has been selected 
     */
    public static final String DELETE_FAIRURE_MSG = " Delete failed , No record has been selected !";
    /**
     *  Error message  -  No record has been selected 
     */
    public static final String NO_RECORD_SELECTED = " No record has been selected !";
    /**
     *  Character encoding utf-8
     */
    public static final String UTF_8 = "utf-8";
    /**
     *  Default pid
     */
    public static final int PID = 0;
    /**
     *  Default level 
     */
    public static final int DEFUALT_LAYER = 1;

    /**
     *  Inappropriate lowest score 
     */
    public static final Integer MIN_SCORE = 1;
    /**
     *  Excellent, highest score 
     */
    public static final Integer MAX_SCORE = 7;

    /**
     * map Of hash Initial value 
     */
    public static final int HASH_MAP_INIT_VALUE = 32;

    /**
     *  The average score of the whole garden is 
     */
    public final static String WHOLE_AVERAGE = " The average score of the whole garden is ";
    /**
     *  The query fails 
     */
    public final static String QUERY_FAIRURE = " The query fails ";
    /**
     *  Successful operation 
     */
    public final static String SUCCESS_MSG = " Successful operation !";
    /**
     *  operation failed 
     */
    public final static String FARIURE_MSG = " operation failed !";
    /**
     *  Export failed 
     */
    public final static String FARIURE_EXPORT = " Export failed !";

    /**
     *  Request header  -  file 
     */
    public final static String CONTENT_TYPE_WORD = "application/msword";
    /**
     *  Request header  -  download 
     */
    public final static String CONTENT_TYPE_DOWNLOAD = "application/x-download";
    /**
     *  Request header  -  Binary 
     */
    public final static String CONTENT_TYPE_STEAM = "application/octet-stream;charset=UTF-8";
    /**
     *  Request header 
     */
    public final static String USER_AGENT = "User-Agent";
    /**
     *  Request header 
     */
    public final static String CONTENT_TYPE = "Content-Type";
    /**
     *  Connect 
     */
    public final static String CONNECTION = "Connection";
    /**
     *  Close the connection 
     */
    public final static String CLOSE = "close";
    /**
     *  Connect 
     */
    public final static String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";
    /**
     *  Connect 
     */
    public final static String CONTENT_DISPOSITION = "Content-Disposition";

    /**
     *  browser  - ie
     */
    public final static String MSIE = "MSIE";
    /**
     *  browser  - Firefox
     */
    public final static String FIREFOX = "Firefox";

    /**
     *  Fill in the report step
     */
    public final static String MODULE_STEP3_REPORT = "qualityreport";

    /**
     *  Supervise the verification materials of the kindergarten 
     */
    public final static String MODULE_STEP1_MATERIAL = "qualitymetrail";

    /**
     *  Numbers 3
     */
    public final static int NUM_3 = 3;
    /**
     *  Numbers 4
     */
    public final static int NUM_4 = 4;

    /**
     *  Numbers 5
     */
    public final static int NUM_5 = 5;
    /**
     *  Numbers 6
     */
    public final static int NUM_6 = 6;
    /**
     *  Numbers 7
     */
    public final static int NUM_7 = 7;
    /**
     *  Numbers 8
     */
    public final static int NUM_8 = 8;
    /**
     *  Numbers 9
     */
    public final static int NUM_9 = 9;
    /**
     *  Numbers 10
     */
    public final static int NUM_10 = 10;
    /**
     *  Numbers 11
     */
    public final static int NUM_11 = 11;

    /**
     *  Numbers 12
     */
    public final static int NUM_12 = 12;
    /**
     *  Numbers 13
     */
    public final static int NUM_13 = 13;
    /**
     *  Numbers 14
     */
    public final static int NUM_14 = 14;
    /**
     *  Numbers 15
     */
    public final static int NUM_15 = 15;
    /**
     *  Numbers 16
     */
    public final static int NUM_16 = 16;
    /**
     *  Numbers 17
     */
    public final static int NUM_17 = 17;
    /**
     *  Numbers 18
     */
    public final static int NUM_18 = 18;
    /**
     *  Numbers 19
     */
    public final static int NUM_19 = 19;
    /**
     *  Numbers 20
     */
    public final static int NUM_20 = 20;

    /**
     *  Formatting Numbers 
     */
    public final static String DECIMAL_Format = "######.00";

}

Page layer processing :

Add a... To the front end form Submit , Use form Submit form data , Realization word Export function :

( Note that the template engine used is thymeleaf)

html Code :
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<!--  Latest version  Bootstrap  The core  CSS  file  -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div class="container">
    <div id="vue1" class="row">
<!--        <form @submit.prevent="submit">-->
<!--            <div>-->
<!--                 export word name :<input class="form-control" type="text" v-model="student.wordName">-->
<!--            </div>-->

<!--            <div>-->
<!--                test0:<input type="text" class="form-control" v-model="student.test0">-->
<!--                test1:<input type="text" class="form-control" v-model="student.test1">-->
<!--                test2:<input type="text" class="form-control" v-model="student.test2">-->
<!--                test4:<input type="text" class="form-control" v-model="student.test4">-->
<!--                test5:<input type="text" class="form-control" v-model="student.test5">-->
<!--                test6:<input type="text" class="form-control" v-model="student.test6">-->
<!--            </div>-->

<!--            <input type="submit" class="btn btn-danger" value=" Submit ">-->
<!--        </form>-->


        <form method="post" action="/quality/exportword">
            <div>
                 export word name :<input class="form-control" type="text" name="wordName">
            </div>

            <div>
                test0:<input type="text" class="form-control" name="test0">
                test1:<input type="text" class="form-control" name="test1">
                test2:<input type="text" class="form-control" name="test2">
                test4:<input type="text" class="form-control" name="test4">
                test5:<input type="text" class="form-control" name="test5">
                test6:<input type="text" class="form-control" name="test6">
            </div>

            <input type="submit" class="btn btn-danger" value=" Submit ">
        </form>

    </div>
</div>

</body>
<!--  Development environment version , Contains helpful command-line warnings  -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<script th:src="@{/js/exportword.js}"></script>
</html>
js Code

Use js Code processing form Form submission , Used jquery Export , In fact, I don't know how to export the binary stream generated by the background , There are many ways to do it , Next time I write an article, I'll summarize some usages .

var v1 = new Vue({
    el: '#vue1',
    data: {
        counter: 0,
        student: {
            test0:'',
            test1:'',
            test2:'',
            test3:'',
            test4:'',
            test5:'',
            test6:'',
            wordName: '',

        }
    },
    methods: {
        test: function () {
            console.log(this.counter);
        },
        submit() {
            console.log(this.student);
            var url = '/quality/exportword';
            var formData = JSON.stringify(this.student); // this Point to this VUE example  data The default binding is under instance . So direct this.student It's the data to be submitted 
            this.$http.post(url, formData).then(function (data) {
                console.log(data);
                let blob = new Blob([data.data],{ type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8'});
                let objectUrl = URL.createObjectURL(blob);
                window.location.href = objectUrl;
            }).catch(function () {
                console.log('test');
            });
        }
    }
})

ending :

Average personal level , I hope this article can help readers , You are welcome to point out the mistakes , When you see it, it will be changed to , thank you !

Some time ago, I was busy interviewing and found a new place to work , When the job is stable , Will continue to dig deep into blogs and technology stacks .

版权声明
本文为[lazytimes]所创,转载请带上原文链接,感谢

Scroll to Top