如何使用Microsoft.Office.Interop.Excel从Excel导入到DataSet?

我想做的事

我试图使用Microsoft.Office.Interop.Excel命名空间来打开一个Excel文件(XSL或CSV,但不幸的是不是 XSLX),并将其导入到DataSet中。 我无法控制工作表或列名,所以我需要允许对它们进行更改。

我试过了

过去我已经尝试过这种OLEDB方法 ,并且有很多问题(bug,慢,并且需要事先了解Excel文件的模式),所以我想避免再这样做。 我想要做的是使用Microsoft.Office.Interop.Excel将工作簿直接导入到数据集,或循环通过工作表,并加载到DataTable中的每一个。

相信与否,我一直在寻找资源的麻烦。 在StackOverflow的一些search发现大多数人试图做相反(DataSet => Excel),或OLEDB技术。 Google没有太多帮助。

到目前为止我所拥有的

public void Load(string filename, Excel.XlFileFormat format = Excel.XlFileFormat.xlCSV) { app = new Excel.Application(); book = app.Workbooks.Open(Filename: filename, Format: format); DataSet ds = new DataSet(); foreach (Excel.Worksheet sheet in book.Sheets) { DataTable dt = new DataTable(sheet.Name); ds.Tables.Add(dt); //??? Fill dt from sheet } this.Data = ds; } 

我可以一次导入整本书,或者一次循环一页。 我可以用Interop.Excel做这个吗?

那么使用Excel Data Reader (先前在这里托pipe)codeplex上的开源项目呢? 它的工作真的很好,我从Excel表导出数据。

在指定的链接上给出的示例代码:

 FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read); //1. Reading from a binary Excel file ('97-2003 format; *.xls) IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream); //... //2. Reading from a OpenXml Excel file (2007 format; *.xlsx) IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream); //... //3. DataSet - The result of each spreadsheet will be created in the result.Tables DataSet result = excelReader.AsDataSet(); //... //4. DataSet - Create column names from first row excelReader.IsFirstRowAsColumnNames = true; DataSet result = excelReader.AsDataSet(); //5. Data Reader methods while (excelReader.Read()) { //excelReader.GetInt32(0); } //6. Free resources (IExcelDataReader is IDisposable) excelReader.Close(); 

UPDATE

经过一番search后,我遇到了这篇文章: 更快的MS Excel阅读使用Office互操作程序集 。 本文只使用Office Interop Assemblies程序集从给定的Excel工作表读取数据。 源代码是该项目也在那里。 我想这篇文章可以成为你想要实现的一个起点。 看看是否有帮助

更新2

下面的代码需要一个excel workbook并读取excel workbook中每个excel worksheet所有值。

 private static void TestExcel() { ApplicationClass app = new ApplicationClass(); Workbook book = null; Range range = null; try { app.Visible = false; app.ScreenUpdating = false; app.DisplayAlerts = false; string execPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase); book = app.Workbooks.Open(@"C:\data.xls", Missing.Value, Missing.Value, Missing.Value , Missing.Value, Missing.Value, Missing.Value, Missing.Value , Missing.Value, Missing.Value, Missing.Value, Missing.Value , Missing.Value, Missing.Value, Missing.Value); foreach (Worksheet sheet in book.Worksheets) { Console.WriteLine(@"Values for Sheet "+sheet.Index); // get a range to work with range = sheet.get_Range("A1", Missing.Value); // get the end of values to the right (will stop at the first empty cell) range = range.get_End(XlDirection.xlToRight); // get the end of values toward the bottom, looking in the last column (will stop at first empty cell) range = range.get_End(XlDirection.xlDown); // get the address of the bottom, right cell string downAddress = range.get_Address( false, false, XlReferenceStyle.xlA1, Type.Missing, Type.Missing); // Get the range, then values from a1 range = sheet.get_Range("A1", downAddress); object[,] values = (object[,]) range.Value2; // View the values Console.Write("\t"); Console.WriteLine(); for (int i = 1; i <= values.GetLength(0); i++) { for (int j = 1; j <= values.GetLength(1); j++) { Console.Write("{0}\t", values[i, j]); } Console.WriteLine(); } } } catch (Exception e) { Console.WriteLine(e); } finally { range = null; if (book != null) book.Close(false, Missing.Value, Missing.Value); book = null; if (app != null) app.Quit(); app = null; } } 

在上面的代码中, values[i, j]是您需要添加到dataseti表示行,而j表示列。

你看过这个吗? 从http://www.aspspider.com/resources/Resource510.aspx

 public DataTable Import(String path) { Microsoft.Office.Interop.Excel.ApplicationClass app = new Microsoft.Office.Interop.Excel.ApplicationClass(); Microsoft.Office.Interop.Excel.Workbook workBook = app.Workbooks.Open(path, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0); Microsoft.Office.Interop.Excel.Worksheet workSheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.ActiveSheet; int index = 0; object rowIndex = 2; DataTable dt = new DataTable(); dt.Columns.Add("FirstName"); dt.Columns.Add("LastName"); dt.Columns.Add("Mobile"); dt.Columns.Add("Landline"); dt.Columns.Add("Email"); dt.Columns.Add("ID"); DataRow row; while (((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 1]).Value2 != null) { rowIndex = 2 + index; row = dt.NewRow(); row[0] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 1]).Value2); row[1] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 2]).Value2); row[2] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 3]).Value2); row[3] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 4]).Value2); row[4] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)workSheet.Cells[rowIndex, 5]).Value2); index++; dt.Rows.Add(row); } app.Workbooks.Close(); return dt; } 
 object[,] valueArray = (object[,])excelRange.get_Value(XlRangeValueDataType.xlRangeValueDefault); //Get the column names for (int k = 0; k < valueArray.GetLength(1); ) { //add columns to the data table. dt.Columns.Add((string)valueArray[1,++k]); } //Load data into data table object[] singleDValue = new object[valueArray.GetLength(1)]; //value array first row contains column names. so loop starts from 1 instead of 0 for (int i = 1; i < valueArray.GetLength(0); i++) { Console.WriteLine(valueArray.GetLength(0) + ":" + valueArray.GetLength(1)); for (int k = 0; k < valueArray.GetLength(1); ) { singleDValue[k] = valueArray[i+1, ++k]; } dt.LoadDataRow(singleDValue, System.Data.LoadOption.PreserveChanges); } 
 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Reflection; using Microsoft.Office.Interop.Excel; namespace trg.satmap.portal.ParseAgentSkillMapping { class ConvertXLStoDT { private StringBuilder errorMessages; public StringBuilder ErrorMessages { get { return errorMessages; } set { errorMessages = value; } } public ConvertXLStoDT() { ErrorMessages = new StringBuilder(); } public System.Data.DataTable XLStoDTusingInterOp(string FilePath) { #region Excel important Note. /* * Excel creates XLS and XLSX files. These files are hard to read in C# programs. * They are handled with the Microsoft.Office.Interop.Excel assembly. * This assembly sometimes creates performance issues. Step-by-step instructions are helpful. * * Add the Microsoft.Office.Interop.Excel assembly by going to Project -> Add Reference. */ #endregion Microsoft.Office.Interop.Excel.Application excelApp = null; Microsoft.Office.Interop.Excel.Workbook workbook = null; System.Data.DataTable dt = new System.Data.DataTable(); //Creating datatable to read the content of the Sheet in File. try { excelApp = new Microsoft.Office.Interop.Excel.Application(); // Initialize a new Excel reader. Must be integrated with an Excel interface object. //Opening Excel file(myData.xlsx) workbook = excelApp.Workbooks.Open(FilePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets.get_Item(1); Microsoft.Office.Interop.Excel.Range excelRange = ws.UsedRange; //gives the used cells in sheet ws = null; // now No need of this so should expire. //Reading Excel file. object[,] valueArray = (object[,])excelRange.get_Value(Microsoft.Office.Interop.Excel.XlRangeValueDataType.xlRangeValueDefault); excelRange = null; // you don't need to do any more Interop. Now No need of this so should expire. dt = ProcessObjects(valueArray); } catch (Exception ex) { ErrorMessages.Append(ex.Message); } finally { #region Clean Up if (workbook != null) { #region Clean Up Close the workbook and release all the memory. workbook.Close(false, FilePath, Missing.Value); System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); #endregion } workbook = null; if (excelApp != null) { excelApp.Quit(); } excelApp = null; #endregion } return (dt); } /// <summary> /// Scan the selected Excel workbook and store the information in the cells /// for this workbook in an object[,] array. Then, call another method /// to process the data. /// </summary> private void ExcelScanIntenal(Microsoft.Office.Interop.Excel.Workbook workBookIn) { // // Get sheet Count and store the number of sheets. // int numSheets = workBookIn.Sheets.Count; // // Iterate through the sheets. They are indexed starting at 1. // for (int sheetNum = 1; sheetNum < numSheets + 1; sheetNum++) { Worksheet sheet = (Worksheet)workBookIn.Sheets[sheetNum]; // // Take the used range of the sheet. Finally, get an object array of all // of the cells in the sheet (their values). You can do things with those // values. See notes about compatibility. // Range excelRange = sheet.UsedRange; object[,] valueArray = (object[,])excelRange.get_Value(XlRangeValueDataType.xlRangeValueDefault); // // Do something with the data in the array with a custom method. // ProcessObjects(valueArray); } } private System.Data.DataTable ProcessObjects(object[,] valueArray) { System.Data.DataTable dt = new System.Data.DataTable(); #region Get the COLUMN names for (int k = 1; k <= valueArray.GetLength(1); k++) { dt.Columns.Add((string)valueArray[1, k]); //add columns to the data table. } #endregion #region Load Excel SHEET DATA into data table object[] singleDValue = new object[valueArray.GetLength(1)]; //value array first row contains column names. so loop starts from 2 instead of 1 for (int i = 2; i <= valueArray.GetLength(0); i++) { for (int j = 0; j < valueArray.GetLength(1); j++) { if (valueArray[i, j + 1] != null) { singleDValue[j] = valueArray[i, j + 1].ToString(); } else { singleDValue[j] = valueArray[i, j + 1]; } } dt.LoadDataRow(singleDValue, System.Data.LoadOption.PreserveChanges); } #endregion return (dt); } } }