]> source.dussan.org Git - poi.git/commitdiff
basic bubble chart support
authorPJ Fanning <fanningpj@apache.org>
Sun, 7 Aug 2022 22:19:10 +0000 (22:19 +0000)
committerPJ Fanning <fanningpj@apache.org>
Sun, 7 Aug 2022 22:19:10 +0000 (22:19 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1903272 13f79535-47bb-0310-9956-ffa450edef68

16 files changed:
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFArea3DChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFAreaChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFBar3DChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFBarChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFBubbleChartData.java [new file with mode: 0644]
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFDoughnutChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFLine3DChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFLineChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFPie3DChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFPieChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFRadarChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFScatterChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFSurface3DChartData.java
poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFSurfaceChartData.java
poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/charts/TestXSSFBubbleChartData.java [new file with mode: 0644]

index ebc0ee63057434cdd0987994006d258a58c9cc84..397b8d88546b5fd201652693f4da513f8fa3da51 100644 (file)
@@ -150,6 +150,13 @@ public class XDDFArea3DChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTAreaSer getCTAreaSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index e09121225cf9bf9064502969a8a75482846954c0..a6488d7415ae7d2462c12e22f93239fc7a351aff 100644 (file)
@@ -23,12 +23,7 @@ import java.util.Map;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAreaChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAreaSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFAreaChartData extends XDDFChartData {
@@ -131,6 +126,13 @@ public class XDDFAreaChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTAreaSer getCTAreaSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index 3f6984f6e43cd3a6fa96248c7f49725cdc6c760a..b4ba523573e321a0c7ce4dd65be19988d32dd12a 100644 (file)
@@ -24,12 +24,7 @@ import org.apache.poi.ooxml.util.POIXMLUnits;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTBar3DChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFBar3DChartData extends XDDFChartData {
@@ -202,6 +197,13 @@ public class XDDFBar3DChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTBarSer getCTBarSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index 9ff0bc0d94fd26409f0a73121c5a48630ae347b7..26c2069db7eaeedbafb279398d7869918ead5c7e 100644 (file)
@@ -24,12 +24,7 @@ import org.apache.poi.ooxml.util.POIXMLUnits;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTBarSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFBarChartData extends XDDFChartData {
@@ -192,6 +187,13 @@ public class XDDFBarChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTBarSer getCTBarSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFBubbleChartData.java b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFBubbleChartData.java
new file mode 100644 (file)
index 0000000..a55ae5e
--- /dev/null
@@ -0,0 +1,224 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+package org.apache.poi.xddf.usermodel.chart;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
+
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.Internal;
+import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTBubbleChart;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTBubbleSer;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumData;
+
+/**
+ * @since POI 5.2.3
+ */
+@Beta
+public class XDDFBubbleChartData extends XDDFChartData {
+    private CTBubbleChart chart;
+
+    public XDDFBubbleChartData(
+            XDDFChart parent,
+            CTBubbleChart chart,
+            XDDFChartAxis category,
+            XDDFValueAxis values) {
+        super(parent);
+        this.chart = chart;
+        Map<Long, XDDFChartAxis> categories = null;
+        Map<Long, XDDFValueAxis> mapValues = null;
+        categories = Collections.singletonMap(category.getId(), category);
+        mapValues = Collections.singletonMap(values.getId(), values);
+        for (CTBubbleSer series : chart.getSerList()) {
+            this.series.add(new Series(series, series.getXVal(), series.getYVal()));
+        }
+        defineAxes(categories, mapValues);
+    }
+
+    @Internal
+    protected XDDFBubbleChartData(
+            XDDFChart parent,
+            CTBubbleChart chart,
+            Map<Long, XDDFChartAxis> categories,
+            Map<Long, XDDFValueAxis> values) {
+        super(parent);
+        this.chart = chart;
+        for (CTBubbleSer series : chart.getSerList()) {
+            this.series.add(new Series(series, series.getXVal(), series.getYVal()));
+        }
+        defineAxes(categories, values);
+    }
+
+    private void defineAxes(Map<Long, XDDFChartAxis> categories, Map<Long, XDDFValueAxis> values) {
+        if (chart.sizeOfAxIdArray() == 0) {
+            for (Long id : categories.keySet()) {
+                chart.addNewAxId().setVal(id);
+            }
+            for (Long id : values.keySet()) {
+                chart.addNewAxId().setVal(id);
+            }
+        }
+        defineAxes(chart.getAxIdArray(), categories, values);
+    }
+
+    @Internal
+    @Override
+    protected void removeCTSeries(int n) {
+        chart.removeSer(n);
+    }
+
+    @Override
+    public void setVaryColors(Boolean varyColors) {
+        if (varyColors == null) {
+            if (chart.isSetVaryColors()) {
+                chart.unsetVaryColors();
+            }
+        } else {
+            if (chart.isSetVaryColors()) {
+                chart.getVaryColors().setVal(varyColors);
+            } else {
+                chart.addNewVaryColors().setVal(varyColors);
+            }
+        }
+    }
+
+    @Override
+    public XDDFChartData.Series addSeries(XDDFDataSource<?> category,
+                                          XDDFNumericalDataSource<? extends Number> values) {
+        final long index = this.parent.incrementSeriesCount();
+        try {
+            final CTBubbleSer ctSer = this.chart.addNewSer();
+            ctSer.addNewXVal();
+            ctSer.addNewYVal();
+            ctSer.addNewIdx().setVal(index);
+            ctSer.addNewOrder().setVal(index);
+            final Series added = new Series(ctSer, category, values);
+            this.series.add(added);
+            return added;
+        } catch (Exception ex) {
+           throw new RuntimeException(ex);
+        }
+    }
+
+    public class Series extends XDDFChartData.Series {
+        private CTBubbleSer series;
+
+        protected Series(CTBubbleSer series, XDDFDataSource<?> category, XDDFNumericalDataSource<?> values) {
+            super(category, values);
+            this.series = series;
+        }
+
+        /**
+         * @since POI 5.2.3
+         */
+        public CTBubbleSer getCTBubbleSer() {
+            return series;
+        }
+
+        protected Series(CTBubbleSer series, CTAxDataSource category, CTNumDataSource values) {
+            super(XDDFDataSourcesFactory.fromDataSource(category), XDDFDataSourcesFactory.fromDataSource(values));
+            this.series = series;
+        }
+
+        public void setBubbleSizes(XDDFNumericalDataSource<?> values) {
+            try {
+                if (series.isSetBubbleSize()) series.unsetBubbleSize();
+                CTNumDataSource bubbleSizes = series.addNewBubbleSize();
+                CTNumData cache = retrieveNumCache(bubbleSizes, values);
+                values.fillNumericalCache(cache);
+            } catch (Exception ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+
+        @Override
+        protected CTSerTx getSeriesText() {
+            if (series.isSetTx()) {
+                return series.getTx();
+            } else {
+                return series.addNewTx();
+            }
+        }
+
+        @Override
+        public void setShowLeaderLines(boolean showLeaderLines) {
+            if (!series.isSetDLbls()) {
+                series.addNewDLbls();
+            }
+            if (series.getDLbls().isSetShowLeaderLines()) {
+                series.getDLbls().getShowLeaderLines().setVal(showLeaderLines);
+            } else {
+                series.getDLbls().addNewShowLeaderLines().setVal(showLeaderLines);
+            }
+        }
+
+        @Override
+        public XDDFShapeProperties getShapeProperties() {
+            if (series.isSetSpPr()) {
+                return new XDDFShapeProperties(series.getSpPr());
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public void setShapeProperties(XDDFShapeProperties properties) {
+            if (properties == null) {
+                if (series.isSetSpPr()) {
+                    series.unsetSpPr();
+                }
+            } else {
+                if (series.isSetSpPr()) {
+                    series.setSpPr(properties.getXmlObject());
+                } else {
+                    series.addNewSpPr().set(properties.getXmlObject());
+                }
+            }
+        }
+
+        @Override
+        protected CTAxDataSource getAxDS() {
+            return series.getXVal();
+        }
+
+        @Override
+        protected CTNumDataSource getNumDS() {
+            return series.getYVal();
+        }
+
+        @Override
+        protected void setIndex(long val) {
+            series.getIdx().setVal(val);
+        }
+
+        @Override
+        protected void setOrder(long val) {
+            series.getOrder().setVal(val);
+        }
+
+        @Override
+        protected List<CTDPt> getDPtList() {
+            return series.getDPtList();
+        }
+    }
+}
index 4669e2e70753cc591aebadb73af2716d0f78aa55..c8e92fea64367da3a437daf15094ee9f43f02316 100644 (file)
@@ -380,7 +380,7 @@ public abstract class XDDFChartData {
             return strCache;
         }
 
-        private CTNumData retrieveNumCache(final CTNumDataSource numDataSource, XDDFDataSource<?> data) {
+        protected CTNumData retrieveNumCache(final CTNumDataSource numDataSource, XDDFDataSource<?> data) {
             CTNumData numCache;
             if (data.isReference()) {
                 CTNumRef numRef;
index 23020f842a66e1e613e31e5f4d9f53dd8993726b..56137092f6663ba9e21530b3b1488e29cdfdad6f 100644 (file)
@@ -23,12 +23,7 @@ import org.apache.poi.ooxml.util.POIXMLUnits;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDoughnutChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFDoughnutChartData extends XDDFChartData {
@@ -142,6 +137,13 @@ public class XDDFDoughnutChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTPieSer getCTPieSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index 5313e8825dcd7c5f89cbbc90afd1196cbdf30336..68a60bcfc5b6bcd9ce52e6b47f6a4d75d3834d44 100644 (file)
@@ -87,31 +87,31 @@ public class XDDFLine3DChartData extends XDDFChartData {
         return Grouping.valueOf(chart.getGrouping().getVal());
     }
 
-   public void setGrouping(Grouping grouping) {
-      if (chart.getGrouping() != null) {
-         chart.getGrouping().setVal(grouping.underlying);
-      } else {
-         chart.addNewGrouping().setVal(grouping.underlying);
-      }
-   }
-
-   public Integer getGapDepth() {
-       return (chart.isSetGapDepth()) ? POIXMLUnits.parsePercent(chart.getGapDepth().xgetVal()) / 1000 : null;
-   }
-
-   public void setGapDepth(Integer depth) {
-       if (depth == null) {
-           if (chart.isSetGapDepth()) {
-               chart.unsetGapDepth();
-           }
-       } else {
-           if (chart.isSetGapDepth()) {
-               chart.getGapDepth().setVal(depth);
-           } else {
-               chart.addNewGapDepth().setVal(depth);
-           }
-       }
-   }
+    public void setGrouping(Grouping grouping) {
+        if (chart.getGrouping() != null) {
+            chart.getGrouping().setVal(grouping.underlying);
+        } else {
+            chart.addNewGrouping().setVal(grouping.underlying);
+        }
+    }
+
+    public Integer getGapDepth() {
+        return (chart.isSetGapDepth()) ? POIXMLUnits.parsePercent(chart.getGapDepth().xgetVal()) / 1000 : null;
+    }
+
+    public void setGapDepth(Integer depth) {
+        if (depth == null) {
+            if (chart.isSetGapDepth()) {
+                chart.unsetGapDepth();
+            }
+        } else {
+            if (chart.isSetGapDepth()) {
+                chart.getGapDepth().setVal(depth);
+            } else {
+                chart.addNewGapDepth().setVal(depth);
+            }
+        }
+    }
 
     @Override
     public XDDFChartData.Series addSeries(XDDFDataSource<?> category,
@@ -141,6 +141,13 @@ public class XDDFLine3DChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTLineSer getCTLineSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index 0a94cf96e9adc2dad2858e51c8d40a4008d2b511..5e9e51d757015bfe6f4c581320a3939bf3d8e0b8 100644 (file)
@@ -23,13 +23,7 @@ import java.util.Map;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTMarker;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFLineChartData extends XDDFChartData {
@@ -122,6 +116,13 @@ public class XDDFLineChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTLineSer getCTLineSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index d2a5059847ff9d5ca945a457a74f4d98caffbd7f..95670cf63d09818c4b0ef5eca4548df0d4a227fd 100644 (file)
@@ -22,12 +22,7 @@ import java.util.List;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTPie3DChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFPie3DChartData extends XDDFChartData {
@@ -91,6 +86,13 @@ public class XDDFPie3DChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTPieSer getCTPieSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index 6a3a28c5763f606c1716980672f114ab66b0642b..3d69e0f163d82674765ec472a19921584eadd1ba 100644 (file)
@@ -116,6 +116,13 @@ public class XDDFPieChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTPieSer getCTPieSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index f7f2edac6d1d8b50c87d3ad28100b457c34fb843..4693773c276a183aebcb350fa560076b84ee085d 100644 (file)
@@ -23,13 +23,7 @@ import java.util.Map;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTRadarChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTRadarSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTRadarStyle;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFRadarChartData extends XDDFChartData {
@@ -122,6 +116,13 @@ public class XDDFRadarChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTRadarSer getCTRadarSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index ba9864bf00b6e5b351adc0bbbd4919b044fd4d79..1bf6ead50136e237921c3d4312de1a94dfd3a58b 100644 (file)
@@ -23,14 +23,7 @@ import java.util.Map;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTMarker;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterSer;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTScatterStyle;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFScatterChartData extends XDDFChartData {
@@ -128,6 +121,13 @@ public class XDDFScatterChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTScatterSer getCTScatterSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index b61764f168b56598db0b18611dbd6b445d6a26fd..41c9700797d24f90bf469a2852acf07b6035696e 100644 (file)
@@ -23,12 +23,7 @@ import java.util.Map;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTAxDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTDPt;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTNumDataSource;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSerTx;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSurface3DChart;
-import org.openxmlformats.schemas.drawingml.x2006.chart.CTSurfaceSer;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
 
 @Beta
 public class XDDFSurface3DChartData extends XDDFChartData {
@@ -128,6 +123,13 @@ public class XDDFSurface3DChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTSurfaceSer getCTSurfaceSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
index 0547a193625779b81a6a76c123b3a8eff7649558..8e5e7558822dc6e42459ea2940e4a7aba9ed1317 100644 (file)
@@ -128,6 +128,13 @@ public class XDDFSurfaceChartData extends XDDFChartData {
             this.series = series;
         }
 
+        /**
+         * @since POI 5.2.3
+         */
+        public CTSurfaceSer getCTSurfaceSer() {
+            return series;
+        }
+
         @Override
         protected CTSerTx getSeriesText() {
             if (series.isSetTx()) {
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/charts/TestXSSFBubbleChartData.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/charts/TestXSSFBubbleChartData.java
new file mode 100644 (file)
index 0000000..34a2bab
--- /dev/null
@@ -0,0 +1,231 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ==================================================================== */
+
+package org.apache.poi.xssf.usermodel.charts;
+
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.xddf.usermodel.PresetColor;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.chart.*;
+import org.apache.poi.xssf.usermodel.*;
+import org.junit.jupiter.api.Test;
+import org.openxmlformats.schemas.drawingml.x2006.chart.*;
+
+import java.io.IOException;
+import java.util.GregorianCalendar;
+
+/**
+ * Tests for XSSFBubbleChartData.
+ */
+public final class TestXSSFBubbleChartData {
+
+    @Test
+    void testExample() throws IOException {
+        Object[][] chartData = new Object[][]{
+                new Object[]{"", "Category 1"},
+                new Object[]{"Bubble Size", "Bubble Date"},
+                new Object[]{1000, new GregorianCalendar(2020, 0, 1)},
+                new Object[]{10, new GregorianCalendar(2020, 0, 1)},
+                new Object[]{300, new GregorianCalendar(2021, 0, 1)},
+                new Object[]{"", ""},
+                new Object[]{"", "Category 2"},
+                new Object[]{"Bubble Size", "Bubble Date"},
+                new Object[]{100, new GregorianCalendar(2018, 0, 1)},
+                new Object[]{100, new GregorianCalendar(2020, 0, 1)}
+        };
+
+        try (XSSFWorkbook wb = new XSSFWorkbook()) {
+            XSSFSheet sheet = wb.createSheet("bubblechart");
+            DataFormat format = wb.createDataFormat();
+            XSSFCellStyle dateStyle = wb.createCellStyle();
+            dateStyle.setDataFormat(14);
+
+            // put sheet data
+            Row row;
+            Cell cell;
+            int rowIndex = 0;
+            int colIndex = 0;
+            for (Object[] dataRow : chartData) {
+                row = sheet.createRow((short) rowIndex);
+                colIndex = 0;
+                for (Object value : dataRow) {
+                    cell = row.createCell((short) colIndex);
+                    if (value instanceof String) cell.setCellValue((String)value);
+                    if (value instanceof Number) cell.setCellValue(((Number)value).doubleValue());
+                    if (value instanceof GregorianCalendar) {
+                        cell.setCellValue((GregorianCalendar)value);
+                        cell.setCellStyle(dateStyle);
+                    }
+                    colIndex++;
+                }
+                rowIndex++;
+            }
+
+            sheet.autoSizeColumn(0);
+            sheet.autoSizeColumn(1);
+
+            // create the chart
+
+            // chart data sources
+            XDDFDataSource<Double> xs1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 4, 1, 1));
+            XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 4, 0, 0));
+            XDDFNumericalDataSource<Double> bSz1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 4, 0, 0));
+
+            XDDFDataSource<Double> xs2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(8, 9, 1, 1));
+            XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(8, 9, 0, 0));
+            XDDFNumericalDataSource<Double> bSz2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(8, 9, 0, 0));
+
+            // chart in drawing
+            XSSFDrawing drawing = sheet.createDrawingPatriarch();
+            XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 3, 0, 15, 20);
+            XSSFChart chart = drawing.createChart(anchor);
+            chart.setTitleText("Chart Title");
+            chart.setTitleOverlay(false);
+            chart.getFormattedTitle().getParagraph(0).addDefaultRunProperties().setFontSize(20d);
+
+            // value axis x
+            XDDFValueAxis valAxisX = chart.createValueAxis(AxisPosition.BOTTOM);
+            valAxisX.setTitle("Axis Title");
+
+            // value axis y
+            XDDFValueAxis valAxisY = chart.createValueAxis(AxisPosition.LEFT);
+            valAxisY.setTitle("Axis Title");
+
+            // cross axes
+            valAxisY.setCrosses(AxisCrosses.AUTO_ZERO);
+
+            // chart data
+            //XDDFChartData data = chart.createData(ChartTypes.???, valAxisX, valAxisY);
+            XDDFBubbleChartData data = new XDDFBubbleChartData(chart, chart.getCTChart().getPlotArea().addNewBubbleChart(), valAxisX, valAxisY);
+
+            // series
+            XDDFBubbleChartData.Series series1 = (XDDFBubbleChartData.Series)data.addSeries(xs1, ys1);
+            series1.setTitle("Category 1", new CellReference(sheet.getSheetName(), 0, 1, true, true));
+            // set bubble sizes
+            series1.setBubbleSizes(bSz1);
+            // add data labels
+            // pos 8 = INT_R , showVal = true, showLegendKey= false, showCatName = true
+            CTDLbls ctDLbls = setDataLabels(series1, 8, true, false, true);
+
+            XDDFBubbleChartData.Series series2 = (XDDFBubbleChartData.Series)data.addSeries(xs2, ys2);
+            series2.setTitle("Category 2", new CellReference(sheet.getSheetName(), 6, 1, true, true));
+            // set bubble sizes
+            series2.setBubbleSizes(bSz2);
+            // add data labels
+            // pos 8 = INT_R , showVal = true, showLegendKey= false, showCatName = true
+            ctDLbls = setDataLabels(series2, 8, true, false, true);
+
+            // plot chart
+            chart.plot(data);
+
+            // legend
+            XDDFChartLegend legend = chart.getOrAddLegend();
+            legend.setPosition(LegendPosition.RIGHT);
+
+            // set series fill color
+            solidFillSeries(data, 0, PresetColor.BLUE);
+            solidFillSeries(data, 1, PresetColor.RED);
+
+            // set rounded corners false
+            setRoundedCorners(chart, false);
+
+            // Write the output to a file
+            try (UnsynchronizedByteArrayOutputStream outStream = new UnsynchronizedByteArrayOutputStream()) {
+                wb.write(outStream);
+                try (XSSFWorkbook wb2 = new XSSFWorkbook(outStream.toInputStream())) {
+                    // see if this fails
+                }
+            }
+        }
+    }
+
+    private static void solidFillSeries(XDDFChartData data, int index, PresetColor color) {
+        XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
+        XDDFChartData.Series series = data.getSeries(index);
+        XDDFShapeProperties properties = series.getShapeProperties();
+        if (properties == null) {
+            properties = new XDDFShapeProperties();
+        }
+        properties.setFillProperties(fill);
+        series.setShapeProperties(properties);
+    }
+
+    private static CTDLbls setDataLabels(XDDFChartData.Series series, int pos, boolean... show) {
+        /*
+        INT_BEST_FIT   1
+        INT_B          2
+        INT_CTR        3
+        INT_IN_BASE    4
+        INT_IN_END     5
+        INT_L          6
+        INT_OUT_END    7
+        INT_R          8
+        INT_T          9
+        */
+        CTDLbls ctDLbls = null;
+        if (series instanceof XDDFBarChartData.Series) {
+            CTBarSer ctBarSer = ((XDDFBarChartData.Series)series).getCTBarSer();
+            if (ctBarSer.isSetDLbls()) ctBarSer.unsetDLbls();
+            ctDLbls = ctBarSer.addNewDLbls();
+            if (!(pos == 3 || pos == 4 || pos == 5 || pos == 7)) pos = 3; // bar chart does not provide other pos
+            ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
+        } else if (series instanceof XDDFLineChartData.Series) {
+            CTLineSer ctLineSer = ((XDDFLineChartData.Series)series).getCTLineSer();
+            if (ctLineSer.isSetDLbls()) ctLineSer.unsetDLbls();
+            ctDLbls = ctLineSer.addNewDLbls();
+            if (!(pos == 3 || pos == 6 || pos == 8 || pos == 9 || pos == 2)) pos = 3; // line chart does not provide other pos
+            ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
+        } else if (series instanceof XDDFPieChartData.Series) {
+            CTPieSer ctPieSer = ((XDDFPieChartData.Series)series).getCTPieSer();
+            if (ctPieSer.isSetDLbls()) ctPieSer.unsetDLbls();
+            ctDLbls = ctPieSer.addNewDLbls();
+            if (!(pos == 3 || pos == 1 || pos == 4 || pos == 5)) pos = 3; // pie chart does not provide other pos
+            ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
+        } else if (series instanceof XDDFBubbleChartData.Series) {
+            CTBubbleSer ctBubbleSer = ((XDDFBubbleChartData.Series)series).getCTBubbleSer();
+            if (ctBubbleSer.isSetDLbls()) ctBubbleSer.unsetDLbls();
+            ctDLbls = ctBubbleSer.addNewDLbls();
+            if (!(pos == 3 || pos == 2 || pos == 6 || pos == 8 || pos == 9)) pos = 3; // bubble chart does not provide other pos
+            ctDLbls.addNewDLblPos().setVal(STDLblPos.Enum.forInt(pos));
+        }// else if ...
+
+        if (ctDLbls != null) {
+            ctDLbls.addNewShowVal().setVal((show.length>0)?show[0]:false);
+            ctDLbls.addNewShowLegendKey().setVal((show.length>1)?show[1]:false);
+            ctDLbls.addNewShowCatName().setVal((show.length>2)?show[2]:false);
+            ctDLbls.addNewShowSerName().setVal((show.length>3)?show[3]:false);
+            ctDLbls.addNewShowPercent().setVal((show.length>4)?show[4]:false);
+            ctDLbls.addNewShowBubbleSize().setVal((show.length>5)?show[5]:false);
+            ctDLbls.addNewShowLeaderLines().setVal((show.length>6)?show[8]:false);
+
+            return ctDLbls;
+        }
+        return null;
+    }
+
+    private static void setRoundedCorners(XDDFChart chart, boolean setVal) {
+        if (chart.getCTChartSpace().getRoundedCorners() == null) chart.getCTChartSpace().addNewRoundedCorners();
+        chart.getCTChartSpace().getRoundedCorners().setVal(setVal);
+    }
+}