poi操作word,指定位置替换为jfreechart统计图表或者大家可以看下poi-tl

2023-01-02 00:00:00 指定 替换 图表

转载:https://www.cnblogs.com/zwdx/p/8403946.html

亲测成功!!!!!!!!!

我这里用的是饼图
各种图生成:https://blog.csdn.net/ntotl/article/details/78225974

首先谢谢这位博主,帮了很大的忙,正好有个需求是根据word模板,生成word文档,其中还需要固定位置插入统计图。
前期我也找了很多文章,都是重写CustomXWPFDocument类,把图片写为xml,在写入word中,但是其中一直有个报错,

org.apache.poi.openxml4j.exceptions.InvalidOperationException: Can’t open the specified file: ‘G:\test.docx’
at org.apache.poi.openxml4j.opc.ZipPackage.(ZipPackage.java:102)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:199)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:178)
at org.apache.poi.POIXMLDocument.openPackage(POIXMLDocument.java:62)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.(XSSFWorkbook.java:188)
at POIExcelTools.readExcelToUserVoByPoi(POIExcelTools.java:36)
at POIExcelTools.main(POIExcelTools.java:59)

不知道为啥,最后也没解决。

记录一下这位博主写的。

pom.xml 依赖

		<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-excelant</artifactId>
            <version>3.12</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.12</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.8</version>
        </dependency>
        <!-- 生成图片-->
        <dependency>
            <groupId>org.jfree</groupId>
            <artifactId>jfreechart</artifactId>
            <version>1.0.19</version>
        </dependency>
        <dependency>
            <!--支持插入图片-->
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j</artifactId>
            <version>3.3.1</version>
        </dependency>

示例:
《poi操作word,指定位置替换为jfreechart统计图表或者大家可以看下poi-tl》如上图,需要替换的字符串地方“$1”为“1231”,预先在word中的某一位置插入书签名为test,并将test书签位置替换为jfreechart生成的统计图片

《poi操作word,指定位置替换为jfreechart统计图表或者大家可以看下poi-tl》

demo:

package com.tyxx.test;

import com.google.common.collect.Maps;
import com.tyxx.util.Image;
import com.tyxx.util.WordText;
import java.util.Map;

public class ExportBgServiceImpl {
    public static void main(String[] args) throws Exception {
        Map<String, String> map = Maps.newHashMap();
        map.put("$1", "1231");
        WordText.textReplace(map);
        Map<String, Integer> mapImage = Maps.newHashMap();
        mapImage.put("啊啊啊啊", 789);
        mapImage.put("11111", 123);
        Image.createImage(mapImage);
        Image.insertImage();
    }

}

替换word文本内容

package com.tyxx.util;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 替换word中的文本内容
 * 2019-5-28
 */
public class WordText {

    /**
     * 模板文件所在位置
     */
    public static final String FILE_PATH = "";

    /**
     * 新生成文件位置
     */
    public static final String FILE_PATH_NEW = "";

    /**
     * 替换word模板中的文本内容,生成新文件
     * @param map 根据键替换值
     * @return
     */
    public static boolean textReplace(Map<String, String> map) {
        XWPFDocument document = null;
        FileOutputStream outStream = null;
        try {
            document = new XWPFDocument(POIXMLDocument.openPackage("G://wordtest//abc.docx"));
            Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
            while (itPara.hasNext()) {
                XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
                List<XWPFRun> runs = paragraph.getRuns();
                for (int i = 0; i < runs.size(); i++) {
                    String oneparaString = runs.get(i).getText(runs.get(i).getTextPosition()).trim();
                    for (Map.Entry<String, String> entry : map.entrySet()) {
                        if (oneparaString.equals(entry.getKey())) {
                            oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
                        }

                    }
                    runs.get(i).setText(oneparaString, 0);
                }
            }
            outStream = new FileOutputStream("G://wordtest//test1.docx");
            document.write(outStream);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                outStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

}

图片生成和插入

package com.tyxx.util;

import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.wml.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.data.general.DefaultPieDataset;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;

/**
 * 生成图片和插入图片
 */
public class Image {

    /**
     * 生成图片
     * @param map 统计图,键值对
     * @return
     */
    public static boolean createImage(Map<String, Integer> map){
        DefaultPieDataset dataset = new DefaultPieDataset();
        if (!map.isEmpty()){
            for (Map.Entry<String, Integer> entry : map.entrySet()){
                // 图表添加数据标注
                dataset.setValue(entry.getKey(), entry.getValue());     // dataset.setValue("修改类", 1);dataset.setValue("提示类", 1);
            }
        } else {
            System.out.println("图表数据空!");
            return false;
        }
        JFreeChart chart = ChartFactory.createPieChart3D(
            null,
            dataset,
            true,
            false,
            false
        );
        // 设置外层图片 无边框 无背景色 背景图片透明
        chart.setBorderVisible(false);
        chart.setBackgroundPaint(null);
        chart.setBackgroundImageAlpha(0.0f);
        chart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 20)); // 设置图例类别字体
        // TextTitle title = new TextTitle(titleString);
        // title.setFont(new Font("黑体", Font.ITALIC, 20));//设置标题字体
        // chart.setTitle(title);
        //chart.setBackgroundPaint(Color.red);      // 设定背景

        PiePlot piePlot = (PiePlot) chart.getPlot();
        piePlot.setOutlinePaint(Color.white); // 设置绘图面板外边的填充颜色
        piePlot.setShadowPaint(Color.white); // 设置绘图面板阴影的填充颜色
        //设置边框的颜色
        piePlot.setBaseSectionOutlinePaint(Color.green);
        //设置边框的粗细,new BasicStroke(2.0f)
        piePlot.setBaseSectionOutlineStroke(new BasicStroke(1));
        //指定 section 的色彩
        // 或者  piePlot.setSectionPaint("key", new Color(0xF7, 0x79, 0xED));     key为图例数据的key
        piePlot.setSectionPaint(0, new Color(48, 72, 247));
        piePlot.setSectionPaint(1, new Color(255, 114, 49));
        DecimalFormat df = new DecimalFormat("0.00%");
        NumberFormat nf = NumberFormat.getInstance();
        // 获得StandardPieSectionLabelGenerator对象,生成的格式,
        // {0}表示section名,{1}表示section的值,{2}表示百分比。可以自定义
        StandardPieSectionLabelGenerator generator = new StandardPieSectionLabelGenerator("{0} {2}", nf, df);
        piePlot.setLabelGenerator(generator);// 设置百分比
        piePlot.setLabelFont(new Font("黑体", Font.ITALIC, 20));  // 设置饼图中类别字体
        piePlot.setForegroundAlpha(0.5F);   // 饼图的透明度
        piePlot.setBackgroundAlpha(0.5F);   // 饼图的背景全透明
        piePlot.setLabelBackgroundPaint(new Color(255, 255, 255));    // 外引导线背景色

        piePlot.setNoDataMessage("此时并没有任何数据可用");    // 加数据空,显示效果
        piePlot.setCircular(false);
        piePlot.setLabelGap(0.02D);

        piePlot.setIgnoreNullValues(true);  // 设置不显示空位
        piePlot.setIgnoreZeroValues(true);  // 设置不显示负值或零值

        String tpPath = "G://pie.png";
        File file = new File(tpPath);
        if (file.exists()) {
            file.delete();
        }

        try {
            ChartUtilities.saveChartAsPNG(file, chart, 800, 500);       // 保存图片
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * word预先书签的位置,插入生成的图片
     * @return
     */
    public static boolean insertImage(){
        File file2 = null;
        WordprocessingMLPackage wPackage = null;
        try {
            file2 = new File("G://wordtest//test1.docx");
            wPackage = WordprocessingMLPackage.load(new FileInputStream(file2));
            MainDocumentPart mainDocumentPart = wPackage.getMainDocumentPart();
            Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
            Body body = wmlDoc.getBody();
            // 提取正文中所有段落
            java.util.List<Object> paragraphs = body.getContent();
            // 提取书签并创建书签的游标
            RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
            new TraversalUtil(paragraphs, rt);
            for (CTBookmark bm : rt.getStarts()) {
                if (bm.getName().equals("test")) {//  这里的test为  word文档中预设的 书签名
                    BufferedImage image = ImageIO.read(new File("G://pie.png"));   // 图片路径
                    //下面为在图片上插入字符串 

                    // Graphics g = image.getGraphics();
                    // 设置颜色
                    // g.setColor(Color.black);

                    // 设置字体
                    //java.awt.Font mFont = new java.awt.Font("Arial", java.awt.Font.PLAIN, 11);// 默认字体
                    // g.setFont(mFont);

                    // 输出文字,不能传入null
                    // g.drawString(jzcsyl==null?"0":jzcsyl, 377, 19);
                    // g.drawString(zzcjll==null?"0":zzcjll, 181, 99);
                    byte[] bytes = ChartUtilities.encodeAsPNG(image);
                    BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
                    Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 10000);//这里的100000不是正常屏幕大小,用于设置插入图片的大小
                    P p = (P) (bm.getParent());

                    ObjectFactory factory = new ObjectFactory();
                    // R对象是匿名的复杂类型,然而我并不知道具体啥意思,估计这个要好好去看看ooxml才知道
                    R run = factory.createR();
                    // drawing理解为画布?
                    Drawing drawing = factory.createDrawing();

                    drawing.getAnchorOrInline().add(inline);
                    run.getContent().add(drawing);
                    p.getContent().add(run);
                }
            }
            wPackage.save(new FileOutputStream(new File("G://wordtest//test1.docx")));
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

}

效果:
模板文档:
《poi操作word,指定位置替换为jfreechart统计图表或者大家可以看下poi-tl》
效果文档:
《poi操作word,指定位置替换为jfreechart统计图表或者大家可以看下poi-tl》

    原文作者:java小菜机
    原文地址: https://blog.csdn.net/zk_1325572803/article/details/90632212
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。

相关文章