2013-08-01 24 views
5

Przeszukałem internet i nie mogłem znaleźć takiego pytania. Wszyscy szukali sposobu na zaimportowanie pojedynczego arkusza do pliku Excela, ale chcę zaimportować wszystkie arkusze w pliku do DataTable w DataSet, nie znając nazw arkuszy.Jak zaimportować wszystkie arkusze Excela do DataSet w języku C#

Przedtem nie robiłem zbyt wiele rzeczy z Excelem. Ten przykładowy kod i częściowo roboczego Znalazłem w internecie i to tylko analizuje daną nazwę arkusza:

public static DataSet Parse(string fileName, string workSheetName) 
{ 
    string connectionString = string.Format("provider=Microsoft.Jet.OLEDB.4.0; data source={0};Extended Properties=Excel 8.0;", fileName); 
    string query = string.Format("SELECT * FROM [{0}$]", workSheetName); 

    DataSet data = new DataSet(); 
    using (OleDbConnection con = new OleDbConnection(connectionString)) 
    { 
     con.Open(); 
     OleDbDataAdapter adapter = new OleDbDataAdapter(query, con); 
     adapter.Fill(data); 
    } 

    return data; 
} 

W powyższym kodzie, jak widać, workSheetName powinny być przekazywane w takim zapytaniu może wiedzieć, gdzie patrzeć na import. W moim przypadku chcę, aby przechodził przez wszystkie arkusze bez względu na to, jak je nazywają i importuje je do pojedynczych DataTable 's z DataSet.

W gruncie rzeczy ostatnią rzeczą będzie DataSet, w której każdy DataTable przechowuje wiersze dla każdego arkusza w zaimportowanym pliku.

+0

Ty naprawdę chcesz pracować z 'csv' pliku zamiast' xls' . Czy możesz zapisać go jako "csv"? – zsong

Odpowiedz

14

Jest to kod wymyśliłem i działa idealnie ale widziałem ktoś już dodał odpowiedź:

static DataSet Parse(string fileName) 
{ 
    string connectionString = string.Format("provider=Microsoft.Jet.OLEDB.4.0; data source={0};Extended Properties=Excel 8.0;", fileName); 


    DataSet data = new DataSet(); 

    foreach(var sheetName in GetExcelSheetNames(connectionString)) 
    { 
     using (OleDbConnection con = new OleDbConnection(connectionString)) 
     {  
      var dataTable = new DataTable(); 
      string query = string.Format("SELECT * FROM [{0}]", sheetName); 
      con.Open(); 
      OleDbDataAdapter adapter = new OleDbDataAdapter(query, con); 
      adapter.Fill(dataTable); 
      data.Tables.Add(dataTable); 
     } 
    } 

    return data; 
} 

static string[] GetExcelSheetNames(string connectionString) 
{ 
     OleDbConnection con = null; 
     DataTable dt = null; 
     con= new OleDbConnection(connectionString); 
     con.Open(); 
     dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); 

     if (dt == null) 
     { 
      return null; 
     } 

     String[] excelSheetNames = new String[dt.Rows.Count]; 
     int i = 0; 

     foreach (DataRow row in dt.Rows) 
     { 
      excelSheetNames[i] = row["TABLE_NAME"].ToString(); 
      i++; 
     } 

     return excelSheetNames; 
} 
+0

czy mogę to uzyskać za pomocą sqlconnection? –

13

bo byłem znudzony:

static void Main(string[] args) 
{ 
      string filename = @"c:\temp\myfile.xlsx";  
      System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection( 
         "Provider=Microsoft.ACE.OLEDB.12.0; " + 
         "data source='" + filename + "';" + 
          "Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" "); 
      myConnection.Open(); 
      DataTable mySheets = myConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });     
      DataSet ds = new DataSet(); 
      DataTable dt; 

      for (int i = 0; i <= mySheets.Rows.Count; i++) 
      { 
        dt = makeDataTableFromSheetName(filename, mySheets.Rows[i]["TABLE_NAME"].ToString()); 
        ds.Tables.Add(dt); 
      } 
} 

private static DataTable makeDataTableFromSheetName(string filename, string sheetName) 
{  
    System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
    "Provider=Microsoft.ACE.OLEDB.12.0; " + 
    "data source='" + filename + "';" + 
    "Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" "); 

    DataTable dtImport = new DataTable(); 
    System.Data.OleDb.OleDbDataAdapter myImportCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + sheetName + "$]", myConnection); 
    myImportCommand.Fill(dtImport); 
    return dtImport; 
} 
+0

bardzo pomocny dla mnie :) – Rebecca

3

funkcji, sugerowano przez Avitus jest poprawny, ale ma błąd logiki, musisz napisać ponownie:

DataTable dtImport = new DataTable(); 
using (System.Data.OleDb.OleDbConnection myConnection = new System.Data.OleDb.OleDbConnection(
      "Provider=Microsoft.ACE.OLEDB.12.0; " + 
      "data source='" + filename + "';" + 
       "Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\" ")){ 


using (System.Data.OleDb.OleDbDataAdapter myImportCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [" + sheetName + "$]", myConnection)) 
myImportCommand.Fill(dtImport); 
} return dtImport; 

to jest poprawne, otherwis e musisz ręcznie usunąć połączenie i moduł danych.

0

To może nie być najlepszym i najszybszym jeden, ale jego inny sposób (Edit- dodany eliminacja pustych komórek):

public static DataSet ReadWorkbook(string excelFileName, bool useFirstRowAsColumnName = false) 
    { 
     var excel = new Microsoft.Office.Interop.Excel.Application(); 
     var workBook = excel.Workbooks.Open(excelFileName, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);//MLHIDE 
     try 
     { 
      System.Data.DataSet ds = new DataSet(excelFileName); 
      foreach (var sheet0 in workBook.Worksheets) 
      { 
       var sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheet0; 
       try 
       { 
        var dt = readSheet(sheet, useFirstRowAsColumnName); 
        if (dt != null) 
         ds.Tables.Add(dt); 
       } 
       finally 
       { 
        releaseObject(sheet); 
       } 
      } 
      return ds; 
     } 
     finally 
     { 
      workBook.Close(true, null, null); 
      excel.Quit(); 

      releaseObject(workBook); 
      releaseObject(excel); 
     } 
    } 

    /// <summary> 
    /// Returns null for empty sheets or if sheet is not found. 
    /// </summary> 
    public static DataTable ReadSheet(string excelFileName, string sheetName, bool useFirstRowAsColumnName = false) 
    { 
     var excel = new Microsoft.Office.Interop.Excel.Application(); 
     var workBook = excel.Workbooks.Open(excelFileName, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);//MLHIDE 
     try 
     { 
      foreach (var sheet0 in workBook.Worksheets) 
      { 
       var sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheet0; 
       try 
       { 
        if (sheet.Name.Equals_Wildcard(sheetName)) 
        { 
         var dt = readSheet(sheet, useFirstRowAsColumnName); 
         if (dt != null) 
          return dt; 
        } 
       } 
       finally 
       { 
        releaseObject(sheet); 
       } 
      } 
      return null; 
     } 
     finally 
     { 
      workBook.Close(true, null, null); 
      excel.Quit(); 

      releaseObject(workBook); 
      releaseObject(excel); 
     } 
    } 

    /// <summary> 
    /// Returns null for empty sheets 
    /// </summary> 
private static DataTable readSheet(Microsoft.Office.Interop.Excel.Worksheet sheet, bool useFirstRowAsColumnName = false) 
     { 
      using (Dece.Common.BeginChangeCurrentCultureBlock_EN_us()) 
      { 
       var range = sheet.UsedRange; 
       try 
       { 
        object[,] values = (object[,])range.Value2; 
        int rowCount = values.GetLength(0); 
        int colCount = values.GetLength(1); 
        int rowCount0 = rowCount; 
        int colCount0 = colCount; 
        #region find row-col count 
        { 
         bool ok = false; 
         for (int row = rowCount; row > 0; row--) 
          if (!ok) 
           for (int col = colCount; col > 0; col--) 
           { 
            var val = values[row, col]; 
            if ((val != null) && (!System.Convert.ToString(val).IsNullOrEmpty())) 
            { 
             rowCount = row; 
             ok = true; 
             break; 
            } 
           } 
          else 
           break; 
        } 
        { 
         bool ok = false; 
         for (int col = colCount; col > 0; col--) 
          if (!ok) 
           for (int row = rowCount; row > 0; row--) 
           { 
            var val = values[row, col]; 
            if ((val != null) && (!System.Convert.ToString(val).IsNullOrEmpty())) 
            { 
             colCount = col; 
             ok = true; 
             break; 
            } 
           } 
          else 
           break; 
        } 
        #endregion 
        if ((rowCount > 0) && (colCount > 0)) 
        { 
         var dt = new DataTable(sheet.Name); 
         dt.BeginLoadData(); 
         try 
         { 
          for (int col = 1; col <= colCount; col++) 
           dt.Columns.Add_RenameIfRequired(useFirstRowAsColumnName ? values[1, col].ToString_NullProof() : col.ToString()); 
          var arr = new object[colCount]; 
          for (int row = useFirstRowAsColumnName ? 1 : 0; row < rowCount; row++) 
          { 
           for (int col = 1; col <= colCount; col++) 
            arr[col - 1] = values[row + 1, col]; 
           dt.Rows.Add(arr); 
          } 
         } 
         finally 
         { 
          dt.EndLoadData(); 
         } 
         return dt;       
        } 
        else 
         return null; 
       } 
       finally 
       { 
        releaseObject(range); 
       } 
      } 
     } 

    private static void releaseObject(object obj) 
    { 
     try 
     { 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); 
      obj = null; 
     } 
     catch (Exception ex) 
     { 
      obj = null; 
      throw new Exception("Unable to release the Object " + ex.ToString(), ex);//MLHIDE 
     } 
     finally 
     { 
      GC.Collect(); 
     } 
    }