.NET导入导出Excel方法总结

最近,应项目的需求,需要实现Excel的导入导出功能,对于Web架构的Excel导入导出功能,比较传统的实现方式是:

1)导入Excel:将Excel文件上传到服务器的某一文件夹下,然后在服务端完成Excel的读取及数据的存储;

2)导出Excel:在服务端生成需要导出的Excel,然后下载到客户端。

其中,文件的上传和下载本文不在详述,以下主要写一些DataTable或DataSet与Excel之间的相互转换。

转换方式多种多样,网上也有很多前辈分享的代码实现,本文也借鉴了前辈的诸多思路及代码,具体方法如下:

1. DCOM方式

使用DCOM方式实现Excel的导入导出功能,首先需要在服务端安装office软件。

具体实现代码如下:

1)数据导出到Excel

    public class ExportExcel : IDisposable
    {
        private Excel.ApplicationClass excelApp;
        private Excel.Workbook workBook;
        private Excel.Worksheet workSheet;
        private Excel.Range range;

        public void DataTableToExcel(DataTable sourceTable, string fileName)
        {
            excelApp = new Excel.ApplicationClass();
            if (excelApp == null)
            {
                throw new Exception("打开Excel程序错误!");
            }

            workBook = excelApp.Workbooks.Add(true);
            workSheet = (Excel.Worksheet)workBook.Worksheets[1];
            int rowIndex = 0;          

            //写入列名
            ++rowIndex;
            for (int i = 0; i < sourceTable.Columns.Count; i++)
            {
                workSheet.Cells[rowIndex, i + 1] = sourceTable.Columns[i].ColumnName;
            }
            range = workSheet.get_Range(workSheet.Cells[rowIndex, 1], workSheet.Cells[rowIndex, sourceTable.Columns.Count]);

            FontStyle headerStyle = new FontStyle
            {
                FontSize = 30,
                BordersValue = 1,
                FontBold = true,
                EntireColumnAutoFit = true
            };
            FontStyleHelper.SetFontStyleForRange(range, headerStyle);

            //写入数据
            ++rowIndex;
            for (int r = 0; r < sourceTable.Rows.Count; r++)
            {
                for (int i = 0; i < sourceTable.Columns.Count; i++)
                {
                    workSheet.Cells[rowIndex, i + 1] = ExportHelper.ConvertToCellData(sourceTable, r, i);
                }
                rowIndex++;
            }
            range = workSheet.get_Range(workSheet.Cells[2, 1], workSheet.Cells[sourceTable.Rows.Count + 1, sourceTable.Columns.Count]);
            FontStyle bodyStyle = new FontStyle
            {
                FontSize = 16,
                BordersValue = 1,
                FontAlign = Infrastruction.FontAlign.Right,
                EntireColumnAutoFit = true
            };
            FontStyleHelper.SetFontStyleForRange(range, bodyStyle);

            //只保存一个sheet页
            //workSheet.SaveAs(fileName, Excel.XlFileFormat.xlTemplate, Type.Missing, Type.Missing, Type.Missing,
            //        Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing);
            //保存整个Excel
            workBook.SaveAs(fileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                    Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing);
            workBook.Close(false, Type.Missing, Type.Missing);
            excelApp.Quit();

            Dispose();
        }

        public void Dispose()
        {
            GC.Collect();
            BaseExcel.Dispose(excelApp, workSheet, workBook, range);
        }
    }
View Code

2)数据导入到内存

    public class ImportExcel : IDisposable
    {
        private Excel.ApplicationClass excelApp;
        private Excel.Workbook workBook;
        private Excel.Worksheet workSheet;
        private Excel.Range range;

        public DataSet ExcelToDataSet(string fileName)
        {
            if (!File.Exists(fileName))
            {
                return null;
            }
            FileInfo file = new FileInfo(fileName);
            string strConnection = string.Empty;
            string extension = file.Extension;
            string vsSql = string.Empty;
            switch (extension)
            {
                case ".xls":
                    strConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;'";
                    break;
                case ".xlsx":
                    strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1;'";
                    break;
                default:
                    strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1;'";
                    break;
            }
            DataSet ds = ImportHelper.GetDataSetFromExcel(strConnection);

            Dispose();
            ds = ImportHelper.ConvertDataSet(ds);
            return ds;
        }

        public DataSet ExcelToDataSetByDcom(string fileName)
        {
            DataSet result = null;
            excelApp = new Excel.ApplicationClass();
            if (excelApp == null)
            {
                throw new Exception("打开Excel程序错误!");
            }

            excelApp.Visible = false; excelApp.UserControl = true;
            // 以只读的形式打开EXCEL文件
            workBook = excelApp.Application.Workbooks.Open(fileName, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing,
             Type.Missing, Type.Missing, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

            int sheets = workBook.Worksheets.Count;
            if (sheets >= 1)
            {
                result = new DataSet();
            }
            for(int i = 1; i <= sheets; i++)
            {
                workSheet = (Excel.Worksheet)workBook.Worksheets.get_Item(i);
                string sheetName = workSheet.Name;

                DataTable dt = new DataTable();
                dt.TableName = sheetName;

                //取得总记录行数
                int rows = workSheet.UsedRange.Cells.Rows.Count; //得到行数
                int columns = workSheet.UsedRange.Cells.Columns.Count;//得到列数
                if (rows == 0 || columns == 0) return null;
                //取得数据范围区域
                range = workSheet.get_Range(workSheet.Cells[1, 1], workSheet.Cells[rows, columns]);
                object[,] arryItem = (object[,])range.Value2; //get range's value

                //生成DataTable的列
                for(int col = 1; col <= columns; col++)
                {
                    string dcName = arryItem[1, col].ToString().Trim();
                    DataColumn dc = new DataColumn(dcName, typeof(string));
                    dt.Columns.Add(dc);
                }
                //将数据填充到DataTable
                for(int row = 2; row <= rows; row++)
                {
                    object[] rowvalue = new object[columns];
                    for (int col = 1; col <= columns; col++)
                    {
                        rowvalue[col - 1] = arryItem[row, col];
                    }
                    dt.Rows.Add(rowvalue);
                }
                //将DataTable填充到DataSet
                result.Tables.Add(dt);
            }

            //清理非托管对象
            workBook.Close(false, Type.Missing, Type.Missing);
            excelApp.Quit();
            Dispose();
            return result;
        }

        public void Dispose()
        {
            GC.Collect();
            BaseExcel.Dispose(excelApp, workSheet, workBook, range);
        }
    }
View Code

3)其他辅助类

    public class BaseExcel
    {
        /// <summary>
        /// 释放Excel资源
        /// </summary>
        /// <param name="excelApp"></param>
        public static void Dispose(Excel.ApplicationClass excelApp, Excel.Worksheet workSheet, Excel.Workbook workBook, Excel.Range range)
        {
            //清理非托管的代码
            if (workSheet != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet);
                workSheet = null;
            }
            if (workBook != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(workBook);
                workBook = null;
            }
            if (excelApp != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
                excelApp = null;
            }
            if (range != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
                range = null;
            }
            KillProcess();
        }
        /// <summary>
        /// 关闭进程
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="ID"></param>
        /// <returns></returns>
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
        private static void Kill(Excel.Application excel)
        {
            int id = 0;
            IntPtr intptr = new IntPtr(excel.Hwnd);    //得到这个句柄,具体作用是得到这块内存入口
            System.Diagnostics.Process p = null;
            try
            {
                GetWindowThreadProcessId(intptr, out id);  //得到本进程唯一标志
                p = System.Diagnostics.Process.GetProcessById(id);  //得到对进程k的引用
                if (p != null)
                {
                    p.Kill();  //关闭进程k
                    p.Dispose();
                }
            }
            catch
            {
            }
        }
        //强制结束进程
        private static void KillProcess()
        {
            System.Diagnostics.Process[] allProcess = System.Diagnostics.Process.GetProcesses();
            foreach (System.Diagnostics.Process thisprocess in allProcess)
            {
                string processName = thisprocess.ProcessName;
                if (processName.ToLower() == "excel")
                {
                    try
                    {
                        thisprocess.Kill();
                    }
                    catch
                    {
                    }
                }
            }
        }
    }
BaseExcel
    public class FontStyle
    {
        /// <summary>
        /// 字体大小
        /// </summary>
        public int FontSize { get; set; }
        /// <summary>
        /// 字体名称
        /// </summary>
        public string FontName { get; set; }
        /// <summary>
        /// 是否为粗体
        /// </summary>
        public bool FontBold { get; set; }
        /// <summary>
        /// 字体对齐方式
        /// </summary>
        public FontAlign FontAlign { get; set; }
        /// <summary>
        /// 边框样式
        /// </summary>
        public int BordersValue { get; set; }
        /// <summary>
        /// 字体颜色索引
        /// </summary>
        public int FontColorIndex { get; set; }
        /// <summary>
        /// 背景颜色索引
        /// </summary>
        public int InteriorColorIndex { get; set; }
        /// <summary>
        /// 列宽自适应
        /// </summary>
        public bool EntireColumnAutoFit { get; set; }
    }

    public enum FontAlign
    {
        Center,
        Right,
        Left
    }
FontStyle
    public class FontStyleHelper
    {
        /// <summary>
        /// 对选中区域设置格式
        /// </summary>
        /// <param name="range">选中区域</param>
        /// <param name="fontStyle">样式表</param>
        public static void SetFontStyleForRange(Excel.Range range, FontStyle fontStyle)
        {
            if (fontStyle.FontSize != 0)
            {
                range.Font.Size = fontStyle.FontSize;
            }
            if (fontStyle.FontName != null)
            {
                range.Font.Name = fontStyle.FontName;
            }
            if (fontStyle.FontBold != false)
            {
                range.Font.Bold = fontStyle.FontBold;
            }
            if (fontStyle.FontAlign == FontAlign.Center)
            {
                range.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter;
            }
            else if (fontStyle.FontAlign == FontAlign.Left)
            {
                range.HorizontalAlignment = Excel.XlHAlign.xlHAlignLeft;
            }
            else if (fontStyle.FontAlign == FontAlign.Right)
            {
                range.HorizontalAlignment = Excel.XlHAlign.xlHAlignRight;
            }
            if (fontStyle.BordersValue != 0)
            {
                range.Borders.Value = fontStyle.BordersValue;
            }
            if (fontStyle.FontColorIndex != 0)
            {
                range.Font.ColorIndex = fontStyle.FontColorIndex;
            }
            if (fontStyle.InteriorColorIndex != 0)
            {
                range.Interior.ColorIndex = fontStyle.InteriorColorIndex;
            }
            if (fontStyle.EntireColumnAutoFit == true)
            {
                range.EntireColumn.AutoFit();
            }
        }
    }
FontStyleHelper
    public class ExportHelper
    {
        public static string ConvertToCellData(DataTable sourceTable, int rowIndex, int colIndex)
        {
            DataColumn col = sourceTable.Columns[colIndex];
            object data = sourceTable.Rows[rowIndex][colIndex];
            if (col.DataType == System.Type.GetType("System.DateTime"))
            {
                if (data.ToString().Trim() != "")
                {
                    return Convert.ToDateTime(data).ToString("yyyy-MM-dd HH:mm:ss");
                }
                else
                {
                    return (Convert.ToDateTime(DateTime.Now)).ToString("yyyy-MM-dd HH:mm:ss");
                }
            }
            else if (col.DataType == System.Type.GetType("System.String"))
            {
                return "'" + data.ToString().Trim();
            }
            else
            {
                return data.ToString().Trim();
            }
        }
    }
ExportHelper
    public class ImportHelper
    {
        /// <summary>
        /// 通过OleDb获得DataSet
        /// </summary>
        /// <param name="connStr"></param>
        /// <param name="sheetNames"></param>
        /// <returns></returns>
        public static DataSet GetDataSetFromExcel(string connStr)
        {
            DataSet ds = null;
            using (OleDbConnection conn = new OleDbConnection(connStr))
            {
                try
                {
                    conn.Open();
                    DataTable tblName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
                    if (tblName.Rows.Count < 1 || tblName == null)
                    {
                        conn.Close();
                        return null;
                    }
                    else
                    {
                        ds = new DataSet();
                        DataTable tbl = null;
                        for (int i = 0; i < tblName.Rows.Count; i++)
                        {
                            tbl = new DataTable();
                            tbl.TableName = tblName.Rows[i]["TABLE_NAME"].ToString().Replace("$", "");
                            string vsSql = "SELECT * FROM [" + tblName.Rows[i]["TABLE_NAME"].ToString() + "]";
                            OleDbDataAdapter myCommand = new OleDbDataAdapter(vsSql, conn);
                            myCommand.Fill(tbl);
                            ds.Tables.Add(tbl.Copy());
                            tbl.Dispose();
                            tbl = null;
                        }
                        conn.Close();
                    }
                }
                catch (Exception ex)
                {
                    conn.Close();
                    throw new Exception(ex.Source + ":" + ex.Message);
                }
            }
            return ds;
        }

        public static DataSet ConvertDataSet(DataSet source)
        {
            if (source == null) return null;

            DataSet result = new DataSet();
            int dataTableCount = source.Tables.Count;
            DataTable temp = null;
            for (int i = 0; i < dataTableCount; i++)
            {
                temp = ConvertDataTable(source.Tables[i]);
                result.Tables.Add(temp);
                result.Tables[i].TableName = source.Tables[i].TableName;
            }
            return result;
        }

        private static DataTable ConvertDataTable(DataTable source)
        {
            DataTable result = new DataTable();
            int columnsCount = source.Columns.Count;
            int rowsCount = source.Rows.Count;
            for (int i = 0; i < columnsCount; i++)
            {
                DataColumn column = new DataColumn(source.Rows[0][i].ToString().Trim());
                result.Columns.Add(column);
            }
            DataRow dr;
            for (int r = 1; r < rowsCount; r++)
            {
                dr = result.NewRow();
                for (int c = 0; c < columnsCount; c++)
                {
                    dr[c] = source.Rows[r][c].ToString().Trim();
                }
                result.Rows.Add(dr);
            }
            return result;
        }
    }
ImportHelper

2. Open XML方式

  该方法只针对office2007及以上版本有效,因为office2007以上版本是基于XML实现的数据存储,详细内容不做讲解,有兴趣的网友可以将Excel文件扩展名修改为zip并解压,然后对解压出的文件进行分析。

 以Open XML的方式实现Excel的导入导出,需要先下载并安装Open XML Format SDK 2.0及其以上版本,具体下载地址为:https://www.microsoft.com/en-us/download/details.aspx?id=5124。SDK默认会安装在C:\Program Files (x86)\Open XML Format SDK\V2.0 (64bit)目录下,lib子目录下的DocumentFormat.OpenXml.dll必须被引用到项目中。

具体代码如下:

    public class ExcelOperater
    {
        #region 读取Excel
        /// <summary>
        /// 将Excel数据读取到DataSet
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public DataSet ExcelToDataSet(string filePath)
        {
            DataSet dataSet = new DataSet();
            try
            {
                using (SpreadsheetDocument spreadDocument = SpreadsheetDocument.Open(filePath, false))
                {
                    //指定WorkbookPart对象
                    WorkbookPart workBookPart = spreadDocument.WorkbookPart;
                    //获取Excel中SheetName集合
                    List<string> sheetNames = GetSheetNames(workBookPart);

                    foreach (string sheetName in sheetNames)
                    {
                        DataTable dataTable = WorkSheetToTable(workBookPart, sheetName);
                        if (dataTable != null)
                        {
                            dataSet.Tables.Add(dataTable);//将表添加到数据集
                        }
                    }
                }
            }
            catch (Exception exp)
            {
                //throw new Exception("可能Excel正在打开中,请关闭重新操作!");
            }
            return dataSet;
        }

        /// <summary>
        /// 将Excel数据读取到DataTable
        /// </summary>
        /// <param name="sheetName"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public DataTable ExcelToDataTable(string sheetName, string filePath)
        {
            DataTable dataTable = new DataTable();
            try
            {
                //根据Excel流转换为spreadDocument对象
                using (SpreadsheetDocument spreadDocument = SpreadsheetDocument.Open(filePath, false))//Excel文档包
                {
                    //Workbook workBook = spreadDocument.WorkbookPart.Workbook;//主文档部件的根元素
                    //Sheets sheeets = workBook.Sheets;//块级结构(如工作表、文件版本等)的容器
                    WorkbookPart workBookPart = spreadDocument.WorkbookPart;
                    //获取Excel中SheetName集合
                    List<string> sheetNames = GetSheetNames(workBookPart);

                    if (sheetNames.Contains(sheetName))
                    {
                        //根据WorkSheet转化为Table
                        dataTable = WorkSheetToTable(workBookPart, sheetName);
                    }
                }
            }
            catch (Exception exp)
            {
                //throw new Exception("可能Excel正在打开中,请关闭重新操作!");
            }
            return dataTable;
        }

        /// <summary>
        /// 获取Excel中的sheet页名称
        /// </summary>
        /// <param name="workBookPart"></param>
        /// <returns></returns>
        private List<string> GetSheetNames(WorkbookPart workBookPart)
        {
            List<string> sheetNames = new List<string>();
            Sheets sheets = workBookPart.Workbook.Sheets;
            foreach (Sheet sheet in sheets)
            {
                string sheetName = sheet.Name;
                if (!string.IsNullOrEmpty(sheetName))
                {
                    sheetNames.Add(sheetName);
                }
            }
            return sheetNames;
        }

        /// <summary>
        /// 获取指定sheet名称的Excel数据行集合
        /// </summary>
        /// <param name="workBookPart"></param>
        /// <param name="sheetName"></param>
        /// <returns></returns>
        public IEnumerable<Row> GetWorkBookPartRows(WorkbookPart workBookPart, string sheetName)
        {
            IEnumerable<Row> sheetRows = null;
            //根据表名在WorkbookPart中获取Sheet集合
            IEnumerable<Sheet> sheets = workBookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName);
            if (sheets.Count() == 0)
            {
                return null;//没有数据
            }

            WorksheetPart workSheetPart = workBookPart.GetPartById(sheets.First().Id) as WorksheetPart;
            //获取Excel中得到的行
            sheetRows = workSheetPart.Worksheet.Descendants<Row>();

            return sheetRows;
        }

        /// <summary>
        /// 将指定sheet名称的数据转换成DataTable
        /// </summary>
        /// <param name="workBookPart"></param>
        /// <param name="sheetName"></param>
        /// <returns></returns>
        private DataTable WorkSheetToTable(WorkbookPart workBookPart, string sheetName)
        {
            //创建Table
            DataTable dataTable = new DataTable(sheetName);

            //根据WorkbookPart和sheetName获取该Sheet下所有行数据
            IEnumerable<Row> sheetRows = GetWorkBookPartRows(workBookPart, sheetName);
            if (sheetRows == null || sheetRows.Count() <= 0)
            {
                return null;
            }

            //将数据导入DataTable,假定第一行为列名,第二行以后为数据
            foreach (Row row in sheetRows)
            {
                //获取Excel中的列头
                if (row.RowIndex == 1)
                {
                    List<DataColumn> listCols = GetDataColumn(row, workBookPart);
                    dataTable.Columns.AddRange(listCols.ToArray());
                }
                else
                {
                    //Excel第二行同时为DataTable的第一行数据
                    DataRow dataRow = GetDataRow(row, dataTable, workBookPart);
                    if (dataRow != null)
                    {
                        dataTable.Rows.Add(dataRow);
                    }
                }
            }
            return dataTable;
        }

        /// <summary>
        /// 获取数字类型格式集合
        /// </summary>
        /// <param name="workBookPart"></param>
        /// <returns></returns>
        private List<string> GetNumberFormatsStyle(WorkbookPart workBookPart)
        {
            List<string> dicStyle = new List<string>();
            Stylesheet styleSheet = workBookPart.WorkbookStylesPart.Stylesheet;
            var test = styleSheet.NumberingFormats;
            if (test == null) return null;
            OpenXmlElementList list = styleSheet.NumberingFormats.ChildElements;//获取NumberingFormats样式集合

            foreach (var element in list)//格式化节点
            {
                if (element.HasAttributes)
                {
                    using (OpenXmlReader reader = OpenXmlReader.Create(element))
                    {
                        if (reader.Read())
                        {
                            if (reader.Attributes.Count > 0)
                            {
                                string numFmtId = reader.Attributes[0].Value;//格式化ID
                                string formatCode = reader.Attributes[1].Value;//格式化Code
                                dicStyle.Add(formatCode);//将格式化Code写入List集合
                            }
                        }
                    }
                }
            }
            return dicStyle;
        }

        /// <summary>
        /// 获得DataColumn
        /// </summary>
        /// <param name="row"></param>
        /// <param name="workBookPart"></param>
        /// <returns></returns>
        private List<DataColumn> GetDataColumn(Row row, WorkbookPart workBookPart)
        {
            List<DataColumn> listCols = new List<DataColumn>();
            foreach (Cell cell in row)
            {
                string cellValue = GetCellValue(cell, workBookPart);
                DataColumn col = new DataColumn(cellValue);
                listCols.Add(col);
            }
            return listCols;
        }

        /// <summary>
        /// 将sheet页中的一行数据转换成DataRow
        /// </summary>
        /// <param name="row"></param>
        /// <param name="dateTable"></param>
        /// <param name="workBookPart"></param>
        /// <returns></returns>
        private DataRow GetDataRow(Row row, DataTable dateTable, WorkbookPart workBookPart)
        {
            //读取Excel中数据,一一读取单元格,若整行为空则忽视该行
            DataRow dataRow = dateTable.NewRow();
            IEnumerable<Cell> cells = row.Elements<Cell>();

            int cellIndex = 0;//单元格索引
            int nullCellCount = cellIndex;//空行索引
            foreach (Cell cell in row)
            {
                string cellVlue = GetCellValue(cell, workBookPart);
                if (string.IsNullOrEmpty(cellVlue))
                {
                    nullCellCount++;
                }

                dataRow[cellIndex] = cellVlue;
                cellIndex++;
            }
            if (nullCellCount == cellIndex)//剔除空行
            {
                dataRow = null;//一行中单元格索引和空行索引一样
            }
            return dataRow;
        }

        /// <summary>
        /// 获得单元格数据值
        /// </summary>
        /// <param name="cell"></param>
        /// <param name="workBookPart"></param>
        /// <returns></returns>
        public string GetCellValue(Cell cell, WorkbookPart workBookPart)
        {
            string cellValue = string.Empty;
            if (cell.ChildElements.Count == 0)//Cell节点下没有子节点
            {
                return cellValue;
            }
            string cellRefId = cell.CellReference.InnerText;//获取引用相对位置
            string cellInnerText = cell.CellValue.InnerText;//获取Cell的InnerText
            cellValue = cellInnerText;//指定默认值(其实用来处理Excel中的数字)

            //获取WorkbookPart中NumberingFormats样式集合
            //List<string> dicStyles = GetNumberFormatsStyle(workBookPart);
            //获取WorkbookPart中共享String数据
            SharedStringTable sharedTable = workBookPart.SharedStringTablePart.SharedStringTable;

            try
            {
                EnumValue<CellValues> cellType = cell.DataType;//获取Cell数据类型
                if (cellType != null)//Excel对象数据
                {
                    switch (cellType.Value)
                    {
                        case CellValues.SharedString://字符串
                            //获取该Cell的所在的索引
                            int cellIndex = int.Parse(cellInnerText);
                            cellValue = sharedTable.ChildElements[cellIndex].InnerText;
                            break;
                        case CellValues.Boolean://布尔
                            cellValue = (cellInnerText == "1") ? "TRUE" : "FALSE";
                            break;
                        case CellValues.Date://日期
                            cellValue = Convert.ToDateTime(cellInnerText).ToString();
                            break;
                        case CellValues.Number://数字
                            cellValue = Convert.ToDecimal(cellInnerText).ToString();
                            break;
                        default: cellValue = cellInnerText; break;
                    }
                }
                else//格式化数据
                {
                    #region 根据Excel单元格格式设置数据类型,该部分代码有误,暂未处理
                    /*
                    if (dicStyles.Count > 0 && cell.StyleIndex != null)//对于数字,cell.StyleIndex==null
                    {
                        int styleIndex = Convert.ToInt32(cell.StyleIndex.Value);
                        string cellStyle = dicStyles[styleIndex - 1];//获取该索引的样式
                        if (cellStyle.Contains("yyyy") || cellStyle.Contains("h")
                            || cellStyle.Contains("dd") || cellStyle.Contains("ss"))
                        {
                            //如果为日期或时间进行格式处理,去掉“;@”
                            cellStyle = cellStyle.Replace(";@", "");
                            while (cellStyle.Contains("[") && cellStyle.Contains("]"))
                            {
                                int otherStart = cellStyle.IndexOf('[');
                                int otherEnd = cellStyle.IndexOf("]");

                                cellStyle = cellStyle.Remove(otherStart, otherEnd - otherStart + 1);
                            }
                            double doubleDateTime = double.Parse(cellInnerText);
                            DateTime dateTime = DateTime.FromOADate(doubleDateTime);//将Double日期数字转为日期格式
                            if (cellStyle.Contains("m")) { cellStyle = cellStyle.Replace("m", "M"); }
                            if (cellStyle.Contains("AM/PM")) { cellStyle = cellStyle.Replace("AM/PM", ""); }
                            cellValue = dateTime.ToString(cellStyle);//不知道为什么Excel 2007中格式日期为yyyy/m/d
                        }
                        else//其他的货币、数值
                        {
                            cellStyle = cellStyle.Substring(cellStyle.LastIndexOf('.') - 1).Replace("\\", "");
                            decimal decimalNum = decimal.Parse(cellInnerText);
                            cellValue = decimal.Parse(decimalNum.ToString(cellStyle)).ToString();
                        }
                    }
                    */
                    #endregion
                }
            }
            catch
            {
                //string expMessage = string.Format("Excel中{0}位置数据有误,请确认填写正确!", cellRefId);
                //throw new Exception(expMessage);
                cellValue = "N/A";
            }
            return cellValue;
        }

        /// <summary>
        /// 获得sheet页集合
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private List<string> GetExcelSheetNames(string filePath)
        {
            string sheetName = string.Empty;
            List<string> sheetNames = new List<string>();//所有Sheet表名
            using (SpreadsheetDocument spreadDocument = SpreadsheetDocument.Open(filePath, false))
            {
                WorkbookPart workBook = spreadDocument.WorkbookPart;
                Stream stream = workBook.GetStream(FileMode.Open);
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(stream);

                XmlNamespaceManager xmlNSManager = new XmlNamespaceManager(xmlDocument.NameTable);
                xmlNSManager.AddNamespace("default", xmlDocument.DocumentElement.NamespaceURI);
                XmlNodeList nodeList = xmlDocument.SelectNodes("//default:sheets/default:sheet", xmlNSManager);

                foreach (XmlNode node in nodeList)
                {
                    sheetName = node.Attributes["name"].Value;
                    sheetNames.Add(sheetName);
                }
            }
            return sheetNames;
        }

        #region SaveCell
        private void InsertTextCellValue(Worksheet worksheet, string column, uint row, string value)
        {
            Cell cell = ReturnCell(worksheet, column, row);
            CellValue v = new CellValue();
            v.Text = value;
            cell.AppendChild(v);
            cell.DataType = new EnumValue<CellValues>(CellValues.String);
            worksheet.Save();
        }
        private void InsertNumberCellValue(Worksheet worksheet, string column, uint row, string value)
        {
            Cell cell = ReturnCell(worksheet, column, row);
            CellValue v = new CellValue();
            v.Text = value;
            cell.AppendChild(v);
            cell.DataType = new EnumValue<CellValues>(CellValues.Number);
            worksheet.Save();
        }
        private static Cell ReturnCell(Worksheet worksheet, string columnName, uint row)
        {
            Row targetRow = ReturnRow(worksheet, row);

            if (targetRow == null)
                return null;

            return targetRow.Elements<Cell>().Where(c =>
               string.Compare(c.CellReference.Value, columnName + row,
               true) == 0).First();
        }
        private static Row ReturnRow(Worksheet worksheet, uint row)
        {
            return worksheet.GetFirstChild<SheetData>().
            Elements<Row>().Where(r => r.RowIndex == row).First();
        }
        #endregion

        #endregion


        #region 写入Excel
        /// <summary>
        /// 在指定路径创建SpreadsheetDocument文档
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private SpreadsheetDocument CreateParts(string filePath)
        {
            SpreadsheetDocument document = SpreadsheetDocument.Create(filePath, SpreadsheetDocumentType.Workbook);

            WorkbookPart workbookPart = document.AddWorkbookPart();

            workbookPart.Workbook = new Workbook();

            return document;
        }

        /// <summary>
        /// 创建WorksheetPart
        /// </summary>
        /// <param name="workbookPart"></param>
        /// <param name="sheetName"></param>
        /// <returns></returns>
        private WorksheetPart CreateWorksheet(WorkbookPart workbookPart, string sheetName)
        {
            WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();

            newWorksheetPart.Worksheet = new Worksheet(new SheetData());

            newWorksheetPart.Worksheet.Save();

            Sheets sheets = workbookPart.Workbook.GetFirstChild<Sheets>();
            if (sheets == null)
                sheets = workbookPart.Workbook.AppendChild<Sheets>(new Sheets());

            string relationshipId = workbookPart.GetIdOfPart(newWorksheetPart);

            uint sheetId = 1;

            if (sheets.Elements<Sheet>().Count() > 0)
            {//确定sheet的唯一编号
                sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
            }
            if (string.IsNullOrEmpty(sheetName))
            {
                sheetName = "Sheet" + sheetId;
            }

            Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = sheetName };
            sheets.Append(sheet);

            workbookPart.Workbook.Save();

            return newWorksheetPart;
        }

        /// <summary>
        /// 创建sheet样式
        /// </summary>
        /// <param name="workbookPart"></param>
        /// <returns></returns>
        private Stylesheet CreateStylesheet(WorkbookPart workbookPart)
        {
            Stylesheet stylesheet = null;

            if (workbookPart.WorkbookStylesPart != null)
            {
                stylesheet = workbookPart.WorkbookStylesPart.Stylesheet;
                if (stylesheet != null)
                {
                    return stylesheet;
                }
            }
            workbookPart.AddNewPart<WorkbookStylesPart>("Style");
            workbookPart.WorkbookStylesPart.Stylesheet = new Stylesheet();
            stylesheet = workbookPart.WorkbookStylesPart.Stylesheet;

            stylesheet.Fonts = new Fonts()
            {
                Count = (UInt32Value)3U
            };

            //fontId =0,默认样式
            Font fontDefault = new Font(
                                         new FontSize() { Val = 11D },
                                         new FontName() { Val = "Calibri" },
                                         new FontFamily() { Val = 2 },
                                         new FontScheme() { Val = FontSchemeValues.Minor });

            stylesheet.Fonts.Append(fontDefault);

            //fontId =1,标题样式
            Font fontTitle = new Font(new FontSize() { Val = 15D },
                                         new Bold() { Val = true },
                                         new FontName() { Val = "Calibri" },
                                         new FontFamily() { Val = 2 },
                                         new FontScheme() { Val = FontSchemeValues.Minor });
            stylesheet.Fonts.Append(fontTitle);

            //fontId =2,列头样式
            Font fontHeader = new Font(new FontSize() { Val = 13D },
                              new Bold() { Val = true },
                              new FontName() { Val = "Calibri" },
                              new FontFamily() { Val = 2 },
                              new FontScheme() { Val = FontSchemeValues.Minor });
            stylesheet.Fonts.Append(fontHeader);

            //fillId,0总是None,1总是gray125,自定义的从fillid =2开始
            stylesheet.Fills = new Fills()
            {
                Count = (UInt32Value)3U
            };

            //fillid=0
            Fill fillDefault = new Fill(new PatternFill() { PatternType = PatternValues.None });
            stylesheet.Fills.Append(fillDefault);

            //fillid=1
            Fill fillGray = new Fill();
            PatternFill patternFillGray = new PatternFill()
            {
                PatternType = PatternValues.Gray125
            };
            fillGray.Append(patternFillGray);
            stylesheet.Fills.Append(fillGray);

            //fillid=2
            Fill fillYellow = new Fill();
            PatternFill patternFillYellow = new PatternFill(new ForegroundColor() { Rgb = new HexBinaryValue() { Value = "FFFFFF00" } })
            {
                PatternType = PatternValues.Solid
            };
            fillYellow.Append(patternFillYellow);
            stylesheet.Fills.Append(fillYellow);

            stylesheet.Borders = new Borders()
            {
                Count = (UInt32Value)2U
            };

            //borderID=0
            Border borderDefault = new Border(new LeftBorder(), new RightBorder(), new TopBorder() { }, new BottomBorder(), new DiagonalBorder());
            stylesheet.Borders.Append(borderDefault);

            //borderID=1
            Border borderContent = new Border(
                new LeftBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
                new RightBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
                new TopBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
                new BottomBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
                new DiagonalBorder()
                );
            stylesheet.Borders.Append(borderContent);

            stylesheet.CellFormats = new CellFormats();
            stylesheet.CellFormats.Count = 3;

            //styleIndex =0U
            CellFormat cfDefault = new CellFormat();
            cfDefault.Alignment = new Alignment();
            cfDefault.NumberFormatId = 0;
            cfDefault.FontId = 0;
            cfDefault.BorderId = 0;
            cfDefault.FillId = 0;
            cfDefault.ApplyAlignment = true;
            cfDefault.ApplyBorder = true;
            stylesheet.CellFormats.Append(cfDefault);

            //styleIndex =1U
            CellFormat cfTitle = new CellFormat();
            cfTitle.Alignment = new Alignment();
            cfTitle.NumberFormatId = 0;
            cfTitle.FontId = 1;
            cfTitle.BorderId = 1;
            cfTitle.FillId = 0;
            cfTitle.ApplyBorder = true;
            cfTitle.ApplyAlignment = true;
            cfTitle.Alignment.Horizontal = HorizontalAlignmentValues.Center;
            stylesheet.CellFormats.Append(cfTitle);

            //styleIndex =2U
            CellFormat cfHeader = new CellFormat();
            cfHeader.Alignment = new Alignment();
            cfHeader.NumberFormatId = 0;
            cfHeader.FontId = 2;
            cfHeader.BorderId = 1;
            cfHeader.FillId = 2;
            cfHeader.ApplyAlignment = true;
            cfHeader.ApplyBorder = true;
            cfHeader.ApplyFill = true;
            cfHeader.Alignment.Horizontal = HorizontalAlignmentValues.Center;
            stylesheet.CellFormats.Append(cfHeader);

            //styleIndex =3U
            CellFormat cfContent = new CellFormat();
            cfContent.Alignment = new Alignment();
            cfContent.NumberFormatId = 0;
            cfContent.FontId = 0;
            cfContent.BorderId = 1;
            cfContent.FillId = 0;
            cfContent.ApplyAlignment = true;
            cfContent.ApplyBorder = true;
            stylesheet.CellFormats.Append(cfContent);

            workbookPart.WorkbookStylesPart.Stylesheet.Save();
            return stylesheet;
        }

        /// <summary>
        /// 创建文本单元格,Cell的内容均视为文本
        /// </summary>
        /// <param name="columnIndex"></param>
        /// <param name="rowIndex"></param>
        /// <param name="cellValue"></param>
        /// <param name="styleIndex"></param>
        /// <returns></returns>
        private Cell CreateTextCell(int columnIndex, int rowIndex, object cellValue, Nullable<uint> styleIndex)
        {
            Cell cell = new Cell();

            cell.DataType = CellValues.InlineString;

            cell.CellReference = GetCellReference(columnIndex) + rowIndex;

            if (styleIndex.HasValue)
                cell.StyleIndex = styleIndex.Value;

            InlineString inlineString = new InlineString();
            Text t = new Text();

            t.Text = cellValue.ToString();
            inlineString.AppendChild(t);
            cell.AppendChild(inlineString);

            return cell;
        }

        /// <summary>
        /// 创建值单元格,Cell会根据单元格值的类型
        /// </summary>
        /// <param name="columnIndex"></param>
        /// <param name="rowIndex"></param>
        /// <param name="cellValue"></param>
        /// <param name="styleIndex"></param>
        /// <returns></returns>
        private Cell CreateValueCell(int columnIndex, int rowIndex, object cellValue, Nullable<uint> styleIndex)
        {
            Cell cell = new Cell();
            cell.CellReference = GetCellReference(columnIndex) + rowIndex;
            CellValue value = new CellValue();
            value.Text = cellValue.ToString();

            //apply the cell style if supplied
            if (styleIndex.HasValue)
                cell.StyleIndex = styleIndex.Value;

            cell.AppendChild(value);

            return cell;
        }

        /// <summary>
        /// 获取行引用,如A1
        /// </summary>
        /// <param name="colIndex"></param>
        /// <returns></returns>
        private string GetCellReference(int colIndex)
        {
            int dividend = colIndex;
            string columnName = String.Empty;
            int modifier;

            while (dividend > 0)
            {
                modifier = (dividend - 1) % 26;
                columnName =
                    Convert.ToChar(65 + modifier).ToString() + columnName;
                dividend = (int)((dividend - modifier) / 26);
            }
            return columnName;
        }

        /// <summary>
        /// 创建行数据,不同类型使用不同的styleIndex
        /// </summary>
        /// <param name="dataRow"></param>
        /// <param name="rowIndex"></param>
        /// <returns></returns>
        private Row CreateDataRow(DataRow dataRow, int rowIndex)
        {
            Row row = new Row
            {
                RowIndex = (UInt32)rowIndex
            };

            //Nullable<uint> styleIndex = null;
            double doubleValue;
            int intValue;
            DateTime dateValue;
            decimal decValue;

            for (int i = 0; i < dataRow.Table.Columns.Count; i++)
            {
                Cell dataCell;
                if (DateTime.TryParse(dataRow[i].ToString(), out dateValue) && dataRow[i].GetType() == typeof(DateTime))
                {
                    dataCell = CreateTextCell(i + 1, rowIndex, dataRow[i], 3u);
                    //dataCell.DataType = CellValues.Date;
                }
                else if (decimal.TryParse(dataRow[i].ToString(), out decValue) && dataRow[i].GetType() == typeof(decimal))
                {
                    dataCell = CreateValueCell(i + 1, rowIndex, decValue, 3u);
                }
                else if (int.TryParse(dataRow[i].ToString(), out intValue) && dataRow[i].GetType() == typeof(int))
                {
                    dataCell = CreateValueCell(i + 1, rowIndex, intValue, 3u);
                }
                else if (Double.TryParse(dataRow[i].ToString(), out doubleValue) && dataRow[i].GetType() == typeof(double))
                {
                    dataCell = CreateValueCell(i + 1, rowIndex, doubleValue, 3u);
                }
                else
                {
                    dataCell = CreateTextCell(i + 1, rowIndex, dataRow[i], 3u);
                }

                row.AppendChild(dataCell);
                //styleIndex = null;
            }
            return row;
        }

        /// <summary>
        /// 将DataTable的列名称导入Excel
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="sheetData"></param>
        private void CreateTableHeader(DataTable dt, SheetData sheetData)
        {
            Row header = new Row
            {
                RowIndex = (UInt32)1
            };
            int colCount = dt.Columns.Count;
            for(int i = 0; i < colCount; i++)
            {
                string colName = dt.Columns[i].ColumnName;
                Cell dataCell = CreateTextCell( i + 1, 1, colName, 3u);
                header.AppendChild(dataCell);
            }
            //Row contentRow = CreateDataRow(header, 1);
            sheetData.AppendChild(header);
        }

        /// <summary>
        /// 将DataTable的数据导入Excel
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="sheetData"></param>
        private void InsertDataIntoSheet(DataTable dt, SheetData sheetData)
        {
            //SheetData sheetData = newWorksheetPart.Worksheet.GetFirstChild<SheetData>();

            //CreateTableHeader(dt, sheetData);

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                Row contentRow = CreateDataRow(dt.Rows[i], i + 2);
                sheetData.AppendChild(contentRow);
            }
            return;
        }

        /// <summary>
        /// 创建一个SharedStringTablePart(相当于各Sheet共用的存放字符串的容器)
        /// </summary>
        /// <param name="workbookPart"></param>
        /// <returns></returns>
        private SharedStringTablePart CreateSharedStringTablePart(WorkbookPart workbookPart)
        {
            SharedStringTablePart shareStringPart = null;
            if (workbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
            {
                shareStringPart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
            }
            else
            {
                shareStringPart = workbookPart.AddNewPart<SharedStringTablePart>();
            }
            return shareStringPart;
        }

        /// <summary>
        /// 导出Excel,执行函数
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="filePath"></param>
        public void DataTableToExcel(DataTable dt, string filePath)
        {
            try
            {
                using (SpreadsheetDocument document = CreateParts(filePath))
                {
                    WorksheetPart worksheetPart = CreateWorksheet(document.WorkbookPart, dt.TableName);

                    SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();

                    Stylesheet styleSheet = CreateStylesheet(document.WorkbookPart);

                    //InsertTableTitle(parameter.SheetName, sheetData, styleSheet);

                    // MergeTableTitleCells(dt.Columns.Count, worksheetPart.Worksheet);

                    CreateTableHeader(dt, sheetData);

                    InsertDataIntoSheet(dt, sheetData);

                    SharedStringTablePart sharestringTablePart = CreateSharedStringTablePart(document.WorkbookPart);
                    sharestringTablePart.SharedStringTable = new SharedStringTable();

                    sharestringTablePart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text("ExcelReader")));
                    sharestringTablePart.SharedStringTable.Save();
                }
                //result = 0;
            }
            catch (Exception ex)
            {
                //iSession.AddError(ex);
                //result = error_result_prefix - 99;
            }
            //return result;
        }

        #endregion
    }
View Code

 

posted @ 2016-01-14 17:55  zhchsh  阅读(1487)  评论(0编辑  收藏  举报