精华内容
下载资源
问答
  • Java 用Freemarker完美导出word文档(带图片)前言最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题。准备材料1.word原件 2.编辑器(推荐...

    Java  用Freemarker完美导出word文档(带图片)

    前言

    最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题。

    准备材料

    1.word原件 2.编辑器(推荐Firstobject free XML editor)

    实现步骤

    1.用Microsoft Office Word打开word原件;

    2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;

    3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Word打开且要保存为Word 2003XML,本人亲测,用WPS找不到Word 2003XML选项,如果保存为Word XML,会有兼容问题,避免出现导出的word文档不能用Word 2003打开的问题】,保存的文件名不要是中文;

    4.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容;

    5. 将文档内容中需要动态修改内容的地方,换成freemarker的标识。其实就是Map中key,如${landName};

    6.在加入了图片占位的地方,会看到一片base64编码后的代码,把base64替换成${image},也就是Map中key,值必须要处理成base64;

    代码如:${image}

    注意:“>${image}

    如果需要循环,则使用:#list>  maps是Map中key,值为数组,map为自定义;

    7. 标识替换完之后,模板就弄完了,另存为.ftl后缀文件即可。注意:一定不要用word打开ftl模板文件,否则xml内容会发生变化,导致前面的工作白做了。

    代码实现

    工具类WordUtils.Java

    1 importjava.io.File;2 importjava.io.FileInputStream;3 importjava.io.FileOutputStream;4 importjava.io.IOException;5 importjava.io.InputStream;6 importjava.io.OutputStreamWriter;7 importjava.io.Writer;8 importjava.net.URLEncoder;9 importjava.util.Date;10 importjava.util.Map;11

    12 importjavax.servlet.ServletOutputStream;13 importjavax.servlet.http.HttpServletRequest;14 importjavax.servlet.http.HttpServletResponse;15

    16 importfreemarker.template.Configuration;17 importfreemarker.template.Template;18

    19 public classWordUtils {20 //配置信息,代码本身写的还是很可读的,就不过多注解了

    21 private static Configuration configuration = null;22 //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置23 //private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";

    24 private static final String templateFolder = "H:/我的项目/lm/lm/web/src/main/webapp/WEB-INF/templates";25 static{26 configuration = newConfiguration();27 configuration.setDefaultEncoding("utf-8");28 try{29 configuration.setDirectoryForTemplateLoading(newFile(templateFolder));30 } catch(IOException e) {31 e.printStackTrace();32 }33 }34

    35 privateWordUtils() {36 throw newAssertionError();37 }38

    39 public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map,String title,String ftlFile) throwsIOException {40 Template freemarkerTemplate =configuration.getTemplate(ftlFile);41 File file = null;42 InputStream fin = null;43 ServletOutputStream out = null;44 try{45 //调用工具类的createDoc方法生成Word文档

    46 file =createDoc(map,freemarkerTemplate);47 fin = newFileInputStream(file);48

    49 response.setCharacterEncoding("utf-8");50 response.setContentType("application/msword");51 //设置浏览器以下载的方式处理该文件名

    52 String fileName = title+DateUtil.formatDateDetailTime(new Date()) + ".doc";53 response.setHeader("Content-Disposition", "attachment;filename="

    54 .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));55

    56 out =response.getOutputStream();57 byte[] buffer = new byte[512]; //缓冲区

    58 int bytesToRead = -1;59 //通过循环将读入的Word文件的内容输出到浏览器中

    60 while((bytesToRead = fin.read(buffer)) != -1) {61 out.write(buffer, 0, bytesToRead);62 }63 } finally{64 if(fin != null) fin.close();65 if(out != null) out.close();66 if(file != null) file.delete(); //删除临时文件

    67 }68 }69

    70 private static File createDoc(Map, ?>dataMap, Template template) {71 String name = "sellPlan.doc";72 File f = newFile(name);73 Template t =template;74 try{75 //这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开

    76 Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");77 t.process(dataMap, w);78 w.close();79 } catch(Exception ex) {80 ex.printStackTrace();81 throw newRuntimeException(ex);82 }83 returnf;84 }85 }

    Action

    1 @RequestMapping("/exportSellPlan")2 public @ResponseBody voidexportSellPlan(Long id){3 Calendar calendar = Calendar.getInstance();//取当前日期。

    4 if(id!=null){5 SellPlan plan=sellService.getSellPlanInfo(id);6 //获得数据

    7 Map map = new HashMap();8 map.put("bYear", plan.getBusinessYear()!=null?plan.getBusinessYear():"");9 map.put("lYear", plan.getLiveYear()!=null?plan.getLiveYear():"");10 map.put("leader",plan.getLeader()!=null?plan.getLeader():"");11 map.put("phone", plan.getPhone()!=null?plan.getPhone():"");12 map.put("curYear", calendar.get(Calendar.YEAR)+"");13 map.put("image", getImageBase(plan.getPositionImage()));14 try{15 WordUtils.exportMillCertificateWord(getRequest(),getResponse(),map,"方案","sellPlan.ftl");16 } catch(IOException e) {17 //TODO Auto-generated catch block

    18 e.printStackTrace();19 }20 }21 }

    Base64处理

    1 //获得图片的base64码

    2 @SuppressWarnings("deprecation")3 publicString getImageBase(String src) {4 if(src==null||src==""){5 return "";6 }7 File file = new File(getRequest().getRealPath("/")+src.replace(getRequest().getContextPath(), ""));8 if(!file.exists()) {9 return "";10 }11 InputStream in = null;12 byte[] data = null;13 try{14 in = newFileInputStream(file);15 } catch(FileNotFoundException e1) {16 e1.printStackTrace();17 }18 try{19 data = new byte[in.available()];20 in.read(data);21 in.close();22 } catch(IOException e) {23 e.printStackTrace();24 }25 BASE64Encoder encoder = newBASE64Encoder();26 returnencoder.encode(data);27 }

    Javascript

    1 window.location.href="/exportSellPlan?id=" + id;

    pom.xml

    org.freemarker

    freemarker

    2.3.20

    结束语

    如果对Freemarker标签不熟的,可以在网上先学习下,了解文档结构。

    相关链接

    非特殊说明,本文版权归 朝雾轻寒 所有,转载请注明出处.

    展开全文
  • Java 用Freemarker完美导出word文档(带图片)前言最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题。准备材料1.word原件 2.编辑器(推荐...

    Java  用Freemarker完美导出word文档(带图片)

    前言

    最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题。

    准备材料

    1.word原件 2.编辑器(推荐Firstobject free XML editor)

    实现步骤

    1.用Microsoft Office Word打开word原件;

    2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;

    3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Word打开且要保存为Word 2003XML,本人亲测,用WPS找不到Word 2003XML选项,如果保存为Word XML,会有兼容问题,避免出现导出的word文档不能用Word 2003打开的问题】;

    4.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容;

    5. 将文档内容中需要动态修改内容的地方,换成freemarker的标识。其实就是Map中key,如${landName};

    6.在加入了图片占位的地方,会看到一片base64编码后的代码,把base64替换成${image},也就是Map中key,值必须要处理成base64;

    代码如:${image}

    注意:“>${image}

    如果需要循环,则使用:#list>  maps是Map中key,值为数组,map为自定义;

    7. 标识替换完之后,模板就弄完了,另存为.ftl后缀文件即可。注意:一定不要用word打开ftl模板文件,否则xml内容会发生变化,导致前面的工作白做了。

    代码实现

    工具类WordUtils.Java

    1 importjava.io.File;2 importjava.io.FileInputStream;3 importjava.io.FileOutputStream;4 importjava.io.IOException;5 importjava.io.InputStream;6 importjava.io.OutputStreamWriter;7 importjava.io.Writer;8 importjava.net.URLEncoder;9 importjava.util.Date;10 importjava.util.Map;11

    12 importjavax.servlet.ServletOutputStream;13 importjavax.servlet.http.HttpServletRequest;14 importjavax.servlet.http.HttpServletResponse;15

    16 importfreemarker.template.Configuration;17 importfreemarker.template.Template;18

    19 public classWordUtils {20 //配置信息,代码本身写的还是很可读的,就不过多注解了

    21 private static Configuration configuration = null;22 //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置23 //private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";

    24 private static final String templateFolder = "H:/我的项目/lm/lm/web/src/main/webapp/WEB-INF/templates";25 static{26 configuration = newConfiguration();27 configuration.setDefaultEncoding("utf-8");28 try{29 configuration.setDirectoryForTemplateLoading(newFile(templateFolder));30 } catch(IOException e) {31 e.printStackTrace();32 }33 }34

    35 privateWordUtils() {36 throw newAssertionError();37 }38

    39 public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map,String title,String ftlFile) throwsIOException {40 Template freemarkerTemplate =configuration.getTemplate(ftlFile);41 File file = null;42 InputStream fin = null;43 ServletOutputStream out = null;44 try{45 //调用工具类的createDoc方法生成Word文档

    46 file =createDoc(map,freemarkerTemplate);47 fin = newFileInputStream(file);48

    49 response.setCharacterEncoding("utf-8");50 response.setContentType("application/msword");51 //设置浏览器以下载的方式处理该文件名

    52 String fileName = title+DateUtil.formatDateDetailTime(new Date()) + ".doc";53 response.setHeader("Content-Disposition", "attachment;filename="

    54 .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));55

    56 out =response.getOutputStream();57 byte[] buffer = new byte[512]; //缓冲区

    58 int bytesToRead = -1;59 //通过循环将读入的Word文件的内容输出到浏览器中

    60 while((bytesToRead = fin.read(buffer)) != -1) {61 out.write(buffer, 0, bytesToRead);62 }63 } finally{64 if(fin != null) fin.close();65 if(out != null) out.close();66 if(file != null) file.delete(); //删除临时文件

    67 }68 }69

    70 private static File createDoc(Map, ?>dataMap, Template template) {71 String name = "sellPlan.doc";72 File f = newFile(name);73 Template t =template;74 try{75 //这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开

    76 Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");77 t.process(dataMap, w);78 w.close();79 } catch(Exception ex) {80 ex.printStackTrace();81 throw newRuntimeException(ex);82 }83 returnf;84 }85 }

    Action

    1 @RequestMapping("/exportSellPlan")2 public @ResponseBody voidexportSellPlan(Long id){3 Calendar calendar = Calendar.getInstance();//取当前日期。

    4 if(id!=null){5 SellPlan plan=sellService.getSellPlanInfo(id);6 //获得数据

    7 Map map = new HashMap();8 map.put("bYear", plan.getBusinessYear()!=null?plan.getBusinessYear():"");9 map.put("lYear", plan.getLiveYear()!=null?plan.getLiveYear():"");10 map.put("leader",plan.getLeader()!=null?plan.getLeader():"");11 map.put("phone", plan.getPhone()!=null?plan.getPhone():"");12 map.put("curYear", calendar.get(Calendar.YEAR)+"");13 map.put("image", getImageBase(plan.getPositionImage()));14 try{15 WordUtils.exportMillCertificateWord(getRequest(),getResponse(),map,"方案","sellPlan.ftl");16 } catch(IOException e) {17 //TODO Auto-generated catch block

    18 e.printStackTrace();19 }20 }21 }

    Base64处理

    1 //获得图片的base64码

    2 @SuppressWarnings("deprecation")3 publicString getImageBase(String src) {4 if(src==null||src==""){5 return "";6 }7 File file = new File(getRequest().getRealPath("/")+src.replace(getRequest().getContextPath(), ""));8 if(!file.exists()) {9 return "";10 }11 InputStream in = null;12 byte[] data = null;13 try{14 in = newFileInputStream(file);15 } catch(FileNotFoundException e1) {16 e1.printStackTrace();17 }18 try{19 data = new byte[in.available()];20 in.read(data);21 in.close();22 } catch(IOException e) {23 e.printStackTrace();24 }25 BASE64Encoder encoder = newBASE64Encoder();26 returnencoder.encode(data);27 }

    Javascript

    1 window.location.href="/exportSellPlan?id=" + id;

    结束语

    如果对Freemarker标签不熟的,可以在网上先学习下,了解文档结构。

    相关链接

    展开全文
  • java freemarker + word 模板 生成 word 文档 (变量替换,数据的循环,表格数据的循环,以及图片的替换) 1,最近有个需求,动态生成 Word 文当并供前端下载,网上找了一下,发现基本都是用 word 生成 xml 然后用...

    java freemarker + word 模板 生成 word 文档 (变量替换,数据的循环,表格数据的循环,以及图片的替换)

    1,最近有个需求,动态生成 Word 文当并供前端下载,网上找了一下,发现基本都是用 word 生成 xml 然后用模板替换变量的方式

    1.1,这种方式虽然可行,但是生成的 xml 是在是太乱了,整理就得整理半天,而且一旦要修改模板,那简直就是灾难,而且据说还不兼容 WPS

    1.2,所以笔者找到了以下可以直接用 word 文档作为模板的方法,这里做以下笔记,以下代码依赖于 JDK8 以上

    2,pom.xml 相应依赖

    复制代码

            <!-- 文档模板操作依赖 -->
            <dependency>
                <groupId>fr.opensagres.xdocreport</groupId>
                <artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
                <version>2.0.1</version>
            </dependency>
            <dependency>
                <groupId>fr.opensagres.xdocreport</groupId>
                <artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
                <version>2.0.1</version>
            </dependency>

    复制代码

    3,使用该模板的操作主要是  IXDocReport 和 IContext 对象,封装两个工具类来对他们进行获取和操作

    3.1,存放和设置插入到模板中的数据的模型类 ExportData,设置一般数据或者循环集合的时候比较简单,直接用 IContent 的 put(key,value)即可

    但是设置 表格循环数据和图片等特殊数据就比较麻烦了,详情看下面 setTable 和 setImg

    复制代码

    package com.hwq.utils.export;
    
    import com.hwq.utils.model.SoMap;
    import fr.opensagres.xdocreport.document.IXDocReport;
    import fr.opensagres.xdocreport.document.images.ByteArrayImageProvider;
    import fr.opensagres.xdocreport.document.images.IImageProvider;
    import fr.opensagres.xdocreport.template.IContext;
    import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
    import org.springframework.core.io.ClassPathResource;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class ExportData {
    
        private IXDocReport report;
        private IContext context;
    
        /**
         * 构造方法
         * @param report
         * @param context
         */
        public ExportData(IXDocReport report, IContext context) {
            this.report = report;
            this.context = context;
        }
    
        /**
         * 设置普通数据,包括基础数据类型,数组,试题对象
         * 使用时,直接 ${key.k} 或者 [#list d as key]
         * @param key   健
         * @param value 值
         */
        public void setData(String key, Object value) {
            context.put(key, value);
        }
    
        /**
         * 设置表格数据,用来循环生成表格的 List 数据
         * 使用时,直接 ${key.k}
         * @param key   健
         * @param value List 集合
         */
        public void setTable(String key, List<SoMap> maps) {
            FieldsMetadata metadata = report.getFieldsMetadata();
            metadata = metadata == null ? new FieldsMetadata() : metadata;
            SoMap map = maps.get(0);
            for (String kk : map.keySet()) {
                metadata.addFieldAsList(key + "." + kk);
            }
            report.setFieldsMetadata(metadata);
            context.put(key, maps);
        }
    
        /**
         * 设置图片数据
         * 使用时 直接在书签出 key
         * @param key 健
         * @param url 图片地址
         */
        public void setImg(String key, String url) {
            FieldsMetadata metadata = report.getFieldsMetadata();
            metadata = metadata == null ? new FieldsMetadata() : metadata;
            metadata.addFieldAsImage(key);
            report.setFieldsMetadata(metadata);
            try (
                    InputStream in = new ClassPathResource(url).getInputStream();
            ) {
                IImageProvider img = new ByteArrayImageProvider(in);
                context.put(key, img);
            } catch (IOException ex) {
                throw new RuntimeException(ex.getMessage());
            }
        }
    
        /**
         * 获取文件流数据
         * @return 文件流数组
         */
        public byte[] getByteArr() {
            try (
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
            ) {
                report.process(context, out);
                return out.toByteArray();
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new RuntimeException(ex.getMessage());
            }
        }
    
    }

    复制代码

    3.2,生成  IXDocReport 和 IContext  的工具类

    复制代码

    package com.hwq.utils.export;
    
    import fr.opensagres.xdocreport.core.XDocReportException;
    import fr.opensagres.xdocreport.document.IXDocReport;
    import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
    import fr.opensagres.xdocreport.template.IContext;
    import fr.opensagres.xdocreport.template.TemplateEngineKind;
    import org.springframework.core.io.ClassPathResource;
    
    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    
    public class WordUtil {
    
        /**
         * 获取 Word 模板的两个操作对象 IXDocReport 和 IContext
         * @param url 模板相对于类路径的地址
         * @return 模板数据对象
         */
        public static ExportData createExportData(String url) {
            try {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                IXDocReport report = createReport(url);
                IContext context = report.createContext();
                return new ExportData(report, context);
            } catch (XDocReportException ex) {
                throw new RuntimeException(ex.getMessage());
            }
        }
    
        /**
         * 加载模板的方法,主要是指定模板的路径和选择渲染数据的模板
         * @param url 模板相对于类路径的地址
         * @return word 文档操作类
         */
        private static IXDocReport createReport(String url) {
            try (
                    InputStream in = new ClassPathResource(url).getInputStream();
            ) {
                IXDocReport ix = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);
                return ix;
            } catch (Exception ex) {
                throw new RuntimeException(ex.getMessage());
            }
        }
    
    }

    复制代码

    4,让我们编辑一个 word 模板,方到资源路径下的 export 目录下, 全路径为 export/template.docx 内容如下

    4.1,我们可以发现上面的模板有些数据的两端有两个尖括号,就是我们需要替换数据的地方,插入方式如下

    4.2,打开 word 文档,光标选中需要替换的位置 如上图的 1 号位  =》 Ctrl + F9 生成域  =》右键点击 =》选择编辑域 =》选择邮件合并 =》加上变量 ${model.order}

    4.3,依次如下,注意输入变量的时候不要动 MERGEFIELD 这个单词,在他的后面空一格输入

     

     

    4.4,IF 判断的写法,需要三个域,每一个的创建方式和上面相同 内容为   "[#if 1 == 1]"  文档内容  " [#else]"  文档内容  " [/#if]"  , 注意要加中括号,两端最好在加上引号

     

    4.5,循环的写法 [#list list as item]  [/#list]  依然是要注意两端的中括号,最好两端在加引号括起来

    4.6,图片的插入方式和上面的不太相同,首先我们点击图片,选择插入,选择书签,输入一个任意的变量名如 img

    4.7,这样我们就编辑了一个包含了多种元素的 word 文档,需要注意的点是 域的 内容必须在 右键 编辑域 邮件合并 处填写,不要直接修改,否则无效

    4.8,图片的比列最好不要调整,否则替换的图片可能会失真等,可以调大小,但是比列不要改

    5,接下来我们测试一下,首先创建一个 SpringBoot 项目

    5.1 创建数据模型类 UserModel(依赖于 lombok)

    复制代码

    package com.hwq.doc.export.model;
    
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class UserModel {
    
        private Integer order;
        private String code;
        private String name;
    
    }

    复制代码

    5.2,创建业务逻辑类  UserService

    复制代码

    package com.hwq.doc.export.service;
    
    import com.hwq.doc.export.model.UserModel;
    import com.hwq.utils.export.ExportData;
    import com.hwq.utils.export.WordUtil;
    import com.hwq.utils.model.SoMap;
    import org.springframework.stereotype.Service;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    
    @Service
    public class UserService {
    
        private final static String rootPath = "E:/text/file/"; // 保存文件的地址
    
        public byte[] downWord() {
            // 准备数据
            List<SoMap> list = new ArrayList<SoMap>();
            UserModel user0 = new UserModel();
            UserModel user1 = new UserModel();
            UserModel user2 = new UserModel();
            user0.setOrder(1);
            user0.setCode("00300.SS");
            user0.setName("爱谁谁");
            user1.setOrder(2);
            user1.setCode("00300.SS");
            user1.setName("爱谁谁");
            user2.setOrder(3);
            user2.setCode("00300.SS");
            user2.setName("爱谁谁");
            list.add(new SoMap(user0));
            list.add(new SoMap(user1));
            list.add(new SoMap(user2));
    
            // 向模板中插入值
            ExportData evaluation = WordUtil.createExportData("export/template.docx");
            evaluation.setData("model", user0);
            evaluation.setData("list", list);
            evaluation.setTable("table", list);
            evaluation.setImg("img", "export/coney.png");
    
            // 获取新生成的文件流
            byte[] data = evaluation.getByteArr();
    
            // 可以直接写入本地的文件
            String fileName = rootPath + UUID.randomUUID().toString().replaceAll("-", "") + ".docx";
            try (
                    FileOutputStream fos = new FileOutputStream(fileName);
            ) {
                fos.write(data, 0, data.length);
            } catch (IOException ex) {
                throw new RuntimeException(ex.getMessage());
            }
    
            return data;
        }
    }

    复制代码

     

    5.3,创建控制器 Usercontroller 

    复制代码

    package com.hwq.doc.export.controller;
    
    import com.hwq.doc.export.service.UserService;
    import com.hwq.utils.http.ResUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/word")
        public Object getTemplate(HttpServletRequest request) {
            byte[] data = userService.downWord();
            return ResUtil.getStreamData(request, data, "文件下载", "docx");
        }
    
    }

    复制代码

    5.4,以上还用到了我自己封装的工具类,SoMap 和 ResUtil 如下 

    复制代码

    package com.hwq.utils.model;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.util.HashMap;
    
    public class SoMap extends HashMap<String, Object> {
    
    
        public SoMap() { }
    
        /**
         * 构造方法,将任意实体类转化为 Map
         * @param obj
         */
        public SoMap(Object obj) {
            Class clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            try {
                for (Field field : fields) {
                    field.setAccessible(true);
                    this.put(field.getName(), field.get(obj));
                }
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex.getMessage());
            }
        }
    
        /**
         * 将 Map 转化为 任意实体类
         * @param clazz 反射获取类字节码对象
         * @return
         */
        public <T> T toEntity(Class<T> clazz) {
            Field[] fields = clazz.getDeclaredFields();
            try {
                Constructor constructor = clazz.getDeclaredConstructor();
                T t = (T) constructor.newInstance();
                for (Field field : fields) {
                    field.setAccessible(true);
                    field.set(t, this.get(field));
                }
                return t;
            } catch (Exception ex) {
                throw new RuntimeException(ex.getMessage());
            }
        }
    
        /**
         * 从集合中获取一个字段的方法,如果字段不存在返回空
         * @param key  字段的唯一标识
         * @param <T>  字段的类型,运行时自动识别,使用时无需声明和强转
         * @return     对应字段的值
         */
        public <T> T get(String key) {
            return (T) super.get(key);
        }
    
    }

    复制代码

    复制代码

    package com.hwq.utils.http;
    
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.UnsupportedEncodingException;
    
    public class ResUtil {
    
        /**
         * 生成下载文件,浏览器直接访问为下载文件
         * @param request  请求对象
         * @param data     数据流数组
         * @param prefix   下载的文件名
         * @param suffix   文件后缀
         * @return 浏览器可以直接下载的文件流
         */
        public static ResponseEntity<byte[]> getStreamData(
                HttpServletRequest request, byte[] data, String prefix, String suffix
        ) {
            HttpHeaders headers = new HttpHeaders();
            prefix = StringUtils.isEmpty(prefix) ? "未命名" : prefix;
            suffix = suffix == null ? "" : suffix;
            try {
                String agent = request.getHeader("USER-AGENT");
                boolean isIE = null != agent, isMC = null != agent;
                isIE = isIE && (agent.indexOf("MSIE") != -1 || agent.indexOf("Trident") != -1);
                isMC = isMC && (agent.indexOf("Mozilla") != -1);
                prefix = isMC ? new String(prefix.getBytes("UTF-8"), "iso-8859-1") :
                        (isIE ? java.net.URLEncoder.encode(prefix, "UTF8") : prefix);
                headers.setContentDispositionFormData("attachment", prefix + "." + suffix);
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                return new ResponseEntity<byte[]>(data, headers, HttpStatus.OK);
            } catch (UnsupportedEncodingException ex) {
                ex.printStackTrace();
                throw new RuntimeException(ex.getMessage());
            }
        }
    }

    复制代码

    6,我们把模板和一张图片存放到项目的资源文件夹下 的 export 下, 图片是用来替换模板中的图片的

    7,启动项目,我们访问上面编写的控制器,效果如下,一切 OK(注意该种方式对于字段的要求比较严苛,只要在模板中编写的变量一定要设置值,否则抛异常)

     

     

     

    8,新版本我们在生成表格数据时,也可以不使用  metadata.addFieldAsList 而在在 list 标签前面添加 @before-row 和 @after-row,这样就支持了表格的嵌套循环,如:

    9,关于图片的循环目前好像暂不支持,只支持书签的方式,期待后续的跟新吧

    转载于  https://www.cnblogs.com/lovling/p/10791139.html   如有问题请联系

    展开全文
  • Java生成word文档

    2018-12-26 10:49:38
    2.把需要动态修改的内容替换成XXX,如果有图片,尽量选择较小的图片几十K左右,并调整好位置; 3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Wor...

    https://www.cnblogs.com/zwqh/p/7182953.html

    实现步骤

    1.用Microsoft Office Word打开word原件;

    2.把需要动态修改的内容替换成XXX,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;

    3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Word打开且要保存为Word 2003XML,本人亲测,用WPS找不到Word 2003XML选项,如果保存为Word XML,会有兼容问题,避免出现导出的word文档不能用Word 2003打开的问题】,保存的文件名不要是中文;

    4.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容;

    5. 将文档内容中需要动态修改内容的地方,换成freemarker的标识。其实就是Map<String, Object>中key,如${landName};

    6.在加入了图片占位的地方,会看到一片base64编码后的代码,把base64替换成${image},也就是Map<String, Object>中key,值必须要处理成base64;

      代码如:<w:binData w:name="wordml://自定义.png" xml:space="preserve">${image}</w:binData>

      注意:“>${image}<”这尖括号中间不能加任何其他的诸如空格,tab,换行等符号。

      如果需要循环,则使用:<#list maps as map></#list>  maps是Map<String, Object>中key,值为数组,map为自定义;

    7. 标识替换完之后,模板就弄完了,另存为.ftl后缀文件即可。注意:一定不要用word打开ftl模板文件,否则xml内容会发生变化,导致前面的工作白做了。

    代码实现

    Controller  ~~~~~~~

    Freemarker   ~~~~~~~

     

    展开全文
  • 2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置; 3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Word打开且要保存为Word ...
  • 建立test.doc文档,内容如下(使用freemarker表达式替换要动态传的内容) 将word另存为xml 修改xm后缀为ftl放入项目目录 引入pom <dependency> <groupId>org.freemarker</groupId> &...
  • 前言最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较...2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;3....
  • 2.把需要动态修改的内容替换成${XX}的形式,如果有图片,尽量选择较小的图片几十K左右的小图片,并调整好位置,占位(小图片转换的base64数据少,便于修改);如下图 3.另存为,选择保存类型Word 2003 XML ...
  • 1.使用Microsoft Office Word编辑word模板,把需要动态修改的内容替换成${xxxxxx},如果有图片,尽量选择较小的图片几十K左右,并调整好位置及大小 图1 模板示例 注意: 1.变量需要使用${},例如:${CORP_...
  • Java 用Freemarker完美导出word文档(带图片)前言最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题。准备材料1.word原件 2.编辑器...
  • 2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Word打...
  • 前言最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较...2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;3....
  • 最近在做一个项目,其中需要把客户的提供的word文档动态提供下载服务,在网上找了N多资料,发现很多对word文档都不是很完美。例如:JACOB和JAVA2WORD,这两个都只能在windows平台上使用,对于跨平台系统来讲,就等于...
  • 动态生成 Word 文当并供前端下载,网上找了一下,发现基本都是用 word 生成 xml 然后用模板替换变量的方式1.1,这种方式虽然可行,但是生成的 xml 是在是太乱了,整理就得整理半天,而且一旦要修改模板,那简直就是...
  • 一、 新建word模板先通过wps或word等文字处理工具新建一个想要的结构的word文档,数据都先用假数据填充好,填充的数据实际使用上是没用的,是为了咱们修改模板能够迅速定位到需要动态填充区域的。二、 java代码填充...
  • 1,最近有个需求,动态生成 Word 文当并供前端下载,网上找了一下,发现基本都是用 word 生成 xml 然后用模板替换变量的方式 1.1,这种方式虽然可行,但是生成的 xml 是在是太乱了,整理就得整理半天,而且一旦要...
  • 基于java新闻发布及管理系统设计软件程序源码+数据库+WORD毕业设计论文文档. Java新闻发布系统新闻发布及管理系统就是一个能够在网上实现新闻的发布及管理,让人们更好的获取更新的新闻资讯。 (1)用户管理: 用户...
  • 大致的思路是先用office2003或者2007编辑好word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出‘.doc’ word文档。经测试这样方式生成的word文档完全符合office标准,...
  • Java使用模板生成Word发给前端下载

    千次阅读 2020-04-13 11:27:38
    1.新建一个Word文档作为模板,需要动态变量的地方用${xxx}进行替代,例如: 在文档中可以根据自己的需求更改字号,字体等等排版格式。 2.将该文档另存为Word.xml格式,不能直接修改文件后缀: 打开该xml文件,...
  • Java 用Freemarker完美导出word文档(带图片)前言最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题。准备材料1.word原件 2.编辑器...
  • 让我动态生成pdf文件.在网上试了好多方法,感觉全是坑.最终采用了用xdocreport转化成pdf. 二.实现 (一).实现步骤 1.把.doc文件字体全部改成宋体 2.把.doc文件另存为.docx文件 3.将.docx文件后缀名改为.zip 4.解压zip...
  • 前言最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较...2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;3....
  • 1.首先,新建一个word文档,内容如下,另存为pdf格式,我的命名:mytest.pdf。 2.用Adobe Acrobat Pro 打开刚刚制作的pdf文件。如下图: 3.点击创建–>PDF表单–>使用当前文档–>使用当前文档,一直点下...
  • javaEE_SSH土地档案管理系统设计软件源码+数据库+WORD毕业论文文档: 技术:java、jsp、struts、spring、hibernate 数据库:oracle 集成开发工具:eclipse 目录 摘 要 i Abstract ii 1 绪论 1 1.1 可行性研究编写...
  • 目前很多程序语言都专注于帮你编写成千上万行的代码,所以此类型的语言所提供的包、命名空间、复杂的类型系统及无数的结构,有上千页的文档需要操作者学习。 而Lua并不帮你编写大量的代码的程序,相反的,Lua仅让你...
  • 1.3 打开xml文件,将需要从数据库或动态获取的数据,使用${xx}符号替换,如:word文档上有“姓名:张三”,具体姓名需要从数据库动态获取,则将“张三”替换为“${name}”,name需要和Java代码中Map...
  • java开源包1

    千次下载 热门讨论 2013-06-28 09:14:34
    JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...
  • java开源包12

    热门讨论 2013-06-28 10:14:45
    JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...

空空如也

空空如也

1 2 3 4 5 6
收藏数 112
精华内容 44
关键字:

动态修改word文档java

java 订阅