2013-06-04 18 views
6

Ho un paio di DataTable e ho bisogno di copiarli in un altro DataTable. Ad esempio, come puoi vedere nell'immagine allegata, ho bisogno di prendere tutti i dati dalla tabella di origine 1 e copiarli nelle prime 2 colonne della tabella Dest, copiare la tabella di origine 2 nelle prossime 2 colonne e così via . Come può essere facilmente raggiunto?Copia datatable come colonne in un altro datatable

enter image description here

Edit: devo leggere diversi file excel (io sono la memorizzazione di ogni file in un DataTable) e io non so esattamente quanti tabella di origine avrò, quindi questo deve essere fatto dinamicamente in qualche modo.

+0

Perché non limitarsi a scorrere le righe nella tabella di origine e per ogni riga, aggiungere le colonne appropriate alla tabella di destinazione appropriata? Le righe e le colonne (in ogni riga) possono essere ripetute. Sarebbe banale creare una mappa di funzioni da SourceTable/row-> TargetTable/row. – user2246674

risposta

6

Supponendo che le vostre tabelle di origine hanno la stessa struttura è possibile utilizzare Table.Copy() per creare il vostro tavolo dest e quindi copiare i dati in loop:

List<DataTable> sourceTables = getYourSourceTablesMethod(); 
if (sourceTables.Length>0) 
{ 
    DataTable destTable = sourceTables[0].Copy(); 

    for (int i = 1; i < sourceTables; i++) 
    { 
     foreach (DataRow drow in sourceTables[i].Rows) 
     destTable.Rows.Add(drow.ItemArray); 
    } 
} 
+1

Motivo per il downvoting? – Alex

0

Si può sparare domande come:

select col1,col2 into sourcetable1 from destTable 
union 
select col3,col4 into sourcetable2 from destTable 
union 
select col5,col6 into sourcetable3 from destTable 
union 
select col7,col8 into sourcetable4 from destTable 

Oppure, può seguire la tecnica menzionata sopra here.

In caso di righe di dati, può essere:

foreach (DataRow row in DestTable) 
{ 
    SourceTable1.ImportRow(row); 
} 
+0

Funziona alla grande .. in SQL. Funziona in DataTable? (I DataTable non * devono * venire da SQL.) – user2246674

1

Si dovrebbe trovare il rapporto b tra quella tabella di origine. Ad esempio, hanno lo stesso ID, è possibile copiarli come questo

insert into destTable( 
select s1.col1, s1.col2, s2.col3, s2.col4, s3.col5, s3.col6, s4.col7, s4.col8 
from sourcetable1 s1, sourcetable2 s2, sourcetable3 s3, sourcetable4 s4 
where s1.id = s2.id and s2.id = s3.id and s3.id = s4.id) 
0

Si può prima creare la tabella di destinazione, aggiungere è colonne (sommando il numero di colonne in tutte le tabelle di input) e poi aggiungere è righe concatenando le singole matrici di valori per ogni riga nelle tabelle di input.

Ovviamente, le righe nel DataTable risultante conterranno i valori come appaiono nella direzione dall'alto verso il basso per ciascuna tabella di input (allineati in alto). Significa anche che il numero di righe risultanti è il numero di righe nella tabella di input più grande.

Per prima cosa inizializziamo e compilare una variabile List<DataTable>, poi ci effettuare il join, utilizzando questa variabile come un parametro di metodo:

#region table collection initialization 
List<DataTable> dts = new List<DataTable>(); 
var dt = new DataTable(); 
dt.Columns.Add("Test0", typeof(string)); 
dt.Rows.Add(1); 
dt.Rows.Add(2); 
dts.Add(dt); 

dt = new DataTable(); 
dt.Columns.Add("Test1", typeof(int)); 
dt.Rows.Add(2); 
dts.Add(dt); 

dt = new DataTable(); 
dt.Columns.Add("Test3", typeof(int)); 
dt.Columns.Add("Test4"); 
dt.Columns.Add("Test5", typeof(int)); 
dt.Rows.Add(3, "a", 1); 
dt.Rows.Add(4); 
dt.Rows.Add(5, "a"); 
dt.Rows.Add(null, "a"); 
dts.Add(dt); 

dt = new DataTable(); 
dt.Columns.Add("Test6", typeof(DateTime)); 
dt.Columns.Add("Test7", typeof(int)); 
dt.Rows.Add(DateTime.Now); 
dts.Add(dt); 
#endregion 

// sample method usage 
var result = GetJoinedTable(dts); 

Creiamo il metodo GetJoinedTable che restituirà nella variabile result tabella unita risultante:

private DataTable GetJoinedTable(List<DataTable> dts) 
{ 
    var dest = new DataTable(); 

    //will be used if you have non-unique column names 
    int counter = 0; 

    foreach (var column in dts 
     .SelectMany<DataTable, DataColumn>(t => 
      t.Columns.Cast<DataColumn>())) 
    { 
     dest.Columns.Add(column.ColumnName, column.DataType); 

     // if you have non-unique column names use the following instead 
     //dest.Columns.Add(String.Format("column_{0}", counter++), 
     // column.DataType); 
    } 

    List<object> rowItems; 

    for (int i = 0; i < dts.Max(t => t.Rows.Count); i++) 
    { 
     rowItems = new List<object>(); 
     for (int j = 0; j < dts.Count; j++) 
     { 
      if (dts[j].Rows.Count > i) 
      { 
       var r = dts[j].Rows[i].ItemArray 
        .Select((v, index) => 
         (v == null || v == System.DBNull.Value) 
          ? GetDefault(dts[j].Columns[index].DataType) : v); 
       rowItems.AddRange(r); 
      } 
      else 
      { 
       for (int c = 0; c < dts[j].Columns.Count; c++) 
       { 
        rowItems.Add(GetDefault(dts[j].Columns[c].DataType)); 
       } 
      } 
     } 
     dest.Rows.Add(rowItems.ToArray()); 
    } 

    return dest; 
} 

Sono necessari per aggiungere il seguente metodo, che restituisce il valore della colonna di default del caso, in base alla DataType di proprietà della colonna:

object GetDefault(Type t) 
{ 
    if (t.IsValueType) 
    { 
     return Activator.CreateInstance(t); 
    } 
    else 
    { 
     return null; 
    } 
} 
Problemi correlati