如何使用 Spreadsheet Gear C# 将 IRange 中所有日期格式的单元格转换为 DateTime?

Cas*_*ngs 1 c# linq excel datetime spreadsheetgear

我正在尝试使用电子表格齿轮读取 Excel 文件的使用范围,目前我已将其设置为执行此操作:

var workbook = Factory.GetWorkbookSet().Workbooks.OpenFromStream(fileStreamInput);
var sheet = workbook.Worksheets[0];
var values = sheet.Cells[sheet.UsedRange.Address].Value;
Run Code Online (Sandbox Code Playgroud)

Excel 文件将由使用不同列格式的人上传,因此此代码需要与类型无关……日期除外。这段代码引入了 Excel 存储日期的双重表示,我不希望这样。我知道以下行会将双精度值转换为日期:

workbook.NumberToDateTime(dateAsADouble);
Run Code Online (Sandbox Code Playgroud)

但是,这假设我事先知道哪个单元格是日期格式的,而我永远不会。我希望能够values使用这种方法转换存储在其中的所有日期双精度单元格,理想情况下不需要单独循环遍历每个值,但如果没有别的,我会接受这样的答案。我以为我可以使用 Linq,但似乎 SpreadsheetGear 的IRange类不支持 Linq。

有没有办法做到这一点?也许是一种测试单元格是否为日期双精度的方法?我在 SpreadsheetGear 的 API 中没有找到类似的东西。

Tim*_*sen 5

您将无法仅从 IRange.Value 确定给定的双精度值是用于序列日期还是仅用作简单的数字值。“日期”或“日期时间”或“时间”单元格只是一个带有数值的单元格,该数值应用了特定的 NumberFormat,将该单元格的值格式化为日期。

我想您可以查找在特定范围内具有数值的单元格,这些单元格可能是“有效”日期的良好候选者(即 2017 年 11 月 2 日的序列数值为 43041),但这绝不是可靠或确定的方法。

要确定何时需要IWorkbook.NumberToDateTime(...)在给定单元格的数值上使用,您还必须考虑单元格的 NumberFormat。在大多数情况下,您可以通过检查单元格的 IRange 来执行此操作。NumberFormatType属性,这将返回NumberFormatType .Date /日期时间/时间如果小区具有一个“日期/时间”一致的输入的NumberFormat诸如“M / d / yyyy的”, “M / d / yyyy的H:MM”,“ 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;
    }
}
Run Code Online (Sandbox Code Playgroud)