POI 画Excel原生图表(折线图和柱状图)

poi画图表

git 地址

MAVEN 依赖

    <properties>
        <poi-version>3.11</poi-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi-version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi-version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>${poi-version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.1</version>
        </dependency>
    </dependencies>

java代码

 /*
   * @param params params.get(0) 为图表位置 0123为起始横坐标,起始纵坐标,终点横,终点纵
   * 
   * @param params params.get(1) 为x轴取值范围,其他为折线取值范围。起始行号,终止行号, 起始列号,终止列号(折线名称坐标
   * )。
   */
  private static void drawLineChart(XSSFSheet sheet, List<int[]> params) {

    Drawing drawing = sheet.createDrawingPatriarch();
    // 设置位置 起始横坐标,起始纵坐标,终点横,终点纵
    ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, params.get(0)[0], params.get(0)[1], params.get(0)[2],
        params.get(0)[3]);
    Chart chart = drawing.createChart(anchor);

    // 创建标题

    // 创建图形注释的位置
    ChartLegend legend = chart.getOrCreateLegend();
    legend.setPosition(LegendPosition.BOTTOM);
    // 创建绘图的类型 LineCahrtData 折线图
    LineChartData chartData = chart.getChartDataFactory().createLineChartData();
    // 设置横坐标
    ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM);
    bottomAxis.setCrosses(AxisCrosses.AUTO_ZERO);
    // 设置纵坐标
    ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);

    leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
    // 从Excel中获取数据.CellRangeAddress-->params: 起始行号,终止行号, 起始列号,终止列号
    // 数据类别(x轴)
    ChartDataSource xAxis = DataSources.fromStringCellRange(sheet,
        new CellRangeAddress(params.get(1)[0], params.get(1)[1], params.get(1)[2], params.get(1)[3]));
    for (int i = 2, len = params.size(); i < len; i++) {
      // 数据源
      ChartDataSource dataAxis = DataSources.fromNumericCellRange(sheet,
          new CellRangeAddress(params.get(i)[0], params.get(i)[1], params.get(i)[2], params.get(i)[3]));

      LineChartSeries chartSeries = chartData.addSeries(xAxis, dataAxis);
      // 给每条折线创建名字
      chartSeries.setTitle(sheet.getRow(params.get(i)[4]).getCell(params.get(i)[5]).getStringCellValue());
    }

    setChartTitle((XSSFChart) chart, sheet.getSheetName());
    // 开始绘制折线图
    chart.plot(chartData, bottomAxis, leftAxis);
  }

  private static void drawCTLineChart(XSSFSheet sheet, int[] position, List<String> xString, Set<String> serTxName,
      List<String> dataRef) {

    Drawing drawing = sheet.createDrawingPatriarch();
    ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, position[0], position[1], position[2], position[3]);

    Chart chart = drawing.createChart(anchor);

    CTChart ctChart = ((XSSFChart) chart).getCTChart();
    CTPlotArea ctPlotArea = ctChart.getPlotArea();
    CTLineChart ctLineChart = ctPlotArea.addNewLineChart();

    ctLineChart.addNewVaryColors().setVal(true);

    // telling the Chart that it has axis and giving them Ids
    setAxIds(ctLineChart);
    // set cat axis
    setCatAx(ctPlotArea);
    // set val axis
    setValAx(ctPlotArea);
    // legend
    setLegend(ctChart);
    // set data lable
    setDataLabel(ctLineChart);
    // set chart title
    setChartTitle((XSSFChart) chart, sheet.getSheetName());

    paddingData(ctLineChart, xString, serTxName, dataRef);
  }

  /*
   * @param position 图表坐标 起始行,起始列,终点行,重点列
   * 
   * @param xString 横坐标
   * 
   * @param serTxName 图形示例
   * 
   * @param dataRef 柱状图数据范围 : sheetName!$A$1:$A$12
   */
  private static void drawBarChart(XSSFSheet sheet, int[] position, List<String> xString, Set<String> serTxName,
      List<String> dataRef) {

    Drawing drawing = sheet.createDrawingPatriarch();
    ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, position[0], position[1], position[2], position[3]);

    Chart chart = drawing.createChart(anchor);

    CTChart ctChart = ((XSSFChart) chart).getCTChart();
    CTPlotArea ctPlotArea = ctChart.getPlotArea();
    CTBarChart ctBarChart = ctPlotArea.addNewBarChart();

    ctBarChart.addNewVaryColors().setVal(false);
    ctBarChart.addNewBarDir().setVal(STBarDir.COL);

    // telling the Chart that it has axis and giving them Ids
    setAxIds(ctBarChart);
    // set cat axis
    setCatAx(ctPlotArea);
    // set val axis
    setValAx(ctPlotArea);
    // add legend and set legend position
    setLegend(ctChart);
    // set data lable
    setDataLabel(ctBarChart);
    // set chart title
    setChartTitle((XSSFChart) chart, sheet.getSheetName());
    // padding data to chart
    paddingData(ctBarChart, xString, serTxName, dataRef);
  }

  private static void paddingData(CTBarChart ctBarChart, List<String> xString, Set<String> serTxName,
      List<String> dataRef) {
    Iterator<String> iterator = serTxName.iterator();
    for (int r = 0, len = dataRef.size(); r < len && iterator.hasNext(); r++) {
      CTBarSer ctBarSer = ctBarChart.addNewSer();

      ctBarSer.addNewIdx().setVal(r);
      // set legend value
      setLegend(iterator.next(), ctBarSer.addNewTx());
      // cat ax value
      setChartCatAxLabel(ctBarSer.addNewCat(), xString);
      // value range
      ctBarSer.addNewVal().addNewNumRef().setF(dataRef.get(r));
      // add border to chart
      ctBarSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[] { 0, 0, 0 });
    }
  }

  private static void setLegend(String str, CTSerTx ctSerTx) {
    if (str.contains("$"))
      // set legend by str ref
      ctSerTx.addNewStrRef().setF(str);
    else
      // set legend by str
      ctSerTx.setV(str);
  }

  private static void paddingData(CTLineChart ctLineChart, List<String> xString, Set<String> serTxName,
      List<String> dataRef) {
    Iterator<String> iterator = serTxName.iterator();
    for (int r = 0, len = dataRef.size(); r < len && iterator.hasNext(); r++) {
      CTLineSer ctLineSer = ctLineChart.addNewSer();
      ctLineSer.addNewIdx().setVal(r);
      setLegend(iterator.next(), ctLineSer.addNewTx());
      setChartCatAxLabel(ctLineSer.addNewCat(), xString);
      ctLineSer.addNewVal().addNewNumRef().setF(dataRef.get(r));
      ctLineSer.addNewSpPr().addNewLn().addNewSolidFill().addNewSrgbClr().setVal(new byte[] { 0, 0, 0 });
    }
  }

  private static void setChartCatAxLabel(CTAxDataSource cttAxDataSource, List<String> xString) {
    if (xString.size() == 1) {
      cttAxDataSource.addNewStrRef().setF(xString.get(0));
    } else {
      CTStrData ctStrData = cttAxDataSource.addNewStrLit();
      for (int m = 0, xlen = xString.size(); m < xlen; m++) {
        CTStrVal ctStrVal = ctStrData.addNewPt();
        ctStrVal.setIdx((long) m);
        ctStrVal.setV(xString.get(m));
      }
    }
  }

  private static void setDataLabel(CTBarChart ctBarChart) {
    setDLShowOpts(ctBarChart.addNewDLbls());
  }

  private static void setDataLabel(CTLineChart ctLineChart) {
    CTDLbls dlbls = ctLineChart.addNewDLbls();
    setDLShowOpts(dlbls);
    setDLPosition(dlbls, null);
  }

  private static void setDLPosition(CTDLbls dlbls, STDLblPos.Enum e) {
    if (e == null)
      dlbls.addNewDLblPos().setVal(STDLblPos.T);
    else
      dlbls.addNewDLblPos().setVal(e);
  }

  private static void setDLShowOpts(CTDLbls dlbls) {
    // 添加图形示例的字符串
    dlbls.addNewShowSerName().setVal(false);
    // 添加x轴的坐标字符串
    dlbls.addNewShowCatName().setVal(false);
    // 添加图形示例的图片
    dlbls.addNewShowLegendKey().setVal(false);
    // 添加x对应y的值---全设置成false 就没什么用处了
    // dlbls.addNewShowVal().setVal(false);
  }

  private static void setAxIds(CTBarChart ctBarChart) {
    ctBarChart.addNewAxId().setVal(123456);
    ctBarChart.addNewAxId().setVal(123457);
  }

  private static void setAxIds(CTLineChart ctLineChart) {
    ctLineChart.addNewAxId().setVal(123456);
    ctLineChart.addNewAxId().setVal(123457);
  }

  private static void setLegend(CTChart ctChart) {
    CTLegend ctLegend = ctChart.addNewLegend();
    ctLegend.addNewLegendPos().setVal(STLegendPos.B);
    ctLegend.addNewOverlay().setVal(false);
  }

  private static void setCatAx(CTPlotArea ctPlotArea) {
    CTCatAx ctCatAx = ctPlotArea.addNewCatAx();
    ctCatAx.addNewAxId().setVal(123456); // id of the cat axis
    CTScaling ctScaling = ctCatAx.addNewScaling();
    ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
    ctCatAx.addNewDelete().setVal(false);
    ctCatAx.addNewAxPos().setVal(STAxPos.B);
    ctCatAx.addNewCrossAx().setVal(123457); // id of the val axis
    ctCatAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);

  }

  // 不要y轴的标签,或者y轴尽可能的窄一些
  private static void setValAx(CTPlotArea ctPlotArea) {
    CTValAx ctValAx = ctPlotArea.addNewValAx();
    ctValAx.addNewAxId().setVal(123457); // id of the val axis
    CTScaling ctScaling = ctValAx.addNewScaling();
    ctScaling.addNewOrientation().setVal(STOrientation.MIN_MAX);
    // 不现实y轴
    ctValAx.addNewDelete().setVal(true);
    ctValAx.addNewAxPos().setVal(STAxPos.L);
    ctValAx.addNewCrossAx().setVal(123456); // id of the cat axis
    ctValAx.addNewTickLblPos().setVal(STTickLblPos.NEXT_TO);
  }

  // 图标标题
  private static void setChartTitle(XSSFChart xchart, String titleStr) {
    CTChart ctChart = xchart.getCTChart();

    CTTitle title = CTTitle.Factory.newInstance();
    CTTx cttx = title.addNewTx();
    CTStrData sd = CTStrData.Factory.newInstance();
    CTStrVal str = sd.addNewPt();
    str.setIdx(123459);
    str.setV(titleStr);
    cttx.addNewStrRef().setStrCache(sd);

    ctChart.setTitle(title);
  }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,562评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,263评论 25 707
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,713评论 6 342
  • 因为依恋,你把窈窕的身姿舒展;因为怀念,你把缱绻的风景展现;因为不舍,你把炽热的情感洒遍。 雨一直下...
    爱着这世界阅读 304评论 0 0
  • 文:大鱼很瘦 写尽世间百态 仍然相信真爱 就算遍体鳞伤 也要笑得猖狂 这是我身边一位不熟朋友的真实故事,如果有幸...
    游走星宿阅读 1,052评论 9 10