Trabalhando com arquivos sequenciais
Há vezes que precisamos trabalhar com arquivos com formatos
diferentes daqueles com que o Excel trabalha e nem sempre é um formato
fácil de importar. Normalmente são usados arquivos sequenciais, ou
seja, arquivos em que cada linha representa um registro e que são
processados do início até o fim, em sequência.
diferentes daqueles com que o Excel trabalha e nem sempre é um formato
fácil de importar. Normalmente são usados arquivos sequenciais, ou
seja, arquivos em que cada linha representa um registro e que são
processados do início até o fim, em sequência.
Se o arquivo for recebido apenas uma vez, não há muito problema em
fazer a importação de maneira manual. Porém, quando é um arquivo
recebido rotineiramente, é melhor automatizar a importação do arquivo.
E o que é melhor, pode-se
automatizar também toda a formatação da tabela
feita após a importação.
fazer a importação de maneira manual. Porém, quando é um arquivo
recebido rotineiramente, é melhor automatizar a importação do arquivo.
E o que é melhor, pode-se
automatizar também toda a formatação da tabela
feita após a importação.
Por outro lado, pode haver a necessidade de gerar um arquivo em um
formato específico. Neste caso, a criação manual do arquivo pode ser
demasiadamente trabalhosa, por isso é melhor fazer um processo
automático para não dar margem para erros na criação do arquivo,
principalmente se houver muitas linhas e colunas para serem
exportadas.
formato específico. Neste caso, a criação manual do arquivo pode ser
demasiadamente trabalhosa, por isso é melhor fazer um processo
automático para não dar margem para erros na criação do arquivo,
principalmente se houver muitas linhas e colunas para serem
exportadas.
O código para ler ou gravar um arquivo não é difícil. O esqueleto
básico para arquivos sequenciais é o seguinte: abrir arquivo, laço
para processar, fechar arquivo. A complexidade está no processamento
do registro, seja para ler ou para gravar o registro. Vejamos o código
para ler um arquivo:
básico para arquivos sequenciais é o seguinte: abrir arquivo, laço
para processar, fechar arquivo. A complexidade está no processamento
do registro, seja para ler ou para gravar o registro. Vejamos o código
para ler um arquivo:
Sub ProcessarArquivo()
Dim Arquivo As String
Dim Registro As String
Arquivo = “C:TempTeste.txt”
Open Arquivo For Input As #1
Do Until EOF(1)
‘ Lê o próximo
registro
registro
Line Input #1,
Registro
Registro
‘ Chama a sub-rotina
para processar o registro lido
para processar o registro lido
ProcessarRegistro
(Registro)
(Registro)
Loop
Close #1
End Sub
Vamos entender esse código. No início ele cria uma variável de
formato texto chamada Arquivo, à qual é associado um arquivo.
Note bem que o caminho do arquivo está completo, com disco e pasta
especificados, caso contrário o Excel pode não encontrar o arquivo e
então gerará uma mensagem de erro.
formato texto chamada Arquivo, à qual é associado um arquivo.
Note bem que o caminho do arquivo está completo, com disco e pasta
especificados, caso contrário o Excel pode não encontrar o arquivo e
então gerará uma mensagem de erro.
É possível obter o arquivo por meio de uma caixa de diálogo, onde o
usuário pode selecionar o arquivo. Neste caso deve-se alterar a linha
para a seguinte forma:
usuário pode selecionar o arquivo. Neste caso deve-se alterar a linha
para a seguinte forma:
Arquivo = Application.GetOpenFilename(FileFilter:=”Arquivo de texto
(*.txt), *.txt”, _
(*.txt), *.txt”, _
title:=”Selecione um arquivo de texto para
importar”)
importar”)
Use a forma que for mais adequada à necessidade. Se o arquivo vem
sempre com o mesmo nome e caminho, a primeira forma é a melhor. Caso o
nome e o caminho possam variar, a segunda forma ajuda a selecionar o
arquivo.
sempre com o mesmo nome e caminho, a primeira forma é a melhor. Caso o
nome e o caminho possam variar, a segunda forma ajuda a selecionar o
arquivo.
Continuando o código, logo a seguir aparece um comando Open,
que irá abrir o arquivo. Ele contém o parâmetro For Input, que
indica que o arquivo será usado para leitura (outros parâmetros serão
vistos mais adiante). A seguir, há outro parâmetro, As #1, que
indica que o número de ordem do arquivo que está sendo aberto. Se
houver outros arquivos a serem abertos ao mesmo tempo, deve-se
incrementar o número: #2, #3 etc, sendo que o limite é
511. Como pode-se imaginar, trabalhar com mais de um arquivo ao mesmo
tempo requer cuidado. Aqui vou limitar a um arquivo para facilitar o
aprendizado.
que irá abrir o arquivo. Ele contém o parâmetro For Input, que
indica que o arquivo será usado para leitura (outros parâmetros serão
vistos mais adiante). A seguir, há outro parâmetro, As #1, que
indica que o número de ordem do arquivo que está sendo aberto. Se
houver outros arquivos a serem abertos ao mesmo tempo, deve-se
incrementar o número: #2, #3 etc, sendo que o limite é
511. Como pode-se imaginar, trabalhar com mais de um arquivo ao mesmo
tempo requer cuidado. Aqui vou limitar a um arquivo para facilitar o
aprendizado.
Após o arquivo ser aberto, há uma estrutura de repetição
Do Until… Loop, que testa uma condição EOF(1).
EOF significa end of file, ou seja, fim do arquivo, e
1 é o número de ordem do arquivo. Traduzindo, o laço será
processado até que não haja mais registros a serem lidos.
Do Until… Loop, que testa uma condição EOF(1).
EOF significa end of file, ou seja, fim do arquivo, e
1 é o número de ordem do arquivo. Traduzindo, o laço será
processado até que não haja mais registros a serem lidos.
Dentro do laço, temos uma o comando
Line Input #1, Registro, que irá preencher a variável
Registro com o conteúdo do registro lido no arquivo. Há também
uma chamada para uma sub-rotina chamada ProcessarRegistro, que
irá processar o registro, onde estará toda a lógica e complexidade do
que fazer com o registro lido.
Line Input #1, Registro, que irá preencher a variável
Registro com o conteúdo do registro lido no arquivo. Há também
uma chamada para uma sub-rotina chamada ProcessarRegistro, que
irá processar o registro, onde estará toda a lógica e complexidade do
que fazer com o registro lido.
Por fim, temos o comando Close #1, que irá fechar o arquivo.
Lembre-se sempre de fechar os arquivos após processar, caso contrário
eles podem ficar presos ao Excel até que este seja fechado, impedindo
outros programas ou outras pessoas de usarem o arquivo.
Lembre-se sempre de fechar os arquivos após processar, caso contrário
eles podem ficar presos ao Excel até que este seja fechado, impedindo
outros programas ou outras pessoas de usarem o arquivo.
Agora vejamos o código para fechar o arquivo:
Sub ProcessarArquivo()
Dim Arquivo As String
Dim Registro As String
Dim Linha As Integer
Dim UltimaLinha As Integer
Arquivo = “C:TempTeste.txt”
Open Arquivo For Output As #1
UltimaLinha = Cells(1, 1).End(xlDown).Row
For Linha = 2 To UltimaLinha
‘ Chama a sub-rotina
para gerar registro para gravação
para gerar registro para gravação
Registro =
GerarRegistro(Linha)
GerarRegistro(Linha)
‘ Grava o registro no
arquivo
arquivo
Print #1, Registro
Next
Close #1
End Sub
Aqui temos três diferenças em relação ao código de abrir arquivo. A
primeira é que o comando Open agora está com o parâmetro
For Output, o que significa que o arquivo será usado para
gravação. A segunda diferença é o laço de repetição, que agora se
refere à planilha, que é de onde sairão os dados para serem gravados
no arquivo. Aqui usei um laço For… Next, mas poderia ser
qualquer outra estrutura de repetição. E a terceira é o comando Print #1, Registro, que irá gravar
o conteúdo da variável Registro no arquivo 1. Há o
comando Write, que é usado da mesma forma, porém este grava
strings entre aspas.
primeira é que o comando Open agora está com o parâmetro
For Output, o que significa que o arquivo será usado para
gravação. A segunda diferença é o laço de repetição, que agora se
refere à planilha, que é de onde sairão os dados para serem gravados
no arquivo. Aqui usei um laço For… Next, mas poderia ser
qualquer outra estrutura de repetição. E a terceira é o comando Print #1, Registro, que irá gravar
o conteúdo da variável Registro no arquivo 1. Há o
comando Write, que é usado da mesma forma, porém este grava
strings entre aspas.
Observe nos códigos uma diferença importante nos laços: na leitura,
primeiro lê o registro e depois processa; na gravação, primeiro gera o
registro e depois grava. É algo bem lógico, mas às vezes uma
desatenção nesse detalhe pode causar a perda de registros.
primeiro lê o registro e depois processa; na gravação, primeiro gera o
registro e depois grava. É algo bem lógico, mas às vezes uma
desatenção nesse detalhe pode causar a perda de registros.
O conhecimento até agora permite ler e gravar arquivos para muitos
casos. Daqui em diante, vamos aprofundar o conhecimento no assunto,
estudando alguns detalhes mais a fundo.
casos. Daqui em diante, vamos aprofundar o conhecimento no assunto,
estudando alguns detalhes mais a fundo.
O comando Open tem a seguinte sintaxe (os parâmetros opcionais
estão entre colchetes):
estão entre colchetes):
Open NomeDoArquivo For Modo [Access Acesso]
[Trava] As Número [Len=Comprimento]
[Trava] As Número [Len=Comprimento]
Vimos os modos Input e Output acima. Tem ainda os
seguintes modos:
seguintes modos:
– Append: Adiciona registros a um arquivo existente;
– Binary: Usado para ler e gravar arquivos em formato
binário;
binário;
– Random: Para arquivos com acesso aleatório (não sequencial).
É a opção padrão.
É a opção padrão.
Os modos Random e Binary não serão abordados neste
artigo devido à complexidade. Eles terão um artigo no futuro.
artigo devido à complexidade. Eles terão um artigo no futuro.
O parâmetro opcional Access pode ter os seguintes valores:
– Read: Permite somente leitura;
– Write: Permite somente escrita;
– Read Write: Permite tanto leitura quanto escrita.
Perceba que não há necessidade deste parâmetro quando se usa os modos
Input, Output e Append, somente nos casos de
modos Binary e Random.
Input, Output e Append, somente nos casos de
modos Binary e Random.
Trava define se o arquivo pode ser aberto por outro processo
enquanto estiver aberto no Excel. Os parâmetros possíveis são:
enquanto estiver aberto no Excel. Os parâmetros possíveis são:
– Shared: Compartilhado, permite leitura e escrita;
– Lock Read: Não permite leitura, só escrita;
– Lock Write: Não permite escrita, só leitura;
– Lock Read Write: Não permite leitura nem escrita.
Por fim, Len define o comprimento do registro. Não há
necessidade de especificar e é mais vantajoso controlar o comprimento
do registro na própria criação, definindo com campos de tamanhos
fixos.
necessidade de especificar e é mais vantajoso controlar o comprimento
do registro na própria criação, definindo com campos de tamanhos
fixos.
Agora vejamos a diferença entre os comandos Print e
Write com um código simples:
Write com um código simples:
Sub GravarTexto()
Dim Arquivo As String
Arquivo = “C:TempTexto Gravado.txt”
Open Arquivo For Output As #1
Print #1, “Olá, mundo!”
Write #1, “Olá, mundo!”
Close #1
End Sub
O resultado do arquivo gravado é o seguinte:
Olá, mundo!
“Olá, mundo!”
Desta forma é mais fácil visualizar a diferença entre os dois
comandos. Enquanto Print apenas gravou o conteúdo do texto,
Write deixou-o entre aspas.
comandos. Enquanto Print apenas gravou o conteúdo do texto,
Write deixou-o entre aspas.
É possível adicionar mais argumentos em ambos comandos, separando por
vírgulas. Desta forma podemos gravar vários campos ou variáveis em uma
linha sem precisar compor um campo com o registro inteiro. Porém, há
diferenças na forma de gravar as linhas. Altere as linhas dos comandos
Print e Write da seguinte forma:
vírgulas. Desta forma podemos gravar vários campos ou variáveis em uma
linha sem precisar compor um campo com o registro inteiro. Porém, há
diferenças na forma de gravar as linhas. Altere as linhas dos comandos
Print e Write da seguinte forma:
Print #1, “Olá, mundo!”, 123
Write #1, “Olá, mundo!”, 123
Acrescentamos um valor numérico, que será gravado ao lado da string.
Observe como fica a gravação:
Observe como fica a gravação:
Olá, mundo! 123
“Olá, mundo!”,123
O comando Print separa campos distintos com uma tabulação,
enquanto o Write separa com vírgulas. Perceba que o valor
numérico não recebeu aspas. Se fosse outro campo do tipo
string, o texto seria envolvido por aspas.
enquanto o Write separa com vírgulas. Perceba que o valor
numérico não recebeu aspas. Se fosse outro campo do tipo
string, o texto seria envolvido por aspas.
Repare também que a string gravada contém uma vírgula. Ela não
vai interferir no registro, pois no registro gravado com
Print não há separação por vírgulas, enquanto no registro
gravado com Write ela está entre aspas. É importante conhecer
esses detalhes para saber decidir como os dados serão gravados, porque
a forma de ler depende diretamente dessa escolha.
vai interferir no registro, pois no registro gravado com
Print não há separação por vírgulas, enquanto no registro
gravado com Write ela está entre aspas. É importante conhecer
esses detalhes para saber decidir como os dados serão gravados, porque
a forma de ler depende diretamente dessa escolha.
Para a leitura dos dados, pode-se ler o registro inteiro e depois
usar um comando como o Instr para localizar os separadores,
seja a tabulação ou a vírgula, e então ir compondo as células com os
valores. Há uma alternativa mais prática que usa o comando
Split, que gera um array com os dados do registro. Observe o
código abaixo:
usar um comando como o Instr para localizar os separadores,
seja a tabulação ou a vírgula, e então ir compondo as células com os
valores. Há uma alternativa mais prática que usa o comando
Split, que gera um array com os dados do registro. Observe o
código abaixo:
Sub LerTexto()
Dim Arquivo As String
Dim Registro As String
Dim Linha As Integer
Dim Conteudo As Variant
Dim Contador As Integer
Arquivo = “C:TempTexto Gravado.txt”
Linha = 1
Open Arquivo For Input As #1
Do Until EOF(1)
Line Input #1,
Registro
Registro
Conteudo =
Split(Registro, vbTab)
Split(Registro, vbTab)
For Contador =
LBound(Conteudo) To UBound(Conteudo)
LBound(Conteudo) To UBound(Conteudo)
Cells(Linha, Contador + 1).Value = Conteudo(Contador)
Next
Linha = Linha + 1
Loop
Close #1
End Sub
Analisando o código: o comando Line Input irá ler o registro e
gravá-lo na variável Registro, como visto anteriormente. A
linha seguinte compõe a variável Conteudo como um array,
separando os itens pelo separador. O caractere da tabulação é
identificado pela constante do VBA vbTab. Por fim, há um laço
For… Next que irá preencher as células da planilha ativa com
os valores do array Conteudo. Atente para o fato de que
um array inicializa sempre em 0, por isso é preciso acrescentar
1 para gravar na primeira coluna.
gravá-lo na variável Registro, como visto anteriormente. A
linha seguinte compõe a variável Conteudo como um array,
separando os itens pelo separador. O caractere da tabulação é
identificado pela constante do VBA vbTab. Por fim, há um laço
For… Next que irá preencher as células da planilha ativa com
os valores do array Conteudo. Atente para o fato de que
um array inicializa sempre em 0, por isso é preciso acrescentar
1 para gravar na primeira coluna.
Experimente criar um arquivo com várias linhas e vários valores em
cada linha, separados por tabulações e então teste o código. Depois
experimente fazer o mesmo, separando por vírgulas, colocando strings
entre aspas, alterando o vbTab no código para “,” (a fim
de indicar que é para separar pelas vírgulas) e teste novamente. Se
você manteve a string “Olá, mundo!” do exemplo anterior,
verá que na separação por vírgulas uma célula ficou com “Olá e
a outra ficou com mundo!”. Outro problema é que as
strings permaneceram com as aspas nas células. São problemas
que demandarão um código adicional para verificar essas eventualidades
e corrigi-las todas.
cada linha, separados por tabulações e então teste o código. Depois
experimente fazer o mesmo, separando por vírgulas, colocando strings
entre aspas, alterando o vbTab no código para “,” (a fim
de indicar que é para separar pelas vírgulas) e teste novamente. Se
você manteve a string “Olá, mundo!” do exemplo anterior,
verá que na separação por vírgulas uma célula ficou com “Olá e
a outra ficou com mundo!”. Outro problema é que as
strings permaneceram com as aspas nas células. São problemas
que demandarão um código adicional para verificar essas eventualidades
e corrigi-las todas.
Particularmente prefiro criar uma variável para compor o registro,
mantendo todos os campos de tamanho fixo, para então gravar o
registro. Em
uma das vídeo-aulas do Alessandro Trovato
foi demonstrado uma forma de como fazer isso, reveja se for
necessário.
mantendo todos os campos de tamanho fixo, para então gravar o
registro. Em
uma das vídeo-aulas do Alessandro Trovato
foi demonstrado uma forma de como fazer isso, reveja se for
necessário.
Por fim, algumas dicas para quando estiver exportando dados para
arquivos:
arquivos:
– Números com casas decimais devem ser exportados de preferência sem
a vírgula. Se for valor de moeda (duas casas decimais), multiplique
por 100 antes de exportar e divida por 100 quando for importar. Caso
sejam valores com mais casas decimais, defina o multiplicador de
acordo com o valor da maior casa decimal para então exportar
todos com o mesmo valor. Isso é para ajudar a manter os números com a
mesma quantidade de dígitos e assim facilitar a exportação e posterior
importação dos valores;
a vírgula. Se for valor de moeda (duas casas decimais), multiplique
por 100 antes de exportar e divida por 100 quando for importar. Caso
sejam valores com mais casas decimais, defina o multiplicador de
acordo com o valor da maior casa decimal para então exportar
todos com o mesmo valor. Isso é para ajudar a manter os números com a
mesma quantidade de dígitos e assim facilitar a exportação e posterior
importação dos valores;
– Transforme as datas para o formato AAAA/MM/DD antes de
exportar, porque o Excel tem um problema na importação de datas. Ele
considera como MM/DD/AAAA a não ser que o MM seja maior que 12,
neste caso ele importa como DD/MM/AAAA. Imagine uma situação
com muitas datas e o Excel bagunçando tudo. Veja o resultado dos
testes nas imagens abaixo:
exportar, porque o Excel tem um problema na importação de datas. Ele
considera como MM/DD/AAAA a não ser que o MM seja maior que 12,
neste caso ele importa como DD/MM/AAAA. Imagine uma situação
com muitas datas e o Excel bagunçando tudo. Veja o resultado dos
testes nas imagens abaixo:
Datas exportadas como DD/MM/AAAA: As datas de 01/02/2001 a 12/02/2001 foram importadas de maneira
errada pelo Excel, enquanto o restante foi importado
corretamente.
errada pelo Excel, enquanto o restante foi importado
corretamente.
Datas exportadas como AAAA/MM/DD: Todas as datas foram
importadas corretamente.
importadas corretamente.
Espero que este artigo lhe ajude a trabalhar com arquivos de forma
satisfatória e sem problemas. Quaisquer dúvidas, use a seção de
comentários abaixo.
satisfatória e sem problemas. Quaisquer dúvidas, use a seção de
comentários abaixo.
Pedro Martins
Formado em Tecnologia em Eletrônica Digital, já trabalhou como
artefinalista, eletrotécnico, programador de CLP (para máquinas
industriais) e analista de sistemas em sistema bancário, programando
em COBOL.
artefinalista, eletrotécnico, programador de CLP (para máquinas
industriais) e analista de sistemas em sistema bancário, programando
em COBOL.
Mexe com computadores e programação desde a segunda metade dos anos
1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor
da disseminação do conhecimento.
1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor
da disseminação do conhecimento.
Catálogo de aulas (NOVIDADE)
Criei um catálogo de aulas para ajudar você em seus estudos. Acesse clicando na imagem abaixo ou clique aqui.