Introducción
Basado en una pregunta que he visto en uno de los foros arme unos ejemplo que explica como poder trabajar con DataTables.
Básicamente el planteo de las consultas se hacían porque era necesario realizar tareas que requieren de la iteración de datos existentes, para ser volcados en un nuevo conjunto de datos resultante.
se atacara dos aspectos en este articulo
- como agregar una línea en blanco, según cierto corte de control
- como unir dos conjuntos de datos, pero que estas sean representadas en columnas
Línea en Blanco
Como se parecía en el código es necesario ciclar cada ítem de los datos obtenidos y mediante un procesamiento o corte de control en cuyo ejemplo es representado mediante un asiento contable, el cual solo es a modo de ejemplo.
private void Form2_Load(object sender, EventArgs e) { //se obtiene el conjunto de datos DataTable dtAsientos = GetDatos(); //se crea el dataset resultado DataTable dt = new DataTable(); dt.Columns.Add("Asiento"); dt.Columns.Add("Importe"); // variables que actuaran como flag para el corte de control // en el ciclo string asientActual = ""; double importe = 0; foreach (DataRow row in dtAsientos.Rows) { if (string.IsNullOrEmpty(asientActual)) { // la primera vez que entre esta sin inicializar la variable "asientActual" // por eso entrara por este pregunta del if asientActual = Convert.ToString(row["asiento"]); importe = Convert.ToDouble(row["Importe"]); } else if (Convert.ToString(row["asiento"]) == asientActual) { //si el asiento es el mismo solo acumulo el importe importe += Convert.ToDouble(row["Importe"]); } else { //aqui es donde se agregas la nueva fila DataRow blankRow = dt.NewRow(); blankRow["Asiento"] = ""; blankRow["Importe"] = importe.ToString("N2"); dt.Rows.Add(blankRow); //se inicializa las variable al nuevo asiento asientActual = Convert.ToString(row["asiento"]); importe = Convert.ToDouble(row["Importe"]); } DataRow newRow = dt.NewRow(); newRow["Asiento"] = row["Asiento"]; newRow["Importe"] = row["Importe"]; dt.Rows.Add(newRow); } // se agrega el registro que refleja el acumulado // para el ultimo asiento, esto se hace fuera del foreach // ya que no se poden registro adicionales que agreguen el ultimo valor DataRow lastRow = dt.NewRow(); lastRow["Asiento"] = ""; lastRow["Importe"] = importe.ToString("N2"); dt.Rows.Add(lastRow); //se carga el nuevo dataset en la grilla dataGridView1.AutoGenerateColumns = true; dataGridView1.DataSource = dt; }
En el código además se lleva un acumulado de los importes de cada registro, y justo en el momento de insertar la línea adicional es que se usa este importe para informar el total del asiento.
Pasar Filas a Columnas, con dos Datatable
en este ejemplo se observaran dos orígenes de datos, lo cuales serán procesador para obtener un único resultado final, pero en donde la unión no sea a nivel de registros, sino que se agregaran las columnas de uno a continuación de las otras.
private void Form1_Load(object sender, EventArgs e) { // // obtengo los datos que seran unidos postermente // DataTable dt1 = GetDatos(); DataTable dt2 = GetDatos2(); // // se crea un nuevo datatable resultande de la union // DataTable dt = new DataTable(); dt.Columns.Add("Columna1"); dt.Columns.Add("Columna2"); dt.Columns.Add("Columna3"); dt.Columns.Add("Columna4"); dt.Columns.Add("Columna5"); // // se recorre el primer origen de datos // en este se insertan los registros // foreach (DataRow row in dt1.Rows) { DataRow newRow = dt.NewRow(); newRow["Columna1"] = row["Columna1"]; newRow["Columna2"] = row["Columna2"]; dt.Rows.Add(newRow); } //se recorre el segundo origen de datos for (int i = 0; i < dt2.Rows.Count; i++) { DataRow copyRow = null; // se pregunta si el indice del registro existe // o debe crearse uno adicional, ya que el segundo origen de datos // posee mas registro que el primero if (dt.Rows.Count <= i) { copyRow = dt.NewRow(); dt.Rows.Add(copyRow); } else copyRow = dt.Rows[i]; DataRow originalRow = dt2.Rows[i]; copyRow["Columna3"] = originalRow["Columna3"]; copyRow["Columna4"] = originalRow["Columna4"]; copyRow["Columna5"] = originalRow["Columna5"]; } dataGridView1.AutoGenerateColumns = true; dataGridView1.DataSource = dt; }
En el código se observar que el dataset de resultado al crearlo se le definen las columnas de los dos dataset que son usados de origen de datos.
El primer ciclo por contar con el dataset resultado sin valores simplemente vuelva los registros allí.
El segundo es algo mas complejo ya que debe usas los índices de los registros creados en el paso anterior.
Además debe verificar si es que este segundo grupo de registro es mayor que el anterior de agregar las filas adicionales.
Conclusión
Para trabajar con DataTables para manipular la información que estos contienen y poder forma un conjunto de datos adicional que represente correctamente la datos en la disposición que se necesita, es necesario mencionar que un punto a tener en cuenta y esta referido al orden en se que proveen los datos iniciales.
Como se verán en ambos ejemplo el orden es importante ya que este determina el éxito del corte que se aplica al recorrer y procesar cada registro.
[C#]
|
Hola Leandro no puedo descargar el codigo del ejemplo parece que ya no esta disponible.
ResponderEliminarhola Augusto
ResponderEliminarPor problemas con skydrive los links de los articulos dejaron de ser validos.
Pero ya actualice para que puedas descargarlo.
saludos
Hola Leandro, te agradecería mucho si me ayudaras con un ejemplo parecido en C# pero en webforms. Tengo una consulta que hago desde C# a SAP y la guardo en un datatable, pero esa bapi me retorna una sola columna con n cantidad de filas y necesito separar esas filas en otras columnas y en un datagrid. Gracias y espero tu pronta respuesta
ResponderEliminarhola adridelvaller
ResponderEliminarlo que podrias hacer es aplcia la misma tecnica, create un datatable auxiliar en dodne definas las columnas que necesitas
luego recorres las filas del datatable original y vas tomando la info asignando a la DataRow del temporal, para al final cuando termines de recorrer asignas el datarow que se genera el dt temporal con todas las columnas
saludos
Hola Leandro que tal, tengo un problema, quiero hacer todo el proceso de agregar automáticamente columnas a una tabla en SQL SERVER. espero y me entiendan, quiero agregar automáticamente varias columnas a una tabla (ALUMNO_ACT) con los registros de otra tabla(mat_prepa), es decir quiero recorrer cada uno de los registros de la tabla “mat_prepa” y poner la condición de que si no existe una columna con ese nombre en la tabla “ALUMNO_ACT” que cree una columna con el registro captado en el cursor y a si sucesivamente hasta terminar con todos los registros de la tabla “mat_prepa”. dejo el código:
ResponderEliminarDECLARE @resp varchar(20)
DECLARE @cursor cursor
SET @cursor = CURSOR FOR
SELECT cve_mat FROM mat_prepa
OPEN @cursor
FETCH NEXT FROM @cursor
WHILE @@FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM @cursor
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ‘ALUMNO_ACT’ AND COLUMN_NAME = @resp)
ALTER TABLE ALUMNO_ACT
ADD [@cursor] varchar (20)
END
–El problema esta en: ADD [@cursor] varchar (20).
ni declarando una variable y asignándole el valor de @cursor me deja, existe alguna otra forma?,
existe alguna forma de hacerlo desde visual studio c#?
Saludos!
Hola Leandro gusto saludarte, como puedo persistir un datatable en un asp.net
ResponderEliminarhola richard10
ResponderEliminarlo harias de la misma forma que con cualquier otra aplicacion
solo que necesitas conocer sobre ado.net
sabes como realizar un INSERT con ado.net ? que base de datos estas utilizando?
o podrias usar el SqlDataAdapter, usando el metodo Update(), pero eso depende como estes actualizando el dataset, yo recomendaria tomes los valroes de forma simple de los controles y definas un INSERT con parametros para ejecutarlo con el ExecuteNonQuery()
saludos
Saludos Leandro, tengo la sig problemática:
ResponderEliminarTengo dos DataTable, una se llama dt y la otra dtINV, al momento de hacer una consulta por separado en cada una me arroja dos registros, es decir 2 registros la dt y dos registro la dtINV, lo que deseo hacer es convinar esas dos consultas y que solo me arroje dos registros.
Gracias por la ayuda
hola Reynaldo
ResponderEliminarno te animas a usar linq sobre estos datatable para poder relacionarlos con un join
[Linq] Join DataTable
con esto podrias relacionar por un campo los datos
saludos
Saludos Leandro, gracias por contestar, al final lo he solucionado, ah quedado de la sig. manera:
ResponderEliminarDataTable table = new DataTable("Union");
//crear las nuevas columnas
DataColumn[] newcolumns = new DataColumn[dt.Columns.Count];
DataColumn[] newcolumns2 = new DataColumn[dtINV.Columns.Count];
for (int i = 0; i < dt.Columns.Count; i++)
{
newcolumns[i] = new DataColumn(dt.Columns[i].ColumnName, dt.Columns[i].DataType);
}
for (int i = 0; i < dtINV.Columns.Count; i++)
{
newcolumns2[i] = new DataColumn(dtINV.Columns[i].ColumnName, dtINV.Columns[i].DataType);
}
//agregar las columnas vacias (esquema o estructura) a la tabla resultante
table.Columns.AddRange(newcolumns);
table.Columns.AddRange(newcolumns2);
table.BeginLoadData();
//cargar los datos desde la primera tabla
foreach (DataRow roww in dt.Rows)
{
table.LoadDataRow(roww.ItemArray, true);
}
//cargar los datos desde la segunda tabla
for (int re = 0; re < dtINV.Rows.Count; re++)
{
for (int c = 0; c < dtINV.Columns.Count; c++)
{
string cn = dtINV.Columns[c].ColumnName.ToString();
table.Rows[re][cn] = dtINV.Rows[re][cn];
}
}
table.EndLoadData();