Sunteți pe pagina 1din 17

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

www.devmedia.com.br

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

[verso para impresso]

Usando JExcel API numa aplicao WEB Struts


Crie uma aplicao web que edita planilhas do Microsoft Excel.

Usando JExcel API numa aplicao WEB Struts


Crie uma aplicao web que edita planilhas do Microsoft Excel
Hoje em dia as empresas usam planilhas Excel para organizar quase tudo que ainda no organizado por um sistema. Muitas vezes,
mesmo havendo um sistema especfico para determinada tarefa (como o MS Project para gerenciamento de projetos ou JIRA para
controle de Trouble Tickets), muitos ainda preferem usar planilhas Excel, por sua flexibilidade e facilidade de uso. Dessa forma, torna-se
extremamente til poder criar sistemas web que saibam manipular planilhas Excel, que o que veremos nesse artigo.
Pr-requisitos
suporto que o leitor saiba usar a ferramenta ANT para empacotar a aplicao em um arquivo WAR (Web Archive). Tambm suporto
que o mesmo saiba usar algum IDE Java para trabalhar com o cdigo fonte que criaremos e a usar um Web Server como o Apache
Tomcat para rodar a aplicao criada.
necessrio tambm baixar a verso 1.3.8 do framework Struts, que pode ser encontrado no site http://struts.apache.org e a JExcel API, que
pode ser encontrada no site http://jexcelapi.sourceforge.net/. No se esquea de ter o ANT instalado em sua mquina no PATH do sistema.
Definindo a aplicao
A aplicao que criaremos ser bem simples, mas suficiente para os fins de demonstrao ao qual esse artigo se prope. Nossa
aplicao ter uma pgina inicial que permite ao usurio escolher um arquivo Excel em sua mquina para formatao. Ao clicar no boto
Formatar, o arquivo ser enviado ao servidor e ser feita uma varredura em todas as clulas de cada planilha. Todas as clulas
numricas tero sua cor de fundo alterada para vermelho e todas as clulas com texto, para azul.
Criando a aplicao
Crie uma pasta raiz para a aplicao em seu disco, com o nome de JExcelApiStrutsExample. Essa pasta pode ser a pasta de seu projeto
no seu IDE predileto. Dentro dessa pasta, crie as seguintes subpastas:
src:para guardar os arquivos .java
lib:para guardar os arquivos .jar de dependncia
build:para guardar o build do ANT
etc:para guardar arquivos .properties
web/jsp: para guardar os JSPs
web/WEB-INF:para guardar deployment descriptors.
web/tld:para guardar arquivos de Tag library, como os que vem com o Struts.

1 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Copie os JARS necessrios do struts e da JExcel API para a pasta libs. Isso inclui o arquivo jxl.jar da JExcel API e todos os JARs
includos na pasta lib da distribuio do struts. Copie os arquivos TLD do struts para a pasta web/tld.
Crie um arquivo chamado index.jsp dentro da pasta web, conforme mostra a listagem 1. Esse o nico arquivo que ficar fora da pasta
JSP. Coloque o seguinte contedo no mesmo:
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<logic:redirect forward="welcome"/>
Listagem 01. Arquivo web/index.jsp
Tudo o que esse JSP faz redirecionar a pgina atual para o JSP definido como welcome na configurao do struts.
Como nossa aplicao bem simples, usaremos s mais um JSP. Crie um arquivo chamado Welcome.jsp na pasta web/jsp e ento
coloque nele o contedo da listagem 2.
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ taglib uri="/tags/struts-logic" prefix="logic"%>
<html:html>
<head>
<title>Exemplo JExcel API</title>
</head>
<html:base />
<body bgcolor="white">
<h3>Exemplo JExcel API</h3>
<p>Por favor, escolha o arquivo excel a ser analisdo</p>
<BR>
<html:form action="/FormatExcelAction.do" method="post"
enctype="multipart/form-data">
<html:file property="arquivo" title="Arquivo Excel" />
<html:submit title="Processar arquivo" />
</html:form>
</body>
</html:html>
Listagem 02. Arquivo web/jsp/Welcome.jsp
Esse JSP simplesmente usa algumas tag libs do Struts para renderizar um form HTML com um input do tipo arquivo e um boto submit.
Perceba que o form foi configurado para ser enviado via mtodo POST com a codificao de multipart. Isso far com que arquivo
selecionado seja enviado pelo prprio stream http (e no como parmetro da URL) e tambm far com que o arquivo binrio seja
transformado em texto para que possa ser enviado viu http, numa codificao MIME especfica para esse fim. O importante disso tudo
que quando o arquivo for recebido no lado do servidor, ser preciso codific-lo de volta para binrio.

2 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Antes de complicarmos mais, vejamos como ficam o web.xml e o struts-config.xml, nas listagens 3 e 4, respectivamente.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<display-name>JExcel Api Struts Example</display-name>
<!-- Standard Action Servlet Configuration (with debugging) -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

<!-- Standard Action Servlet Mapping -->


<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

<!-- The Usual Welcome File List -->


<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

3 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

<!-- Struts Tag Library Descriptors -->


<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-logic</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-logic.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-nested</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-nested.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-tiles</taglib-uri>
<taglib-location>/WEB-INF/tld/struts-tiles.tld</taglib-location>
</taglib>
</web-app>
Listagem 03. Arquivo web/WEB-INF/web.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
<!-- ================================================ Form Bean Definitions -->
<form-beans>
<form-bean name="FormatExcelForm" type="FormatExcelForm" />
</form-beans>
<!-- ========================================= Global Exception Definitions -->
<global-exceptions></global-exceptions>
<!-- =========================================== Global Forward Definitions -->
<global-forwards>

4 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

<forward name="welcome" path="/Welcome.do" />


</global-forwards>
<!-- =========================================== Action Mapping Definitions -->
<action-mappings>
<!-- Default "Welcome" action -->
<!-- Forwards to Welcome.jsp -->
<action path="/Welcome" forward="/WEB-INF/jsp/Welcome.jsp" />
<action path="/FormatExcelAction" type="FormatExcelAction"
name="FormatExcelForm" scope="request" validate="false"
input="/WEB-INF/jsp/Welcome.jsp">
<forward name="sucesso" path="/WEB-INF/jsp/Welcome.jsp" />
</action>
</action-mappings>
</struts-config>
Listagem 04. Arquivo web/WEB-INF/struts-config.xml
Nada demais, para quem j est acostumado com Struts, certo? Simplesmente configuramos o servlet controller do Struts no web.xml e
indicamos as TLDS. No struts-config.xml, configuramos o forward welcome, que havamos usado no index.jsp, para que redirecionasse
para o Welcome.jsp que criamos. Como esse ltimo fica dentro de WEB-INF, no podemos acess-lo diretamente, tornando nossa
aplicao mais bem feita em termos de segurana.
Tambm definimos uma action e um form. A action ser chamada pelo boto submit de nosso formulrio JSP e o form um bean que
conter o arquivo transmitido. O forward sucesso opcional, no vamos us-lo em nosso exemplo, est a somente para ficar claro
que no vamos sair nunca dessa pgina.
Vejamos como ficou o bean Form que usamos na listagem 5.
import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;
public class FormatExcelForm extends ActionForm {
private static final long serialVersionUID = 4294242013432948993L;
private FormFile arquivo;
public FormFile getArquivo() {
return arquivo;
}
public void setArquivo(FormFile arquivo) {
this.arquivo = arquivo;
}

5 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

}
Listagem 05. Arquivo src/FormatExcelForm.java
O serial version UID existe somente pelo fato do arquivo implementar a interface Serializable. Perceba que usamos a classe FormFile do
Struts. Essa classe faz parte do suporte que o Struts tem para upload de arquivos. Como temos uma propriedade desse tipo em nosso
form com o mesmo nome do campo tipo file do formulrio html (o nome da propriedade arquivo), o Struts automaticamente ir
decodificar o arquivo de volta para binrio, colocar nessa propriedade atravs do mtodo setter e fornecer o form como parmetro para
nossa action.
Vejamos como ficou a action na listagem 6:
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import
import
import
import
import
import
import

jxl.Cell;
jxl.CellType;
jxl.Workbook;
jxl.format.Colour;
jxl.write.WritableCell;
jxl.write.WritableCellFormat;
jxl.write.WritableWorkbook;

import
import
import
import
import

org.apache.struts.action.Action;
org.apache.struts.action.ActionForm;
org.apache.struts.action.ActionForward;
org.apache.struts.action.ActionMapping;
org.apache.struts.upload.FormFile;

public class FormatExcelAction extends Action {


public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
FormatExcelForm uploadForm = (FormatExcelForm) form;
FormFile arquivo = uploadForm.getArquivo();
try {
InputStream in = arquivo.getInputStream();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment; filename=sampleName.xls");

6 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

// Cria workbook novo a partir do recebido


WritableWorkbook w = Workbook.createWorkbook(response
.getOutputStream(), Workbook.getWorkbook(in));
for (int i = 0; i < w.getNumberOfSheets(); i++) {
for (int j = 0; j < w.getSheet(i).getColumns(); j++)
for (int k = 0; k < w.getSheet(i).getRows(); k++) {
Cell celula = w.getSheet(i).getCell(j, k);
System.out.println("celula sheet(" + i + ") [" + j
+ ", " + k + "] = " + celula);
if (celula.getType() == CellType.NUMBER) {
WritableCellFormat novoFormato = new WritableCellFormat(
celula.getCellFormat());
novoFormato.setBackground(Colour.RED);
WritableCell celulaModificavel = w.getSheet(i)
.getWritableCell(j, k);
celulaModificavel.setCellFormat(novoFormato);
} else if (celula.getType() == CellType.LABEL) {
WritableCellFormat novoFormato = new WritableCellFormat(
celula.getCellFormat());
novoFormato.setBackground(Colour.AQUA);
WritableCell celulaModificavel = w.getSheet(i)
.getWritableCell(j, k);
celulaModificavel.setCellFormat(novoFormato);
}
}
}
w.write();
w.close();
} catch (Exception e) {
throw new Exception("Erro ao transformar o arquivo: ", e);
} finally {
}
return null;
}
}
Listagem 06. Arquivo src/FormatExcelAction.java
Aqui que comea a entrar a JExcel API. Atravs do FormFile que o Struts j nos forneceu prontinho, s precisamos conseguir um
InputStream para ler os dados transmitidos. O que queremos fazer : criar um novo arquivo Excel a partir desse, para que seja
modificado e enviado como resposta.
Para tanto, obtemos tambm um OutputStream a partir do objeto response, usando o mtodo Response.getOutputStream(). Dessa

7 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

forma, usamos o InputStream para recuperar os dados transmitidos pela pgina e o OutputStream para transmitir os dados de volta.
Com a JExcel API, esse trabalho facilitado. O comando
WritableWorkbook w = Workbook.createWorkbook(
response.getOutputStream(), Workbook.getWorkbook(in));
cria um novo objeto WorkBook modificvel, que corresponde a uma planilha, no OutputStream, usando o arquivo transmitido como
base. Ento ns modificamos o Workbook e executamos os comandos
w.write();
w.close();
para escrever de fato o arquivo para a resposta http.
Perceba que setamos alguma propriedade importantes no objeto response:
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment; filename=sampleName.xls");
O primeiro comando dir ao browser que um arquivo Excel est sendo transmitido. A segunda linha indica que no estamos
redirecionando para uma outra pgina, mas sim para um download, de forma que o browser mostrar uma tela ao usurio perguntando
se ele deseja abrir ou salvar o arquivo sendo transmitido. Se escolher salvar, o arquivo ter o nome default de sampleName.xls.
Mas afinal, o que fizemos no arquivo Excel? Fizemos um loop (alis, trs loops) pelo arquivo, percorrendo cada uma de suas
worksheets. Para cada worksheet, usamos os comandos w.getSheet(i).getColumns() e w.getSheet(i).getRows() para percorrer por todas
as clulas de cada sheet. O tamanho de cada sheet retornado dependendo do contedo existente em suas clulas.
Para cada clula, verificamos o tipo do contedo. Se for um nmero, pintamos a cor de vermelho e, se for texto esttico (LABEL),
pintamos de azul.
Foi muito importante criarmos um objeto do tipo WriteableCell para modificarmos o formato. A JExcel API faz distino entre Cell e
WriteableCell, de forma que o ltimo herda do primeiro. S conseguimos modificar o arquivo porque criamos um objeto
WritableWorkbook a partir do arquivo de entrada no OutputStream do response. No possvel criar um objeto desses apenas a partir de
um InputStream, somente um Workbook simples, no modificvel.
Por ltimo, mas no menos importante, falta o arquivo de build, para construirmos nossa aplicao. Vejamos como ficou o nosso nas
listagens 7 e 8:
tomcat_home=G:/dev_env/Tomcat5/
tomcatlib=${tomcat_home}/common/lib
tomcatapps=${tomcat_home}/webapps
lib=lib
debug_on=true

8 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Listagem 07. Arquivo build/build.properties


<?xml version='1.0'?>
<project name="JExcelApiStrutsExample" default="package" basedir="..">
<property file="build/build.properties" />
<!-- set global properties for this build -->
<property name="webinf" value="web/WEB-INF" />
<property name="src" value="src" />
<property name="etc" value="etc" />
<property name="jsp" value="web/jsp" />
<property name="index.jsp" value="web/index.jsp" />
<property name="web.xml" value="${webinf}/web.xml" />
<property name="tld" value="web/tld" />
<property name="build" value="build/" />
<property name="appname" value="JExcelApiStrutsExample" />
<!-- generated folders -->
<property name="dist" value="dist" />
<property name="distbuild" value="${dist}/build" />
<property name="distwebinf" value="${distbuild}/WEB-INF" />
<property name="classes" value="${distwebinf}/classes" />
<property name="distjsp" value="${distwebinf}/jsp" />
<property name="disttld" value="${distwebinf}/tld" />
<property name="distlibs" value="${dist}/lib" />
<property name="warname" value="${dist}/${appname}.war" />
<target name="init">
<!-- Create the build directory structure used by compile -->
<mkdir dir="${dist}" />
<mkdir dir="${distbuild}" />
<mkdir dir="${distwebinf}" />
<mkdir dir="${classes}" />
<mkdir dir="${disttld}" />
<mkdir dir="${distjsp}" />
<!-- Create the directory for the jar files -->
<mkdir dir="${distlibs}" />
</target>
<target name="compile" depends="init">
<!-- run javac to compile the source files -->
<javac srcdir="${src}" destdir="${classes}" debug="${debug_on}">
<classpath>
<!-- include all jar files -->
<fileset dir="${tomcatlib}">

9 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

<include name="**/*.jar" />


</fileset>
<fileset dir="${lib}">
<include name="**/*.jar" />
</fileset>
</classpath>
</javac>
</target>
<target name="package" depends="compile">
<!-- Copy files to dist dir -->
<copy todir="${distlibs}/" flatten="true">
<fileset dir="${lib}">
<include name="**/*.jar" />
</fileset>
</copy>
<copy todir="${classes}/">
<fileset dir="${etc}">
<include name="**" />
</fileset>
</copy>
<copy todir="${disttld}/">
<fileset dir="${tld}">
<include name="**" />
</fileset>
</copy>
<copy todir="${distjsp}/">
<fileset dir="${jsp}">
<include name="**" />
</fileset>
</copy>
<copy tofile="${distbuild}/index.jsp" file="${index.jsp}" />
<copy todir="${distwebinf}/">
<fileset dir="${webinf}">
<include name="**.xml" />
</fileset>
</copy>
<!-- make a war file -->
<war destfile="${warname}" webxml="${web.xml}">
<fileset dir="${distbuild}">
<include name="**" />
</fileset>
<lib dir="${distlibs}">

10 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

<include name="**" />


</lib>
</war>
</target>
<target name="clean">
<!-- Delete the ${dist} directory tree -->
<delete dir="${dist}" />
</target>
<target name="deploy" depends="package">
<!-- Delete the ${dist} directory tree -->
<delete dir="${tomcatapps}/${appname}" />
<delete file="${tomcatapps}/${appname}.war" />
<copy todir="${tomcatapps}" file="${warname}" />
</target>
</project>
Listagem 08. Arquivo build/build.xml
O build.properties simplesmente configura algumas propriedades a serem usadas no build.xml, como a pasta onde se encontra instalado
o tomcat, pastas onde se encontram as libs e opes de debug. O segundo tem os targets para construo. O target init simplesmente
cria uma pasta dist dentro do projeto, o target compile compila os arquivos .Java e os joga para dentro de dist, o target package copie
os arquivos do projeto para uma estrutura de pastas de um arquivo war dentro de DIST e gera o WAR a partir da mesma. Finalmente,
existe um target deploy, que copia o WAR gerado para dentro da pasta webapps do Tomcat, apagando primeiro a verso anterior.
Vejamos como funciona a aplicao rodando:

11 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Figura 01. Entrando na aplicao

12 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Figura 02. Escolhendo um arquivo exemplo

13 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Figura 03. Arquivo exemplo original

14 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Figura 04. Clicando no boto submit

15 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

Figura 05. Arquivo exemplo depois do processamento


A ltima linha no foi modificada, pois era uma frmula. Poderamos t-la modificado tambm, bastante verificar seu tipo.
Agora sua vez! Baixe a JExcel API e manipule arquivos Excel a vontade em suas aplicaes web! At o prximo artigo.

por MARCELO ELIAS DEL VALLE


Marcelo Elias Del Valle (mvallebr@gmail.com) trabalha com Java e desenvolvimento de software em geral desde 1998, j tendo
trabalhado em vrias multinacionais relacionadas com o setor de TI em vrias reas, desde telecomunicaes e rea bancria at
desenvolvimento de software cientfico. Marcelo SCJP 1.4, tem SCEA parte 1 e superior incompleto em engenharia eltrica na USP. Usa
seu raro tempo livre estudando processos de desenvolvimento de software e imaginando arquiteturas possveis para jogos de
computador.

16 de 17

17/8/2013 20:13

Verso para impresso: Usando JExcel API numa aplicao WEB Struts

http://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=5547

www.devmedia.com.br/articles/viewcomp.asp?comp=5547

17 de 17

17/8/2013 20:13

S-ar putea să vă placă și