2014-06-06 147 views
0

我有幾列DataTable。列數是動態的,但它們都是字符串。 我需要將DataTable的字段從字符串轉換爲DataType,這將是該列中所有行的最佳匹配。C#更改DataTable列數據類型

實施例:

如果在一列中的所有行都是數字,然後改變該列數的數據類型;或者如果值是日期則返回DateTime;否則留作字符串。

這怎麼辦?我知道我必須創建一個新的DataTable。

回答

1

這裏是我將如何做它的大綱。基本上使用基本類型的TryParse方法來確定最高計數。然後添加一個新類型的新列,儘可能多地轉換值。無法轉換的部分將保留爲DBNull.Value。

public class TypeCount { 
    public int IntCount; 
    public int LongCount; 
    public int DoubleCount; 
    public int DecimalCount; 
    public int DateCount; 
    // etc; 

    // provide your own logic to determine the best type 
    public Type BestType { 
     get { 
      int[] counts = new int[] { IntCount, LongCount, DoubleCount, DecimalCount, DateCount }; 
      Type[] types = new Type[] { typeof(int), typeof(long), typeof(double), typeof(decimal), typeof(DateTime) }; 
      Type bt = typeof(String); 
      int max = 0; 
      for (int i = 0; i < counts.Length; i++) { 
       if (counts[i] > max) { 
        bt = types[i]; 
        max = counts[i]; 
       } 
      } 
      return bt; 
     } 
    } 
} 

public static void TryParse(String s, NumberStyles ns, DateTimeStyles dts, IFormatProvider fp, String[] dateFormats, TypeCount counts) { 
    if (String.IsNullOrEmpty(s)) 
     return; 

    long l; 
    int i; 
    double d; 
    decimal m; 

    // could test byte and short too if needed 
    if (int.TryParse(s, ns, fp, out i)) { 
     counts.IntCount++; 
     counts.LongCount++; // if int parses, then long also parses 
    } 
    else if (long.TryParse(s, ns, fp, out l)) 
     counts.LongCount++; 

    // etc. 

    foreach (String f in dateFormats) { 
     DateTime date; 
     if (DateTime.TryParseExact(s, f, fp, dts, out date)) 
      counts.DateCount++; 
    } 
} 

public static void ConvertColumns(DataTable table) { 
    IFormatProvider fp = CultureInfo.InvariantCulture; 
    NumberStyles ns = NumberStyles.Any; 
    DateTimeStyles dts = DateTimeStyles.None; 
    String[] dateFormats = new String[] { "yyyy-MM-dd", "MM/dd/yyyy" }; 

    for (int i = 0; i < table.Columns.Count; i++) { 
     DataColumn col = table.Columns[i]; 
     if (col.DataType != typeof(String)) 
      continue; 

     TypeCount counts = new TypeCount(); 
     for (int j = 0; j < table.Rows.Count; j++) { 
      String s = table.Rows[j][col] as String; 
      TryParse(s, ns, dts, fp, dateFormats, counts); 
     } 

     Type bestType = counts.BestType; 
     DataColumn temp = null; 
     if (bestType == typeof(int)) { 
      temp = table.Columns.Add("temp", typeof(int)); 
      for (int j = 0; j < table.Rows.Count; j++) { 
       int val = 0; 
       String s = table.Rows[j][col] as String; 
       if (int.TryParse(s, ns, fp, out val)) 
        table.Rows[j][temp] = val; 
      } 
     } 
     //else if (bestType == ...) {} 

     if (temp != null) { 
      temp.SetOrdinal(col.Ordinal); 
      table.Columns.Remove(col); 
      temp.ColumnName = col.ColumnName; 
     } 
    } 
} 
1

這是您嘗試執行的相當危險的操作。所有你需要的是一個單一的不可預知的值,你將會有一個異常,並且測試每個單元格的價值會非常昂貴。不知道你在試圖完成什麼,我建議 1.測試每列中的所有單元格,以瞭解您需要什麼類型(非常昂貴) 2.在每列中創建具有正確DataType的新DataTable,然後從舊的。與測試相比,這將是閃電fas