Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repetition again, could it just be:

var dateTime = DateUtil.FromCellValue(this);
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