diff --git a/main/SS/UserModel/Charts/ChartAxis.cs b/main/SS/UserModel/Charts/ChartAxis.cs
index 0a7350d83..d115cfb18 100644
--- a/main/SS/UserModel/Charts/ChartAxis.cs
+++ b/main/SS/UserModel/Charts/ChartAxis.cs
@@ -106,6 +106,13 @@ public interface IChartAxis
* @return minor tick mark.
*/
AxisTickMark MinorTickMark { get; set; }
+
+
+ ///
+ /// Use this to check before retrieving a number format, as calling {@link #getNumberFormat()} may create a default one if none exists.
+ ///
+ /// return true if a number format element is defined, false if not
+ bool HasNumberFormat();
}
diff --git a/main/SS/UserModel/Charts/ChartAxisFactory.cs b/main/SS/UserModel/Charts/ChartAxisFactory.cs
index 6cdd465f6..df303fd8c 100644
--- a/main/SS/UserModel/Charts/ChartAxisFactory.cs
+++ b/main/SS/UserModel/Charts/ChartAxisFactory.cs
@@ -22,16 +22,24 @@ namespace NPOI.SS.UserModel.Charts
///
/// @author Roman Kashitsyn
public interface IChartAxisFactory
- {
+ {
///
- /// returns new value axis
+ /// create new value axis at the end of the list at the specified chart position.
///
///
///
IValueAxis CreateValueAxis(AxisPosition pos);
-
+ ///
+ /// create new category axis at the end of the list at the specified chart position.
+ ///
+ ///
+ ///
IChartAxis CreateCategoryAxis(AxisPosition pos);
-
+ ///
+ /// create new date category axis at the end of the list at the specified chart position.
+ ///
+ ///
+ ///
IChartAxis CreateDateAxis(AxisPosition pos);
}
diff --git a/ooxml/XSSF/Streaming/SXSSFWorkbook.cs b/ooxml/XSSF/Streaming/SXSSFWorkbook.cs
index 7e71323c6..61d5aa277 100644
--- a/ooxml/XSSF/Streaming/SXSSFWorkbook.cs
+++ b/ooxml/XSSF/Streaming/SXSSFWorkbook.cs
@@ -471,7 +471,8 @@ private void InjectData(FileInfo zipfile, Stream outStream, bool leaveOpen)
zos.PutNextEntry(new ZipEntry(ze.Name));
var inputStream = zip.GetInputStream(ze);
XSSFSheet xSheet = GetSheetFromZipEntryName(ze.Name);
- if (xSheet != null)
+ // See bug 56557, we should not inject data into the special ChartSheets
+ if (xSheet != null && !(xSheet is XSSFChartSheet))
{
SXSSFSheet sxSheet = GetSXSSFSheet(xSheet);
var xis = sxSheet.GetWorksheetXMLInputStream();
diff --git a/ooxml/XSSF/UserModel/Charts/XSSFCategoryAxis.cs b/ooxml/XSSF/UserModel/Charts/XSSFCategoryAxis.cs
index f44a77e9d..d01b4fc6f 100644
--- a/ooxml/XSSF/UserModel/Charts/XSSFCategoryAxis.cs
+++ b/ooxml/XSSF/UserModel/Charts/XSSFCategoryAxis.cs
@@ -88,6 +88,11 @@ public void SetAuto(CT_Boolean au)
ctCatAx.auto = au;
}
+ public override CT_ChartLines GetMajorGridLines()
+ {
+ return ctCatAx.majorGridlines;
+ }
+
private void createAxis(long id, AxisPosition pos)
{
ctCatAx = chart.GetCTChart().plotArea.AddNewCatAx();
@@ -109,6 +114,11 @@ private void createAxis(long id, AxisPosition pos)
this.MajorTickMark=(AxisTickMark.Cross);
this.MinorTickMark=(AxisTickMark.None);
}
+
+ public override bool HasNumberFormat()
+ {
+ return ctCatAx.IsSetNumFmt();
+ }
}
}
diff --git a/ooxml/XSSF/UserModel/Charts/XSSFChartAxis.cs b/ooxml/XSSF/UserModel/Charts/XSSFChartAxis.cs
index 32448b39a..82eed5578 100644
--- a/ooxml/XSSF/UserModel/Charts/XSSFChartAxis.cs
+++ b/ooxml/XSSF/UserModel/Charts/XSSFChartAxis.cs
@@ -45,11 +45,11 @@ public AxisPosition Position
{
get
{
- return toAxisPosition(GetCTAxPos());
+ return ToAxisPosition(GetCTAxPos());
}
set
{
- GetCTAxPos().val = fromAxisPosition(value);
+ GetCTAxPos().val = FromAxisPosition(value);
}
}
@@ -180,12 +180,12 @@ public AxisOrientation Orientation
{
get
{
- return toAxisOrientation(GetCTScaling().orientation);
+ return ToAxisOrientation(GetCTScaling().orientation);
}
set
{
CT_Scaling scaling = GetCTScaling();
- ST_Orientation stOrientation = fromAxisOrientation(value);
+ ST_Orientation stOrientation = FromAxisOrientation(value);
if (scaling.IsSetOrientation())
{
scaling.orientation.val = stOrientation;
@@ -201,11 +201,11 @@ public AxisCrosses Crosses
{
get
{
- return toAxisCrosses(GetCTCrosses());
+ return ToAxisCrosses(GetCTCrosses());
}
set
{
- GetCTCrosses().val = fromAxisCrosses(value);
+ GetCTCrosses().val = FromAxisCrosses(value);
}
}
public bool IsVisible
@@ -220,27 +220,27 @@ public bool IsVisible
}
}
- public AxisTickMark MajorTickMark
+ public virtual AxisTickMark MajorTickMark
{
get
{
- return toAxisTickMark(GetMajorCTTickMark());
+ return ToAxisTickMark(GetMajorCTTickMark());
}
set
{
- GetMajorCTTickMark().val = fromAxisTickMark(value);
+ GetMajorCTTickMark().val = FromAxisTickMark(value);
}
}
- public AxisTickMark MinorTickMark
+ public virtual AxisTickMark MinorTickMark
{
get
{
- return toAxisTickMark(GetMinorCTTickMark());
+ return ToAxisTickMark(GetMinorCTTickMark());
}
set
{
- GetMinorCTTickMark().val = fromAxisTickMark(value);
+ GetMinorCTTickMark().val = FromAxisTickMark(value);
}
}
@@ -251,8 +251,11 @@ public AxisTickMark MinorTickMark
protected abstract CT_Boolean GetDelete();
protected abstract CT_TickMark GetMajorCTTickMark();
protected abstract CT_TickMark GetMinorCTTickMark();
+ public abstract CT_ChartLines GetMajorGridLines();
- private static ST_Orientation fromAxisOrientation(AxisOrientation orientation)
+ public abstract bool HasNumberFormat();
+
+ private static ST_Orientation FromAxisOrientation(AxisOrientation orientation)
{
switch (orientation)
{
@@ -263,7 +266,7 @@ private static ST_Orientation fromAxisOrientation(AxisOrientation orientation)
}
}
- private static AxisOrientation toAxisOrientation(CT_Orientation ctOrientation)
+ private static AxisOrientation ToAxisOrientation(CT_Orientation ctOrientation)
{
switch (ctOrientation.val)
{
@@ -274,7 +277,7 @@ private static AxisOrientation toAxisOrientation(CT_Orientation ctOrientation)
}
}
- private static ST_Crosses fromAxisCrosses(AxisCrosses crosses)
+ private static ST_Crosses FromAxisCrosses(AxisCrosses crosses)
{
switch (crosses)
{
@@ -286,7 +289,7 @@ private static ST_Crosses fromAxisCrosses(AxisCrosses crosses)
}
}
- private static AxisCrosses toAxisCrosses(CT_Crosses ctCrosses)
+ private static AxisCrosses ToAxisCrosses(CT_Crosses ctCrosses)
{
switch (ctCrosses.val)
{
@@ -298,7 +301,7 @@ private static AxisCrosses toAxisCrosses(CT_Crosses ctCrosses)
}
}
- private static ST_AxPos fromAxisPosition(AxisPosition position)
+ private static ST_AxPos FromAxisPosition(AxisPosition position)
{
switch (position)
{
@@ -311,7 +314,7 @@ private static ST_AxPos fromAxisPosition(AxisPosition position)
}
}
- private static AxisPosition toAxisPosition(CT_AxPos ctAxPos)
+ private static AxisPosition ToAxisPosition(CT_AxPos ctAxPos)
{
switch (ctAxPos.val)
{
@@ -322,7 +325,7 @@ private static AxisPosition toAxisPosition(CT_AxPos ctAxPos)
default: return AxisPosition.Bottom;
}
}
- private static ST_TickMark fromAxisTickMark(AxisTickMark tickMark)
+ private static ST_TickMark FromAxisTickMark(AxisTickMark tickMark)
{
switch (tickMark)
{
@@ -335,7 +338,7 @@ private static ST_TickMark fromAxisTickMark(AxisTickMark tickMark)
}
}
- private static AxisTickMark toAxisTickMark(CT_TickMark ctTickMark)
+ private static AxisTickMark ToAxisTickMark(CT_TickMark ctTickMark)
{
switch (ctTickMark.val)
{
diff --git a/ooxml/XSSF/UserModel/Charts/XSSFDateAxis.cs b/ooxml/XSSF/UserModel/Charts/XSSFDateAxis.cs
index 61e1081e2..5af8e6a51 100644
--- a/ooxml/XSSF/UserModel/Charts/XSSFDateAxis.cs
+++ b/ooxml/XSSF/UserModel/Charts/XSSFDateAxis.cs
@@ -1,4 +1,21 @@
-using NPOI.OpenXmlFormats.Dml.Chart;
+/* ====================================================================
+ 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.
+==================================================================== */
+
+using NPOI.OpenXmlFormats.Dml.Chart;
using NPOI.SS.UserModel.Charts;
using System;
using System.Collections.Generic;
@@ -14,7 +31,7 @@ public XSSFDateAxis(XSSFChart chart, long id, AxisPosition pos)
: base(chart)
{
- createAxis(id, pos);
+ CreateAxis(id, pos);
}
public XSSFDateAxis(XSSFChart chart, CT_DateAx ctDateAx)
@@ -84,7 +101,7 @@ protected override CT_TickMark GetMinorCTTickMark()
return ctDateAx.minorTickMark;
}
- protected CT_ChartLines GetMajorGridLines()
+ public override CT_ChartLines GetMajorGridLines()
{
return ctDateAx.majorGridlines;
}
@@ -94,14 +111,10 @@ public override void CrossAxis(IChartAxis axis)
ctDateAx.crossAx.val = (uint)axis.Id;
}
- public CT_TimeUnit GetBaseTimeUnit()
+ public CT_TimeUnit BaseTimeUnit
{
- return ctDateAx.baseTimeUnit;
- }
-
- public void SetBaseTimeUnit(CT_TimeUnit unit)
- {
- ctDateAx.baseTimeUnit = unit;
+ get { return ctDateAx.baseTimeUnit; }
+ set { ctDateAx.baseTimeUnit = value;}
}
public void SetAuto(CT_Boolean au)
@@ -109,7 +122,7 @@ public void SetAuto(CT_Boolean au)
ctDateAx.auto = au;
}
- private void createAxis(long id, AxisPosition pos)
+ private void CreateAxis(long id, AxisPosition pos)
{
ctDateAx = chart.GetCTChart().plotArea.AddNewDateAx();
ctDateAx.AddNewAxId().val = (uint)id;
@@ -130,5 +143,10 @@ private void createAxis(long id, AxisPosition pos)
this.MajorTickMark = (AxisTickMark.Cross);
this.MinorTickMark = (AxisTickMark.None);
}
+
+ public override bool HasNumberFormat()
+ {
+ return ctDateAx.IsSetNumFmt();
+ }
}
}
diff --git a/ooxml/XSSF/UserModel/Charts/XSSFValueAxis.cs b/ooxml/XSSF/UserModel/Charts/XSSFValueAxis.cs
index c28a161d0..ad0ea59fc 100644
--- a/ooxml/XSSF/UserModel/Charts/XSSFValueAxis.cs
+++ b/ooxml/XSSF/UserModel/Charts/XSSFValueAxis.cs
@@ -55,7 +55,7 @@ public override long Id
public void SetCrossBetween(AxisCrossBetween crossBetween)
{
- ctValAx.crossBetween.val= fromCrossBetween(crossBetween);
+ ctValAx.crossBetween.val= FromCrossBetween(crossBetween);
}
public AxisCrossBetween GetCrossBetween()
@@ -106,6 +106,10 @@ protected override CT_Crosses GetCTCrosses()
{
return ctValAx.crosses;
}
+ public override CT_ChartLines GetMajorGridLines()
+ {
+ return ctValAx.majorGridlines;
+ }
public override void CrossAxis(IChartAxis axis)
{
@@ -135,7 +139,7 @@ private void CreateAxis(long id, AxisPosition pos)
MinorTickMark=(AxisTickMark.None);
}
- private static ST_CrossBetween fromCrossBetween(AxisCrossBetween crossBetween)
+ private static ST_CrossBetween FromCrossBetween(AxisCrossBetween crossBetween)
{
switch (crossBetween)
{
@@ -156,5 +160,10 @@ private static AxisCrossBetween ToCrossBetween(ST_CrossBetween ctCrossBetween)
throw new ArgumentException();
}
}
+
+ public override bool HasNumberFormat()
+ {
+ return ctValAx.IsSetNumFmt();
+ }
}
}
diff --git a/ooxml/XSSF/UserModel/XSSFChart.cs b/ooxml/XSSF/UserModel/XSSFChart.cs
index eb43b5ade..e59886e49 100644
--- a/ooxml/XSSF/UserModel/XSSFChart.cs
+++ b/ooxml/XSSF/UserModel/XSSFChart.cs
@@ -383,6 +383,7 @@ private bool HasAxis()
private void ParseAxis()
{
ParseCategoryAxis();
+ ParseDateAxis();
ParseValueAxis();
}
private void ParseCategoryAxis()
@@ -394,6 +395,17 @@ private void ParseCategoryAxis()
axis.Add(new XSSFCategoryAxis(this, catAx));
}
}
+
+ private void ParseDateAxis()
+ {
+ if (chart.plotArea.dateAx == null)
+ return;
+ foreach (CT_DateAx dateAx in chart.plotArea.dateAx)
+ {
+ axis.Add(new XSSFDateAxis(this, dateAx));
+ }
+ }
+
private void ParseValueAxis()
{
if (chart.plotArea.valAx == null)
diff --git a/testcases/ooxml/XSSF/Streaming/TestSXSSFWorkbook.cs b/testcases/ooxml/XSSF/Streaming/TestSXSSFWorkbook.cs
index 3080e8aeb..addbfcecd 100644
--- a/testcases/ooxml/XSSF/Streaming/TestSXSSFWorkbook.cs
+++ b/testcases/ooxml/XSSF/Streaming/TestSXSSFWorkbook.cs
@@ -613,6 +613,20 @@ public void CreateFromReadOnlyWorkbook()
ClassicAssert.AreEqual("Test Row 9", s.GetRow(9).GetCell(2).StringCellValue);
}
+ [Test]
+ public void Test56557()
+ {
+ IWorkbook wb = XSSFTestDataSamples.OpenSampleWorkbook("56557.xlsx");
+
+ // Using streaming XSSFWorkbook makes the output file invalid
+ wb = new SXSSFWorkbook((XSSFWorkbook)wb);
+
+ // Should not throw POIXMLException: java.io.IOException: Unable to parse xml bean when reading back
+ IWorkbook wbBack = XSSFTestDataSamples.WriteOutAndReadBack(wb);
+ ClassicAssert.IsNotNull(wbBack);
+ wbBack.Close();
+
+ wb.Close();
+ }
}
-
}
\ No newline at end of file
diff --git a/testcases/ooxml/XSSF/UserModel/TestXSSFDateAxis.cs b/testcases/ooxml/XSSF/UserModel/TestXSSFDateAxis.cs
new file mode 100644
index 000000000..4dd7f2fb1
--- /dev/null
+++ b/testcases/ooxml/XSSF/UserModel/TestXSSFDateAxis.cs
@@ -0,0 +1,50 @@
+/* ====================================================================
+ 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.
+==================================================================== */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NPOI.XSSF.UserModel;
+using NPOI.SS.UserModel.Charts;
+using NPOI.XSSF.UserModel.Charts;
+using NUnit.Framework;
+using NUnit.Framework.Legacy;
+
+namespace TestCases.XSSF.UserModel
+{
+ [TestFixture]
+ internal class TestXSSFDateAxis
+ {
+ [Test]
+ public void TestAccessMethods()
+ {
+ XSSFWorkbook wb = new XSSFWorkbook();
+ XSSFSheet sheet = wb.CreateSheet() as XSSFSheet;
+ XSSFDrawing Drawing = sheet.CreateDrawingPatriarch() as XSSFDrawing;
+ XSSFClientAnchor anchor = Drawing.CreateAnchor(0, 0, 0, 0, 1, 1, 10, 30) as XSSFClientAnchor;
+ XSSFChart chart = Drawing.CreateChart(anchor) as XSSFChart;
+ XSSFDateAxis axis = chart.ChartAxisFactory.CreateDateAxis(AxisPosition.Bottom) as XSSFDateAxis;
+
+ axis.Crosses = AxisCrosses.AutoZero;
+ ClassicAssert.AreEqual(axis.Crosses, AxisCrosses.AutoZero);
+
+ ClassicAssert.AreEqual(chart.GetAxis().Count, 1);
+ }
+ }
+}
\ No newline at end of file
diff --git a/testcases/ooxml/XSSF/XSSFTestDataSamples.cs b/testcases/ooxml/XSSF/XSSFTestDataSamples.cs
index 77554ba63..e36198a45 100644
--- a/testcases/ooxml/XSSF/XSSFTestDataSamples.cs
+++ b/testcases/ooxml/XSSF/XSSFTestDataSamples.cs
@@ -25,7 +25,9 @@ limitations under the License.
using NPOI.HSSF;
using TestCases.HSSF;
using System.Diagnostics;
-using NUnit.Framework;using NUnit.Framework.Legacy;
+using NUnit.Framework;
+using NUnit.Framework.Legacy;
+using NPOI.XSSF.Streaming;
namespace NPOI.XSSF
{
@@ -86,6 +88,10 @@ public static IWorkbook WriteOutAndReadBack(IWorkbook wb)
sw2.Stop();
Debug.WriteLine("XSSFWorkbook parse time: " + sw2.ElapsedMilliseconds + "ms");
}
+ else if (wb is SXSSFWorkbook)
+ {
+ result = new SXSSFWorkbook(new XSSFWorkbook(is1));
+ }
else
{
throw new RuntimeException("Unexpected workbook type ("
diff --git a/testcases/test-data/spreadsheet/56557.xlsx b/testcases/test-data/spreadsheet/56557.xlsx
new file mode 100644
index 000000000..7ca891cf5
Binary files /dev/null and b/testcases/test-data/spreadsheet/56557.xlsx differ