Skip to content

Commit

Permalink
Merge pull request #1119 from nissl-lab/Enable-getting-DateOnly-CellV…
Browse files Browse the repository at this point in the history
…alue

Add DateOnlyCellValue and TimeOnlyCellValue
  • Loading branch information
tonyqus committed Jul 26, 2023
2 parents 995f5f1 + 540aef4 commit fd8103d
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 43 deletions.
49 changes: 29 additions & 20 deletions main/HSSF/UserModel/HSSFCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -850,44 +850,53 @@ private void CheckFormulaCachedValueType(CellType expectedTypeCode, FormulaRecor

/// <summary>
/// Get the value of the cell as a date. For strings we throw an exception.
/// For blank cells we return a null.
/// For non-Numeric cells including blank cell we return a null.
/// </summary>
/// <value>The date cell value.</value>
public DateTime DateCellValue
public DateTime? DateCellValue
{
get
{
if (cellType == CellType.Blank)
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return DateTime.MaxValue;
return null;
}
if (cellType == CellType.String)
{
throw new InvalidDataException(
"You cannot get a date value from a String based cell");
}
if (cellType == CellType.Boolean)
{
throw new InvalidDataException(
"You cannot get a date value from a bool cell");
}
if (cellType == CellType.Error)
double value = this.NumericCellValue;
return DateUtil.GetJavaDate(value, book.IsDate1904());
}
}
#if NET6_0_OR_GREATER
public DateOnly? DateOnlyCellValue
{
get{
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
throw new InvalidDataException(
"You cannot get a date value from an error cell");
return null;
}
double value = this.NumericCellValue;
if (book.IsDate1904())
{
return DateUtil.GetJavaDate(value, true);
return DateOnly.FromDateTime(DateUtil.GetJavaDate(value, true));
}
else
{
return DateUtil.GetJavaDate(value, false);
return DateOnly.FromDateTime(DateUtil.GetJavaDate(value, false));
}
}
}
public TimeOnly? TimeOnlyCellValue
{
get{
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return null;
}
double value = NumericCellValue;
bool date1904 = Sheet.Workbook.IsDate1904();
return TimeOnly.FromDateTime(DateUtil.GetJavaDate(value, date1904));
}
}

#endif
/// <summary>
/// Get the value of the cell as a string - for numeric cells we throw an exception.
/// For blank cells we return an empty string.
Expand Down
2 changes: 1 addition & 1 deletion main/SS/Format/CellFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public CellFormatResult Apply(ICell c)
{
if (DateUtil.IsValidExcelDate(value))
{
return Apply(c.DateCellValue, value);
return Apply((DateTime)c.DateCellValue, value);
}
else
{
Expand Down
15 changes: 12 additions & 3 deletions main/SS/UserModel/Cell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,21 @@ CellType CellType
double NumericCellValue { get; }

/// <summary>
/// Get the value of the cell as a date.
/// Get the value of the cell as a date. For non-Numeric cells including blank cell we return a null.
/// </summary>
/// <exception cref="InvalidOperationException">if the cell type returned by GetCellType() is CELL_TYPE_STRING</exception>
/// <exception cref="FormatException">if the cell value isn't a parsable double</exception>
DateTime DateCellValue { get; }

DateTime? DateCellValue { get; }
#if NET6_0_OR_GREATER
/// <summary>
/// Get DateOnly-type cell value
/// </summary>
DateOnly? DateOnlyCellValue { get; }
/// <summary>
/// Get TimeOnly-type cell value
/// </summary>
TimeOnly? TimeOnlyCellValue { get; }
#endif
/// <summary>
/// Get the value of the cell RichTextString
/// </summary>
Expand Down
6 changes: 4 additions & 2 deletions main/SS/UserModel/DataFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -842,8 +842,10 @@ private String GetFormattedDateString(ICell cell)
cell.NumericCellValue
);
}
DateTime d = cell.DateCellValue;
return PerformDateFormatting(d, dateFormat);
var d = cell.DateCellValue;
if (d == null)
return "";
return PerformDateFormatting((DateTime)d, dateFormat);
}

/**
Expand Down
45 changes: 37 additions & 8 deletions ooxml/XSSF/Streaming/SXSSFCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ the License. You may obtain a copy of the License at
limitations under the License.
==================================================================== */
using System;
using System.IO;
using NPOI.SS;
using NPOI.SS.Formula.Eval;
using NPOI.SS.UserModel;
Expand Down Expand Up @@ -196,23 +197,51 @@ public int ColumnIndex
return _row.GetCellIndex(this);
}
}

public DateTime DateCellValue
/// <summary>
/// Get DateTime-type cell value
/// </summary>
public DateTime? DateCellValue
{
get
{
CellType cellType = _value.GetType();
if (cellType == CellType.Blank)
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return new DateTime();
return null;
}

double value = NumericCellValue;
bool date1904 = Sheet.Workbook.IsDate1904();
return DateUtil.GetJavaDate(value, date1904);
return DateUtil.GetJavaDate(value,date1904);
}
}

#if NET6_0_OR_GREATER
/// <summary>
/// Get DateOnly-type cell value
/// </summary>
public DateOnly? DateOnlyCellValue
{
get{
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return null;
}
double value = NumericCellValue;
bool date1904 = Sheet.Workbook.IsDate1904();
return DateOnly.FromDateTime(DateUtil.GetJavaDate(value, date1904));
}
}
public TimeOnly? TimeOnlyCellValue
{
get{
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return null;
}
double value = NumericCellValue;
bool date1904 = Sheet.Workbook.IsDate1904();
return TimeOnly.FromDateTime(DateUtil.GetJavaDate(value, date1904));
}
}
#endif
public byte ErrorCellValue
{
get
Expand Down
35 changes: 32 additions & 3 deletions ooxml/XSSF/UserModel/XSSFCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ limitations under the License.
using NPOI.Util;
using NPOI.SS.Formula.Eval;
using System.Globalization;
using System.IO;

namespace NPOI.XSSF.UserModel
{

Expand Down Expand Up @@ -827,20 +829,47 @@ private CellType GetBaseCellType(bool blankCells)
/// <summary>
/// Get the value of the cell as a date.
/// </summary>
public DateTime DateCellValue
public DateTime? DateCellValue
{
get
{
if (CellType == CellType.Blank)
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return DateTime.MinValue;
return null;
}

double value = NumericCellValue;
bool date1904 = Sheet.Workbook.IsDate1904();
return DateUtil.GetJavaDate(value, date1904);
}
}
#if NET6_0_OR_GREATER
public DateOnly? DateOnlyCellValue
{
get{
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return null;
}
double value = NumericCellValue;
bool date1904 = Sheet.Workbook.IsDate1904();
return DateOnly.FromDateTime(DateUtil.GetJavaDate(value, date1904));
}
}

public TimeOnly? TimeOnlyCellValue
{
get{
if (CellType != CellType.Numeric && CellType != CellType.Formula)
{
return null;
}
double value = NumericCellValue;
bool date1904 = Sheet.Workbook.IsDate1904();
return TimeOnly.FromDateTime(DateUtil.GetJavaDate(value, date1904));
}
}
#endif
public void SetCellValue(DateTime? value)
{
if (value == null)
Expand Down
23 changes: 21 additions & 2 deletions testcases/main/HSSF/UserModel/TestHSSFCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ private static void SetCell(HSSFWorkbook workbook, int rowIdx, int colIdx, DateT
cell.SetCellValue(date);
}

private static DateTime ReadCell(HSSFWorkbook workbook, int rowIdx, int colIdx)
private static DateTime? ReadCell(HSSFWorkbook workbook, int rowIdx, int colIdx)
{
NPOI.SS.UserModel.ISheet sheet = workbook.GetSheetAt(0);
IRow row = sheet.GetRow(rowIdx);
Expand Down Expand Up @@ -485,7 +485,7 @@ public void TestCellType()
HSSFCell cell = row.CreateCell(0) as HSSFCell;

cell.SetCellType(CellType.Blank);
Assert.AreEqual("9999-12-31 23:59:59.999", cell.DateCellValue.ToString("yyyy-MM-dd HH:mm:ss.fff"));
Assert.IsNull(cell.DateCellValue);
Assert.IsFalse(cell.BooleanCellValue);
Assert.AreEqual("", cell.ToString());

Expand Down Expand Up @@ -520,6 +520,25 @@ public void TestCellType()
cell.SetCellValue((IRichTextString)null);
wb.Close();
}

[Test]
public void TestGetDateTimeCellValue()
{
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.CreateSheet() as HSSFSheet;
HSSFRow row = sheet.CreateRow(0) as HSSFRow;
HSSFCell cell = row.CreateCell(0) as HSSFCell;
cell.SetCellValue(new DateTime(2022, 5, 10, 13, 20, 50));
Assert.IsNotNull(cell.DateCellValue);
Assert.AreEqual(new DateTime(2022, 5, 10, 13, 20, 50), cell.DateCellValue);
#if NET6_0_OR_GREATER
Assert.AreEqual(new DateOnly(2022, 5, 10), cell.DateOnlyCellValue);
Assert.AreEqual(new TimeOnly(13, 20, 50), cell.TimeOnlyCellValue);
#endif
HSSFCell cell2 = row.CreateCell(1) as HSSFCell;
cell2.SetCellValue("test");
Assert.IsNull(cell2.DateCellValue);
}
}

}
2 changes: 1 addition & 1 deletion testcases/main/HSSF/UserModel/TestHSSFDateUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ public void TestBug19172()

cell.SetCellValue(valueToTest);

DateTime returnedValue = cell.DateCellValue;
DateTime returnedValue = (DateTime)cell.DateCellValue;

Assert.AreEqual(valueToTest.TimeOfDay, returnedValue.TimeOfDay);
}
Expand Down
4 changes: 2 additions & 2 deletions testcases/main/SS/UserModel/BaseTestCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,13 @@ public void TestSetValues()

DateTime dt = DateTime.Now.AddMilliseconds(123456789);
cell.SetCellValue(dt);
Assert.IsTrue((dt.Ticks - cell.DateCellValue.Ticks) >= -20000);
Assert.IsTrue((dt.Ticks - ((DateTime)cell.DateCellValue).Ticks) >= -20000);
Assert.AreEqual(CellType.Numeric, cell.CellType);
AssertProhibitedValueAccess(cell, CellType.Boolean, CellType.String,
CellType.Formula, CellType.Error);

cell.SetCellValue(dt);
Assert.IsTrue((dt.Ticks - cell.DateCellValue.Ticks) >= -20000);
Assert.IsTrue((dt.Ticks - ((DateTime)cell.DateCellValue).Ticks) >= -20000);
Assert.AreEqual(CellType.Numeric, cell.CellType);
AssertProhibitedValueAccess(cell, CellType.Boolean, CellType.String,
CellType.Formula, CellType.Error);
Expand Down
2 changes: 1 addition & 1 deletion testcases/ooxml/XSSF/UserModel/TestXSSFWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,7 @@ public void TestBug56957CloseWorkbook()

// read-only mode works!
workbook = WorkbookFactory.Create(OPCPackage.Open(file, PackageAccess.READ));
DateTime dateAct = workbook.GetSheetAt(0).GetRow(0).GetCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).DateCellValue;
var dateAct = workbook.GetSheetAt(0).GetRow(0).GetCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).DateCellValue;
Assert.AreEqual(dateExp, dateAct);
workbook.Close();
workbook = null;
Expand Down

0 comments on commit fd8103d

Please sign in to comment.