JfreeChart生成统计图,导出word文档

本文介绍了一个实用的工具类,用于生成各种类型的统计图表(如饼图、柱状图等),并将其整合到Word文档中。该工具利用Java的JFreeChart库生成图表,并通过Apache POI库将图表插入到Word文档内。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.zhxg.zhsq.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableCell.XWPFVertAlign;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DefaultDrawingSupplier;
import org.jfree.chart.plot.PieLabelLinkStyle;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.TextAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;

import com.zhxg.zhsq.common.api.JsonResponse;
import com.zhxg.zhsq.vo.BarChart;
import com.zhxg.zhsq.vo.LineChart;
import com.zhxg.zhsq.vo.PieChart;
import com.zhxg.zhsq.vo.PieChartSeriesData;

/**
 * 生成饼图、环形、柱状、线型、面积等统计图片
 * Utils:poi生成word工具类
 * @author zyl
 * @date 2017-09-20
 */
public class JfreeChartUtil {
    private static final String FILE_OUT_PUT_PATH = "D://";
    private static final Logger log = LoggerFactory.getLogger(JfreeChartUtil.class);
    private static String NO_DATA_MSG = "数据加载失败";
    private static Font FONT = new Font("宋体", Font.PLAIN, 10);
    private static Font FONT_BOLD = new Font("宋体",Font.BOLD+Font.PLAIN,20);
    public static Color[] CHART_COLORS = {
        new Color(31,129,188), new Color(92,92,97), new Color(144,237,125), new Color(255,188,117),
        new Color(153,158,255), new Color(255,117,153), new Color(253,236,109), new Color(128,133,232),
        new Color(158,90,102),new Color(255, 204, 102)};//颜色
    static {
        setChartTheme();
    }
    /**
     * 中文主题样式 解决乱码
     */
    public static void setChartTheme() {
        // 设置中文主题样式 解决乱码
        StandardChartTheme chartTheme = new StandardChartTheme("CN");
        // 设置标题字体,加粗
        chartTheme.setExtraLargeFont(FONT_BOLD);
        // 设置图例的字体
        chartTheme.setRegularFont(FONT);
        // 设置轴向的字体
        chartTheme.setLargeFont(FONT);
        
        chartTheme.setSmallFont(FONT);
        chartTheme.setTitlePaint(new Color(51, 51, 51));
        chartTheme.setSubtitlePaint(new Color(85, 85, 85));

        chartTheme.setLegendBackgroundPaint(Color.WHITE);// 设置标注
        chartTheme.setLegendItemPaint(Color.BLACK);//
        chartTheme.setChartBackgroundPaint(Color.WHITE);
        // 绘制颜色绘制颜色.轮廓供应商
        // paintSequence,outlinePaintSequence,strokeSequence,outlineStrokeSequence,shapeSequence

        Paint[] OUTLINE_PAINT_SEQUENCE = new Paint[] { Color.WHITE };
        // 绘制器颜色源
        DefaultDrawingSupplier drawingSupplier = new DefaultDrawingSupplier(CHART_COLORS, CHART_COLORS, OUTLINE_PAINT_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
                DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
        chartTheme.setDrawingSupplier(drawingSupplier);

        chartTheme.setPlotBackgroundPaint(Color.WHITE);// 绘制区域
        chartTheme.setPlotOutlinePaint(Color.WHITE);// 绘制区域外边框
        chartTheme.setLabelLinkPaint(new Color(8, 55, 114));// 链接标签颜色
        chartTheme.setLabelLinkStyle(PieLabelLinkStyle.CUBIC_CURVE);

        chartTheme.setAxisOffset(new RectangleInsets(5, 12, 5, 12));
        chartTheme.setDomainGridlinePaint(new Color(192, 208, 224));// X坐标轴垂直网格颜色
        chartTheme.setRangeGridlinePaint(new Color(192, 192, 192));// Y坐标轴水平网格颜色

        chartTheme.setBaselinePaint(Color.WHITE);
        chartTheme.setCrosshairPaint(Color.BLUE);// 不确定含义
        chartTheme.setAxisLabelPaint(new Color(51, 51, 51));// 坐标轴标题文字颜色
        chartTheme.setTickLabelPaint(new Color(67, 67, 72));// 刻度数字
        chartTheme.setBarPainter(new StandardBarPainter());// 设置柱状图渲染
        chartTheme.setXYBarPainter(new StandardXYBarPainter());// XYBar 渲染

        chartTheme.setItemLabelPaint(Color.black);
        chartTheme.setThermometerPaint(Color.white);// 温度计

        ChartFactory.setChartTheme(chartTheme);
    }
    
    /**
     * 获取饼状图
     * @param title  标题
     * @param data  饼状体数据集
     * @param is3D   是否3D生成
     */
    public static JFreeChart getPieChart(String title,PieChart data,boolean is3D){
        DefaultPieDataset dataset = new DefaultPieDataset();
        for(PieChartSeriesData data_ : data.getOpinionData()){
            String name = data_.getName();
            Integer value = data_.getValue();
            dataset.setValue(name, value);
        }
        //创建 Jfreechart对象  
        JFreeChart jfreechart = null;
        if(is3D){
            jfreechart = ChartFactory.createPieChart3D(title, dataset, true, true, false);
        }else{
            jfreechart = ChartFactory.createPieChart(title, dataset, true, true, false);
        }
        //设置文本抗锯齿
        jfreechart.setTextAntiAlias(false);
        PiePlot piePlot = (PiePlot) jfreechart.getPlot();  
        piePlot.setNoDataMessage(NO_DATA_MSG);
        piePlot.setInsets(new RectangleInsets(0, 0, 0, 0));
        piePlot.setCircular(true);// 圆形

        piePlot.setLabelGap(0.01);
        piePlot.setInteriorGap(0.05D);
        piePlot.setLegendItemShape(new Rectangle(10, 10));// 图例形状
        //去掉背景色
        piePlot.setLabelBackgroundPaint(null);
        //去掉阴影
        piePlot.setLabelShadowPaint(null);
        //去掉边框
        piePlot.setLabelOutlinePaint(null);
        piePlot.setShadowPaint(null);
        //设置Pie的边框是否可见  
        piePlot.setSectionOutlinesVisible(false);  
        // 指定图片的透明度(0.0-1.0)  
        piePlot.setForegroundAlpha(1.0f);
        //设置边框的颜色  
        piePlot.setBaseSectionOutlinePaint(Color.green);
        //设置边框的粗细,new BasicStroke(2.0f)  
        piePlot.setBaseSectionOutlineStroke(new BasicStroke(1));  
        //设置空值,0值,负值是否显示出来,如果显示的话就是false  
        piePlot.setIgnoreNullValues(true);  
        piePlot.setIgnoreZeroValues(true);
        //设置上面的样式,0表示KEY,1表示VALUE,2表示百分之几,DecimalFormat用来显示百分比的格式  
        piePlot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{2}",NumberFormat.getNumberInstance(),new DecimalFormat("0.00%")));  
        //设置下面方框的样式,0表示KEY,1表示VALUE,2表示百分之几,DecimalFormat用来显示百分比的格式  
        piePlot.setLegendLabelGenerator(new StandardPieSectionLabelGenerator("{0}({1},{2})",NumberFormat.getNumberInstance(),   new DecimalFormat("0.00%")));
        //爆炸模式,使Pie的一块分离出去,不支持3D  piePlot.setExplodePercent("正面", 0.10);
        
        return jfreechart;
    }
    
    /**
     * 获取折线图
     * @param title  标题
     * @param data  折线图数据集
     * @param is3D   是否3D生成
     */
    public static JFreeChart getLineChart(String title,LineChart data,boolean is3D){
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        List<String> navdata = data.getNavdata();
        List<String> xAxisdata = data.getxAxisdata();
        for(int i = 0;i < navdata.size();i++){
            String navName = navdata.get(i);
            List<Integer> dataList = data.getOpinionData().get(i).getData();
            for(int j = 0; j< xAxisdata.size();j++){
                String date = xAxisdata.get(j);
                Integer count = dataList.get(j);
                dataset.setValue(count, navName, String.valueOf(date));
            }
        }
        //创建 Jfreechart对象  
        JFreeChart jfreechart = null;
        if(is3D){
            jfreechart = ChartFactory.createLineChart3D(title,
                "时间", //横坐标名称
                "数量", //纵坐标名称
                dataset,//数据
                PlotOrientation.VERTICAL, //垂直视图
                true, //include legend
                true, //tooltips
                false
            );
        }else{
            jfreechart = ChartFactory.createLineChart(title,
                "时间", //横坐标名称
                "数量", //纵坐标名称
                dataset,//数据
                PlotOrientation.VERTICAL, //垂直视图
                true, //include legend
                true, //tooltips
                false
            );
        }
        
        //设置文本抗锯齿
        jfreechart.setTextAntiAlias(false);
        CategoryPlot plot = jfreechart.getCategoryPlot();
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setRangeGridlinesVisible(true); //是否显示格子线
        plot.setBackgroundAlpha(0.3f); //设置背景透明度
        NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        rangeAxis.setAutoRangeIncludesZero(true);
        rangeAxis.setUpperMargin(0.10);
        rangeAxis.setLabelAngle(Math.PI / 2.0);
        
        // 数据渲染部分 主要是对折线做操作
        LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
        renderer.setBaseItemLabelsVisible(true);
        renderer.setBaseShapesFilled(true);
        renderer.setBaseItemLabelsVisible(true);     
        renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_LEFT));
        renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());  
        plot.setRenderer(renderer);
        return jfreechart;
    }
    
    /**
     * 获取柱状图
     * @param title  标题
     * @param data   柱状图数据集
     * @param is3D   是否3D生成
     */
    public static JFreeChart getBarChart(String title,BarChart data,boolean is3D){
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        List<String> navdata = data.getNavdata();
        List<String> xAxisdata = data.getxAxisdata();
        for(int i = 0;i < navdata.size();i++){
            String navName = navdata.get(i);
            List<Integer> dataList = data.getOpinionData().get(i).getData();
            for(int j = 0; j< xAxisdata.size();j++){
                String date = xAxisdata.get(j);
                Integer count = dataList.get(j);
                dataset.setValue(count, navName, String.valueOf(date));
            }
        }
        //创建 Jfreechart对象  
        JFreeChart jfreechart = null;
        if(is3D){
            jfreechart = ChartFactory.createBarChart3D(title,
                "时间", //横坐标名称
                "数量", //纵坐标名称
                dataset,//数据
                PlotOrientation.VERTICAL, //垂直视图
                true, //include legend
                true, //tooltips
                false
            );
        }else{
            jfreechart = ChartFactory.createBarChart(title,
                "时间", //横坐标名称
                "数量", //纵坐标名称
                dataset,//数据
                PlotOrientation.VERTICAL, //垂直视图
                true, //include legend
                true, //tooltips
                false
            );
        }
        //设置文本抗锯齿
        jfreechart.setTextAntiAlias(false);
        CategoryPlot plot = jfreechart.getCategoryPlot();
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setInsets(new RectangleInsets(10, 10, 5, 10));
        plot.setRangeGridlinesVisible(true); //是否显示格子线
        plot.setBackgroundAlpha(0.3f); //设置背景透明度
        //对y轴操作
        NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        //上边距
        rangeAxis.setUpperMargin(0.10);
        //字体倾斜度
        rangeAxis.setLabelAngle(Math.PI / 2.0);
        
        BarRenderer renderer = (BarRenderer) plot.getRenderer();
        renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
        renderer.setMaximumBarWidth(0.075);// 设置柱子最大宽度
        renderer.setBaseItemLabelsVisible(true);
        //显示数字和数字显示的位置
        renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.TOP_CENTER));  
        renderer.setItemLabelAnchorOffset(20D);
        return jfreechart;
    }
    
    /**
     *获取面积图
     * @param title  标题
     * @param data  数据集
     * @param is3D   是否3D生成
     */
    public static JFreeChart getAreaChart(String title,LineChart data){
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        List<String> navdata = data.getNavdata();
        List<String> xAxisdata = data.getxAxisdata();
        for(int i = 0;i < navdata.size();i++){
            String navName = navdata.get(i);
            List<Integer> dataList = data.getOpinionData().get(i).getData();
            for(int j = 0; j< xAxisdata.size();j++){
                String date = xAxisdata.get(j);
                Integer count = dataList.get(j);
                dataset.setValue(count, navName, String.valueOf(date));
            }
        }
        //创建 Jfreechart对象  
        JFreeChart jfreechart = ChartFactory.createAreaChart(title,
            "时间", //横坐标名称
            "数量", //纵坐标名称
            dataset,//数据
            PlotOrientation.VERTICAL, //垂直视图
            true, //include legend
            true, //tooltips
            false
        );
        //设置文本抗锯齿
        jfreechart.setTextAntiAlias(false);
        CategoryPlot plot = jfreechart.getCategoryPlot();
        plot.setNoDataMessage(NO_DATA_MSG);
        plot.setRangeGridlinesVisible(true); //是否显示格子线
        plot.setBackgroundAlpha(0.3f); //设置背景透明度
        NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        rangeAxis.setAutoRangeIncludesZero(true);
        rangeAxis.setUpperMargin(0.10);
        rangeAxis.setLabelAngle(Math.PI / 2.0);
        
        return jfreechart;
    }
    
    /**
     * 获取环形图
     * @param title  标题
     * @param data  数据集
     * @param is3D   是否3D生成
     */
    public static JFreeChart getRingChart(String title,PieChart data){
        DefaultPieDataset dataset = new DefaultPieDataset();
        for(PieChartSeriesData data_ : data.getOpinionData()){
            String name = data_.getName();
            Integer value = data_.getValue();
            dataset.setValue(name, value);
        }
        //创建 Jfreechart对象  
        JFreeChart jfreechart = ChartFactory.createRingChart(title, dataset, true, true, false);
        //设置文本抗锯齿
        jfreechart.setTextAntiAlias(false);
        PiePlot piePlot = (PiePlot) jfreechart.getPlot();  
        piePlot.setNoDataMessage(NO_DATA_MSG);
        piePlot.setInsets(new RectangleInsets(0, 0, 0, 0));
        piePlot.setCircular(true);// 圆形

        piePlot.setLabelGap(0.01);
        piePlot.setInteriorGap(0.05D);
        piePlot.setLegendItemShape(new Rectangle(10, 10));// 图例形状
        //去掉背景色
        piePlot.setLabelBackgroundPaint(null);
        //去掉阴影
        piePlot.setLabelShadowPaint(null);
        //去掉边框
        piePlot.setLabelOutlinePaint(null);
        piePlot.setShadowPaint(null);
        //设置Pie的边框是否可见  
        piePlot.setSectionOutlinesVisible(false);  
        // 指定图片的透明度(0.0-1.0)  
        piePlot.setForegroundAlpha(1.0f);
        //设置边框的颜色  
        piePlot.setBaseSectionOutlinePaint(Color.green);
        //设置边框的粗细,new BasicStroke(2.0f)  
        piePlot.setBaseSectionOutlineStroke(new BasicStroke(1));  
        //设置空值,0值,负值是否显示出来,如果显示的话就是false  
        piePlot.setIgnoreNullValues(true);  
        piePlot.setIgnoreZeroValues(true);
        //设置上面的样式,0表示KEY,1表示VALUE,2表示百分之几,DecimalFormat用来显示百分比的格式  
        piePlot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{2}",NumberFormat.getNumberInstance(),new DecimalFormat("0.00%")));  
        //设置下面方框的样式,0表示KEY,1表示VALUE,2表示百分之几,DecimalFormat用来显示百分比的格式  
        piePlot.setLegendLabelGenerator(new StandardPieSectionLabelGenerator("{0}({1},{2})",NumberFormat.getNumberInstance(),   new DecimalFormat("0.00%")));
        //爆炸模式,使Pie的一块分离出去,不支持3D  
        //piePlot.setExplodePercent("正面", 0.10);  
        return jfreechart;
    }
    
    /**
     * 获取图片流
     * @param jfreechart
     * @param weight
     * @param height
     * @return
     */
    public static InputStream getChartStream(JFreeChart jfreechart,int weight, int height){
        InputStream input = null;
        try {
            BufferedImage bufferedImage = jfreechart.createBufferedImage(weight, height);
            ByteArrayOutputStream os = new ByteArrayOutputStream();  
            ImageIO.write(bufferedImage, "png", os);
            input = new ByteArrayInputStream(os.toByteArray());  
        } catch (Exception e) {
            e.printStackTrace();
            log.info("------------------------------------" + e.getMessage());
        }
        return input;
        
    }
    /**
     * 保存为文件
     * @param chart
     * @param fileName
     * @param weight
     * @param height
     * @throws Exception
     */
    public static void saveAsFile(JFreeChart chart, String fileName,int weight, int height) {      
        FileOutputStream out = null;      
        File outFile = new File(FILE_OUT_PUT_PATH + fileName);      
        if (!outFile.getParentFile().exists()) {      
            outFile.getParentFile().mkdirs();      
        }      
        try {
            out = new FileOutputStream(FILE_OUT_PUT_PATH + fileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            log.info("------------------------------------" + e.getMessage());
        }      
        // 保存为PNG      
        try {
            ChartUtilities.writeChartAsPNG(out, chart, weight, height);
        } catch (IOException e) {
            e.printStackTrace();
            log.info("------------------------------------" + e.getMessage());
        }finally{
            try {
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }  
    }
    
    //比较器类  
    static class MapValueComparator implements Comparator<Map.Entry<String, String>> {  
        public int compare(Entry<String, String> me1, Entry<String, String> me2) {  
            return me1.getValue().compareTo(me2.getValue());  
        }  
    }  
    /**
     * poi生成word工具类
     * @author zyl
     *
     */
    public static class Utils{
        private static final String FONT_FAMILY = "宋体";//字体类型
        private static final int DOC_NAME = 20;//文档名称
        private static final int FONT_TITLE_1 = 18;//一级标题文字大小
        private static final int FONT_TITLE_2 = 10;//二级标题文字大小
        private static final int FONT_SIZE = 10;//正文字体大小
        private static final String HEAD_BG_COLOR = "ffff66";//表格标题背景颜色
        private static final int HR_HEIGHT = 300;//表格行高
        private static final int IMG_WIDTH = 600;//图片宽度
        private static final int IMG_HEIGHT = 400;//图片高度
        
        /**
         * 为段落添加内容
         * @param p  当前段落
         * @param isBold  是否加粗
         * @param fontSize  字体大小
         * @param text  文本内容
         * @param isBreak  是否换行
         */
        public static void addText(XWPFParagraph p,String text,boolean isBold,int fontSize,String fontColor,boolean isBreak){
            XWPFRun run = p.createRun();
            run.setFontSize(fontSize == 0 ? FONT_SIZE : fontSize);
            run.setText(text);
            run.setFontFamily(FONT_FAMILY);
            if(fontColor != null && !"".equals(fontColor))
                run.setColor(fontColor);
            run.setBold(isBold);
            if(isBreak)
                run.addBreak();
        }
        /**
         * 添加正文内容和颜色
         * @param p
         * @param colors
         * @param content
         * @param isBreak
         */
        public static void addText(XWPFParagraph p,Map<String,String> colors,String content,boolean isBreak){
            //关键词位置
            if(colors != null && !colors.isEmpty() && content != null && !"".equals(content)){
                int curPos = 0;
                String curStr = content;
                for(String key : colors.keySet()){
                    String color = colors.get(key);
                    Integer pos = curStr.indexOf(key);
                    if(pos < 0){
                        continue;
                    }
                    //添加文本
                    Utils.addText(p, curStr.substring(curPos, pos), false, Utils.FONT_SIZE, "", false);
                    //添加文本
                    Utils.addText(p,curStr.substring(pos, (pos + key.length()) > curStr.length() ? curStr.length() : (pos + key.length())), true, Utils.FONT_SIZE,color, false);
                    curStr= curStr.substring(pos + key.length());
                }
                if(curStr != null && !"".equals(curStr))
                    Utils.addText(p,curStr, false, Utils.FONT_SIZE,"", isBreak);
                
            }else{
                Utils.addText(p,content, false, Utils.FONT_SIZE,"", isBreak);
            }
        }
        
        /**  添加正文
         * @param p
         * @param content
         * @param isBreak
         */
        public static void addText(XWPFParagraph p,String content,boolean isBreak){
            Utils.addText(p,content, false, Utils.FONT_SIZE,"", isBreak);
          }
        
        /**
         * 文档添加表格
         * @param p
         * @param rows
         * @param cols
         * @param dataset  key:类型,value:类型的数据
         */
        public static void addTable(XWPFParagraph p,int w,String[][] dataset){
            if(dataset.length == 0){
                return;
            }
            int rows = dataset.length;
            int cols = dataset[0].length;
            //创建表格
            XWPFTable table= p.getDocument().createTable(rows, cols);
            
            CTTbl ttbl = table.getCTTbl();  
            CTTblPr tblPr = ttbl.getTblPr() == null ? ttbl.addNewTblPr() : ttbl.getTblPr();  
            CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW();  
            CTJc cTJc=tblPr.addNewJc();  
            cTJc.setVal(STJc.Enum.forString("center"));  
            tblWidth.setW(new BigInteger(String.valueOf(w == 0 ? 8000 : w)));  
            tblWidth.setType(STTblWidth.DXA);
            
            
            //设置表格行高
            for(XWPFTableRow  row : table.getRows()){
                row.setHeight(HR_HEIGHT);
            }
            //设置表格数据
            for(int i= 0;i < dataset.length;i++){
                for(int j = 0;j < dataset[i].length;j++){
                    if(i == 0){
                        //填充表头数据
                        Utils.addCell(table.getRow(i),j, dataset[i][j], Utils.HEAD_BG_COLOR,"", 9, true);
                    }else{
                        Utils.addCell(table.getRow(i),j,dataset[i][j], "","", 9, false);
                    }
                }
            }
            
            //删除第一列
            for(XWPFTableRow r : table.getRows()){
                r.removeCell(0);
            }
            
        }
        /**
         * 添加单元格
         * @param r  当前行
         * @param index 列索引
         * @param text  文本内容
         * @param cellColor  单元格背景颜色
         * @param textColor  单元格文本颜色
         * @param fontSize   单元格文字大小
         * @param isBold  是否加粗
         */
        public static void addCell(XWPFTableRow r,int index,String text,String cellColor,String textColor,int fontSize,boolean isBold){
            XWPFTableCell cell = r.getCell(index);
            cell.setVerticalAlignment(XWPFVertAlign.CENTER);
            if(cellColor != null && !"".equals(cellColor))
                cell.setColor(cellColor);
            XWPFParagraph xp = cell.addParagraph();
            xp.setAlignment(ParagraphAlignment.CENTER);
            cell.removeParagraph(0);
            XWPFRun xpRun = xp.createRun();
            xpRun.setBold(isBold);
            xpRun.setText(text);
            xpRun.setFontSize(fontSize == 0 ? FONT_SIZE : fontSize );
            if(textColor != null && !"".equals(textColor))
                xpRun.setColor(textColor);
        }
        /**
         * 添加图片
         * @param doc    文档对象
         * @param input  图片流
         * @param width  图片宽度
         * @param height 图片高度
         */
        public static void addImage(CustomXWPFDocument doc,InputStream input,int width,int height){
            //创建空的段落
            XWPFParagraph p = doc.createParagraph();
            try {
                doc.addPictureData(input, XWPFDocument.PICTURE_TYPE_PNG);
                doc.createPicture(p,doc.getAllPictures().size()-1, width, height,"");
            } catch (InvalidFormatException e) {
                
                e.printStackTrace();
            }
        }
        /**
         * 添加文档概括信息
         * @param doc 文档对象
         * @param dataset 数据集
         */
        public static void addSummary(CustomXWPFDocument doc,Map<String,String> colors,Map<String,String> dataset){
            if(dataset == null || dataset.isEmpty()) return;
            XWPFParagraph p  = doc.createParagraph();
            p.setAlignment(ParagraphAlignment.LEFT);
            for(String key : dataset.keySet()){
                String[] array = dataset.get(key).split("\n");
                addText(p, key+":", true, FONT_SIZE, "", array.length > 1 ? true : false);
                for(String str : array){
                    StringBuilder sb = new StringBuilder("");
                    if(array.length > 1){
                        for(int j = 1;j < 4;j++){//缩进两个字符
                            sb.append(" ");
                        }
                    }
                    sb.append(str);
                    if(array.length > 1)
                        addText(p, colors,sb.toString(),true);
                    else addText(p,sb.toString(),true);
                }
            }
        }
        /**
         * 添加文档标题
         * @param doc  文档对象
         * @param title  标题名称
         */
        public static void addTitle(CustomXWPFDocument doc,String title){
            if(title == null || "".equals(title)) return;
            XWPFParagraph p  = doc.createParagraph();
            p.setAlignment(ParagraphAlignment.CENTER);
            addText(p, title, true, DOC_NAME, "", false);
        }
        /**
         * 添加段落
         * @param doc  当前文档
         * @param text  内容
         * @param isBold 是否加粗
         * @param isBreak 是否换行
         * @param position 对齐方式
         */
        public static XWPFParagraph addParagraph(CustomXWPFDocument doc,String text,boolean isBold,boolean isBreak,ParagraphAlignment position){
            XWPFParagraph p  = doc.createParagraph();
            p.setAlignment(position == null ? ParagraphAlignment.CENTER : position);
            if(text != null && !"".equals(text))
                addText(p,text, isBold, FONT_SIZE, "", isBreak);
            return p;
        }
        /**  添加一级段落
         * @param doc  当前文档对象
         * @param title 段落内容
         * @param index 段落索引
         */
        public static XWPFParagraph addParagraphLevel1(CustomXWPFDocument doc,String text,String index){
            XWPFParagraph p  = doc.createParagraph();
            p.setAlignment(ParagraphAlignment.LEFT);
            addText(p, index + "."+text, true, FONT_TITLE_1, "", false);
            return p;
        }
        /**  添加二级段落
         * @param doc  当前文档对象
         * @param title 段落内容
         * @param index 段落索引
         */
        public static XWPFParagraph addParagraphLevel2(CustomXWPFDocument doc,String text,String index){
            XWPFParagraph p  = doc.createParagraph();
            p.setAlignment(ParagraphAlignment.LEFT);
            addText(p, index + "."+text, true, FONT_TITLE_2, "", true);
            return p;
        }
        
        /**
         *  
         * @param doc  当前文档
         * @param name  二级标题名称
         * @param index  二级标题索引
         * @param content 文本内容
         * @param dataset 表格数据集
         * @param img  图片集
         */
        public static void addPart(CustomXWPFDocument doc,String name,String index,String content,Map<String,String> colors,Map<String,String[][]> dataset,Map<String,InputStream> img){
            //添加二级段落
            XWPFParagraph para1 = Utils.addParagraphLevel2(doc, name,index);
            if(content != null && !"".equals(content)){
                //添加文本内容
                Utils.addText(para1, colors, content,false);
            }
            if(dataset != null && dataset.size() > 0){
                for(String key : dataset.keySet()){
                    //添加居中段落
                    Utils.addParagraph(doc, key, false, false,ParagraphAlignment.CENTER);
                    //添加表格
                    Utils.addTable(para1, 8000, dataset.get(key));
                }
            }
            if(img != null && !img.isEmpty()){
                for(String key : img.keySet()){
                    Utils.addImage(doc,img.get(key),IMG_WIDTH,IMG_HEIGHT);
                    Utils.addParagraph(doc,key, false, false,ParagraphAlignment.CENTER);
                }
            }
        }
        /**
         * 使用 Map按value进行排序
         * @param map
         * @return
         */  
        public static Map<String, String> sortMapByValue(Map<String, String> map) {  
            if (map == null || map.isEmpty()) {  
                return null;  
            }  
            Map<String, String> sortedMap = new LinkedHashMap<>();  
            List<Map.Entry<String, String>> entryList = new ArrayList<Map.Entry<String, String>>(map.entrySet());  
            Collections.sort(entryList, new MapValueComparator());  
            Iterator<Map.Entry<String, String>> iter = entryList.iterator();  
            Map.Entry<String, String> tmpEntry = null;  
            while (iter.hasNext()) {  
                tmpEntry = iter.next();  
                sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue());  
            }  
            return sortedMap;  
        }  
        /**
         * @param doc  文档对象
         * @param fileName 文件名称
         */
        public static void saveDoc(CustomXWPFDocument doc,String fileName){
            try {
                FileOutputStream out = new FileOutputStream(FILE_OUT_PUT_PATH + fileName);
                try {
                    doc.write(out);
                    out.close();
                    log.info(FILE_OUT_PUT_PATH + fileName + "----------------------------创建成功");
                } catch (IOException e) {
                    
                    e.printStackTrace();
                    log.info("------------------------------------" + e.getMessage());
                }
            } catch (FileNotFoundException e) {
                
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        System.out.println("");
        /*//饼状图数据集
        PieChart pieData = new PieChart();
        pieData.setLeftData(new ArrayList<String>(){{
            add("正面");
            add("负面");
            add("中性");
        }});
        pieData.setOpinionData(new ArrayList<PieChartSeriesData>(){{
            PieChartSeriesData dd = new PieChartSeriesData(){{
                setName("正面");
                setValue(300);
            }};
            PieChartSeriesData dd1 = new PieChartSeriesData(){{
                setName("负面");
                setValue(565);
            }};
            PieChartSeriesData dd2 = new PieChartSeriesData(){{
                setName("中性");
                setValue(196);
            }};
            add(dd);
            add(dd1);
            add(dd2);
        }});
        //表格数据集
        Map<String,String[][]> dataset = new HashMap<String,String[][]>();
        String[][] table = {{"正面","负面"},{"121","2323"}};
        dataset.put("这是一个表格",table);
        //文档概括数据集
        Map<String,String> summaryDataset = new HashMap<String,String>(){{
            put("监测时间","2012年2月16日");
            put("监测范围","新闻、博客、论坛、贴吧、、、、、等全面监测");
            put("监测方案","监测方案一、监测方案二、监测方案二");
            put("内容摘要论坛内容","2012年2月16日信息总量1124条,比2012年2月15日增加75条信息。\n2012年2月16日信息量最多的网站类型是新闻,占总数的35.7%\n2012年2月16日信息量最多的网站是zhidao.baidu.com");
        }};
        
        
        
        //创建word文档
        CustomXWPFDocument doc = new CustomXWPFDocument();
        //添加标题
        Utils.addTitle(doc, "智慧商情日报");
        //添加文档综述
        Utils.addSummary(doc,new HashMap(){{

        /*String projectPath = request.getRealPath("/");


            put("新闻","cc0033");
            put("2012","cc66ff");
        }},summaryDataset);
        //添加一级段落
        Utils.addParagraphLevel1(doc,"信息综述", "1");
        Utils.addPart(doc, "七日传播趋势汇总", "1.1", "2012年2月16日,新闻网站上共监测到信息401条,比2012年2月15日增加64条信息。",null, dataset, new HashMap(){{
            put("传播趋势七天不同类型饼图",JfreeChartUtil.getChartStream(JfreeChartUtil.getPieChart("七天饼状图", pieData, false),500, 300));
        }});
        
        //生成doc文件
        Utils.saveDoc(doc, "智慧商情日报.docx");*/
    }

}





CustomXWPFDocument.java

package com.zhxg.zhsq.util;

import java.io.IOException;  
import java.io.InputStream;  
 
import org.apache.poi.openxml4j.opc.OPCPackage;  
import org.apache.poi.xwpf.usermodel.XWPFDocument;  
import org.apache.poi.xwpf.usermodel.XWPFParagraph;  
import org.apache.xmlbeans.XmlException;  
import org.apache.xmlbeans.XmlToken;  
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;  
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;  
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;  
    
/**  
 * POI 导出图片bug修复
 * @author  zyl
 *   
 */    
public class CustomXWPFDocument extends XWPFDocument {    
    public CustomXWPFDocument(InputStream in) throws IOException {    
        super(in);    
    }    
    
    /**  
     *   
     */    
    public CustomXWPFDocument() {    
        super();    
    }    
    
    /**  
     * @param pkg  
     * @throws IOException  
     */    
    public CustomXWPFDocument(OPCPackage pkg) throws IOException {    
        super(pkg);    
    }  // picAttch 图片后面追加的字符串 可以是空格  
    public void createPicture(XWPFParagraph paragraph,int id, int width, int height,String picAttch) {    
        final int EMU = 9525;    
        width *= EMU;    
        height *= EMU;    
        String blipId = getAllPictures().get(id).getPackageRelationship()    
                .getId();    
    
        CTInline inline = paragraph.createRun().getCTR()    
                .addNewDrawing().addNewInline();    
        paragraph.createRun().setText(picAttch);  
        String picXml = ""    
                + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"    
                + "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"    
                + "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"    
                + "         <pic:nvPicPr>" + "            <pic:cNvPr id=\""    
                + id    
                + "\" name=\"Generated\"/>"    
                + "            <pic:cNvPicPr/>"    
                + "         </pic:nvPicPr>"    
                + "         <pic:blipFill>"    
                + "            <a:blip r:embed=\""    
                + blipId    
                + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"    
                + "            <a:stretch>"    
                + "               <a:fillRect/>"    
                + "            </a:stretch>"    
                + "         </pic:blipFill>"    
                + "         <pic:spPr>"    
                + "            <a:xfrm>"    
                + "               <a:off x=\"0\" y=\"0\"/>"    
                + "               <a:ext cx=\""    
                + width    
                + "\" cy=\""    
                + height    
                + "\"/>"    
                + "            </a:xfrm>"    
                + "            <a:prstGeom prst=\"rect\">"    
                + "               <a:avLst/>"    
                + "            </a:prstGeom>"    
                + "         </pic:spPr>"    
                + "      </pic:pic>"    
                + "   </a:graphicData>" + "</a:graphic>";    
    
        inline.addNewGraphic().addNewGraphicData();    
        XmlToken xmlToken = null;    
        try {    
            xmlToken = XmlToken.Factory.parse(picXml);    
        } catch (XmlException xe) {    
            xe.printStackTrace();    
        }    
        inline.set(xmlToken);    
    
        inline.setDistT(0);    
        inline.setDistB(0);    
        inline.setDistL(0);    
        inline.setDistR(0);    
    
        CTPositiveSize2D extent = inline.addNewExtent();    
        extent.setCx(width);    
        extent.setCy(height);    
    
        CTNonVisualDrawingProps docPr = inline.addNewDocPr();    
        docPr.setId(id);    
        docPr.setName("图片" + id);    
        docPr.setDescr("");    
    }    
}



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值