2014-11-05 66 views
0

我寫了一些方法,這是爲了獲取在一個Excel文件中的每個工作表的DataTable:爲什麼OleDbDataAdapter在填充DataTable時會留下工件?

步驟1是讓所有表的名稱中包含一個.xlsx文件:

private static List<string> GetSheetNames(string filePath) 
     { 
      List<string> sheetNames = new List<string>(); 
      DataTable dt = null; 

      try 
      { 
       OleDbConnection connection = new OleDbConnection("provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + filePath + "';Extended Properties='Excel 12.0 Xml;HDR=YES;'"); 
       connection.Open(); 
       dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); 

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

       // Add the sheet name to the string array. 
       foreach (DataRow row in dt.Rows) 
       { 
        sheetNames.Add(row["TABLE_NAME"].ToString()); 

       } 

      }catch(Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 

      return sheetNames; 
     } 

步驟2是讀取每片,並返回一個根據DataTable

private static DataTable ReadExcelSheet(string filePath,string sheetName) 
{ 
    DataTable table = new DataTable(); 
    ValidateSheetName(ref sheetName); 
    try 
    {     
     OleDbConnection connection; 
     DataSet DtSet; 
     OleDbDataAdapter cmd; 
     connection = new OleDbConnection("provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + filePath + "';Extended Properties='Excel 12.0 Xml;HDR=YES;'"); 
     cmd = new OleDbDataAdapter("select * from ["+sheetName+"]", connection); 
     cmd.TableMappings.Add("Table", sheetName.Replace("$",string.Empty)); 
     DtSet = new DataSet(); 
     cmd.Fill(DtSet); 
     table = DtSet.Tables[0]; 
     connection.Close(); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 

    return table; 
} 

這兩種方法從這個LA稱爲ST方法返回一個List<DataTable>

private static List<DataTable> ConvertExcelToTables(string filePath) 
{ 
    List<string> sheetNames = GetSheetNames(filePath); 
    List<DataTable> tableList = new List<DataTable>(); 

    foreach(string sheetName in sheetNames) 
    { 
     tableList.Add(ReadExcelSheet(filePath,sheetName)); 
    } 

    return tableList; 
} 

,還應該對這個問題是不相關的一個小幫手方法:

private static void ValidateSheetName(ref string sheetName) 
{ 
    sheetName = sheetName.EndsWith("$") ? sheetName : sheetName + "$"; 
} 

如果我從一個例子一個表文件,它看起來像這樣:

enter image description here

現在不管,如果我只看到DataTable在調試時,或者如果我綁定它作爲一個DataGridView結果的DataSource看起來有點怪異:

enter image description here

我的猜測是,這可能與Excel表格開始與計數做1不是0。但即使是這樣的情況下,我無法真正想到一個解決方案。或者我錯過了什麼。其實這是一個遺憾,因爲這似乎是一個乾淨的解決方案imo。

回答

1

沒有,問題是由

HDR=YES; 

在連接字符串中造成的。 將其更改爲

HDR=NO; 

HDR=YES意味着你的Excel工作表的第一行被認爲包含的字段你的表的名稱。但作爲一個例子,這並非如此。事實上,OleDb提供商不能確定第二列的名稱(它是空白的),因此它指定了默認值(字母F,後面跟着列的逐行編號)

您可以找到很多關於示例和解釋excel的連接字符connectionstrings.com

+0

這確實解決了問題。也許你想提供一些關於這個參數實際上代表什麼的信息?順便說一句,列標題仍然被命名爲F1,F2 ..這不是一個大問題,但仍然不完美^^ – 2014-11-05 09:40:10

+0

不值得另一篇文章。如果所有單元格都是空的,並且包含信息的第一個單元格是B7,它將位於我的數據表單的單元格(0,0)中。有沒有辦法避免這種情況? – 2014-11-05 09:50:08

+1

通常情況下,您的工作表是從A1延伸到最後一個有效行/單元格的表格。用所有的空行和列。除非您在Excel工作表中定義一個範圍,然後在您的OleDb命令中使用[RangeName]語法中的SELECT * – Steve 2014-11-05 10:00:04