Exemplo n.º 1
0
        /// <summary>
        /// 读取上传文件中的Excel(返回表格,如果需要导入,还需要格式化表头)
        /// </summary>
        /// <param name="workbook">Excel工作本</param>
        /// <param name="sheetIndex">第N个Sheet表格</param>
        /// <param name="isMergedCellName">是否把合并列头的名称连接起来</param>
        /// <param name="startIndex">开始索引</param>
        /// <param name="headCrossRowNum">头部跨行数(为0时自动识别)</param>
        /// <returns></returns>
        private static MDataTable ReadExcel(IWorkbook workbook, Stream stream = null, int sheetIndex = 0, int startIndex = 0, int headCrossRowNum = 0, bool isMergedCellName = false)
        {
            MDataTable dt = new MDataTable();

            try
            {
                if (workbook != null)
                {
                    ISheet sheet = workbook.GetSheetAt(sheetIndex);
                    dt.TableName   = sheet.SheetName;
                    dt.DynamicData = sheet;
                    IRow excelRow     = sheet.GetRow(startIndex);
                    int  dataRowStart = startIndex;

                    if (headCrossRowNum <= 0)
                    {
                        dataRowStart += 1;
                        #region 遍历、找出(头部跨行数)最大行。用最大行进行遍历列(如果为空,往上一级找)
                        int mIndex = 0;
                        for (int i = 0; i < excelRow.Cells.Count; i++)
                        {
                            ICell cell = excelRow.GetCell(i, MissingCellPolicy.CREATE_NULL_AS_BLANK);// .Cells[i];
                            if (cell.IsMergedCell)
                            {
                                NPOI.SS.Util.CellRangeAddress range = sheet.GetCellRange(cell);//获取范围块。
                                if (range != null)
                                {
                                    dataRowStart = Math.Max(dataRowStart, range.LastRow + 1);//设置数据的读取行数。
                                    mIndex++;
                                    i += range.LastColumn - range.FirstColumn;
                                }
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        dataRowStart += headCrossRowNum;
                    }

                    //读取列头。
                    if (dataRowStart > 1)
                    {
                        excelRow = sheet.GetRow(dataRowStart - 1);
                    }
                    dt.RecordsAffected        = dataRowStart;
                    dt.Columns.CheckDuplicate = false;

                    #region 读取列头
                    //if (excelRow.FirstCellNum > 0)
                    //{
                    //    for (int i = 0; i < excelRow.FirstCellNum; i++)
                    //    {
                    //        string columnName = "该列头为空_" + i;
                    //        dt.Columns.Add(columnName);
                    //    }
                    //}
                    int emptyCellCount = 0;//兼容处理错误的Excel格式(读了256个空格列)
                    for (int i = 0; i < excelRow.Cells.Count; i++)
                    {
                        string columnName = string.Empty;
                        for (int j = dataRowStart; j > startIndex; j--)
                        {
                            #region MyRegion
                            IRow  row = sheet.GetRow(j - 1);
                            ICell cell;
                            try
                            {
                                cell = row.GetCell(i, MissingCellPolicy.CREATE_NULL_AS_BLANK);//不能用GetCell(i),会多出一行导致下面错误位。
                            }
                            catch (Exception)
                            {
                                continue;
                            }
                            string name = cell.ToString().Trim();                          // .StringCellValue.Trim();
                            if (!string.IsNullOrEmpty(name) && !columnName.Contains(name)) //
                            {
                                columnName += name + "_";
                            }
                            else if (j != dataRowStart && cell.IsMergedCell)
                            {
                                cell = sheet.GetMergedRegion(cell);//获取范围块。
                                if (cell != null)
                                {
                                    name = cell.ToString().Trim();
                                    if (!string.IsNullOrEmpty(name) && !columnName.Contains(name))
                                    {
                                        columnName += name + "_";
                                    }
                                }
                            }
                            if (!isMergedCellName && !string.IsNullOrEmpty(columnName))
                            {
                                break;
                            }
                            #endregion
                        }
                        columnName = columnName.TrimEnd('_').Trim();
                        if (string.IsNullOrEmpty(columnName))
                        {
                            if (emptyCellCount > 30)//连续30次空格列
                            {
                                break;
                            }
                            emptyCellCount++;
                            columnName = "该列头为空_" + i;
                        }
                        else
                        {
                            emptyCellCount = 0;//只要一个正常,即回归索引
                        }
                        if (dt.Columns.Contains(columnName))
                        {
                            columnName += "_" + i;
                        }
                        dt.Columns.Add(columnName);
                    }
                    //移除空格列
                    if (emptyCellCount > 0)
                    {
                        dt.Columns.RemoveRange(dt.Columns.Count - emptyCellCount, emptyCellCount);
                    }
                    if (dt.Columns.Count > 0)
                    {
                        dt.Conn = dt.Columns.Count.ToString();//找个变量存储实际的列的长度,在SetError中使用。(dt可能在SetError前列被变更)
                    }
                    #endregion

                    ICell sheetCell;
                    int   emptyCount = 0;
                    for (int i = dataRowStart; i <= sheet.LastRowNum; i++)
                    {
                        excelRow = sheet.GetRow(i);
                        if (excelRow == null)
                        {
                            break;
                        }
                        MDataRow tbRow = dt.NewRow();
                        bool     isOk  = false;
                        for (int j = 0; j < dt.Columns.Count; j++)
                        {
                            #region 读一行
                            sheetCell = excelRow.GetCell(j, MissingCellPolicy.RETURN_BLANK_AS_NULL);
                            if (sheetCell != null)
                            {
                                string value = string.Empty;
                                if (sheetCell.CellType == CellType.Numeric)
                                {
                                    try
                                    {
                                        if (sheetCell.ToString().Split('/', '-').Length > 1)
                                        {
                                            value = sheetCell.DateCellValue.ToString();
                                        }
                                        else
                                        {
                                            value = sheetCell.NumericCellValue.ToString();
                                        }
                                    }
                                    catch
                                    {
                                        value = sheetCell.ToString();
                                    }
                                }
                                else if (sheetCell.CellType == CellType.Formula)
                                {
                                    try
                                    {
                                        /*公式不一定是Numeric的取值,也有可能是=G4 这种,然而单元格G4不是数字;
                                         * 公式单元格也有可能读取错误 #VALUE!  #REF! 等*/
                                        CellType resultType = sheetCell.CachedFormulaResultType;
                                        switch (resultType)
                                        {
                                        case CellType.Boolean:
                                            value = sheetCell.BooleanCellValue.ToString();
                                            break;

                                        case CellType.Numeric:
                                            value = sheetCell.NumericCellValue.ToString();
                                            break;

                                        case CellType.Blank:
                                        case CellType.Error:
                                        case CellType.Unknown:
                                            value = string.Empty;
                                            break;

                                        default:
                                            value = sheetCell.StringCellValue;
                                            break;
                                        }


                                        //value = sheetCell.NumericCellValue.ToString(); //由公式取值
                                    }
                                    catch
                                    {
                                    }
                                }
                                else
                                {
                                    value = sheetCell.ToString();
                                }
                                value = value.Trim();
                                if (!isOk && !string.IsNullOrEmpty(value))
                                {
                                    isOk = true;
                                }
                                if (!string.IsNullOrEmpty(value))//空值当Null值处理,避免字段有Check对空值的约束
                                {
                                    tbRow.Set(sheetCell.ColumnIndex, value);
                                }
                            }
                            #endregion
                        }
                        if (isOk)//忽略空行数据。
                        {
                            dt.Rows.Add(tbRow);
                        }
                        else
                        {
                            if (dt.Rows.Count == 0)
                            {
                                dt.RecordsAffected++;
                            }
                            emptyCount++;
                            if (emptyCount > 1)//超过2次空格行,跳出。
                            {
                                break;
                            }
                        }
                    }
                    workbook.Close();//关闭了,dt.DynamicData带出了Sheet,还是可以后续使用(估计NPOI的没处理)
                }
            }
            catch (Exception err)
            {
                Log.WriteLogToTxt(err);
            }
            return(dt);
        }