C# OpenXml组件

  public class OpenXmlHelper
    {
        #region 导入
        /// <summary>
        /// 按照给定的地址读取Excel转换成DataTable
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="page">页码</param>
        /// <param name="pagesize">页行数</param>
        /// <param name="sheetName">Excel的Sheet名;默认第一个Sheet</param>
        /// <param name="index">列头行;默认第一列</param>
        /// <returns></returns>
        /// OpenXml只支持Excel2007版后的.xlsx
        public static DataTable Read(string path, int page = 0, int pagesize = 0, string sheetName = null, int index = 1)
        {
            try
            {
                DataTable dt = new DataTable();
                if (!path.ToLower().Trim().EndsWith(".xlsx"))
                {
                    throw new Exception("OpenXml组件只支持Office Excel2007版后的.xlsx格式文件");
                }
                using (SpreadsheetDocument document = SpreadsheetDocument.Open(path, false))
                {
                    //打开Stream
                    IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>();
                    if (!string.IsNullOrEmpty(sheetName))
                    {
                        sheets = sheets.Where(s => s.Name.ToString().ToLower() == sheetName.ToLower());
                        if (sheets.Count() == 0)
                        {
                            throw new Exception("没有找到该Sheet");
                        }
                    }
                    WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id);
                    //获取Excel中共享数据
                    SharedStringTable stringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
                    IEnumerable<Row> rows = worksheetPart.Worksheet.Descendants<Row>();//获得Excel中得数据行
                    foreach (Row row in rows)
                    {
                        if (row.RowIndex == index)//Excel的列名列
                        {
                            GetDataColumn(row, stringTable, ref dt);
                            break;
                        }
                    }
                    if (page != 0 && pagesize != 0)
                    {
                        rows = rows.Skip((pagesize * (page-1))+1).Take(pagesize);
                        foreach (Row row in rows)
                        {
                            if (row.RowIndex != index)
                            {
                                GetDataRow(row, stringTable, ref dt, document.WorkbookPart);//Excel中行数大于列头的都作为数据列处理
                            }
                        }
                    }
                    else
                    {

                        foreach (Row row in rows)
                        {
                            if (row.RowIndex != index) {
                                GetDataRow(row, stringTable, ref dt, document.WorkbookPart);//Excel中行数大于列头的都作为数据列处理
                            }
                           
                        }
                    }
                    return dt;
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }

        }
        /// <summary>
        /// Excel数据列总行数(不包括列头)
        /// </summary>
        /// <param name="path"></param>
        /// <param name="sheetName"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static int GetExcelCount(string path, string sheetName = null, int index = 1)
        {
            try
            {
                DataTable dt = new DataTable();
                if (!path.ToLower().Trim().EndsWith(".xlsx"))
                {
                    throw new Exception("OpenXml组件只支持Office Excel2007版后的.xlsx格式文件");
                }
                using (SpreadsheetDocument document = SpreadsheetDocument.Open(path, false))
                {
                    //打开Stream
                    IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>();
                    if (!string.IsNullOrEmpty(sheetName))
                    {
                        sheets = sheets.Where(s => s.Name.ToString().ToLower() == sheetName.ToLower());
                        if (sheets.Count() == 0)
                        {
                            throw new Exception("没有找到该Sheet");
                        }
                    }
                    WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id);
                    //获取Excel中共享数据
                    SharedStringTable stringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
                    IEnumerable<Row> rows = worksheetPart.Worksheet.Descendants<Row>();//获得Excel中得数据行
                    return rows.Count() - 1;
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
        /// <summary>
        /// 获取Excel原始列下标
        /// </summary>
        /// <param name="str">原始列名</param>
        /// <returns></returns>
        private static int GetIndexNumber(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return -1;
            }
            char[] chars = value.ToLower().ToCharArray();
            int index = 0;
            for (int i = 0; i < chars.Length; i++)
            {
                index += ((int)chars[i] - (int)'a' + 1) * (int)Math.Pow(26, chars.Length - i - 1);
            }
            return index - 1;
        }

        /// <summary>
        /// 构建DataTable的列
        /// </summary>
        /// <param name="row">OpenXML定义的Row对象</param>
        /// <param name="stringTablePart"></param>
        /// <param name="dt">须要返回的DataTable对象</param>
        /// <returns></returns>
        private static void GetDataColumn(Row row, SharedStringTable stringTable, ref DataTable dt)
        {
            DataColumn col = new DataColumn();
            Dictionary<string, int> columnCount = new Dictionary<string, int>();
            foreach (Cell cell in row)
            {
                string cellVal = GetValue(cell, stringTable);
                col = new DataColumn(cellVal);
                if (IsContainsColumn(dt, col.ColumnName))
                {
                    if (!columnCount.ContainsKey(col.ColumnName))
                        columnCount.Add(col.ColumnName, 0);
                    col.ColumnName = col.ColumnName + (columnCount[col.ColumnName]++);
                }
                dt.Columns.Add(col);
            }
        }
        /// <summary>
        /// 构建DataTable的每一行数据,并返回该Datatable
        /// </summary>
        /// <param name="row">OpenXML的行</param>
        /// <param name="stringTablePart"></param>
        /// <param name="dt">DataTable</param>
        private static void GetDataRow(Row row, SharedStringTable stringTable, ref DataTable dt, WorkbookPart workbookPart)
        {
            //读取数据
            DataRow dr = dt.NewRow();
            int number = 0;
            foreach (Cell cell in row)
            {
                //获取Excel列头
                var column = Regex.Replace(cell.CellReference.Value, "[0-9]", "");
                //列头转换成下标
                var index = GetIndexNumber(column);
                if (index < 0)
                {
                    continue;
                }
                string cellVal = GetValue(cell, stringTable);
                if (!string.IsNullOrEmpty(cellVal))
                {
                    if (cell.DataType != null && (cell.DataType.Value == CellValues.SharedString || cell.DataType.Value == CellValues.String || cell.DataType.Value == CellValues.Number))
                    {
                        if (index < dt.Columns.Count)
                        {
                            switch (cell.DataType.Value)
                            {
                                case CellValues.Boolean:
                                    dr[index] = Convert.ToBoolean(GetValue(cell, stringTable));
                                    break;
                                case CellValues.Date:
                                    dr[index] = Convert.ToDateTime(GetValue(cell, stringTable));
                                    break;
                                default:
                                    dr[index] = Convert.ToString(GetValue(cell, stringTable));
                                    break;
                            }

                        }
                    }
                    else
                    {
                        //日期格式
                        if (workbookPart.WorkbookStylesPart!=null/*cell.StyleIndex != null*/)
                        {
                            var styleSheet = workbookPart.WorkbookStylesPart.Stylesheet;
                            if (styleSheet!= null) {
                                CellFormat cellFormat = (CellFormat)styleSheet.CellFormats.ChildElements[(int)cell.StyleIndex.Value];
                                int formatId = (int)cellFormat.NumberFormatId.Value;
                                if (formatId == 177)
                                {
                                    dr[index] = DateTime.FromOADate(double.Parse(GetValue(cell, stringTable)));
                                }
                                //双精度浮点格式
                                else
                                {
                                    dr[index] = double.Parse(GetValue(cell, stringTable));

                                }
                            }
                          
                        }
                        else
                        {
                            dr[index] = GetValue(cell, stringTable);
                        }
                    }
                }
                else
                {
                    dr[index] = cellVal;
                }

                if (!string.IsNullOrEmpty(cellVal))
                {
                    number++;
                }

            }
            if (number != 0)
            {
                dt.Rows.Add(dr);
            }
        }
        /// <summary>
        /// 获取单位格的值
        /// </summary>
        /// <param name="cell"></param>
        /// <param name="stringTablePart"></param>
        /// <returns></returns>
        private static string GetValue(Cell cell, SharedStringTable stringTable)
        {
            //因为Excel的数据存储在SharedStringTable中,须要获取数据在SharedStringTable 中的索引
            string value = string.Empty;
            try
            {

                if (cell.ChildElements.Count == 0)
                    return value;
                value = double.Parse(cell.CellValue.InnerText).ToString();
                if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
                {
                    value = stringTable.ChildElements[Int32.Parse(value)].InnerText;
                }
            }
            catch (Exception)
            {
                value = string.Empty;
            }
            return value;
        }
        /// <summary>
        /// 判断网格是否存在列
        /// </summary>
        /// <param name="dt">网格</param>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        private static bool IsContainsColumn(DataTable dt, string columnName)
        {
            if (dt == null || columnName == null)
            {
                return false;
            }
            return dt.Columns.Contains(columnName);
        }
        #endregion
        #region 导出
        /// <summary>
        /// 获取Excel原始Colum名称
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        static string GetLetter(int index)
        {
            if (index < 0)
            {
                throw new Exception($"参数{nameof(index)}异常");
            }
            List<string> chars = new List<string>();
            do
            {
                if (chars.Count > 0) index--;
                chars.Insert(0, ((char)(index % 26 + (int)'A')).ToString());
                index = (int)((index - index % 26) / 26);
            } while (index > 0);

            return String.Join(string.Empty, chars.ToArray());
        }
        /// <summary>
        /// 添加WorkSheet
        /// </summary>
        private static WorksheetPart InsertWorksheet(WorkbookPart workbookPart, string sheetName)
        {
            //创建新的WorksheetPart
            WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();
            newWorksheetPart.Worksheet = new Worksheet(new SheetData());
            newWorksheetPart.Worksheet.Save();
            //在末尾追加一个Sheets
            Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
            string relationshipId = workbookPart.GetIdOfPart(newWorksheetPart);
            Sheet sheet = new Sheet() { Id = relationshipId, SheetId = 1, Name = sheetName };
            //添加Sheet
            sheets.Append(sheet);
            workbookPart.Workbook.Save();
            return newWorksheetPart;
        }
        /// <summary>
        /// DataTable导出Excel到MemoryStream;
        ///Return File(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "test.xlsx");
        ///MVC模式下返回文件流结果,参数一为流,参数二为文件类型,参数三为文件名
        /// </summary>
        /// <param name="dtSource">数据源</param>
        /// <param name="sheetName">Sheet名称</param>
        /// <returns></returns>
        public static MemoryStream ToExcelIntoMemoryStream(DataTable dtSource, string sheetName = "Sheet0")
        {
            try
            {
                var memoryStream = new MemoryStream();
                using (var document = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook))
                {
                    var workbookPart = document.AddWorkbookPart();
                    workbookPart.Workbook = new Workbook();
                    //创建新的SharedStringTablePart
                    SharedStringTablePart shareStringPart = document.WorkbookPart.AddNewPart<SharedStringTablePart>();
                    // 添加一个WorkSheet
                    WorksheetPart worksheetPart = InsertWorksheet(workbookPart, sheetName);
                    // 添加SharedStringTable
                    shareStringPart.SharedStringTable = new SharedStringTable();
                    int rowIndex = 1;
                    int cellIndex = 0;
                    Worksheet worksheet = worksheetPart.Worksheet;
                    SheetData sheetData = worksheet.GetFirstChild<SheetData>();
                    //Excel表头列
                    SetSheetDataHeadRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
                    //Excel数据列
                    SetSheetDataRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
                    shareStringPart.SharedStringTable.Save();
                    worksheet.Save();
                    worksheetPart.Worksheet.Save();
                }
                memoryStream.Seek(0, SeekOrigin.Begin);
                return memoryStream;
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        /// <summary>
        /// DataTable固定路径导出Excel,单个Sheet生成
        /// 指定路径
        /// </summary>
        /// <param name="excelFilePath">存储路径</param>
        /// <param name="table">数据</param>
        /// <param name="sheetName">Sheet名称</param>
        public static void ToExcelFixUrl(string excelFilePath, DataTable dtSource, string sheetName = "Sheet0")
        {
            try
            {
                using (var document = SpreadsheetDocument.Create(excelFilePath, SpreadsheetDocumentType.Workbook))
                {
                    var workbookPart = document.AddWorkbookPart();
                    workbookPart.Workbook = new Workbook();
                    //创建新的SharedStringTablePart
                    SharedStringTablePart shareStringPart = document.WorkbookPart.AddNewPart<SharedStringTablePart>();
                    // 添加WorkSheet
                    WorksheetPart worksheetPart = InsertWorksheet(workbookPart, sheetName);
                    // 添加SharedStringTable
                    shareStringPart.SharedStringTable = new SharedStringTable();
                    int rowIndex = 1;
                    int cellIndex = 0;
                    Worksheet worksheet = worksheetPart.Worksheet;
                    SheetData sheetData = worksheet.GetFirstChild<SheetData>();
                    //Excel表头列
                    SetSheetDataHeadRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
                    //Excel数据列
                    SetSheetDataRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
                    shareStringPart.SharedStringTable.Save();
                    worksheet.Save();
                    worksheetPart.Worksheet.Save();
                }

            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
        /// <summary>
        /// 将DataTable的ColumnsName转换为Excel表头Row
        /// </summary>
        /// <param name="dtSource">数据</param>
        /// <param name="shareStringPart"></param>
        /// <param name="sheetData"></param>
        /// <param name="rowIndex">行下标</param>
        /// <param name="cellIndex">单元格下标/param>
        private static void SetSheetDataHeadRow(DataTable dtSource, ref SharedStringTablePart shareStringPart, ref SheetData sheetData, ref int rowIndex, ref int cellIndex)
        {
            {
                Row row = new Row() { RowIndex = Convert.ToUInt32(rowIndex) };
                sheetData.Append(row);
                for (int c = 0; c < dtSource.Columns.Count; c++)
                {

                    string cellReference = GetLetter(c) + rowIndex;
                    //SharedStringTable里,取数据也是根据SharedStringTable来取
                    shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(Convert.ToString(dtSource.Columns[c]))));
                  

                    Cell refCell = null;
                    foreach (Cell cell in row.Elements<Cell>())
                    {
                        if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
                        {
                            refCell = cell;
                            break;
                        }
                    }
                    Cell newCell = new Cell() { CellReference = cellReference };
                    row.InsertBefore(newCell, refCell);

                    newCell.CellValue = new CellValue(cellIndex++.ToString());
                    newCell.DataType = new EnumValue<CellValues>(CellValues.SharedString);

                    if (c == dtSource.Columns.Count - 1)
                    {
                        rowIndex++;
                    }
                }

            }
        }
        /// <summary>
        /// 将DataTable的ColumnsData转换为数据Row
        /// </summary>
        /// <param name="dtSource">数据</param>
        /// <param name="shareStringPart"></param>
        /// <param name="sheetData"></param>
        /// <param name="rowIndex">行下标</param>
        /// <param name="cellIndex">单元格下标/param>
        private static void SetSheetDataRow(DataTable dtSource, ref SharedStringTablePart shareStringPart, ref SheetData sheetData, ref int rowIndex, ref int cellIndex)
        {
            {
                //Excel的数据列生成
                for (int r = 0; r < dtSource.Rows.Count; r++)
                {
                    Row dataRow = new Row() { RowIndex = Convert.ToUInt32(rowIndex) };
                    sheetData.Append(dataRow);
                    for (int c = 0; c < dtSource.Columns.Count; c++)
                    {
                        string cellReference = GetLetter(c) + rowIndex;
                        shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(Convert.ToString(dtSource.Rows[r][c]))));
                     
                        Cell refCell = null;
                        foreach (Cell cell in dataRow.Elements<Cell>())
                        {
                            if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
                            {
                                refCell = cell;
                                break;
                            }
                        }
                        Cell newCell = new Cell() { CellReference = cellReference };
                        dataRow.InsertBefore(newCell, refCell);

                        newCell.CellValue = new CellValue(cellIndex++.ToString());
                        newCell.DataType = new EnumValue<CellValues>(CellValues.SharedString);


                    }
                    rowIndex++;
                }
            }
        }

        #endregion
        /// <summary>
        /// list模型转换为DataTable
        /// </summary>
        /// <typeparam name="T">模型</typeparam>
        /// <param name="list">数据集合</param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(List<T> list)
        {
            if (list == null || list.Count <= 0)
            {
                throw new Exception("参数异常");
            }
            DataTable dt = new DataTable();
            if (list.Count <= 0 || list == null)
            {
                return dt;
            }
            //添加列名
            {
                var type = list.First().GetType();
                PropertyInfo[] PropertyList = type.GetProperties();
                foreach (PropertyInfo item in PropertyList)
                {
                    DataColumn dc = new DataColumn();
                    string name = item.Name;
                    dc.ColumnName = name;//反射类字段添加列名
                    dt.Columns.Add(dc);
                }

            }
            //添加数据列
            foreach (var model in list)
            {
                var type = model.GetType();
                PropertyInfo[] PropertyList = type.GetProperties();
                DataRow dr = dt.NewRow();
                foreach (PropertyInfo item in PropertyList)
                {
                    string name = item.Name;
                    string value = Convert.ToString(item.GetValue(model, null));
                    dr[name] = value;
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }

    }

猜你喜欢

转载自www.cnblogs.com/laukings/p/12935550.html
今日推荐