none
INSERTAR UNA FILA NUEVA EN UNA CELDA DETERMINADA LUEGO DE UNA CONDICION

    Question

  • Hola gracias de antemano por la ayuda... que estoy seguro me darán...

    Mi problema es el siguiente... estoy programado en c#... es un miniproyecto de contabilidad basica en el que tengo que mostrar un libro diario....
    el libro diario se muestra en un datagridview ... pero necesito que se inserte una fila en blanco luego de una condicion en la que se evaluara cuando un asiento contable termina.. ahi debe insertar la nueva fila (que hace la separacion de un asiento contable con otro), luego de ello se debera mostrar el sigueinte asiento....

    Si alguien me ayuda le agradecere siempre...
    ya tengo el recorrido del datagridview con un for y eso sale perfectamente
    Sunday, January 31, 2010 4:36 PM

Answers

  • hola

    ahora que estoy viendo el codigo no me percate de un problema, cuando recorres las filas del datatable como bien refleja el mensaje del error no deja insertar una nueva fila, ya que estarias cambiando el indice de las coleccion

    esto sucede porque mientras recorres una coleccion si insertas o agregas un valor modificas las posiciones de los items lo cual hace inestable el ciclo, es por eso que .net lo detecta y lanza la exception

    lo que deberias hacer es crear un datatable nuevo y hacer un volcado completo de los datos que has obtenidos de la consulta, mas el agregado de los registros adicionales

    la logica que has aplicado esta correcta, solo que ahora crea un nuevo datatable con la misma estructura de campos que el que se crera cuando usas el Fill()
    si el asiento es igual copias todos los registro del datatable original a este nuevo, si es distonto el asiento agregas al datatable nuevo el registro en blanco

    de esta forma cuando termines en el datatable nuevo tendras los datos de la consulta, mas el agregado de los registros ene blanco
    pero estaran en otro datatable, y no en el que estas recorriendo con el foreach

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Sunday, February 07, 2010 3:47 AM
  • hola

    creo quee sto podra ser de utilidad

    C# – DataTable – Pasar Filas a Columnas y agregar filas adicionales

    como veras alli explico como agregar registro adicionales en el dataset y como implementar la logica de corte de control que necesitas

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Monday, February 08, 2010 3:34 AM

All replies

  • hola

    una primera recomendacion que podrias hacerte es sino ahs evaluado usar una grilla por ahi como esta

    SourceGrid - Open Source C# Grid Control

    por lo que vi el proyecto ha sido movido a SourceGrid codeplex

    me imaginaba que algo como se muestra en esta imagen , podria ser de utilidad


    pero bueno volvamos al datagridview
    bien en realidad lo que podrias hacer es no insertar este espacio directo en la grilla, sino que insertalo en los datos asi al momento de bindear se creara esta fila sin datos separando la informacion

    o sea imagino que la info del asineto contable la estas recuperando desde una consulta a tu db
    si es asi peudes seguir haciendolo igual, solo que antes de bidnear este datatable a al datagridview deberas aplicar cierta logica que valida cuando cambia de asiento y alli insertar un DataRow nuevo en el datatable

    para crerar una fila en nueva en el datatable puedes hacer

    Datarow row = dt.NewRow();

    row["campo1"] = "";
    row["campo2"] = "";
    row["campo3"] = "";

    dt.Rows.InsertAt (row, posicion)

    en donde posicion sera el nuemro de la fila que deberias detectar donde hay un cambio de asiento

    para detectar el cambio de asiento podrias hacer algo como esto

    string asientactual = "";

    foreach(DataRow row in dt.Rows)
    {
        if(Convert.ToString(row["asiento"]) != asientoactual)
        {
              //la primera vez que entre esta sin inicializar el asiento por eso no se agrega un registro en blanco
              if(asientoactual == "") 
              {
                 asientoactual =Convert.ToString(row["asiento"]);
                 continue;
               }

              //aqui es donde agregas la nueva fila

              asientoactual =Convert.ToString(row["asiento"]);
         }
    }

    como veras hasta aqui estas simpre haciendo uso del datatable, aun no has bindeado los datos en la grilla, cuando lo hagas al haber agregado filas con datos en blanco solo deberian apareceran como rows en el datagridview

    esta es solo una tecnica imagino que la misam se podria aplicar directo sobre el datagridview, crrando un nuevo DataGridViewRow
    pero creo que seria algo mas complejo de lograr

    tambine estaria la tecnica que directo la consulta sql agregue estas lineas, pero creo que para lograrlo seria necesario hacer uso de un StoredProcedure, con alguna tabla temporar para ir acomodando la informacion que luego devolverra el SP
    si usas Stored Procedure por ahi seria una buena opcion para investigar

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Sunday, January 31, 2010 6:10 PM
  • Gracias... si como en la ultima imagen es como necesito que quede... estoy siguiendo el consejo de insertar en la base de datos la fila en blanco....
    Monday, February 01, 2010 2:05 PM
  • hola

    insertar en la db?

    o sea no se si estos es buena idea, o sea te refieres a crear registro en tu tabla para simular estas lineas en blanco ?

    lo que yo decia era por ahi usar una tabla temporal para el reporte, una que se regenere cada vez que se necesita mostrar el libro diario, pero no que sean fijas en tu db como parte transaccional

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Monday, February 01, 2010 2:11 PM
  • y ahora??? y como le hago para crear la tabla temporal donde le pongo???
    Monday, February 01, 2010 2:15 PM
  • ya estoy utilizando una tabla temporal.. si en ella esta la relacion entre tbAsiento y tbCuenta... en ella puedo insertar la nueva fila... sin que sea necesario crear otra tabla tempora??
    Monday, February 01, 2010 2:17 PM
  • estas usando sql server como db ?

    si es asi podrias create un stored procedure

    y en este usar algo como esto:

    Differences between SQL Server temporary tables and table variables

    alli en la tabla temporal que creas en el SP es que armas los datos con la estructura como la necesitas

    saludos

    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    • Marked as answer by aangy Monday, February 01, 2010 2:30 PM
    • Unmarked as answer by aangy Thursday, February 04, 2010 2:16 AM
    Monday, February 01, 2010 2:24 PM
  • SIGO CON PROBLEMAS... IMPLEMENTE EL CODIGO DE ARRIBA EL DE LA TABLA TEMPORAL....
    TENGO EL SIGUIENTE  CODIGO PERO DESPUES DE INSERTAR LA PRIMERA FILA, ME DA ERROR..  Y SE INDICA EL EL DATAROW... SERA POR QUE ESTOY UTILIZANDO DOS DATAROW?? QUE PUEDO HACER???

    try

                {

                    SqlConnection MiConexion = new SqlConnection ();

                    MiConexion.ConnectionString = @"Data Source=......;Initial Catalog=Contabilidad;Integrated Security=True" ;

                

                    SqlDataAdapter MiAdaptador = new SqlDataAdapter ("SELECT ASIENTO.NREFERENCIA, ASIENTO.IDCUENTA, CUENTA.DESCUENTA, ASIENTO.REFERENCIA, ASIENTO.DEBITO, ASIENTO.CREDITO FROM ASIENTO INNER JOIN CUENTA ON ASIENTO.IDCUENTA = CUENTA.IDCUENTA ORDER BY NREFERENCIA" , MiConexion);

     

                    DataTable tempDt = new DataTable ();

     

                    MiAdaptador.Fill(tempDt);

     

                    int posicion = 0;

                    int posiactual = 0;

                  

                    /// AQUI MARCA EL ERROR, LUEGO DE INSERTAR LA FILA NUEVA///

                    foreach (DataRow row  in tempDt.Rows)

                    {

                        posiactual = posicion + 1;

                       

                        if (Convert .ToString(row["NREFERENCIA" ]) != asientoactual)

                        {

                            if (asientoactual == "" )

                            {

                                posicion = posicion + 1;

     

                                posiactual = posicion + 1;

     

                                asientoactual = Convert .ToString(row["NREFERENCIA" ]);

     

                                MiAdaptador.Fill(Midataset, "tempDt" );

                                dataGridView2.DataSource = Midataset;

                                dataGridView2.DataMember = "tempDt" ;

                                dataGridView2.Refresh();

     

                                MessageBox .Show("CONTINUAR" , asientoactual);

                            }

                            asientoactual = Convert .ToString(row["NREFERENCIA" ]);

                           

                            posicion = posicion + 1;

                            MessageBox .Show("insertar registro en blanco" + posiactual);

     

                            //La primera vez funciona, inserta el datos en la posision correcta...

                            //en la segunda vez envia el siguiente error InvalididOperationException was unhandled

                            //Coleccion modificada; la operacion de enumeracion no se puede ejecutar

                            DataRow Fila = Midataset.Tables["tempDt" ].NewRow();

                            Fila["DESCUENTA" ] = "             2" ;

                             Midataset.Tables["tempDt" ].Rows.InsertAt(Fila, posicion);

                            MiAdaptador.Fill(tempDt);

                            dataGridView2.DataSource = Midataset;

                            dataGridView2.DataMember = "tempDt" ;

                             dataGridView2.Refresh();

                        }

                        else

                        {

                            posicion = posicion + 1;

                            MessageBox .Show("sobn iguales" + posicion);

                        }

     

                    }

                }

                catch (Exception )

                {

                    MessageBox .Show("Ha surgido un error" , "ConBas 1.0" , MessageBoxButtons .OK, MessageBoxIcon .Error);

                }

            }


    Espero me puedas ayudar... pues he intentado cambiar el nombre del segundo datarow.. pero no ha tenido resultado
    • Edited by aangy Thursday, February 04, 2010 2:12 AM
    Wednesday, February 03, 2010 4:22 PM
  • SIGO CON PROBLEMAS... IMPLEMENTE EL CODIGO DE ARRIBA EL DE LA TABLA TEMPORAL....
    TENGO EL SIGUIENTE  CODIGO PERO DESPUES DE INSERTAR LA PRIMERA FILA, ME DA ERROR..  Y SE INDICA EL EL DATAROW... SERA POR QUE ESTOY UTILIZANDO DOS DATAROW?? QUE PUEDO HACER???

    try

                {

                    SqlConnection MiConexion = new SqlConnection ();

                    MiConexion.ConnectionString = @"Data Source=......;Initial Catalog=Contabilidad;Integrated Security=True" ;

                

                    SqlDataAdapter MiAdaptador = new SqlDataAdapter ("SELECT ASIENTO.NREFERENCIA, ASIENTO.IDCUENTA, CUENTA.DESCUENTA, ASIENTO.REFERENCIA, ASIENTO.DEBITO, ASIENTO.CREDITO FROM ASIENTO INNER JOIN CUENTA ON ASIENTO.IDCUENTA = CUENTA.IDCUENTA ORDER BY NREFERENCIA" , MiConexion);

     

                    DataTable tempDt = new DataTable ();

     

                    MiAdaptador.Fill(tempDt);

     

                    int posicion = 0;

                    int posiactual = 0;

                  

                    /// AQUI MARCA EL ERROR, LUEGO DE INSERTAR LA FILA NUEVA///

                    foreach (DataRow row  in tempDt.Rows)

                    {

                        posiactual = posicion + 1;

                       

                        if (Convert .ToString(row["NREFERENCIA" ]) != asientoactual)

                        {

                            if (asientoactual == "" )

                            {

                                posicion = posicion + 1;

     

                                posiactual = posicion + 1;

     

                                asientoactual = Convert .ToString(row["NREFERENCIA" ]);

     

                                MiAdaptador.Fill(Midataset, "tempDt" );

                                dataGridView2.DataSource = Midataset;

                                dataGridView2.DataMember = "tempDt" ;

                                dataGridView2.Refresh();

     

                                MessageBox .Show("CONTINUAR" , asientoactual);

                            }

                            asientoactual = Convert .ToString(row["NREFERENCIA" ]);

                           

                            posicion = posicion + 1;

                            MessageBox .Show("insertar registro en blanco" + posiactual);

     

                            //La primera vez funciona, inserta el datos en la posision correcta...

                            //en la segunda vez envia el siguiente error InvalididOperationException was unhandled

                            //Coleccion modificada; la operacion de enumeracion no se puede ejecutar

                            DataRow Fila = Midataset.Tables["tempDt" ].NewRow();

                            Fila["DESCUENTA" ] = "             2" ;

                             Midataset.Tables["tempDt" ].Rows.InsertAt(Fila, posicion);

                            MiAdaptador.Fill(tempDt);

                            dataGridView2.DataSource = Midataset;

                            dataGridView2.DataMember = "tempDt" ;

                             dataGridView2.Refresh();

                        }

                        else

                        {

                            posicion = posicion + 1;

                            MessageBox .Show("sobn iguales" + posicion);

                        }

     

                    }

                }

                catch (Exception )

                {

                    MessageBox .Show("Ha surgido un error" , "ConBas 1.0" , MessageBoxButtons .OK, MessageBoxIcon .Error);

                }

            }


    Espero me puedas ayudar... pues he intentado cambiar el nombre del segundo datarow.. pero no ha tenido resultado

    Thursday, February 04, 2010 2:11 AM
  • por fis responde mi ultima pregunta....  les agradesco mucho...
    Thursday, February 04, 2010 7:40 PM
  • hola

    la verdad es muy raro lo que intentas hacer

    o sea estas haciando una consulta, de esta recorrer cada item para crear otro dataset que vas cargando por fila

    pero resulta que dentro del loop, asignas el DataSource lo cual no esta bien

    asignar el dataset a el gridview deberia ser al final por fuera del for
    sino aun no tienes armada el dataset con los items

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Thursday, February 04, 2010 7:58 PM

  • Hola:

    ya asigne  el dataset a el datagridview despues del for...
    mi pregunta ahora es al momento de insertar la fila nueva
    a la tabla temporal, esto si debe hacerse dentro del
    for???

    he intentado lo siguiente:

    Datarow row1 = temp.NewRow();

    row1["campo1"] = "";
    row1["campo2"] = "";
    row1["campo3"] = "";

    temp.Rows.InsertAt (row1, posicionactual)

    el error se marca en el for Datarow... solo me falta insertar la fila en blanco
    pues ya tengo la posicion.... pero no se como hacerle, pues no me permite
    utilizar otro Datarow, dentro del for... por favor una idea que me ayude a resolverlo


    Muchas Gracias Leandro por tu ayuda

     

    Friday, February 05, 2010 8:36 PM
  • hola

    podrias postear un ejemplo de codigo mas amplio de lo que estas haciendo, algo que incluya el for que mencionas

    Nota, cuando pegues codigo verifica qeu la identacion este correcta asi es ams simple analziar el codigo

    y de ser posible marca donde se genera el error y que mensaje estas visualizando


    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, February 05, 2010 9:04 PM
  • Hola....

    ESTE EL CODIGO ACTUAL QUE HE ARMADO CON TU VALIOSA AYUDA, SOLO ME FALTA INSERTAR LA FILA NUEVA EN LA TABLA TEMPORAL, PARA LUEGO MOSTRARLA EN EL DATAGRIDVIEW, PUES COMO VERAS LA POSICION YA LE TENGO...

    private
    void FrmLibro_Load(object sender, EventArgs e)
    {

          try

          {

             SqlConnection MiConexion = new SqlConnection();

             MiConexion.ConnectionString = @"Data Source=..SQLEXPRESS;Initial Catalog=Contabilidad;Integrated Security=True";

                

             SqlDataAdapter MiAdaptador = new SqlDataAdapter("SELECT ASIENTO.NREFERENCIA, ASIENTO.IDCUENTA, CUENTA.DESCUENTA, ASIENTO.REFERENCIA, ASIENTO.DEBITO, ASIENTO.CREDITO FROM ASIENTO INNER JOIN CUENTA ON ASIENTO.IDCUENTA = CUENTA.IDCUENTA ORDER BY NREFERENCIA", MiConexion);

     

             DataTable tempDt = new DataTable();

     

              MiAdaptador.Fill(tempDt);

     

              int posicion = 0;

              int posiactual = 0;

                  

              ///AQUI MARCA EL ERROR, LUEGO DE INSERTAR LA PRIMERA FILA NUEVA EN LA TABLA TEMPORAL Y SEÑALA EN EL IN///
    ERROR

               InvalididOperationException was unhandled

               Coleccion modificada; la operacion de enumeracion no se puede ejecutar

     

                    foreach (DataRow row  in tempDt.Rows)

                    {

                        posiactual = posicion + 1;

                       

                        if (Convert.ToString(row["NREFERENCIA"])!= asientoactual)

                        {

                          

     if (asientoactual == "")

                            {

                              

                                posicion = posicion + 1;

                                posiactual = posicion + 1;

     

                                asientoactual = Convert.ToString(row["NREFERENCIA"]);

     

                                MessageBox.Show("CONTINUAR", asientoactual);

                               

                            }

                            asientoactual = Convert.ToString(row["NREFERENCIA"]);

     

                            posicion = posicion + 1;

                          

                            MessageBox.Show("insertar registro en blanco" + posiactual);

     

                            //QUE PUEDO USAR AQUI PARA INSERTAR LA FILA NUEVA EN ESTA POSICION "posiactual"

                            //ESTO ES LO QUE TENGO, PERO NADA QUE TENGA CON EL DataRow me acepta
                           

                            DataRow aaa= new Datarow;

                            aaa = tempDt.NewRow();

                            aaa["DESCUENTA"] = "             2";

                            tempDt.Rows.InsertAt(aaa, posiactual);

                        }

                        else

                     

                            posicion = posicion + 1;

                            MessageBox.Show("son iguales"+ posicion);

                        }

     

                       

                    }

                   

                    MiAdaptador.Fill(Midataset, "tempDt");

                    dataGridView2.DataSource = Midataset;

                    dataGridView2.DataMember = "tempDt";

               

                }

     

                catch (Exception)

                {

                    MessageBox.Show("Ha surgido un error", "ConBas 1.0", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }

            }




    Gracias de nuevo...

    Saturday, February 06, 2010 4:24 AM
  • Hola de nuevo....

    ESTE EL CODIGO ACTUAL QUE HE ARMADO CON TU VALIOSA AYUDA, SOLO ME FALTA INSERTAR LA FILA NUEVA EN LA TABLA TEMPORAL, PARA LUEGO MOSTRARLA EN EL DATAGRIDVIEW, PUES COMO VERAS LA POSICION YA LE TENGO...




    private void FrmLibro_Load(object sender, EventArgs e)
    {
          try
          {
                SqlConnection MiConexion = new SqlConnection();
                MiConexion.ConnectionString = @"Data Source=..SQLEXPRESS;Initial Catalog=Contabilidad;Integrated Security=True";

             SqlDataAdapter MiAdaptador = new SqlDataAdapter("SELECT ASIENTO.NREFERENCIA, ASIENTO.IDCUENTA, CUENTA.DESCUENTA, ASIENTO.REFERENCIA,   ASIENTO.DEBITO, ASIENTO.CREDITO FROM ASIENTO INNER JOIN CUENTA ON ASIENTO.IDCUENTA = CUENTA.IDCUENTA ORDER BY NREFERENCIA", MiConexion);

             DataTable tempDt = new DataTable();
             MiAdaptador.Fill(tempDt);
             int posicion = 0;
             int posiactual = 0;

    ///AQUI MARCA EL ERROR, LUEGO DE INSERTAR LA PRIMERA FILA NUEVA EN LA TABLA TEMPORAL Y SEÑALA EN EL IN///
    ERROR

               InvalididOperationException was unhandled
               Coleccion modificada; la operacion de enumeracion no se puede ejecutar

              foreach (DataRow row  in tempDt.Rows)
             {
                 posiactual = posicion + 1;
                       if (Convert.ToString(row["NREFERENCIA"])!= asientoactual)
                       {
                              if (asientoactual == "")
                             {
                                   posicion = posicion + 1;
                                   posiactual = posicion + 1;
                                   asientoactual = Convert.ToString(row["NREFERENCIA"]);
                                   MessageBox.Show("CONTINUAR", asientoactual);
                              }
                         asientoactual = Convert.ToString(row["NREFERENCIA"]);
                         posicion = posicion + 1;
                         MessageBox.Show("insertar registro en blanco" + posiactual);
                           
                 //QUE PUEDO USAR AQUI PARA INSERTAR LA FILA NUEVA EN ESTA POSICION "posiactual"
                 //ESTO ES LO QUE TENGO, PERO NADA QUE TENGA CON EL DataRow me acepta

                           DataRow aaa= new Datarow;
                           aaa= tempDt.NewRow();
                           aaa["DESCUENTA"] = "             2";
                           tempDt.Rows.InsertAt(aaa, posiactual);
                     }
                else
                {
                           posicion = posicion + 1;
                           MessageBox.Show("son iguales"+ posicion);
                 }

           } //FIN FOR
              MiAdaptador.Fill(Midataset, "tempDt");
              dataGridView2.DataSource = Midataset;
              dataGridView2.DataMember = "tempDt";
      }
        catch (Exception
      {
              MessageBox.Show("Ha surgido un error", "ConBas 1.0", MessageBoxButtons.OK, MessageBoxIcon.Error);
       }
    }

    Gracias .... Este es el mismo codigo de arriba, pero esta alineado

    Saturday, February 06, 2010 3:05 PM
  • Hola....

    Disculpe... que moleste tanto... responda por favor mi ultimo mensaje.... Gracias... estoy segura que con la respuesta a mi ultimo mensaje quedara solucionado mi problema
    Sunday, February 07, 2010 1:10 AM
  • hola

    ahora que estoy viendo el codigo no me percate de un problema, cuando recorres las filas del datatable como bien refleja el mensaje del error no deja insertar una nueva fila, ya que estarias cambiando el indice de las coleccion

    esto sucede porque mientras recorres una coleccion si insertas o agregas un valor modificas las posiciones de los items lo cual hace inestable el ciclo, es por eso que .net lo detecta y lanza la exception

    lo que deberias hacer es crear un datatable nuevo y hacer un volcado completo de los datos que has obtenidos de la consulta, mas el agregado de los registros adicionales

    la logica que has aplicado esta correcta, solo que ahora crea un nuevo datatable con la misma estructura de campos que el que se crera cuando usas el Fill()
    si el asiento es igual copias todos los registro del datatable original a este nuevo, si es distonto el asiento agregas al datatable nuevo el registro en blanco

    de esta forma cuando termines en el datatable nuevo tendras los datos de la consulta, mas el agregado de los registros ene blanco
    pero estaran en otro datatable, y no en el que estas recorriendo con el foreach

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Sunday, February 07, 2010 3:47 AM
  • no tines un codigo... que me sirva...
    gracias
    Sunday, February 07, 2010 3:55 AM
  • hola

    creo quee sto podra ser de utilidad

    C# – DataTable – Pasar Filas a Columnas y agregar filas adicionales

    como veras alli explico como agregar registro adicionales en el dataset y como implementar la logica de corte de control que necesitas

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Monday, February 08, 2010 3:34 AM
  • Gracias Leandro por tu amabilidad... 
    Sunday, February 14, 2010 9:52 PM