C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# NPOI操作Excel

C#使用NPOI操作Excel工具类的实现

作者:rjcql

NPOI是POI项目的.NET迁移版本,使用NPOI可以在没有安装Office或者相应环境的机器上对Word或Excel文档进行读写操作,下面我们就来学习一下如何使用NPOI编写操作Excel的工具类吧

写在前面

NPOI是POI项目的.NET迁移版本。POI是一个开源的Java 读写 Excel、Word 等微软Ole2组件文档的项目;使用NPOI可以在没有安装Office或者相应环境的机器上对Word或Excel文档进行读写操作。

NPOI类库中操作EXCEL有两个模块分别是:

1️.HSSF模块,操作拓展名为.xls的Excel,对应Excel2003及以前的版本。

2️.XSSF模块,操作拓展名为.xlsx的Excel,对应Excel2007及以后的版本,可向下兼容xls,故本例使用XSSF下的XSSFWorkbook来操作。

通过NuGet获取NPOI

需要引用的命名空间如下:

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Collections;
using System.Data;

代码实现

   public class ExcelProcessor
    {
        #region 私有变量
 
        private int _perSheetCount = 40000;//每个sheet要保存的条数
 
        private string _filePath;
 
        private IWorkbook _currentWorkbook;
 
        private List<string> _sheets;
 
        private Dictionary<string, DataTable> _dataDict;
 
        #endregion
 
        #region 属性
 
        public List<string> Sheets
        {
            get { return _sheets ?? (_sheets = GetSheets(_filePath)); }
        }
 
        #endregion
 
        #region 构造器
 
        /// <summary>
        /// 默认构造器
        /// </summary>
        /// <param name="filePath"></param>
        public ExcelProcessor(string filePath)
        {
            _filePath = filePath;
            _dataDict = new Dictionary<string, DataTable>();
        }
 
        /// <summary>
        /// 加载数据
        /// </summary>
        public bool LoadData()
        {
            try
            {
                using (var fs = new FileStream(_filePath, FileMode.OpenOrCreate, FileAccess.Read))
                {
                    _currentWorkbook = new XSSFWorkbook(fs);
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
 
        /// <summary>
        /// 最大接收5万条每页,大于5万时,使用系统默认的值(4万)
        /// </summary>
        /// <param name="perSheetCounts"></param>
        public ExcelProcessor(int perSheetCounts)
        {
            if (_perSheetCount <= 50000)
                _perSheetCount = perSheetCounts;
        }
 
        #endregion
 
        #region 公有方法
 
        public List<string> GetSheets(string fileName)
        {
            var sheets = new List<string>();
            if (_currentWorkbook == null)
                return sheets;
            for (int i = 0; i < _currentWorkbook.NumberOfSheets; i++)
            {
                sheets.Add(_currentWorkbook.GetSheetName(i));
            }
            return sheets;
        }
 
        public object GetNumericCellValue(string sheetName, int rowIndex, int colIndex)
        {
            if (!Sheets.Contains(sheetName))
                return null;
            var cell = _currentWorkbook.GetSheet(sheetName).GetRow(rowIndex).GetCell(colIndex - 1);
            return cell.NumericCellValue;
        }
 
        public object GetStringCellValue(string sheetName, int rowIndex, int colIndex)
        {
            if (!Sheets.Contains(sheetName))
                return null;
            var cell = _currentWorkbook.GetSheet(sheetName).GetRow(rowIndex).GetCell(colIndex - 1);
            if (cell == null)
                return null;
            if (cell.CellType == CellType.Formula)
            {
                if (cell.CachedFormulaResultType == CellType.String)
                    return cell.StringCellValue;
                if (cell.CachedFormulaResultType == CellType.Numeric)
                    return cell.NumericCellValue;
                if (cell.CachedFormulaResultType == CellType.Boolean)
                    return cell.BooleanCellValue;
                return null;
            }
            if (cell.CellType == CellType.Numeric)
                return cell.NumericCellValue;
            if (cell.CellType == CellType.Boolean)
                return cell.NumericCellValue;
            return cell.StringCellValue;
        }
 
        public object GetDateTimeCellValue(string sheetName, int rowIndex, int colIndex)
        {
            if (!Sheets.Contains(sheetName))
                return null;
            var cell = _currentWorkbook.GetSheet(sheetName).GetRow(rowIndex).GetCell(colIndex - 1);
            if (cell.CellType == CellType.String)
                return cell.StringCellValue;
            return cell.DateCellValue;
        }
 
        public ICell GetCell(string sheetName, int rowIndex, int colIndex)
        {
            if (!Sheets.Contains(sheetName))
                return null;
            var sheet = _currentWorkbook.GetSheet(sheetName);
            if (sheet == null)
                return null;
            var row = sheet.GetRow(rowIndex);
            if (row == null)
                return null;
            var cell = row.GetCell(colIndex - 1);
            if (cell == null)
                return null;
            return cell;
        }
 
        /// <summary>
        /// 获取单元格里面的值
        /// </summary>
        /// <param name="sheetName">表名</param>
        /// <param name="x">行索引从1开始</param>
        /// <param name="y">列索引从1开始</param>
        /// <returns></returns>
        public object GetCellValue(string sheetName, int rowIndex, int colIndex)
        {
            if (!Sheets.Contains(sheetName))
                return null;
 
            DataTable dt = null;
            if (!_dataDict.ContainsKey(sheetName))
            {
                dt = Import(sheetName);
                _dataDict.Add(sheetName, dt);
            }
            else
            {
                dt = _dataDict[sheetName];
            }
            if (dt == null)
                return null;
 
            if (dt.Rows.Count < rowIndex)
                return null;
 
            var rowIdx = rowIndex - 1;
            var row = dt.Rows[rowIdx];
            var colIdx = colIndex - 1;
            return row[colIdx];
        }
 
        public void SetCellValues(ICell cell, string cellType, string cellValue)
        {
            switch (cellType)
            {
                case "System.String": //字符串类型
                    double result;
                    if (double.TryParse(cellValue, out result))
                        cell.SetCellValue(result);
                    else
                        cell.SetCellValue(cellValue);
                    break;
                case "System.DateTime": //日期类型
                    DateTime dateV;
                    DateTime.TryParse(cellValue, out dateV);
                    cell.SetCellValue(dateV);
                    break;
                case "System.Boolean": //布尔型
                    bool boolV = false;
                    bool.TryParse(cellValue, out boolV);
                    cell.SetCellValue(boolV);
                    break;
                case "System.Int16": //整型
                case "System.Int32":
                case "System.Int64":
                case "System.Byte":
                    int intV = 0;
                    int.TryParse(cellValue, out intV);
                    cell.SetCellValue(intV);
                    break;
                case "System.Decimal": //浮点型
                case "System.Double":
                    double doubV = 0;
                    double.TryParse(cellValue, out doubV);
                    cell.SetCellValue(doubV);
                    break;
                case "System.DBNull": //空值处理
                    cell.SetCellValue("");
                    break;
                default:
                    cell.SetCellValue("");
                    break;
            }
        }
 
        public DataTable Import(string sheetName)
        {
            sheetName = string.IsNullOrEmpty(sheetName) ? "Sheet1" : sheetName;
 
            ISheet sheet = _currentWorkbook.GetSheet(sheetName);
            if (sheet == null)
            {
                sheet = _currentWorkbook.GetSheetAt(0);
            }
 
            IEnumerator ie = sheet.GetRowEnumerator();
 
            IRow row = null;
            var maxCol = 0;
            while (ie.MoveNext())
            {
                row = ie.Current as IRow;//取一行,为了得到column的总数
                if (row.LastCellNum > maxCol)
                    maxCol = row.LastCellNum;
            }
 
            var dt = new DataTable();
            for (int i = 0; i < maxCol; i++)
            {
                dt.Columns.Add(string.Format("Col{0}", i));
            }
 
            ie.Reset();
            DataRow drow = null;
            ICell cell = null;
            var isHeader = true;
            while (ie.MoveNext())
            {
                if (isHeader)
                {
                    isHeader = false;
                    continue;
                }
                row = ie.Current as IRow;
                drow = dt.NewRow();
                for (int i = 0; i < row.LastCellNum; i++)
                {
                    if (row.GetCell(i) == null)
                    {
                        drow[i] = null;
                        continue;
                    }
                    cell = row.GetCell(i) as ICell;
 
                    switch (cell.CellType)
                    {
                        case CellType.Blank:
                            drow[i] = string.Empty;
                            break;
                        case CellType.Boolean:
                            drow[i] = cell.BooleanCellValue;
                            break;
                        case CellType.Error:
                            drow[i] = cell.ErrorCellValue;
                            break;
                        case CellType.Formula:
                            drow[i] = "=" + cell.CellFormula;
                            break;
                        case CellType.Numeric:
                            if (DateUtil.IsCellDateFormatted(cell))
                            {
                                drow[i] = cell.DateCellValue;
                            }
                            else
                            {
                                drow[i] = cell.NumericCellValue;
                            }
                            break;
                        case CellType.String:
                            drow[i] = cell.StringCellValue;
                            break;
                        case CellType.Unknown:
                            break;
                        default:
                            drow[i] = null;
                            break;
                    }
                }
                dt.Rows.Add(drow);
            }
            return dt;
        }
 
        public string Export(string excelFileName, List<DataTable> dataTables)
        {
            var workbook = new HSSFWorkbook();
            ISheet sheet = null;
            IRow row = null;
            ICell cell = null;
 
            var index = 0;
            foreach (var dataTable in dataTables)
            {
                var tableName = dataTable.TableName;
                if (string.IsNullOrEmpty(tableName))
                    tableName = "Sheet" + (++index);
                sheet = workbook.CreateSheet(tableName);
 
                //填充表头
                row = sheet.CreateRow(0);
                for (int i = 0; i < dataTable.Columns.Count; i++)
                {
                    cell = row.CreateCell(i);
                    cell.SetCellValue(dataTable.Columns[i].ColumnName);
                }
 
                //填充内容
                for (int i = 0; i < dataTable.Rows.Count; i++)
                {
                    row = sheet.CreateRow(i + 1);
                    for (int j = 0; j < dataTable.Columns.Count; j++)
                    {
                        cell = row.CreateCell(j);
                        SetCellValues(cell, dataTable.Columns[j].DataType.ToString(), dataTable.Rows[i][j].ToString());
                    }
                }
            }
            if (File.Exists(excelFileName)) File.Delete(excelFileName);
            using (var fs = new FileStream(excelFileName, FileMode.CreateNew, FileAccess.Write)) workbook.Write(fs);
            return excelFileName;
        }
 
        public string Export(string excelFileName, DataTable dataTable)
        {
            HSSFWorkbook workbook = new HSSFWorkbook();
 
            ISheet sheet = null;
            IRow row = null;
            ICell cell = null;
            int sheetCount = 1;//当前的sheet数量
            int currentSheetCount = 0;//循环时当前保存的条数,每页都会清零
 
            //表头样式
            ICellStyle style = workbook.CreateCellStyle();
            style.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
            //内容样式
            style = workbook.CreateCellStyle();
            style.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
 
            sheet = workbook.CreateSheet("Sheet" + sheetCount);
            //填充表头
            row = sheet.CreateRow(0);
            for (int i = 0; i < dataTable.Columns.Count; i++)
            {
                cell = row.CreateCell(i);
                cell.SetCellValue(dataTable.Columns[i].ColumnName);
                cell.CellStyle = style;
            }
            //填充内容
            for (int i = 0; i < dataTable.Rows.Count; i++)
            {
                if (currentSheetCount >= _perSheetCount)
                {
                    sheetCount++;
                    currentSheetCount = 0;
                    sheet = workbook.CreateSheet("Sheet" + sheetCount);
                }
                if (sheetCount == 1)//因为第一页有表头,所以从第二页开始写
                    row = sheet.CreateRow(currentSheetCount + 1);
                else//以后没有表头了,所以从开始写,都是基于0的
                    row = sheet.CreateRow(currentSheetCount);
                currentSheetCount++;
                for (int j = 0; j < dataTable.Columns.Count; j++)
                {
                    cell = row.CreateCell(j);
                    cell.CellStyle = style;
                    SetCellValues(cell, dataTable.Columns[j].DataType.ToString(), dataTable.Rows[i][j].ToString());
                }
            }
            FileStream fs = new FileStream(excelFileName, FileMode.CreateNew, FileAccess.Write);
            workbook.Write(fs);
            fs.Close();
            return excelFileName;
        }
 
        #endregion
 
    }

总结

本例中主要侧重对目标excel的单元格数据进行访问,对单元格的数据格式进行了比较详细的区分,可自行参考删减。

以上就是C#使用NPOI操作Excel工具类的实现的详细内容,更多关于C# NPOI操作Excel的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文