quarta-feira, 13 de junho de 2012

Criando arquivos Excel no Android


Este post foi escrito e sugerido por Leonardo Malkes (e pequenos ajustes meus :)

Um cliente que estava precisando desenvolver uma app para Android e me perguntou se era possível criar arquivos do Excel a partir da aplicação. De imediato eu respondi que não sabia, mas complementei a frase dizendo: “Hoje em dia em programação quase tudo é possível”. Entretanto, alguns dias depois esse mesmo cliente disse que não seria mais necessário gerar o arquivo. Mas a minha curiosidade de como fazer isso já havia sido atiçada.

Após algumas pesquisas na internet, encontrei uma biblioteca Java, open source e bem documentada (com JavaDoc incluso), chamada JExcelAPI. Baixe a última versão, vamos aos trabalhos!

Crie um novo projeto Android e na raiz do projeto adicione uma pasta chamada lib, e dentro dela  coloque o arquivo jxl.jar que está no zip da biblioteca.
Para trabalhar com biblioteca de terceiros, precisamos adicioná-la ao Build Path do projeto. Para fazer isso, clique com o botão direito sobre o arquivo da biblioteca e selecione Build Path > Add to Build Path. Em seguida, clique com o botão direito sobre o projeto e selecione Build Path > Configure Build Path. Na janela que for exibida, na aba Order and Export, marque a biblioteca jxl.jar.

Agora estamos prontos para iniciar o projeto. Lembrando que se queremos criar um arquivo no Excel, o mais natural é gravá-lo no cartão de memória do aparelho (apesar de ser possível gravar na memória interna do aparelho). Para fazer isso precisamos adicionar a permissão WRITE_EXTERNAL_STORAGE no AndroidManifest.xml.
<uses-permission 
  android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Para criar o arquivo, usamos a classe File (do Java padrão) definindo o local e o nome do arquivo. Não esquecendo de importar o java.io.
File file = new File(
  getExternalFilesDir(null), 
  "MeuArquivoXLS.xls");
Isso criará o arquivo MeuArquivoXLS.xls no diretório Android/data/pacote.sua.app/files do cartão de memória. O método getExternalFilesDir é da classe Context, então parta do pressuposto que estou chamando o código acima de uma Activity. Esse método fará com que, se a aplicação for excluída, os arquivos da mesma também sejam. Caso não queira que isso aconteça, você pode usar o método Environment.getExternalStorageDirectory() que salvará o arquivo na raiz do cartão de memória.

Em seguida vamos criar o Excel Workbook, que é uma pasta de trabalho do Excel que pode conter uma ou mais Planilhas (Sheets). Observe que para criar o workbook usamos a classe WritableWorkbook que não tem construtor, e faz uso do FactoryMethod createWorkbook.
WritableWorkbook wb = null;
try {
  wb = Workbook.createWorkbook(file);
} catch (IOException e) {
  e.printStackTrace();
}
Já com o workbook criado, é preciso criar a planilha(Sheet). O método createSheet recebe dois parâmetros: o nome da planilha e a posição que ela vai ficar dentro do workbook.
wb.createSheet("Planilha", 0);
Agora para escrever nesta planilha precisamos pegar a instância de um WritableSheet através do método getSheet do objeto WorkBook. Esse método recebe como parâmetro o índice na planilha ou o nome.
WritableSheet plan = wb.getSheet(0);
Com a instância da planilha, podemos inserir valores nas células usando o método addCell que recebe um WritableCell que é uma interface. A classe Label representa um texto simples e implementa esta interface. Para criar um  Label em uma célula, passamos coluna, linha e o valor da célula.
Label label = new Label(0,0,"Primeira célula");
// Como o método pode levantar exceção 
// iremos coloca-lo dentro de um try/catch
try {
  plan.addCell(label);
} catch (RowsExceededException e1) {
  e1.printStackTrace();
} catch (WriteException e1) {
  e1.printStackTrace();
}
Pronto agora é só gravar o fechar o workbook.
wb.write();
wb.close();

Feito isso, basta rodar a aplicação e testar o código. Para pegar o arquivo, você pode utilizar a janela File Explorer da perspectiva DDMS. Navegue até o diretório e selecione o botão Pull File from Device.


Dúvidas? Mandem pra Leo :)

 4br4ç05,
nglauber

28 comentários:

Anônimo disse...

ola amigo como eu faço para saber onde o arquivo vai ficar no android um aparelho real, e parabens pelo tutorial muito bom

Nelson Glauber disse...

Oi Anônimo,

O caminho do arquivo vai ser o que eu coloquei no post. Para ver o arquivo no aparelho real, é só conectá-lo via USB e acessar via gerenciador de arquivos do seu sist. operacional.

4br4ç05,
nglauber

Unknown disse...

Poxa cara parabéns pelo post, eu estava procurando exatamente isso, agora algo que poderia ajudar ao pessoal é fazer o seguinte... Onde tem
File file = new File(
getExternalFilesDir(null),
"MeuArquivoXLS.xls");

trocar por:
String diretorio = Environment.getExternalStorageDirectory()+ "/Relatorios/";
File file = new File(diretorio,"MeuArquivoXLS.xls");

assim o pessoal pode salvar o arquivo no sdcard, na pasta que preferir!!!

Schelb disse...

Muito interessante o post, irei testar aki na minha aplicação, eu vou continuar procurando um meio de gerar outros arquivos tmb, como por exemplo pdf e word.

Vlw demais!

Unknown disse...

wb.write();
wb.close();

Essas opções apresentaram erro, como resolvo?

Nelson Glauber disse...

Oi Diogo,

Está dando erro em tempo de compilação ou execução?Esse bloco está dentro de um try/catch?

4br4ç05,
nglauber

Unknown disse...

Boa tarde!

Muito bom o post...
porém ao implementar em meu app está dando erro na linha

wb.createSheet("Planilha", 0);

no LogCat do Eclipse apresenta:
java.lang.NullPointerException

O que pode ser?

Abraços e Parabéns pelo trabalho!

Nelson Glauber disse...

Oi Marcos,

NullPointer é quando você tenta utilizar algum método ou atributo de um objeto nulo.

4br4ç05,
nglauber

Unknown disse...

Acho que o problema deve ser na criação do objeto wb:

wb = Workbook.createWorkbook(file);

Inseri a permissão no arquivo AndroidManifest.xml como orientado, mas mesmo assim acho que não está funcionando...

Sabe me dizer onde está o erro?
Estou rodando diretamente no meu Galaxy S3 com Android 4.3

Abraços!

Nelson Glauber disse...

Oi Marcos,

Vê se o objeto File está sendo criado e se ele existe.

4br4ç05,
nglauber

Unknown disse...

Ótimo post. Vai ser muito útil em meu projeto. Obrigado!

joão disse...

blz???
Vei, como eu faço pra gravar na memória interna do celular?

Vlw pelo tutorial

Nelson Glauber disse...

Oi joão,

Basicamente é só mudar isso aqui:
File file = new File(
context.getFilesDir(),
"MeuArquivoXLS.xls");

Mais informações aqui:
https://developer.android.com/guide/topics/data/data-storage.html#filesInternal
https://developer.android.com/reference/android/content/Context.html#getFilesDir()

4br4ç05,
nglauber

Unknown disse...

Boa noite amigo...

Ótimo post, estou com um problema!

Como faço para inserir um registro na planilha?

Se puder me ajudar agradeço!

Nelson Glauber disse...

Oi Unknown :p

Esse exemplo insere um texto na linha 0, coluna 0... Então você pode ir colocando as demais colunas que você precisar...

Label label = new Label(0,0,"Primeira célula");
plan.addCell(label);

4br4ç05,
nglauber

Unknown disse...

Boa noite...

Como faço para abrir novamente a Planilha e a Aba?

Nelson Glauber disse...

Oi Dione,

Dá uma olhada na documentação. Acho que a classe Workbook permite selecionar a aba com o método getSheet().
http://jexcelapi.sourceforge.net/resources/javadocs/2_6_10/docs/index.html


4br4ç05,
nglauber

Anônimo disse...

No meu não foi criado o documento .xls dentro de files. Só localizo a pasta sdcard>android>data>pacote.aplicacao>files

Sabe o que fazer para visualizar o .xls criado ou ele realmente nao foi criado?

Nelson Glauber disse...

Oi Anônimo,

Impressionante, mas esse post tem quase 5 anos e ainda funciona :)
O local mudou, é /storage/emulated/0/Android/data/pacote do seu app/files/MeuArquivoXLS.xls

Se quiser baixar o arquivo no seu computador (no desktop), basta usar o comando
adb pull /storage/emulated/0/Android/data/br.com.nglauber.aula09_receiver/files/MeuArquivoXLS.xls ~/Desktop

4br4ç05,
nglauber

Unknown disse...

Boa noite Glauber,

Teria como definir as colunas e alimentar as várias linhas a partir dos meus campos.

Exemplo: Colunas ("Nome", "Local", "Hora", "Data", "Obs") e conforme for salvando as linhas vão sendo inseridas, através de um button "Salvar" (sem fechar a planilha) e ao finalizar o preenchimento através de outro button "Finalizar Registro" ele cria o xls.

Grato e Parabéns pelo post.

Nelson Glauber disse...

Oi André,

Você pode fazer essa lógica em memória, e no botão de finalizar, salvar no arquivo.
Ou seja, você utiliza uma estrutura de dados para armazenar os dados, e ao final, envia para a planilha.

4br4ç05,
nglauber

Unknown disse...

grato!

Unknown disse...

Olá Nélson, gostaria de pedir uma ajuda para utilizar seu algoritmo. Não consigo instanciar o WritableWorkBook. Já verifiquei, e o objeto File está sendo instanciado sem problema. Tento instanciar o objeto da seguinte forma, mas ele permanece nulo.

WritableWorkbook ww = null;
try{
ww = Workbook.createWorkbook(pasta);
}catch(IOException e){
e.printStackTrace();
}

Agradeço desde já qualquer ajuda.

Nelson Glauber disse...

Oi Rodolfo,

Você está testando em um aparelho com Android 6 (Marshmallow) ou superior?
Em caso positivo, você está verificando se ter permissão para acessar o sistema de arquivos?
Caso ainda não tenha resolvido, compartilha teu código no GitHub que assim que puder dou uma olhada.

4br4ç05,
nglauber

Unknown disse...

Não consigo depois editar o ficheiro. Como alterar?

Nelson Glauber disse...

Já tentaste isto aqui?
https://stackoverflow.com/questions/3605923/modifying-existing-excel-using-jxl

4br4ç05,
nglauber

Oseias disse...

Excelente post, mas me responde uma duvida, para utilizar .jar é necessário permitir no manifest?

Nelson Glauber disse...

Oi Oseias,

Não precisa. Basta colocar na pasta libs.

4br4ç05,
nglauber