如何使用 Spreadsheet Gear C# 将 IRange 中所有日期格式的单元格转换为 DateTime?
How to convert all date-formatted cells in IRange to DateTime using Spreadsheet Gear C#?
我正在尝试使用 Spreadsheet Gear 读取 Excel 文件的使用范围,目前我已将其设置为执行此操作:
var workbook = Factory.GetWorkbookSet().Workbooks.OpenFromStream(fileStreamInput);
var sheet = workbook.Worksheets[0];
var values = sheet.Cells[sheet.UsedRange.Address].Value;
Excel 文件将由使用不同列格式的人上传,因此此代码需要与类型无关...日期除外。此代码引入 Excel 存储日期的双重表示,我不希望这样。我知道以下行会将双精度转换为日期:
workbook.NumberToDateTime(dateAsADouble);
但是,这假设我事先知道哪个单元格是日期格式的,但我永远不会知道。我希望能够使用此方法转换 values
中存储的所有日期双精度单元格,理想情况下无需单独遍历每个值,但如果没有别的,我会接受这样的答案。我以为我可以使用 Linq,但 SpreadsheetGear 的 IRange
class 似乎不支持 Linq。
有办法吗?也许是一种测试单元格是否为双重日期的方法?我在 SpreadsheetGear 的 API.
中没有找到类似的东西
您无法仅根据 IRange.Value 来确定给定的双精度值是用于序列日期还是仅用作简单的数值。 "date" 或 "datetime" 或 "time" 单元格只是一个具有数值的单元格,该数值应用了特定的 NumberFormat,formats 此单元格的值作为约会。
我想您可以查找数值在特定范围内的单元格,这些单元格可能适合 "valid" 日期(即 2017 年 11 月 2 日的序列数值为 43041),但是这绝不是一个非常可靠或确定的方法。
要确定何时需要对给定单元格的数值使用 IWorkbook.NumberToDateTime(...)
,您还必须考虑单元格的 NumberFormat。对于大多数情况,您可以通过检查单元格的 IRange.NumberFormatType property, which will return NumberFormatType.Date / DateTime / Time 来执行此操作,前提是单元格的 NumberFormat 与 "date/time" 类型(例如 "m/d/yyyy"、[=27)匹配=]、"h:mm:ss" 等。这种方法需要遍历范围。示例:
// Get used range.
IRange usedRange = sheet.UsedRange;
// Setup 2D object array to copy cell values into.
object[,] values = new object[usedRange.RowCount, usedRange.ColumnCount];
// Loop through range in row groups.
for (int row = 0; row < usedRange.RowCount; row++)
{
// Loop through each column in a single row.
for (int col = 0; col < usedRange.ColumnCount; col++)
{
// Get current cell.
IRange cell = usedRange[row, col];
object cellVal;
// Special Case: Number formatted as dates/dateTimes/times.
if (cell.ValueType == SpreadsheetGear.ValueType.Number)
{
// Cells formatted as a Date, DateTime or Time
if (cell.NumberFormatType == NumberFormatType.Date || cell.NumberFormatType == NumberFormatType.DateTime || cell.NumberFormatType == NumberFormatType.Time)
{
DateTime dateTime = workbook.NumberToDateTime((double)cell.Value);
Console.WriteLine($"Found a 'date' or 'datetime' or 'time' cell - {cell.Address} - {dateTime.ToString()}");
cellVal = dateTime;
}
// For any other numeric value, copy as-is.
else
{
cellVal = cell.Value;
}
}
// For all other ValueTypes (Text / Logical / Empty / Error), copy as-is.
else
cellVal = cell.Value;
// Set object[,] value.
values[row, col] = cellVal;
}
}
我正在尝试使用 Spreadsheet Gear 读取 Excel 文件的使用范围,目前我已将其设置为执行此操作:
var workbook = Factory.GetWorkbookSet().Workbooks.OpenFromStream(fileStreamInput);
var sheet = workbook.Worksheets[0];
var values = sheet.Cells[sheet.UsedRange.Address].Value;
Excel 文件将由使用不同列格式的人上传,因此此代码需要与类型无关...日期除外。此代码引入 Excel 存储日期的双重表示,我不希望这样。我知道以下行会将双精度转换为日期:
workbook.NumberToDateTime(dateAsADouble);
但是,这假设我事先知道哪个单元格是日期格式的,但我永远不会知道。我希望能够使用此方法转换 values
中存储的所有日期双精度单元格,理想情况下无需单独遍历每个值,但如果没有别的,我会接受这样的答案。我以为我可以使用 Linq,但 SpreadsheetGear 的 IRange
class 似乎不支持 Linq。
有办法吗?也许是一种测试单元格是否为双重日期的方法?我在 SpreadsheetGear 的 API.
中没有找到类似的东西您无法仅根据 IRange.Value 来确定给定的双精度值是用于序列日期还是仅用作简单的数值。 "date" 或 "datetime" 或 "time" 单元格只是一个具有数值的单元格,该数值应用了特定的 NumberFormat,formats 此单元格的值作为约会。
我想您可以查找数值在特定范围内的单元格,这些单元格可能适合 "valid" 日期(即 2017 年 11 月 2 日的序列数值为 43041),但是这绝不是一个非常可靠或确定的方法。
要确定何时需要对给定单元格的数值使用 IWorkbook.NumberToDateTime(...)
,您还必须考虑单元格的 NumberFormat。对于大多数情况,您可以通过检查单元格的 IRange.NumberFormatType property, which will return NumberFormatType.Date / DateTime / Time 来执行此操作,前提是单元格的 NumberFormat 与 "date/time" 类型(例如 "m/d/yyyy"、[=27)匹配=]、"h:mm:ss" 等。这种方法需要遍历范围。示例:
// Get used range.
IRange usedRange = sheet.UsedRange;
// Setup 2D object array to copy cell values into.
object[,] values = new object[usedRange.RowCount, usedRange.ColumnCount];
// Loop through range in row groups.
for (int row = 0; row < usedRange.RowCount; row++)
{
// Loop through each column in a single row.
for (int col = 0; col < usedRange.ColumnCount; col++)
{
// Get current cell.
IRange cell = usedRange[row, col];
object cellVal;
// Special Case: Number formatted as dates/dateTimes/times.
if (cell.ValueType == SpreadsheetGear.ValueType.Number)
{
// Cells formatted as a Date, DateTime or Time
if (cell.NumberFormatType == NumberFormatType.Date || cell.NumberFormatType == NumberFormatType.DateTime || cell.NumberFormatType == NumberFormatType.Time)
{
DateTime dateTime = workbook.NumberToDateTime((double)cell.Value);
Console.WriteLine($"Found a 'date' or 'datetime' or 'time' cell - {cell.Address} - {dateTime.ToString()}");
cellVal = dateTime;
}
// For any other numeric value, copy as-is.
else
{
cellVal = cell.Value;
}
}
// For all other ValueTypes (Text / Logical / Empty / Error), copy as-is.
else
cellVal = cell.Value;
// Set object[,] value.
values[row, col] = cellVal;
}
}