none
Transferência de dados entre DataGridView RRS feed

  • Pergunta

  • Boa noite pessoal.

    Estou com um problema para transferir dados entre datagridview, vou tentar colocar de forma clara o meu problema.

    Tenho o form1 com um botão ENVIAR e um datagridview1, onde neste datagridview1 estará relacionado vários pedidos. O usuário selecionará alguns pedidos e clicará em ENVIAR. Abrirá um outro form (form2) com um datagridview2 contendo todos os pedidos selecionados no datagridview1 (do form1). As duas telas ficam abertas, tanto o form1 quanto o form2.

    O objetivo é enviar os dados do segundo form por e-mail dentro do C#.

    Desde já agradeço a todos que contribuirão para a solução do meu problema.

    Forte abraço a todos e até mas!!!!

    quinta-feira, 16 de janeiro de 2014 21:24

Respostas

  • Olá Alberto,

    estou com muito sono, por isso fiz um exemplo bem simples e em vb.net, espero que ajude

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim dt As New DataTable
            dt.Columns.Add("teste1")
            dt.Columns.Add("teste2")
            dt.Columns.Add("teste3")
    
            For i As Integer = 0 To 10
                Dim row As DataRow = dt.NewRow
                row.Item("Teste1") = "11"
                row.Item("Teste2") = "11"
                row.Item("Teste3") = "11"
                dt.Rows.Add(row)
            Next
            DataGridView1.DataSource = dt
    
            ''DataGridView1.CurrentCell = DataGridView1.Rows(20).Cells(0)
        End Sub
    
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim dt As New DataTable
            dt.Columns.Add("teste1")
            dt.Columns.Add("teste2")
            dt.Columns.Add("teste3")
    
            For Each d As DataGridViewRow In DataGridView1.Rows
                If d.Cells("Column1").Value = True Then
                    Dim c As DataRow = dt.NewRow
                    c.Item("Teste1") = d.Cells(1).Value
                    c.Item("Teste2") = d.Cells(2).Value
                    c.Item("Teste3") = d.Cells(3).Value
                    dt.Rows.Add(c)
                End If
            Next
            DataGridView2.DataSource = dt
        End Sub

    no load estou carregando o grid1 e button estou verificando o que foi checado no grid1 e jogo no grid2.

    Segue abaixo vários links falando sobre envio de email no c#:

    http://www.devmedia.com.br/como-enviar-um-e-mail-utilizando-c/15285

    http://wiki.locaweb.com.br/pt-br/Envio_de_e-mails_via_.NET_utilizando_o_System.Net.Mail

    http://code.msdn.microsoft.com/windowsdesktop/Envio-de-E-mail-em-C-84c68ce6

    http://www.macoratti.net/10/12/c_email2.htm

    Qualquer dúvida posta ae.

    Att,

    Wennder A. dos Santos

    Se minha resposta solucionou seu problema ou sua dúvida marque como Resposta ou se foi útil marque como útil. Isso ajuda outras pessoas com o mesmo problema ou dúvida.


    sexta-feira, 17 de janeiro de 2014 03:33

Todas as Respostas

  • Olá Alberto,

    estou com muito sono, por isso fiz um exemplo bem simples e em vb.net, espero que ajude

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim dt As New DataTable
            dt.Columns.Add("teste1")
            dt.Columns.Add("teste2")
            dt.Columns.Add("teste3")
    
            For i As Integer = 0 To 10
                Dim row As DataRow = dt.NewRow
                row.Item("Teste1") = "11"
                row.Item("Teste2") = "11"
                row.Item("Teste3") = "11"
                dt.Rows.Add(row)
            Next
            DataGridView1.DataSource = dt
    
            ''DataGridView1.CurrentCell = DataGridView1.Rows(20).Cells(0)
        End Sub
    
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim dt As New DataTable
            dt.Columns.Add("teste1")
            dt.Columns.Add("teste2")
            dt.Columns.Add("teste3")
    
            For Each d As DataGridViewRow In DataGridView1.Rows
                If d.Cells("Column1").Value = True Then
                    Dim c As DataRow = dt.NewRow
                    c.Item("Teste1") = d.Cells(1).Value
                    c.Item("Teste2") = d.Cells(2).Value
                    c.Item("Teste3") = d.Cells(3).Value
                    dt.Rows.Add(c)
                End If
            Next
            DataGridView2.DataSource = dt
        End Sub

    no load estou carregando o grid1 e button estou verificando o que foi checado no grid1 e jogo no grid2.

    Segue abaixo vários links falando sobre envio de email no c#:

    http://www.devmedia.com.br/como-enviar-um-e-mail-utilizando-c/15285

    http://wiki.locaweb.com.br/pt-br/Envio_de_e-mails_via_.NET_utilizando_o_System.Net.Mail

    http://code.msdn.microsoft.com/windowsdesktop/Envio-de-E-mail-em-C-84c68ce6

    http://www.macoratti.net/10/12/c_email2.htm

    Qualquer dúvida posta ae.

    Att,

    Wennder A. dos Santos

    Se minha resposta solucionou seu problema ou sua dúvida marque como Resposta ou se foi útil marque como útil. Isso ajuda outras pessoas com o mesmo problema ou dúvida.


    sexta-feira, 17 de janeiro de 2014 03:33
  • Olá, 

    algum progresso?

    Wennder

    sexta-feira, 17 de janeiro de 2014 14:24
  • Bom dia Wennder.

    Não consegui implementar o seu exemplo. Deu o seguinte erro:

    "An unhandled exception of type 'System.NullReferenceException' occurred in Integra Processos.exe
    Additional information: Object reference not set to an instance of an object."

    Já tentei criar a tabela em uma classe à parte, mas também não está dando certo. Dá o erro: "Object reference not set to an instance of an object."

    Mas a parte de envio de e-mail já está funcionando corretamente, só está faltando mesmo transferir as informações para o segundo datagrid, que será o corpo do e-mail.

    Mas mesmo assim lhe agradeço a boa vontade em me ajudar. Caso tenha alguma outra solução, serei grato.

    Valeu Wennder, abraçoss e até mas.

    sábado, 18 de janeiro de 2014 12:16
  • Fala Wenner, não respondi antes, pois ontem fiquei baixando o Visual Studio 2013 profissional, como minha máquina está lenta, eu deixei só baixando para não demorar muito.

    Mas coloquei a resposta acima!!!

    Valeu Wennder, abraçoss e até mas.

    sábado, 18 de janeiro de 2014 12:18
  • Olá Alberto,

    este erro está acontecendo quando você está tentando carregar o grid1 não é? pode postar o trecho de código onde está acontecendo o erro?

    Wennder


    sábado, 18 de janeiro de 2014 12:20
  • Bom dia Wennder.

    Segue o código:

    private void InserirDadosParaTransferencia()
            {
                bdpedidos tab = new bdpedidos();
                
                tab.Tabela.Columns.Add("teste1");
                tab.Tabela.Columns.Add("teste2");
                tab.Tabela.Columns.Add("teste3");
                tab.Tabela.Columns.Add("teste4");
                 
                for (int i = 0; i < dgDados.Rows.Count; i++)
                {
                    if (dgDados.Rows[i].Cells[1].Selected)
                    {
                        tab.Tabela.Rows.Add(Convert.ToString(dgDados.Rows[i].Cells[0].Value), Convert.ToString(dgDados.Rows[i].Cells[0].Value), Convert.ToString(dgDados.Rows[i].Cells[0].Value), Convert.ToString(dgDados.Rows[i].Cells[0].Value));
                    }
                }
                
            }
    Dá o erro na primeira linha: 
    tab.Tabela.Columns.Add("teste1");

    sábado, 18 de janeiro de 2014 12:28
  • Olá,

    já que você está criando o datatable na classe bdpedidos porque não cria as colunas lá também? 

    Wennder

    sábado, 18 de janeiro de 2014 12:39
  • Wennder, tentei e não deu certo. Deu o mesmo erro na primeira linha da criação da coluna.

    Creio que a solução disto é muito simples, porem não estou conseguindo emplementar devido a minha inesperiência!!!


    sábado, 18 de janeiro de 2014 13:08
  • Como você está declarando seu datatable?

    Wennder

    sábado, 18 de janeiro de 2014 13:14
  • Wenner, já tentei de várias maneiras. Agora tentei fazer dentro da classe do form, mas também deu o mesmo erro.

    Esta foi a que tentei agora.

    namespace Integra_Processos
    {
        public partial class Ciclo : Form
        {
            public DataTable ped;

    Mas antes estava declarando na classe do pedido

    private  DataTable ctabela;
    
                
            public DataTable Tabela
            {
                get { return ctabela; }
                set { ctabela = value; }
    
            }
    Eu não estou sabendo manipular a DataTable.


    • Editado AlbertoGold sábado, 18 de janeiro de 2014 13:30
    sábado, 18 de janeiro de 2014 13:28
  • Alberto,

    no .net  existem 2 tipos de variáveis, as de valor e as de referência.

    as de valor = int, boolean, decimal ..

    as de instancia = todas que você usa o "new" para poder acessar e o datatable é uma dessa.

    Quando você usa o "new" para declarar a variável é alocado na memória, definida pelo framework como memória heap, para essa variável.  Como você não está usando o "new" ele não está encontrando, por isso o erro System.NullReferenceException.

    Repare em como é declarado o datatable no meu exemplo.

    Quando tiver um tempinho vale a pena ler essa explicação

    http://www.macoratti.net/vbn_conc.htm

    Wennder





    sábado, 18 de janeiro de 2014 13:39
  • Wenner, dei uma lida no artigo... consegui abrir o form2 sem dar o erro, porem não estou conseguindo abrir o form2 atualizando os dados armazenados no DataTable que criei dentro da classa do form1.

    Coloquei como public mas ele não aparece.

    sábado, 18 de janeiro de 2014 14:12
  • Posta o código de como você esta declarando o datatable e de como você está populando ele.

    Wennder

    sábado, 18 de janeiro de 2014 14:15
  • Este é o código no form1:

    public void InserirDadosParaTransferencia()
            {
                DataTable ped = new DataTable();
                ped.Columns.Add("teste1");
                ped.Columns.Add("teste2");
                ped.Columns.Add("teste3");
                ped.Columns.Add("teste4");
     
                for (int i = 0; i < dgDados.Rows.Count; i++)
                {
                    if (dgDados.Rows[i].Cells[1].Selected)
                    {
                        ped.Rows.Add(Convert.ToString(dgDados.Rows[i].Cells[0].Value), Convert.ToString(dgDados.Rows[i].Cells[0].Value), Convert.ToString(dgDados.Rows[i].Cells[0].Value), Convert.ToString(dgDados.Rows[i].Cells[0].Value));
                        
                    }
                }
                            
            }
    Não estou conseguindo pegar este "ped" e transferir para o form2.

    sábado, 18 de janeiro de 2014 14:22
  • Alberto,

    o que define que uma linha será copiada para o datatable?

    você colocou um checkbox na coluna1?

    Wennder

    sábado, 18 de janeiro de 2014 14:31
  • Não usei checkbox, estou defindo se a linha estiver selecionada:

    if (dgDados.Rows[i].Cells[1].Selected)

    Usei desta forma em outra parte do código e funcionou legal.

    sábado, 18 de janeiro de 2014 14:40
  • ok,

    meu exemplo no começo está fazendo corretamente a cópia das informações, você só precisava converter para c#, de uma olhada abaixo, só troque a validação do if para sua validação, pois, aqui estou usando um checkbox para selecionar, dessa forma pode ser selecionada mais de uma linha por vez.

    DataTable ped = new DataTable();
                ped.Columns.Add("teste1");
                ped.Columns.Add("teste2");
                ped.Columns.Add("teste3");
                ped.Columns.Add("teste4");
    
                   foreach (DataGridViewRow d in dataGridView1.Rows)
                {
                    if (Convert.ToBoolean(d.Cells[0].Value) == true)
                       {
                            DataRow row = ped.NewRow();
                            row["teste1"] = d.Cells[1].Value;
                            row["teste2"] = d.Cells[2].Value;
                            row["teste3"] = d.Cells[3].Value;
                            row["teste4"] = d.Cells[4].Value;
                            ped.Rows.Add(row);
                       }
                }
                

    Wennder

    sábado, 18 de janeiro de 2014 14:49
  • Wennder, fiz conforme seu exemplo e ainda coloquei um datagrid no mesmo form1 só para ver se popula o segundo grid, mas também não foi. Veja a imagem.

    Observe que está preenchendo o row, mas não vai para o segundo grid

    sábado, 18 de janeiro de 2014 15:15
  • Alberto,

    você tem que primeiro adicionar a row no datatable ped e depois fazer dgmensage.DataSource = ped

    De uma olhada novamente no meu exemplo, você está pulando um passo.

    Wennder

    sábado, 18 de janeiro de 2014 17:35
  • Boa noite Wennder.

    Pior que é!!! Estava pulando esta etapa mesmo, fiz o que você falou e funcionou, porem só com uma linha, quando eu marco duas ele dá erro. Não está acrescentando linha no "ped". Dá o erro:

    An unhandled exception of type 'System.ArgumentException' occurred in System.Data.dll
    Additional information: This row already belongs to this table.

    Tentei colocar: ped.rows[i].add(row); Mas não aceita!!!

    E depois, como vou fazer para conseguir passar para o segund grid no segundo form?

    sábado, 18 de janeiro de 2014 22:03
  • Olá, 

    você não precisa passar um índice para adicionar linha no datatable, faz dessa forma:

    ped.rows.add(row);

    dessa forma você adiciona quantas linhas quiser.

    testa desse jeito e da um retorno.

    Wennder

    domingo, 19 de janeiro de 2014 03:51
  • Bom dia Wennder.

    Mas foi assim que fiz, conforme você tinha falado anteriormente, mas deu o erro: An unhandled exception of type 'System.ArgumentException' occurred in System.Data.dll
    Additional information: This row already belongs to this table.

    Funcionou quando marquei somente uma linha, quando fui fazer o teste com duas linhas, deu este erro. Por isso tentei colocar o índice para adicionar a linha. É como se tivesse tentando salvar sobre a linha já existente. (Estou deduzindo que seja isso)

    domingo, 19 de janeiro de 2014 12:33
  • Boa tarde Wennder.

    Estamos quase lá!!! Repassei o código e consegui achar onde que eu errei. Olhei, reolhei seu código e ví que eu coloquei o código DataRow row = ped.NewRow(); no lugar errado, por isso ele não estava criando a nova linha.

    Só ainda não consegui descobrir como vou passar para o segundo form (form2), os pedidos guardados em ped.

    Desde já lhe agradeço pela grande força que está me dando. Está me ajudando muito.

    Valeu Wennder!!!

    domingo, 19 de janeiro de 2014 15:12
  • Alberto,

    Você poderia tentar usar a orientação neste objeto tendo uma classe Pedido por exemplo e para o form2 passaria um List<Pedido> como parametro, como segue abaixo:

        public class Pedido
        {
            public int ID { get; set; }
            public string Numero { get; set; }
            public decimal Valor { get; set; }
        }

    Código que seria usada para preencher o dataGridView1

            private void PreencheDataGridView1()
            {
                // aqui eu apenas estou preenchendo uma lsita ficticia para exibir oos dados aqui seria sua busca do banco p/ retornar a list
                List<Pedido> lstPedidos = new List<Pedido>();
                for (int i = 0; i < 100; i++)
                {
                    Pedido p = new Pedido() { ID = i + 1, Numero = i.ToString(), Valor = i + 100 };
                }
    
                dataGridView1.DataSource = lstPedidos;
            }


    E este código seria usadao no click do botão que chama o form2 (que recebe como parâmetro no inicializador uma list<pedido>.

            void btnEnviar_Click(object sender, EventArgs e)
            {
                var qrSelecionados = from row in dataGridView1.SelectedRows.Cast<DataGridViewRow>()
                                     select new Pedido() {
                                         ID = Convert.ToInt32(row.Cells["ColunaQueArmazenaOIdPedido"].Value),
                                         Numero = row.Cells["ColunaQueArmazenaONUmeroPedido"].Value.ToString(),
                                         Valor = Convert.ToDecimal(row.Cells["ColunaQueArmazenaOValorDoPedido"].Value)
                                     };
    
                Form2 frm = new Form2(qrSelecionados.ToList());
                frm.ShowDialog();
            }

    Acho que assim fica bem fácil, você poderia até usar uma coluna com check box e fazer dai um where no link acima algo que ficaria mais ou menos como o código abaixo:

            void btnEnviar_Click(object sender, EventArgs e)
            {
                var qrSelecionados = from row in dataGridView1.Rows.Cast<DataGridViewRow>()
                                     where Convert.ToBoolean(row.Cells["ColunaCheckBox"])
                                     select new Pedido() {
                                         ID = Convert.ToInt32(row.Cells["ColunaQueArmazenaOIdPedido"].Value),
                                         Numero = row.Cells["ColunaQueArmazenaONUmeroPedido"].Value.ToString(),
                                         Valor = Convert.ToDecimal(row.Cells["ColunaQueArmazenaOValorDoPedido"].Value)
                                     };
    
                Form2 frm = new Form2(qrSelecionados.ToList());
                frm.ShowDialog();
            }

    Ai no inicializador do seu form você faria apenas dataGridView2.DataSource=listaPedidoQueVeioComoParametro;

    Espero ter ajudado,

    Att.


    segunda-feira, 20 de janeiro de 2014 13:19
  • Boa noite Wennder.

    Dei uma olhada nas suas dicas, mas este tipo de transferência, com um dado, eu consigo fazer, inclusive usei muito isso no meu programa. O meu problema está sendo transferir conjunto de dados.

    Mas mesmo assim lhe agradeço imensamente Wennder.

    Vou dar uma estudada melhor na dica do nosso amigo Lucas, pois tentei fazer, mas não funcionou.

    Valeu Wenner, abraçoss e até mas.

    segunda-feira, 20 de janeiro de 2014 22:35
  • Boa noite Lucas.

    Tentei implementar sua sugestão, porem não deu certo. Mas vou dar uma estudada melhor nela de depois lhe dou um retorno mais certo. É porque estou meio na correria e não estou tendo muito tempo para mexer no programa. Mas deste final de semana não passa.

    Desde já lhe agradeço pela sua força.

    Mas acho que a idéia seria fazer uma lista global (não sei se é possível em c#) para poder acessá-la do form2.

    Abraçoss e até mas.

    segunda-feira, 20 de janeiro de 2014 22:39
  • Olá,

    use a forma que eu te passei para pegar as informações, e a forma que o Lucas passou para passa-las para outro form.

    Form2 frm = new Form2(Seu_DataTable));
                frm.ShowDialog();

    Wennder

    segunda-feira, 20 de janeiro de 2014 23:58
  • Boa noite Wennder e Lucas.

    Desculpe a demora do retorno. Como eu falei, estou na correria. Mas vamos lá!!!

    Vejam só, eu acabei fazendo diferente das duas sugestões. Tentei fazer da sua forma Lucas, e deu um erro. 

    Vou postar aqui a forma que fiz aproveitando as sugestões dadas por vocês:

    Tenho uma classe bdpedidos e nesta classe eu criei a tabela:

    private static DataTable ctabela;
    
            public DataTable tabela
            {
                get { return ctabela; }
                set { ctabela = value; }
            }

    Na classe do form1, coloquei este código (99,9% sugerido pelo nosso amigo Wennder):

    public void InserirDadosParaTransferencia()
            {
                DataTable ped = new DataTable();
                
                ped.Columns.Add("Cliente");
                ped.Columns.Add("Ordem Venda");
                ped.Columns.Add("Transportadora");
                ped.Columns.Add("Volume");
     
                for (int i = 0; i < dgDados.Rows.Count; i++)
                {
                    if (dgDados.Rows[i].Cells[1].Selected)
                    {
                        DataRow row = ped.NewRow();
                        row["Cliente"] = dgDados.Rows[i].Cells[0].Value;
                        row["Ordem Venda"] = dgDados.Rows[i].Cells[1].Value;
                        row["Transportadora"] = dgDados.Rows[i].Cells[2].Value;
                        row["Volume"] = dgDados.Rows[i].Cells[3].Value;
                        ped.Rows.Add(row);
                         
                    }
                }
                bdpedidos ax = new bdpedidos();
                ax.tabela = ped;
                      
            }

    E no load do form2, coloquei assim:

    private void Email_Load(object sender, EventArgs e)
            {
                bdpedidos ab = new bdpedidos();
                dgmensagem.DataSource = ab.tabela;
                
            }

    Para mim funcionou perfeitamente!!!

    O datagridview2 fica preenchido com todos os ítens selecionados no datagridview1.

    Valeu Wennder e Lucas pela força e espero que o meu questionamento e as soluções apresentadas por vocês ajudem os apaixonados por C#.

    Abraçoss e até mas!!!

    quarta-feira, 22 de janeiro de 2014 23:00