qq_57346419 2024-05-30 10:07 采纳率: 0%
浏览 58
已结题

使用xdocreport 生成word

使用xdocreport 生成word

网页导出word文档,需要生成表格,表格内有些内容是一行两列的,左侧列是标题,右侧列是数据,现在对数据列进行加域处理,使用的是«@before-row[#list studentXXZT as l]»« ${l.XXZT}» «@after-row[/#list]»进行遍历,数据列有多条数据的话,会在原有模板基础下,在当前行向下生成新的数据行,一条数据占一行。
期望达成的效果如图:

img

目前效果:

img

img


#问题描述:
数据行会生成,但是左侧标题列也会跟着生成新的行,并且内容自动填充。
注:后端代码是没问题的数据能正常封装。
代码:

public void downLoadWord(String id) throws IOException {
        String getXC = "select XCC_YEAR,XCC_XXCS,XCC_XXRQ,XCC_XXSC,XCC_XXDD,XCC_CYCQL,XCC_WCJRYJYY,XCC_XCZP,XCC_TBRLXR,XCC_LXRY from SASIRMPROPAGANDA where id = '" + id + "'";
        Map<String, Object> XCMap = NativeQueryUtils.queryOne(getXC);
        String imageSql = "select * from eisimagefile where billid = '" + id + "'";
        List<Map<String, Object>> imageMapList = NativeQueryUtils.queryList(imageSql);
        try {
            Properties allproper = PropertiesUtil.getAllproper();
//            String confFile = allproper.getProperty("wordPath");
            String confFile = "server" + File.separator + "runtime" + File.separator + "recordTable.docx";
            File conf = new File(confFile);
            if (!conf.exists()) {
                log.error(conf.getAbsolutePath() + "配置文件不存在");
            }
            InputStream ins = new FileInputStream(conf);
            //注册xdocreport实例并加载FreeMarker模板引擎
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins, TemplateEngineKind.Freemarker);
            //创建xdocreport上下文对象
            IContext context = report.createContext();
            //创建字段元数据
            FieldsMetadata fm = report.createFieldsMetadata();

            List<TestPicNameVo> list = new ArrayList<>();
            List<TestPicVo> picVoList = new ArrayList<>();
            TestPicNameVo picNameVo1 = new TestPicNameVo();
            //List<IImageProvider> imagList = new ArrayList<>(); //---
            //验证是否能导出图片
            /*IImageProvider p1 = new FileImageProvider(new File("E:\\images\\woman\\1.jpg"));
            TestPicVo testPicVo1 = new TestPicVo(p1);
            TestPicNameVo picNameVo1 = new TestPicNameVo();
            picVoList.add(testPicVo1);

            IImageProvider p2 = new FileImageProvider(new File("E:\\images\\woman\\2.jpg"));
            TestPicVo testPicVo2 = new TestPicVo(p2);
            picVoList.add(testPicVo2);

            picNameVo1.setPicVoList(picVoList);
            list.add(picNameVo1);*/
            for (Map<String, Object> imageMap : imageMapList) {
                String ext = String.valueOf(imageMap.get("ext"));
                if (verifyIfPicture(ext)) {
                    String FileID = String.valueOf(imageMap.get("id"));
                    LinkedHashMap<String, Object> map = new LinkedHashMap();
                    HashMap<Object, Object> paramMap = new HashMap<>();
                    paramMap.put("FileID", FileID);
                    map.put("imageFileMapParam", paramMap);
                    ResultFrontModel result = this.client.invoke(ResultFrontModel.class, "com.inspur.gs.eis.image.restful.eis.ImageAPIEisRest.getImageFileByFileID", "EIS", map, null);
                    String code = result.code;
                    String imageFileBytes = ((LinkedHashMap) result.data).get("imageFileBytes").toString();
                    byte[] decode = Base64.getDecoder().decode(imageFileBytes);
                    InputStream inputStream = new ByteArrayInputStream(decode);

                    //测试图片是否完整
                    /*File filess = File.createTempFile("abc",".jpg");
                    try (OutputStream outputStream = new FileOutputStream(filess)) {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, bytesRead);
                        }
                    }*/
                    File file = inputStreamToFile(inputStream);
                    FileImageProvider fileImageProvider = new FileImageProvider(file);
                    //imagList.add(fileImageProvider); //---
                    TestPicVo testPicVo = new TestPicVo(fileImageProvider);
                    picVoList.add(testPicVo);
                }
                picNameVo1.setPicVoList(picVoList);
            }
            list.add(picNameVo1);

            context.put("data", list);
            fm.load("data", TestPicNameVo.class, true);
            //fm.addFieldAsImage("pic","pic", NullImageBehaviour.RemoveImageTemplate);
            fm.addFieldAsImage("pic","list1.pic", NullImageBehaviour.RemoveImageTemplate);
            //创建要替换的文本变量
            context.put("XCC_YEAR", String.valueOf(XCMap.get("xcc_year")));
            context.put("XCC_XXCS", String.valueOf(XCMap.get("xcc_xxcs")));
            context.put("XCC_XXRQ", String.valueOf(XCMap.get("xcc_xxrq")));
            context.put("XCC_XXSC", String.valueOf(XCMap.get("xcc_xxsc")));
            context.put("XCC_XXDD", String.valueOf(XCMap.get("xcc_xxdd")));
            context.put("XCC_CYCQL", String.valueOf(XCMap.get("xcc_cycql")));
            context.put("XCC_WCJRYJYY", String.valueOf(XCMap.get("xcc_wcjryjyy")));
            context.put("XCC_XCZP", String.valueOf(XCMap.get("xcc_xczp")));
            context.put("XCC_TBRLXR", String.valueOf(XCMap.get("xcc_tbrlxr")));
            context.put("XCC_LXRY", String.valueOf(XCMap.get("xcc_lxry")));
            context.put("XXZT", "学习专题");
            context.put("XXYC", "学习议程");

            //学习专题子表
            String getXXzt = "select * from SASIRMPROPAGANDAXXZT where PARENTID = '" + id + "'";
            List<Map<String, Object>> mapList = NativeQueryUtils.queryList(getXXzt);
            if (mapList.size() > 0) {
                List<LearningTopicsDto> propagandaxxzt = new ArrayList<>();
                for (int i = 0; i < mapList.size(); i++) {
                    LearningTopicsDto learningTopicsDto = new LearningTopicsDto();
                    String xxzt = ObjectUtils.isEmpty(mapList.get(i).get("xxzt").toString()) ? "" : mapList.get(i).get("xxzt").toString();
                    learningTopicsDto.setXXZT(xxzt);
                    propagandaxxzt.add(learningTopicsDto);
                }
                context.put("studentXXZT", propagandaxxzt);
                fm.load("studentXXZT", LearningTopicsDto.class, true);
            }

            //学习议程子表
            String getXXyc = "select * from SASIRMPROPAGANDAXXYC where PARENTID = '"+id+"'";
            List<Map<String, Object>> YcMapList = NativeQueryUtils.queryList(getXXyc);
            if(YcMapList.size()>0){
                ArrayList<LearningAgendaDto> propagandaxxyc = new ArrayList<>();
                for (int i = 0; i < YcMapList.size(); i++) {
                    LearningAgendaDto learningAgendaDto = new LearningAgendaDto();
                    String xxyc = ObjectUtils.isEmpty(YcMapList.get(i).get("xxyc").toString()) ? "" : YcMapList.get(i).get("xxyc").toString();
                    learningAgendaDto.setXXYC(xxyc);
                    propagandaxxyc.add(learningAgendaDto);
                }
                context.put("studentXXYC",propagandaxxyc);
                fm.load("studentXXYC",LearningAgendaDto.class,true);
            }

            //发言题目子表
            String getFYtm = "select * from SASIRMPROPAGANDAFYTM where PARENTID = '"+id+"'";
            List<Map<String, Object>> FyMapList = NativeQueryUtils.queryList(getFYtm);
            if(FyMapList.size() > 0){
                ArrayList<SpeechTitleDto> propagandafytm = new ArrayList<>();
                for (int i = 0; i < FyMapList.size(); i++) {
                    SpeechTitleDto speechTitleDto = new SpeechTitleDto();
                    String workZDFYMC = ObjectUtils.isEmpty(FyMapList.get(i).get("zdfymc").toString()) ? "" : FyMapList.get(i).get("zdfymc").toString();
                    String workFYTM = ObjectUtils.isEmpty(FyMapList.get(i).get("fytm").toString()) ? "" : FyMapList.get(i).get("fytm").toString();
                    speechTitleDto.setZDFYMC(workZDFYMC);
                    speechTitleDto.setFYTM(workFYTM);
                    propagandafytm.add(speechTitleDto);
                }
                context.put("studentFYTM",propagandafytm);
                fm.load("studentFYTM",SpeechTitleDto.class,true);
            }

            //输出到本地目录
            //FileOutputStream out = new FileOutputStream(new File("D://商品销售报表.docx"));
            //report.process(context, out);
            //浏览器端下载
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            RequestContextHolder.getRequestAttributes();
            HttpServletResponse response = ((ServletRequestAttributes)requestAttributes).getResponse();
            assert response != null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword;charset=utf-8");
//            response.setHeader("Content-Length", String.valueOf(bais.available()));
            response.addHeader("Content-Disposition", "attachment;filename= 记录表.docx");
            String fileName = "记录表.docx";
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
//            report.setFieldsMetadata(fm);
            report.process(context, response.getOutputStream());

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

还有个问题是导出多个图片,然后导出来的文件,用wps打开没问题,用word2019打开报无法读取内容,需要恢复,点击恢复后也能打开,然后用word2016打开得时候就直接报无法打开,报文件错误,求解答

  • 写回答

24条回答 默认 最新

  • 阿里嘎多学长 2024-05-30 10:14
    关注
    获得0.15元问题酬金

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    从您提供的描述和图片内容来看,您在使用xdocreport库生成Word文档时遇到了两个主要问题:

    1. 表格合并问题:您期望生成的Word文档中的表格应该与图【b26a8dfb-87ce-42ab-874a-1f757d1af585_353bb642f9ec435cb8074dfda05a4341.png】中的效果一致,但实际生成的效果与图【dd1b22a3-b988-40a9-b7a3-640cb0350292_94e62fba9b014f13a166cedd79bebe18.png】和图【8fd85d03-2a08-46cb-8d6a-274256a00b07_667e1eee2c984e45a775b0c3979cf8cf.png】不符。

    2. 图片插入问题:在生成的Word文档中插入多个图片后,使用WPS打开没有问题,但是使用Word 2019打开时会提示无法读取内容,需要恢复,而使用Word 2016打开时则直接报错,显示文件错误。

    针对这些问题,以下是一些可能的解决方案和建议:

    解决表格合并问题

    1. 检查模板:确保您的Word模板中的表格格式是正确的,特别是合并单元格的部分。

    2. 调整代码:在Java代码中,确保您正确地使用了xdocreport的API来处理表格合并。例如,使用XWPFTableXWPFTableCell类来创建和合并单元格。

    3. 使用正确的库版本:确保您使用的xdocreport库版本与您的Word版本兼容。

    4. 检查数据绑定:确保在数据绑定过程中,表格的数据被正确填充,并且合并逻辑与模板中的合并单元格相匹配。

    解决图片插入问题

    1. 图片格式:检查插入的图片格式是否被Word支持。有时,某些图片格式在不同版本的Word中可能不被支持。

    2. 图片大小:过大的图片可能会导致Word处理时出现问题。尝试调整图片大小或压缩图片。

    3. Word兼容性:Word的不同版本可能对图片的处理方式不同。尝试使用Word的“另存为”功能,将文档保存为较旧的格式,看是否能解决兼容性问题。

    4. 使用补丁或更新:检查是否有适用于xdocreport的补丁或更新,以解决图片插入的问题。

    代码实现示例

    // 示例代码,用于创建和合并单元格
    XWPFDocument document = ...; // 获取文档对象
    XWPFTable table = document.createTable(rows, cols); // 创建表格
    
    // 假设我们要合并第一行的前两个单元格
    XWPFTableCell cell1 = table.getRow(0).getCell(0);
    XWPFTableCell cell2 = table.getRow(0).getCell(1);
    cell1.setCTTc(new CTTc() {{
        setTcPr(new CTTcPr() {{
            setGridSpan(BigInteger.valueOf(2)); // 合并两个单元格
        }});
    }});
    
    // 插入图片
    XWPFParagraph paragraph = document.createParagraph();
    XWPFRun run = paragraph.createRun();
    run.addPicture(new FileInputStream("path/to/image"), 
                    XWPFDocument.PICTURE_TYPE_JPEG, 
                    "image.jpg", 
                    Units.toEMU(100), 
                    Units.toEMU(100));
    

    参考资料

    请注意,由于我无法直接访问外部链接,以上链接需要您自行验证。希望这些建议能帮助您解决问题。如果需要更具体的代码帮助,请提供更详细的代码片段或错误信息。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 6月7日
  • 修改了问题 5月30日
  • 创建了问题 5月30日

悬赏问题

  • ¥15 Stata链式中介效应代码修改
  • ¥15 latex投稿显示click download
  • ¥15 请问读取环境变量文件失败是什么原因?
  • ¥15 在若依框架下实现人脸识别
  • ¥15 添加组件无法加载页面,某块加载卡住
  • ¥15 网络科学导论,网络控制
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错