在导入之前都需要将上传的文件保存到服务器,所以避免重复的写这些代码,先贴出上传文件并保存到服务器指定路径的代码。

    1. protected void btnImport_Click(object sender, EventArgs e)
    2. {
    3. Random random = new Random();
    4. ImportClass Import = new ImportClass();
    5. //保存文件的虚拟路径
    6. string path = "Import/";
    7. //获取选择的文件名
    8. string fileName = FileUpload1.FileName;
    9. //获取文件扩展名称
    10. string fileExt = Path.GetExtension(fileName);
    11. //生成新文件名
    12. string newName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + random.Next(0, 9999).ToString();
    13. //获取指定虚机路径的物理路径
    14. string fullPath = HttpContext.Current.Server.MapPath(path);
    15. //上传文件保存路径
    16. string savePath = fullPath + newName + fileExt;
    17. //保存文件到服务器
    18. FileUpload1.SaveAs(savePath);
    19. try
    20. {
    21. //获取导入的数据
    22. DataSet ds = Import.ImportExcel(savePath);
    23. if (ds != null && ds.Tables.Count > 0)
    24. {
    25. //这里可以写插入数据库的方法
    26. }
    27. }
    28. catch (Exception ex)
    29. {
    30. throw;
    31. }
    32. }

    第一种:OleDB

    1. public DataSet ImportExcel(string filePath)
    2. {
    3. DataSet ds = null;
    4. OleDbConnection conn;
    5. string strConn = string.Empty;
    6. string sheetName = string.Empty;
    7. try
    8. {
    9. // Excel 2003 版本连接字符串
    10. strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0; HDR=YES; IMEX=1;'";
    11. conn = new OleDbConnection(strConn);
    12. conn.Open();
    13. }
    14. catch
    15. {
    16. // Excel 2007 以上版本连接字符串
    17. strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1;'";
    18. conn = new OleDbConnection(strConn);
    19. conn.Open();
    20. }
    21. //获取所有的 sheet 表
    22. DataTable dtSheetName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" });
    23. ds = new DataSet();
    24. for (int i = 0; i < dtSheetName.Rows.Count; i++)
    25. {
    26. DataTable dt = new DataTable();
    27. dt.TableName = "table" + i.ToString();
    28. //获取表名
    29. sheetName = dtSheetName.Rows[i]["TABLE_NAME"].ToString();
    30. OleDbDataAdapter oleda = new OleDbDataAdapter("select * from [" + sheetName + "]", conn);
    31. oleda.Fill(dt);
    32. ds.Tables.Add(dt);
    33. }
    34. //关闭连接,释放资源
    35. conn.Close();
    36. conn.Dispose();
    37. return ds;
    38. }

    除了读取过程不太灵活之外,这种读取方式还有个弊端就是,当 Excel 数据量很大时。会非常占用内存,当内存不够时会抛出内存溢出的异常,不过一般都能适用了。

    第二种:Microsoft.Office.Interop.Excel.dll

    1. public DataSet ImportExcel(string filePath)
    2. {
    3. DataSet ds = null;
    4. DataTable dt = null;
    5. Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
    6. Microsoft.Office.Interop.Excel.Workbook workbook = null;
    7. Microsoft.Office.Interop.Excel.Worksheet worksheet = null;
    8. Microsoft.Office.Interop.Excel.Sheets sheets = null;
    9. Microsoft.Office.Interop.Excel.Range range = null;
    10. object missing = System.Reflection.Missing.Value;
    11. try
    12. {
    13. if (excel == null)
    14. {
    15. return null;
    16. }
    17. //打开 Excel 文件
    18. workbook = excel.Workbooks.Open(filePath, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);
    19. //获取所有的 sheet 表
    20. sheets = workbook.Worksheets;
    21. ds = new DataSet();
    22. for (int i = 1; i <= sheets.Count; i++)
    23. {
    24. //获取第一个表
    25. worksheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(i);
    26. int rowCount = worksheet.UsedRange.Rows.Count;
    27. int colCount = worksheet.UsedRange.Columns.Count;
    28. int rowIndex = 1; //起始行为 1
    29. int colIndex = 1; //起始列为 1
    30. DataColumn dc;
    31. dt = new DataTable();
    32. dt.TableName = "table" + i.ToString();
    33. //读取列名
    34. for (int j = 0; j < colCount; j++)
    35. {
    36. range = worksheet.Cells[rowIndex, colIndex + j];
    37. dc = new DataColumn();
    38. dc.DataType = Type.GetType("System.String");
    39. dc.ColumnName = range.Text.ToString().Trim();
    40. //添加列
    41. dt.Columns.Add(dc);
    42. }
    43. //读取行数据
    44. for (int k = 1; k < rowCount; k++)
    45. {
    46. DataRow dr = dt.NewRow();
    47. for (int l = 0; l < colCount; l++)
    48. {
    49. range = worksheet.Cells[rowIndex + k, colIndex + l];
    50. //使用 range.Value.ToString(); 或 range.Value2.ToString(); 或 range.Text.ToString(); 都可以获取单元格的值
    51. dr[l] = range.Text.ToString();
    52. }
    53. dt.Rows.Add(dr.ItemArray);
    54. }
    55. ds.Tables.Add(dt);
    56. }
    57. }
    58. catch (Exception ex)
    59. {
    60. throw;
    61. }
    62. finally
    63. {
    64. workbook.Close();
    65. //关闭退出
    66. excel.Quit();
    67. //释放 COM 对象
    68. Marshal.ReleaseComObject(worksheet);
    69. Marshal.ReleaseComObject(workbook);
    70. Marshal.ReleaseComObject(excel);
    71. worksheet = null;
    72. workbook = null;
    73. excel = null;
    74. GC.Collect();
    75. }
    76. return ds;
    77. }

    这种方法首先需要安装有 office Excel,并且是一个单元格一个单元格的读取,所以性能会比较差。

    第三种:NPOI

    1. public DataSet ImportExcel(string filePath)
    2. {
    3. DataSet ds = null;
    4. try
    5. {
    6. //打开文件
    7. FileStream fileStream = new FileStream(filePath, FileMode.Open);
    8. XSSFWorkbook workbook = new XSSFWorkbook(fileStream);
    9. ISheet sheet = null;
    10. IRow row = null;
    11. ds = new DataSet();
    12. DataTable dt = null;
    13. for (int i = 0; i < workbook.Count; i++)
    14. {
    15. dt = new DataTable();
    16. dt.TableName = "table" + i.ToString();
    17. //获取 sheet 表
    18. sheet = workbook.GetSheetAt(i);
    19. //起始行索引
    20. int rowIndex = sheet.FirstRowNum;
    21. //获取行数
    22. int rowCount = sheet.LastRowNum;
    23. //获取第一行
    24. IRow firstRow = sheet.GetRow(rowIndex);
    25. //起始列索引
    26. int colIndex = firstRow.FirstCellNum;
    27. //获取列数
    28. int colCount = firstRow.LastCellNum;
    29. DataColumn dc = null;
    30. //获取列名
    31. for (int j = colIndex; j < colCount; j++)
    32. {
    33. dc = new DataColumn(firstRow.GetCell(j).StringCellValue);
    34. dt.Columns.Add(dc);
    35. }
    36. //跳过第一行列名
    37. rowIndex++;
    38. for (int k = rowIndex; k <= rowCount; k++)
    39. {
    40. DataRow dr = dt.NewRow();
    41. row = sheet.GetRow(k);
    42. for (int l = colIndex; l < colCount; l++)
    43. {
    44. if (row.GetCell(l) == null)
    45. {
    46. continue;
    47. }
    48. dr[l] = row.GetCell(l).StringCellValue;
    49. }
    50. dt.Rows.Add(dr);
    51. }
    52. ds.Tables.Add(dt);
    53. }
    54. sheet = null;
    55. workbook = null;
    56. fileStream.Close();
    57. fileStream.Dispose();
    58. }
    59. catch (Exception ex)
    60. {
    61. throw;
    62. }
    63. return ds;
    64. }

    我这里用的是 .xlsx 格式的,也就是 Excel 2007 及以上版本,2003 版本的话方法类似,只是打开文件的操作类不一样。
    // 2007 及以上版本
    XSSFWorkbook xWorkbook = new XSSFWorkbook(fileStream);

    // 2003 版本
    HSSFWorkbook hWorkbook = new HSSFWorkbook(fileStream);

    第四种:Aspose.Cells.dll

    1. public DataSet ImportExcel(string filePath)
    2. {
    3. DataSet ds = null;
    4. try
    5. {
    6. Aspose.Cells.Workbook workbook = new Aspose.Cells.Workbook();
    7. //打开文件,参数可以是文件的路径,也可以直接传入一个文件流
    8. workbook.Open(filePath);
    9. //获取 sheet 表
    10. Aspose.Cells.Worksheets worksheets = workbook.Worksheets;
    11. Aspose.Cells.Worksheet worksheet = null;
    12. Aspose.Cells.Cells cells = null;
    13. ds = new DataSet();
    14. DataTable dt = null;
    15. int rowIndex = 0; //起始行
    16. int colIndex = 0; //起始列
    17. for (int i = 0; i < worksheets.Count; i++)
    18. {
    19. dt = new DataTable();
    20. dt.TableName = "table" + i.ToString();
    21. worksheet = worksheets[i];
    22. //获取每个 sheet 表的所有单元格
    23. cells = worksheet.Cells;
    24. dt = cells.ExportDataTableAsString(rowIndex, colIndex, cells.MaxDataRow + 1, cells.MaxDataColumn + 1, true);
    25. ds.Tables.Add(dt);
    26. }
    27. worksheets.Clear();
    28. worksheet = null;
    29. worksheets = null;
    30. workbook = null;
    31. }
    32. catch (Exception ex)
    33. {
    34. throw;
    35. }
    36. return ds;
    37. }

    这种方法操作比较方便,跟 OleDB 一样直接获取一个 sheet 表的数据,不用一个单元格一个单元格的获取。而且操作也比较灵活,你可以一行一行的获取数据,甚至一个单元格一个单元格的获取数据。

    第五种:EPPlus

    1. public DataSet ImportExcel(string filePath)
    2. {
    3. DataSet ds = null;
    4. try
    5. {
    6. //打开文件
    7. FileStream fileStream = new FileStream(filePath, FileMode.Open);
    8. //读取文件流
    9. ExcelPackage package = new ExcelPackage(fileStream);
    10. //获取 sheet 表
    11. ExcelWorksheets worksheets = package.Workbook.Worksheets;
    12. ExcelWorksheet worksheet = null;
    13. ds = new DataSet();
    14. DataTable dt = null;
    15. for (int i = 1; i <= worksheets.Count; i++)
    16. {
    17. dt = new DataTable();
    18. dt.TableName = "table" + i.ToString();
    19. worksheet = worksheets[i];
    20. //获取行数
    21. int rowCount = worksheet.Dimension.End.Row;
    22. //获取列数
    23. int colCount = worksheet.Dimension.End.Column;
    24. //起始行为 1
    25. int rowIndex = worksheet.Dimension.Start.Row;
    26. //起始列为 1
    27. int colIndex = worksheet.Dimension.Start.Column;
    28. DataColumn dc = null;
    29. for (int j = colIndex; j <= colCount; j++)
    30. {
    31. dc = new DataColumn(worksheet.Cells[rowIndex, j].Value.ToString());
    32. dt.Columns.Add(dc);
    33. }
    34. rowIndex++;
    35. for (int k = rowIndex; k <= rowCount; k++)
    36. {
    37. DataRow dr = dt.NewRow();
    38. for (int l = colIndex; l <= colCount; l++)
    39. {
    40. if (worksheet.GetValue(k, l) == null)
    41. {
    42. continue;
    43. }
    44. dr[l - 1] = worksheet.GetValue(k, l).ToString();
    45. }
    46. dt.Rows.Add(dr);
    47. }
    48. ds.Tables.Add(dt);
    49. }
    50. package.Dispose();
    51. worksheet = null;
    52. worksheets = null;
    53. package = null;
    54. fileStream.Close();
    55. fileStream.Dispose();
    56. }
    57. catch (Exception ex)
    58. {
    59. throw;
    60. }
    61. return ds;
    62. }

    这种方法读取 Excel 数据性能还不错,但是要注意的是,sheet、row、col 的起始值都是从 1 开始的。