Como se comento, el objetivo de esta primera fase será la de leer un fichero excel y crear un fichero de reporte con formato txt en el que se resumirán los datos que tenga el fichero excel.
El fichero excel que se empleará los generados por la agencia estatal de meteorología con la información de 24 de una determinada localidad http://www.aemet.es/es/eltiempo/observacion/ultimosdatos?k=mad&l=2462&w=0&datos=det, para los ejemplos se ha utilizado el fichero datos.xls, para leer los ficheros excel se empleará la librería jxl-2.6.jar, existen otras librerías para leer ficheros excel pero para este ejemplo jxl funciona perfectamente para más información
El proyecto tendrá la siguiente estructura.
En MicroProject.java se encuentra el método main, que será donde comenzará la ejecución.
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Comienza microProject");
String dirFichero="";
String dirReporte="";
EntradaDatos entradaDatos = new EntradaDatos();
ProcesaDatos procesaDatos = new ProcesaDatos();
try {
dirFichero=entradaDatos.entradaCampo("fichero excel");
dirReporte=entradaDatos.entradaCampo("fichero reporte");
Map
Files files = new Files(dirReporte);
files.crearReporte(resultados);
System.out.println("Fin de la ejecucion");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Se ha poducido un error al operar sobre los ficheros");
} catch (BiffException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Se ha poducido un error al leer el fichero excel");
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.println("Se ha producido un eror en la ejecucion");
}
}
Hay que tener en cuenta que el método main debe tener el mínimo código posible y limitarse a llamar a las distintas clases que es donde se sitúa el código.
Tanto el path al fichero excel como el nombre del fichero con el reporte lo indicaremos por la consola de entrada y el metodo "entradaCampo" responsable de esto se encuentra en la clase EntradaDatos.java
public String entradaCampo(String campo) {
// TODO Auto-generated method stub
campo = campo+": ";
System.out.print(campo);
Scanner sc = new Scanner(System.in);
return sc.next();
}
La variable campo tiene el texto que se va a escribir en la consola de salida y la clase Scanner lee la consola de entrada y devuelve lo que ponga, de forma que cuando en la clase main se escribe
dirFichero=entradaDatos.entradaCampo("fichero excel")
En la consola aparece
y el metodo entradaCampo() devolverá "C:\datos.xls" y queda almacenado en dirFichero de forma similar obtendrá el fichero del reporte.
En la clase ProcesaDatos se operará sobre los datos del fichero obteniendo, se obtendrá la media, el valor máximo y las palabra más repetida, con estos datos se rellenara un objeto Map con la información.
public Map
Map
ExcelOperations excelOperations = new ExcelOperations(dirFichero);
String [] fechas = excelOperations.readColumns(Globales.SHEET, 0);
resultados.put(Globales.FECHA, fechas);
String mediaTemperaturas = calculaMedia(excelOperations.readColumns(Globales.SHEET, 1)); resultados.put(Globales.MEDIA_TEMPERATURAS, mediaTemperaturas);
String maximaTemperaturas = calculaMaxima(excelOperations.readColumns(Globales.SHEET, 1)); resultados.put(Globales.MAXIMA_TEMPERATURAS, maximaTemperaturas);
String mediaVelocidadViento = calculaMedia(excelOperations.readColumns(Globales.SHEET, 2));resultados.put(Globales.MEDIA_VELOCIDAD_VIENTO, mediaVelocidadViento);
String maximaVelocidadViento = calculaMaxima(excelOperations.readColumns(Globales.SHEET, 2));
resultados.put(Globales.MAXIMA_VELOCIDAD_VIENTO, maximaVelocidadViento);
String direccionViento = masRepetida(excelOperations.readColumns(Globales.SHEET, 3));
resultados.put(Globales.DIRECCION_VIENTO, direccionViento);
String mediaRacha = calculaMedia(excelOperations.readColumns(Globales.SHEET, 4));
resultados.put(Globales.MEDIA_RACHA, mediaRacha);
String maximaRacha = calculaMaxima(excelOperations.readColumns(Globales.SHEET, 4));
resultados.put(Globales.MAXIMA_RACHA, maximaRacha);
String direccionRacha = masRepetida(excelOperations.readColumns(Globales.SHEET, 5));
resultados.put(Globales.DIRECCION_RACHA, direccionRacha);
String mediaPrecipitaciones = calculaMedia(excelOperations.readColumns(Globales.SHEET, 6));
resultados.put(Globales.MEDIA_PRECIPITACIONES, mediaPrecipitaciones);
String maximaPrecipitaciones = calculaMaxima(excelOperations.readColumns(Globales.SHEET, 6));
resultados.put(Globales.MAXIMA_PRECIPITACIONES, maximaPrecipitaciones);
String mediaPresion = calculaMedia(excelOperations.readColumns(Globales.SHEET, 7));
resultados.put(Globales.MEDIA_PRESION, mediaPresion);
String maximaPresion = calculaMaxima(excelOperations.readColumns(Globales.SHEET, 7));
resultados.put(Globales.MAXIMA_PRESION, maximaPresion);
String mediaTendencia = calculaMedia(excelOperations.readColumns(Globales.SHEET, 8));
resultados.put(Globales.MEDIA_TENDENCIA, mediaTendencia);
String maximaTendencia = calculaMaxima(excelOperations.readColumns(Globales.SHEET, 8));
resultados.put(Globales.MAXIMA_TENDENCIA, maximaTendencia);
String mediaHumedad = calculaMedia(excelOperations.readColumns(Globales.SHEET, 9));
esultados.put(Globales.MEDIA_HUMEDAD, mediaHumedad);
String maximaHumedad = calculaMaxima(excelOperations.readColumns(Globales.SHEET, 9));
resultados.put(Globales.MAXIMA_HUMEDAD, maximaHumedad);
return resultados;
}
En el metodo creaResultados() rellena un objeto Map donde se almacena una dupla key, value, se han utilizado una serie de constantes globales de manera que si hay que cambiar el valor de una key se que se utiliza en varios lugares, si se emplean globales basta con modificar el valor de la contante global.
los metodo calculaMedia(), calculaMaxima() y masRepetida() son simples algoritmos para calcular los distintos valores. no están muy pesados por lo que seguramente se podrá hacer de alguna forma más optima, como son pocos datos no es muy importante, pero cuando hay muchos datos este tipo de operaciones hay que optimizarlos porque son los causantes de que muchas aplicaciones se ralenticen mucho
public String calculaMedia(String[] datos){
int longitud = datos.length;
float suma=0;
for (int i=0;i suma = suma+Float.parseFloat(datos[i].replace(',', '.'));
}
float media = suma/longitud;
return String.valueOf(media);
}
int longitud = datos.length;
float suma=0;
for (int i=0;i
}
float media = suma/longitud;
return String.valueOf(media);
}
public String masRepetida(String [] datos){
List
String dato="";
boolean esta=false;
int repeticiones=0;
int auxRepeticiones=0;
String repetida="";
for(int i=0;i
if(!lDatos.isEmpty()){
for(int k=0;k
esta=true;
}
}
}else{
lDatos.add(dato);
}
if(!esta){
lDatos.add(dato);
for(int j=0;j
auxRepeticiones++;
}
}
if(auxRepeticiones>repeticiones){
repeticiones=auxRepeticiones;
auxRepeticiones=0;
repetida=dato;
}
}
esta=false;
}
return repetida;
}
public String calculaMaxima(String [] datos){
float dato=0;
float maximo=-100000000;
for (int i=0;i
if(dato>maximo)
maximo=dato;
}
return String.valueOf(maximo);
}
public class ExcelOperations {
private Workbook archivoExcel;
public ExcelOperations(String excel_file) throws BiffException, IOException{
archivoExcel = Workbook.getWorkbook(new File(excel_file));
}
public String[] readColumns(String sheet_name, int column_num){
Sheet sheet = archivoExcel.getSheet(sheet_name);
Cell[] celdas = sheet.getColumn(column_num);
String [] datos = new String[celdas.length-4];
for(int i = 0;i datos[i]=celdas[i+4].getContents();
}
return datos;
}
public Workbook getArchivoExcel(){
return this.archivoExcel;
}
}
private Workbook archivoExcel;
public ExcelOperations(String excel_file) throws BiffException, IOException{
archivoExcel = Workbook.getWorkbook(new File(excel_file));
}
public String[] readColumns(String sheet_name, int column_num){
Sheet sheet = archivoExcel.getSheet(sheet_name);
Cell[] celdas = sheet.getColumn(column_num);
String [] datos = new String[celdas.length-4];
for(int i = 0;i
}
return datos;
}
public Workbook getArchivoExcel(){
return this.archivoExcel;
}
}
En el constructor se crea el objeto Wokbook a partir del path que se ha obtenido anteriormente por la consola de entrada, el metodo readColumns() devuelve un array con los valores de la columna que indiquemos (int column_num) de la pestaña que se especifique (String sheet_name), para este ejemplo será un valor global porque siempre es el mismo ("Últimos Datos AEMET"), hay que tener en cuenta que este método esta pensado para un fichero excel particular, si se quiere emplear otro excel habría que hacer algún ajuste.
Por ultimo, una vez se tiene el el objeto Map con los resultados es el momento de crear el fichero con el reporte, esto se realiza en la clase Files.
public class Files {
String fileName;
public Files(String filename){
this.fileName=filename;
}
public void crearReporte(Map resultados) throws IOException{
BufferedWriter bw;
bw =new BufferedWriter(new FileWriter(fileName));
String[] fechas = (String[])resultados.get(Globales.FECHA);
bw.newLine();
bw.write(fechas[fechas.length-1]+" - "+fechas[0]);
bw.newLine();
bw.newLine();
bw.write("TEMPERATURAS: "+"\r\n");
bw.flush();
bw.write("Temperatura media: "+resultados.get(Globales.MEDIA_TEMPERATURAS)+" ºC"+"\r\n");
bw.write("Temperatura máxima: "+resultados.get(Globales.MAXIMA_TEMPERATURAS)+" ºC"+"\r\n");
bw.flush();
bw.newLine();
bw.write("VIENTO: "+"\r\n");
bw.flush();
String fileName;
public Files(String filename){
this.fileName=filename;
}
public void crearReporte(Map resultados) throws IOException{
BufferedWriter bw;
bw =new BufferedWriter(new FileWriter(fileName));
String[] fechas = (String[])resultados.get(Globales.FECHA);
bw.newLine();
bw.write(fechas[fechas.length-1]+" - "+fechas[0]);
bw.newLine();
bw.newLine();
bw.write("TEMPERATURAS: "+"\r\n");
bw.flush();
bw.write("Temperatura media: "+resultados.get(Globales.MEDIA_TEMPERATURAS)+" ºC"+"\r\n");
bw.write("Temperatura máxima: "+resultados.get(Globales.MAXIMA_TEMPERATURAS)+" ºC"+"\r\n");
bw.flush();
bw.newLine();
bw.write("VIENTO: "+"\r\n");
bw.flush();
bw.write("Velocidad media del viento: "+ resultados.get(Globales.MEDIA_VELOCIDAD_VIENTO)+" km/h"+"\r\n");
bw.write("Velocidad máxima del viento: "+resultados.get(Globales.MAXIMA_VELOCIDAD_VIENTO)+" km/h"+"\r\n");
bw.flush();
bw.write("Dirección del viento: "+resultados.get(Globales.DIRECCION_VIENTO)+"\r\n");
bw.flush();
bw.newLine();
bw.write("RACHA: "+"\r\n");
bw.flush();
bw.write("Racha media: "+resultados.get(Globales.MEDIA_RACHA)+" km/h"+"\r\n");
bw.write("Racha máxima: "+resultados.get(Globales.MAXIMA_RACHA)+" km/h"+"\r\n");
bw.flush();
bw.write("Dirección de la racha; "+resultados.get(Globales.DIRECCION_RACHA)+"\r\n");
bw.flush();
bw.newLine();
bw.write("PRECIPITACIONES: "+"\r\n");
bw.flush();
bw.write("Precipitaciones media: "+resultados.get(Globales.MEDIA_PRECIPITACIONES)+" mm"+"\r\n");
bw.write("Precipitaciones máxima: "+resultados.get(Globales.MAXIMA_PRECIPITACIONES)+" mm"+"\r\n");
bw.flush();
bw.newLine();
bw.write("PRESION: "+"\r\n");
bw.flush();
bw.write("Presión media: "+resultados.get(Globales.MEDIA_PRESION)+" hPa"+"\r\n");
bw.write("Prexión máxima: "+resultados.get(Globales.MAXIMA_PRESION)+" hPa"+"\r\n");
bw.flush();
bw.newLine();
bw.write("TENDENCIA: "+"\r\n");
bw.flush();
bw.write("Tendencia media: "+resultados.get(Globales.MEDIA_TENDENCIA)+" hPa"+"\r\n");
bw.write("Tendencia máxima: "+resultados.get(Globales.MAXIMA_TENDENCIA)+" hPa"+"\r\n");
bw.flush();
bw.newLine();
bw.write("HUMEDAD: "+"\r\n");
bw.flush();
bw.write("Humedad media: "+resultados.get(Globales.MEDIA_HUMEDAD)+" %"+"\r\n");
bw.write("Humedad máxima: "+resultados.get(Globales.MAXIMA_HUMEDAD)+" %"+"\r\n");
bw.flush();
bw.close();
}
}
bw.write("Velocidad máxima del viento: "+resultados.get(Globales.MAXIMA_VELOCIDAD_VIENTO)+" km/h"+"\r\n");
bw.flush();
bw.write("Dirección del viento: "+resultados.get(Globales.DIRECCION_VIENTO)+"\r\n");
bw.flush();
bw.newLine();
bw.write("RACHA: "+"\r\n");
bw.flush();
bw.write("Racha media: "+resultados.get(Globales.MEDIA_RACHA)+" km/h"+"\r\n");
bw.write("Racha máxima: "+resultados.get(Globales.MAXIMA_RACHA)+" km/h"+"\r\n");
bw.flush();
bw.write("Dirección de la racha; "+resultados.get(Globales.DIRECCION_RACHA)+"\r\n");
bw.flush();
bw.newLine();
bw.write("PRECIPITACIONES: "+"\r\n");
bw.flush();
bw.write("Precipitaciones media: "+resultados.get(Globales.MEDIA_PRECIPITACIONES)+" mm"+"\r\n");
bw.write("Precipitaciones máxima: "+resultados.get(Globales.MAXIMA_PRECIPITACIONES)+" mm"+"\r\n");
bw.flush();
bw.newLine();
bw.write("PRESION: "+"\r\n");
bw.flush();
bw.write("Presión media: "+resultados.get(Globales.MEDIA_PRESION)+" hPa"+"\r\n");
bw.write("Prexión máxima: "+resultados.get(Globales.MAXIMA_PRESION)+" hPa"+"\r\n");
bw.flush();
bw.newLine();
bw.write("TENDENCIA: "+"\r\n");
bw.flush();
bw.write("Tendencia media: "+resultados.get(Globales.MEDIA_TENDENCIA)+" hPa"+"\r\n");
bw.write("Tendencia máxima: "+resultados.get(Globales.MAXIMA_TENDENCIA)+" hPa"+"\r\n");
bw.flush();
bw.newLine();
bw.write("HUMEDAD: "+"\r\n");
bw.flush();
bw.write("Humedad media: "+resultados.get(Globales.MEDIA_HUMEDAD)+" %"+"\r\n");
bw.write("Humedad máxima: "+resultados.get(Globales.MAXIMA_HUMEDAD)+" %"+"\r\n");
bw.flush();
bw.close();
}
}
El mtodo creaReporte() crea el fichero a partir del objeto Map hay distintos formas de escribir en ficheros pero todas son muy similares, el fichero reporte.txt tendrá el siguiente aspecto:
29/10/2012 14:00 - 30/10/2012 13:00
TEMPERATURAS:
Temperatura media: 0.6041666 ºC
Temperatura máxima: 8.0 ºC
VIENTO:
Velocidad media del viento: 22.416666 km/h
Velocidad máxima del viento: 32.0 km/h
Dirección del viento: Sur
RACHA:
Racha media: 34.291668 km/h
Racha máxima: 47.0 km/h
Dirección de la racha; Sur
PRECIPITACIONES:
Precipitaciones media: 0.4333333 mm
Precipitaciones máxima: 3.8 mm
PRESION:
Presión media: 801.7583 hPa
Prexión máxima: 806.1 hPa
TENDENCIA:
Tendencia media: -1.2083334 hPa
Tendencia máxima: -0.4 hPa
HUMEDAD:
Humedad media: 85.791664 %
Humedad máxima: 100.0 %
TEMPERATURAS:
Temperatura media: 0.6041666 ºC
Temperatura máxima: 8.0 ºC
VIENTO:
Velocidad media del viento: 22.416666 km/h
Velocidad máxima del viento: 32.0 km/h
Dirección del viento: Sur
RACHA:
Racha media: 34.291668 km/h
Racha máxima: 47.0 km/h
Dirección de la racha; Sur
PRECIPITACIONES:
Precipitaciones media: 0.4333333 mm
Precipitaciones máxima: 3.8 mm
PRESION:
Presión media: 801.7583 hPa
Prexión máxima: 806.1 hPa
TENDENCIA:
Tendencia media: -1.2083334 hPa
Tendencia máxima: -0.4 hPa
HUMEDAD:
Humedad media: 85.791664 %
Humedad máxima: 100.0 %
Con esto termina el resumen de la primera parte del proyecto espero que haya quedado claro, pero la mejor forma de entender como funciona es descargar el proyecto depurarlo, entenderlo y modificarlo para casos particlares etc.
El fichero comprimido se puede descargar aquí se puede descomprimir en el workspace e importarlo desde eclipse luego simplemete hay que ejecutarlo, hay que tener en cuenta que tiene que estra la libreria correctamente y que hay que tener el fichero excel con los datos, como recomendacion es mejor copiarlo en c: o en d: de forma que cuando pida en path solo hay que poner c:\datos.xls
Para cualquier duda aquí estamos!!!!!