2011-08-30 2 views
20

는 내가 Excel 파일 열기 위해 Microsoft.Office.Interop.Excel namespace를 사용하기 위해 노력하고있어

하고 싶은 (XSL 또는 CSV,하지만 슬프게도 하지 XSLX)과 DataSet으로 가져 무엇. 워크 시트 나 열 이름을 제어 할 수 없으므로 변경을 허용해야합니다.Microsoft.Office.Interop.Excel을 사용하여 Excel에서 DataSet으로 어떻게 가져 옵니까?

내가

내가 과거에이의 OLEDB method을 시도했습니다 시도, 그리고 (버그, 느린 및 Excel 파일의 스키마에 대한 사전 지식이 필요)에 문제를 많이 했어 무엇

, 그래서 나는 그것을 다시하고 싶지 않다. 내가하고 싶은 것은 Microsoft.Office.Interop.Excel을 사용하여 통합 문서를 DataSet으로 직접 가져 오거나 워크 시트를 반복하고 각 문서를 DataTable에로드하는 것입니다.

믿거 나 말거나,이 문제를 해결하는 데 어려움이 있습니다. A few searches on StackOverflow은 주로 역 (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을 사용하여이 작업을 수행 할 수 있습니까?

+0

현상금을 추가. Excel 파일 내용에 대한 사전 지식없이 누구나 가능한 한 자동으로 데이터를 얻을 수 있다면 현상금을 수여 할 것입니다. –

+0

미리 데이터에 대해 보증 할 수 있습니다. 내가 두려워하는 것은 오래된 통합 문서가 들어가서 테이블 형식의 데이터를 가져올 수있는 무언가를 원한다는 것입니다. 이 표의 데이터는 명명 된 범위로 구분되어야하거나 일종의 규칙을 따라야합니다. 컨벤션을 따랐다면 통합 문서의 모든 시트가 행 1에 헤더 행이있는 레코드 집합과 똑같이 보입니다. 그렇지 않으면 운이 없게 될 것입니다 ... – adamleerich

답변

31

Excel Data Reader (이전에 here 호스트)을 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 주변의 일부 검색 후

, 나는이 기사를 건너 왔어요 : Faster MS Excel Reading using Office Interop Assemblies. 이 기사에서는 Office Interop Assemblies을 사용하여 주어진 Excel 시트의 데이터를 읽습니다. 소스 코드가 프로젝트에 있습니다. 나는이 기사가 당신이 성취하고자하는 것에 대한 출발점이 될 수 있다고 생각한다. 즉, excel workbook 내부의 각 excel worksheet를 들어, 발견 된 모든 값을

가 UPDATE 2

코드는 아래 excel workbook 소요 데 도움이 읽는 경우를 참조하십시오. 위의 코드에서

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] 당신이 dataset에 추가 할 필요가있는 값입니다. i은 행을 나타내지 만 j은 열을 나타냅니다.

+0

가능한 경우 Interop.Excel을 사용하는 것을 선호하지만 이것은 훌륭한 백업 계획입니다. 감사. –

+1

Interop.Excel과 관련된 것이 있으면 여기에 게시하십시오. 그것도 기초하여 무언가를하는 것이 좋을 것입니다. – reggie

+0

@Justin Morgan 저는 Office Interop 어셈블리만을 사용하는 CodeProject에 대한 기사 링크로 답변을 업데이트했습니다. 도움이되는지 알려주세요. – reggie

4

본 적이 있습니까? http://www.aspspider.com/resources/Resource510.aspx에서 : 정말 Interop.Excel이 기능이 있는지 알고 싶습니다 때문에

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; 
} 
+0

아마 적응할 수 있습니다. 미리 열 개수 나 데이터 유형을 알지 못하므로 해결 방법을 찾아야합니다. Interop.Excel에 실제로 데이터 개체로 직접 변환 할 수있는 것이 있으면 좋겠지 만 얻을 수있는 것을 취할 것입니다. –

+0

Interop.Excel은 한 데이터 형식에서 다른 데이터 형식으로의 직접 변환을 허용하지 않습니다. Sheets 객체에 액세스 할 수 있으므로 각 시트에 액세스 한 다음 해당 시트의 각 Range를 반복 할 수 있습니다. 일단 거기에 있으면 변환 코드를 작성해야합니다. – adamleerich

+0

이 코드는 꽤 구조적으로 보입니다. 업데이트를 연장하여 동일한 기능을 수행합니까? – Shalem

4
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); 
} 
+0

멋지고 빠릅니다. 고마워. –

1
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); 
     } 
    } 
} 
관련 문제