欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#通过NPOI操作Excel的实例代码

程序员文章站 2022-06-17 21:19:43
c#操作excel的方法有很多种,常见的有微软官方的ole automation,apache的poi等。这里介绍的是poi翻译成c#的npoi。 poi是apache的...

c#操作excel的方法有很多种,常见的有微软官方的ole automation,apache的poi等。这里介绍的是poi翻译成c#的npoi。

poi是apache的通过java操作office的一个api,可以对excel,word,ppt等进行操作,十分的强大。然后就被翻译成c#版本的npoi了,和log4j与log4net很相似。

好像在npoi的.net4.0版本之前是不支持office2007及以上的xml格式的,但是最新的版本已经支持了。只需要下载并引用下面五个程序集就能使用了。

C#通过NPOI操作Excel的实例代码

这里提供一个操作excel的类,类中提供了4个方法,两个导出,两个导入。可以通过dataset导出拥有多个sheet的excel文件,也可以通过datatable导出拥有一个sheet的excel。导入也是一样,通过指定sheet索引,导出datatable,或者直接导出所有sheet返回一个dataset。

public class excelhelper
  {
    /// <summary>
    /// 根据excel和sheet返回datatable
    /// </summary>
    /// <param name="filepath">excel文件地址</param>
    /// <param name="sheetindex">sheet索引</param>
    /// <returns>datatable</returns>
    public static datatable getdatatable(string filepath, int sheetindex)
    {
      return getdataset(filepath, sheetindex).tables[0];
    }

    /// <summary>
    /// 根据excel返回dataset
    /// </summary>
    /// <param name="filepath">excel文件地址</param>
    /// <param name="sheetindex">sheet索引,可选,默认返回所有sheet</param>
    /// <returns>dataset</returns>
    public static dataset getdataset(string filepath, int? sheetindex = null)
    {
      dataset ds = new dataset();
      iworkbook fileworkbook;
      using (filestream fs = new filestream(filepath, filemode.open, fileaccess.read))
      {
        if (filepath.last() == 's')
        {
          try
          {
            fileworkbook = new hssfworkbook(fs);
          }
          catch (exception ex)
          {
            throw ex;
          }
        }
        else
        {
          try
          {
            fileworkbook = new xssfworkbook(fs);
          }
          catch
          {
            fileworkbook = new hssfworkbook(fs);
          }
        }
      }

      for (int i = 0; i < fileworkbook.numberofsheets; i++)
      {
        if (sheetindex != null && sheetindex != i)
          continue;
        datatable dt = new datatable();
        isheet sheet = fileworkbook.getsheetat(i);

        //表头
        irow header = sheet.getrow(sheet.firstrownum);
        list<int> columns = new list<int>();
        for (int j = 0; j < header.lastcellnum; j++)
        {
          object obj = getvaluetypeforxls(header.getcell(j) as hssfcell);
          if (obj == null || obj.tostring() == string.empty)
          {
            dt.columns.add(new datacolumn("columns" + j.tostring()));
          }
          else
            dt.columns.add(new datacolumn(obj.tostring()));
          columns.add(j);
        }
        //数据
        ienumerator rows = sheet.getenumerator();
        while (rows.movenext())
        {
          int j = sheet.firstrownum + 1;
          datarow dr = dt.newrow();
          bool hasvalue = false;
          foreach (int k in columns)
          {
            dr[k] = getvaluetypeforxls(sheet.getrow(k).getcell(k) as hssfcell);
            if (dr[k] != null && dr[k].tostring() != string.empty)
            {
              hasvalue = true;
            }
          }
          if (hasvalue)
          {
            dt.rows.add(dr);
          }
          j++;
        }
        ds.tables.add(dt);
      }

      return ds;
    }

    /// <summary>
    /// 根据datatable导出excel
    /// </summary>
    /// <param name="dt">datatable</param>
    /// <param name="file">保存地址</param>
    public static void getexcelbydatatable(datatable dt, string file)
    {
      dataset ds = new dataset();
      ds.tables.add(dt);
      getexcelbydataset(ds, file);
    }

    /// <summary>
    /// 根据dataset导出excel
    /// </summary>
    /// <param name="ds">dataset</param>
    /// <param name="file">保存地址</param>
    public static void getexcelbydataset(dataset ds, string file)
    {
      iworkbook fileworkbook = new hssfworkbook();
      int index = 0;
      foreach (datatable dt in ds.tables)
      {
        index++;
        isheet sheet = fileworkbook.createsheet("sheet" + index);

        //表头
        irow row = sheet.createrow(0);
        for (int i = 0; i < dt.columns.count; i++)
        {
          icell cell = row.createcell(i);
          cell.setcellvalue(dt.columns[i].columnname);
        }

        //数据
        for (int i = 0; i < dt.rows.count; i++)
        {
          irow row1 = sheet.createrow(i + 1);
          for (int j = 0; j < dt.columns.count; j++)
          {
            icell cell = row1.createcell(j);
            cell.setcellvalue(dt.rows[i][j].tostring());
          }
        }
      }

      //转为字节数组
      memorystream stream = new memorystream();
      fileworkbook.write(stream);
      var buf = stream.toarray();

      //保存为excel文件
      using (filestream fs = new filestream(file, filemode.create, fileaccess.write))
      {
        fs.write(buf, 0, buf.length);
        fs.flush();
      }
    }

    /// <summary>
    /// 根据单元格将内容返回为对应类型的数据
    /// </summary>
    /// <param name="cell">单元格</param>
    /// <returns>数据</returns>
    private static object getvaluetypeforxls(hssfcell cell)
    {
      if (cell == null)
        return null;
      switch (cell.celltype)
      {
        case celltype.blank: //blank:
          return null;
        case celltype.boolean: //boolean:
          return cell.booleancellvalue;
        case celltype.numeric: //numeric:
          return cell.numericcellvalue;
        case celltype.string: //string:
          return cell.stringcellvalue;
        case celltype.error: //error:
          return cell.errorcellvalue;
        case celltype.formula: //formula:
        default:
          return "=" + cell.cellformula;
      }
    }
  }

这里面可以有一些有意思的操作,比如版本兼容问题。这里通过多态很好的实现了兼容,但是如果是2007版本的xlsm被修改为xsl的后缀怎么办呢,或者2003版本的被修改为xlsm后缀怎么办呢。2003版本改为xlsm还是可以将其视为xls来处理的,但是2007改为xls就不行了。这时候可以强行修改文件的后缀名再打开。

但是上面的代码没有实现这个功能,两个原因:一、这样做不是很安全。二、这时候需要修改系统中其它地方此文件的文件名,放在类中实现不是很方便。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。