Ler (importar) dados de arquivo excel usando filtro

10/08/2010

Bom dia!   Eu faço uso do código abaixo para ler (importar) dados de uma determinada planilha em excel:               string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" +
                                     @"Data Source=" + arquivoExcel + ";" +
                                      "Extended Properties='Excel 12.0;HDR=YES;'";             string sql = "SELECT * FROM [" + regiao + " " + mesImportacao + "$]";             DataTable vendasCorrentes = new DataTable();
            using (OleDbDataAdapter adapter = new OleDbDataAdapter(sql, connectionString))
            {
                adapter.Fill(vendasCorrentes);
            }   O select funciona, só que ele me traz todas as linhas do Excel, o que acarreta em mais tempo de processamento (para ele ler tudo isso). Eu recebo essa planilha do cliente, não tem nada na primeira linha para eu usar como cabeçalho de coluna (vem na formatação deles), e eu gostaria de saber se no SELECT do Excel tem como eu usar uma condição do tipo: WHERE B <> '' ou WHERE ISNULL(B, '') <> ''. B no caso seria a segunda coluna do arquivo excel.   Com isso, minha intenção é de, ao invés de ele levar um tempo maior para trazer 60.000 linha, ele me traga só 40 linhas, que eu sei que são válidas para eu importar, e com isso, diminuo esse tempo de processamento no momento da leitura, sabe?   Fico no aguardo, valeu!    
Carlos Nogueira

Carlos Nogueira

Curtidas 0

Respostas

Luiz Maia

Luiz Maia

10/08/2010

Carlos, infeliamente não tem como filtrar no EXCEL, mas depois que carregou tudo num Datatable, fica facil fazer os filtros, basta usar um dos recursos abaixo:   Existem 3 formas básicas de você localizar registros em um DataTable : DataTable.Select() - Usa o método Select() do objeto DataTable - Retorna um array de objetos DataRow que coincidem com critério definido. Por padrão as linhas no array são ordenadas pela chave primária , ou pela ordem na qual as linhas foram incluidas na tabela. Podemos usar o método Select() com um argumento opcional para selecionar registros de acordo com o estado de uma linha a partir da enumeração do DataViewRowState. DataTable.Rows.Find() - Usa o método Find() de DataRowCollection() de uma tabela para retornar uma linha que coincide com um valor da chave primária ou com valores passados como um argumento objeto our um array de objetos. Para usar o método Find() , o objeto Datatable no qual a DataRowCollection pertence precisa ter uma chave primária definida caso contrário a exceção MissingPrimaryKeyException será disparada. Se a chave primária não existe em DataRowCollection o método retorna Null. DataView.RowFilter - Podemos usar um DataView baseado em um Datatable para localizar registros das seguintes formas : Usar a propriedade RowFilter do DataView. Cria um DataView baseado em um DataTable e define RowFilter para uma expressão de filtro. Usar o método Find() do DataView para retornar o indice da linha que coincide com a chave ordenada ou com valores passados como argumentos objetos ou um array de objetos. Se a chave ordenada não existir será retornado Null. Usar o método FindRows() do DataView para retornar um array de objetos DataRowView cujas colunas coincidem com o valor da chave ordenada especificada. Se ela não existir um array DataRowView vazio será retornado. Exemplo do uso: Private Sub btnLocalizaLinhas_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLocalizaLinhas.Click
' obtem a tabela vinculada ao datagrid
Dim dt As DataTable = CType(dgLocalizaLinhas.DataSource, DataView).Table   ' constroi o filtro usando o conteudo do combobox
Dim filtro As [String] = CAMPO_SHIPCOUNTRY & " = '" & cboPais.Text & "'" ' localiza os registros usando o método select do datatable
Dim drc As DataRow() = dt.Select(filtro)
txtResultado.Text = "DataTable.Select retornou " & drc.Length & " registros(s)." & Environment.NewLine ' percorre a coleção de linhas filtradas no passo anterior e localiza o item
'na tabela usando o método Find() de DataRowCollection do DataTable
Dim contador As Integer = 0
Dim linha As DataRow For Each linha In drc
    Dim RegistroLocalizado As DataRow = dt.Rows.Find(linha(CAMPO_ORDERID))
    If Not (RegistroLocalizado Is Nothing) Then
       contador = contador + 1
     End If
Next linha txtResultado.Text = txtResultado.Text & "DataTable.Rows.Find retornou " & contador & " registros(s)." & Environment.NewLine ' localiza os registros usando a propriedade RowFilter do DataView
Dim dv As New DataView(dt) 'executa o filtro no dataview
dv.RowFilter = filtro 'vincula o resultado ao dtagrid
dgLocalizaLinhas.DataSource = dv 'exibe o resultado dos três métodos usados para retornar os registros com o criterio usado
txtResultado.Text = txtResultado.Text & "DataView.RowFilter retornou " & dv.Count & " registro(s)." End Sub Destacamos a seguir as linhas de código que usam os métodos indicados : O filtro usado é obtido usando o nome do país selecionado na combobox pelo usuário : Dim filtro As [String] = CAMPO_SHIPCOUNTRY & " = '" & cboPais.Text & "'" Dim drc As DataRow() = dt.Select(filtro) Dim RegistroLocalizado As DataRow = dt.Rows.Find(linha(CAMPO_ORDERID)) dv.RowFilter = filtro
GOSTEI 0
Carlos Nogueira

Carlos Nogueira

10/08/2010

Boa tarde Luiz!   Eu entendo, até havia feito alguns testes com o método Select do DataTable, mas ele não é exatamente o que eu desejo, pois ainda sim o tempo de processamento para ler as linhas do excel continuará o mesmo, e isso que queria tentar diminuir. Vou conversar com o cliente, quem sabe ele cede e acrescente ao menos uma descrição na primeira linha para o programa entender que aquilo é uma leitura. Ai sim, deve melhorar a performance no momento de fazer importação.   De qualquer maneira eu agradeço, e pode finalizar o chamado!   Valeu!
GOSTEI 0
Luiz Maia

Luiz Maia

10/08/2010

Uma alternativa seria vc importar os arquivos do Excel e criar um Documento XML, assim ficaria mais leve para manipular e bem mais rápido quanto a performance.    
GOSTEI 0
POSTAR