【问题标题】:C#. xlsx date cell import to DataTable by NPOI 2.0C#。 NPOI 2.0 将 xlsx 日期单元格导入 DataTable
【发布时间】:2013-02-23 12:32:46
【问题描述】:

我尝试使用 NPOI 2.0 库将 .xlsx 文件转换为 DataTable 格式。没关系,但是我在转换为字符串日期单元格时遇到了问题。当我尝试使用 row.GetCell(j).ToString() 之类的构造时 - 它抛出异常“无法从文本单元格获取数值”。我尝试使用 DateCellValue 属性,但它也抛出了这个异常。使用其他单元格格式效果很好。 功能,我用的是:

private DataTable xlsxToDT(string fileName)
    {
        DataTable table = new DataTable();
        XSSFWorkbook workbook = new XSSFWorkbook(new FileStream(fileName, FileMode.Open, FileAccess.Read));
        ISheet sheet = workbook.GetSheetAt(0);
        IRow headerRow = sheet.GetRow(0);
        int cellCount = headerRow.LastCellNum;
        for (int i = headerRow.FirstCellNum; i < cellCount; i++)
        {
            DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
            table.Columns.Add(column);
        }
        int rowCount = sheet.LastRowNum;
        for (int i = (sheet.FirstRowNum); i < sheet.LastRowNum; i++)
        {
            IRow row = sheet.GetRow(i);
            DataRow dataRow = table.NewRow();
            for (int j = row.FirstCellNum; j < cellCount; j++)
            {
                if (row.GetCell(j) != null)
                {
                    //EXCEPTION GENERATING IN THIS CODE
                    dataRow[j] = row.GetCell(j).ToString();
                    ////////////////////////////
                }
            }
            table.Rows.Add(dataRow);
        }
        workbook = null;
        sheet = null;
        return table;
    }

更新: 如果我插入类似的代码

row.GetCell(j).SetCellType(CellType.STRING);

在问题单元格中,我的值类似于“36496.392581018517”。另一个单元格转换正确

【问题讨论】:

  • 我用日期单元格试了一下,没有出现错误。你的单元格内容是什么?
  • MD.Unicorn,02.12.1999 9:25:19。单元格属性写的是日期格式,但现在我看到如果我复制和粘贴单元格(不是单元格值) - 它只粘贴“02.12.1999”...
  • 这似乎没有什么问题。 CellType 的值是多少?
  • MD.Unicorn,CellType 为 NUMERIC,但 NumericCellValue 抛出“无法从文本单元格获取数值”异常
  • 如果你把你的excel上传到某个地方,我会看看。

标签: c# excel apache-poi xlsx npoi


【解决方案1】:

您的 Excel 文件的第二列具有日期格式 (12/2/1999)。 NPOI 在您当前的文化(“ru-RU”)中无法识别此格式。这似乎是 NPOI 中的一个错误,因为当这种情况发生时,无法从该单元格中读取任何内容。我想到的唯一方法是在读取 excel 文件之前更改线程的文化(并在之后将其更改回来):

private DataTable xlsxToDT(string fileName)
{
    var prevCulture = Thread.CurrentThread.CurrentCulture;
    Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
    try
    {
        // Put your whole method body here.
    }
    finally
    {
        Thread.CurrentThread.CurrentCulture = prevCulture;
    }
}

【讨论】:

    【解决方案2】:
    ICell cell = row.GetCell(j);
    if (cell != null)
    {
        switch (cell.CellType)
        {
            case CellType.String:
                dataRow[j] = cell.StringCellValue;
                break;
            case CellType.Numeric:
                dataRow[j] = cell.NumericCellValue;
                break;
            case CellType.Boolean:
                dataRow[j] = cell.BooleanCellValue;
                break;
            default: dataRow[j] = "ERROR";
                break;
        }
    }
    

    【讨论】:

    • 如果是Numeric,最好用DateUtil.IsCellDateFormatted(cell)检查是否是日期。如果是,dataRow[j] = cell.DateCellValue;
    • 如果DateUtil.IsCellDateFormatted(cell) 为真,但cell.DateCellValue 返回System.NullReferenceException 怎么办?
    【解决方案3】:

    我的解决方案是像这样创建函数 getValue

    FileStream fs = new FileStream(@"\export.xlsx", FileMode.Open);
    XSSFWorkbook wb = new XSSFWorkbook(fs);
    ISheet sheet = wb.GetSheetAt(0);
    // GetValue here
    string text = getValueFromCell(sheet.GetRow(row).GetCell(1));
    
    public string getValueFromCell(ICell cell) {
                string output ="";
                if (cell != null)
                {
                    switch (cell.CellType)
                    {
                        case CellType.String:
                            output = cell.StringCellValue;
                            break;
                        case CellType.Numeric:
                            //dataRow[j] = cell.NumericCellValue;
                            output = cell.NumericCellValue.ToString();
                            break;
                        case CellType.Boolean:
                            output = cell.BooleanCellValue.ToString();
                            //dataRow[j] = cell.BooleanCellValue;
                            break;
                        default:
                            output = "";
                            break;
                    }
                }
                return output;
            }
    

    【讨论】:

      【解决方案4】:

      这是 xls 的正确代码

      public DataTable GetDataTableFromExcelFile(string excel_file_Path)
      {
          HSSFWorkbook wb;
          NPOI.SS.UserModel.ISheet sh;
          string Sheet_name;
      
          using (var fs = new FileStream(excel_file_Path, FileMode.Open, FileAccess.Read))
          {
              wb = new HSSFWorkbook(fs);
      
              Sheet_name = wb.GetSheetAt(0).SheetName;  //get first sheet name
          }
          DataTable DT = new DataTable();
          DT.Rows.Clear();
          DT.Columns.Clear();
      
          // get sheet
          sh = wb.GetSheet(Sheet_name);
      
          // add neccessary columns
          if (DT.Columns.Count < sh.GetRow(0).Cells.Count)
          {
              for (int j = 0; j < sh.GetRow(0).Cells.Count; j++)
              {
                  DT.Columns.Add(Convert.ToString(sh.GetRow(0).Cells[j]), typeof(string));
              }
          }
      
          // add row
          DT.Rows.Add();
      
          int i = 1;
          while (sh.GetRow(i) != null)
          {
              // write row value
              for (int j = 0; j < sh.GetRow(i).Cells.Count; j++)
              {
                  var cell = sh.GetRow(i).GetCell(j);
      
                  if (cell != null)
                  {
                      // TODO: you can add more cell types capatibility, e. g. formula
                      switch (cell.CellType)
                      {
                          case CellType.Numeric:
                              DT.Rows[i][j] = sh.GetRow(i).GetCell(j).NumericCellValue;
                              //dataGridView1[j, i].Value = sh.GetRow(i).GetCell(j).NumericCellValue;
      
                              break;
                          case CellType.String:
                              DT.Rows[i-1][j] = sh.GetRow(i).GetCell(j).StringCellValue;
      
                              break;
                      }
                  }
              }
      
              i++;
          }
      
          return DT;
      }
      

      【讨论】:

      猜你喜欢
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多