之前都是用csv文件的,简单暴力,但是未免太过弱小,很多东西实现不了,所以正好有时间学一学一个非常流行的excel处理库:jxl
读取excel
JExcelApi支持从文件和输入流读取excel表格。要想读取excel第一步你应该创建一个Workbook:
import java.io.File;
import java.util.Date;
import jxl.*;
...
Workbook workbook = Workbook.getWorkbook(new File("myfile.xls"));
(需要注意的是如果是来自输入流创建的表格,你需要把http的header信息删掉)
你声明了一个workbook后你就可以通过下面的方法来访问sheets(工作表的意思)了
sheets是从序号0开始的的,当然你也可以通过sheets的名字去取到sheets对象
Sheet sheet = workbook.getSheet(0);
取到了sheets对象之后,你就可以访问里面的元素了。可以使用getContents()方法返回string类型的内容,比如下面的例子,A1是一个文本类型,B2是数字类型,C2是日期类型,那么可以这么访问(可以看出cells是再封装了一层的,然后才调用getContents):
Cell a1 = sheet.getCell(0,0);
Cell b2 = sheet.getCell(1,1);
Cell c2 = sheet.getCell(2,1);
String stringa1 = a1.getContents();
String stringb2 = b2.getContents();
String stringc2 = c2.getContents();
// Do stuff with the strings etc
...
然而,如果你想要作为一个具体类型访问cells的话,比如数字、时间,那么就需要进行转换,并且提供了getType方法判断,避免转型错误。
String stringa1 = null;
double numberb2 = 0;
Date datec2 = null;
Cell a1 = sheet.getCell(0,0);
Cell b2 = sheet.getCell(1,1);
Cell c2 = sheet.getCell(2,1);
if (a1.getType() == CellType.LABEL)
{
LabelCell lc = (LabelCell) a1;
stringa1 = lc.getString();
}
if (b2.getType() == CellType.NUMBER)
{
NumberCell nc = (NumberCell) b2;
numberb2 = nc.getValue();
}
if (c2.getType() == CellType.DATE)
{
DateCell dc = (DateCell) c2;
datec2 = dc.getDate();
}
// Do stuff with dates and doubles
...
(cell对象分别转成对应的类型封装,再通过get方法获取java里面的对应类型)
当你完成所有工作后,使用close()方法释放内存
// Finished - close the workbook and free up memory
workbook.close();
写excel
这一部分是教你怎么写的简单无格式的数据,比如没有字体呀,小数点呀
和读excel一样,第一步是创建一个Workbook对象
import java.io.File;
import java.util.Date;
import jxl.*;
import jxl.write.*;
...
WritableWorkbook workbook = Workbook.createWorkbook(new File("output.xls"));
这句话是新创建一个名为output.xls的workbook对象,这个api也可以直接从客户端浏览器直接发送一个输出流给服务器,如果http的头信息设置正确的话,那么就会成功打开excel文件了。
下一步,就要为workbook创建sheet对象了,嗯可以看出是在第0个位置创建某个名字的sheet了。
WritableSheet sheet = workbook.createSheet("First Sheet", 0);
现在,就要把数据加到workbook里面,下面是把数据加到sheet里面去的简单实例,需要把一个文本写到a3位置,把数据3.14159写到d5位置
Label label = new Label(0, 2, "A label record");
sheet.addCell(label);
Number number = new Number(3, 4, 3.1459);
sheet.addCell(number);
这里有两点要注意的,第一点,cell的位置是表格信息的一部分了,所以你之后更新cell的内容的时候位置也无法更改。
另外一点,cell的位置是从0开始计数的。
一旦你写完新加的sheet和cell,请在workbook调用write()方法,然后关闭它,一定要调用write(),不然无法保存(类似output的flush方法了)。
...
// All sheets and cells added. Now write out the workbook
workbook.write();
workbook.close();
增加格式化信息
上面两部分只是JExcelApi的用法,然而现在我们的excel展示的是默认的字体,并且只保留小数点后三位,那么为了给excel增加格式化信息,我们可以使用重载的构造方法去给我们的cell增加额外的格式化信息,就是字体和样式了。
下面的代码演示了创建字体为arial,大小为10的文本
// Create a cell format for Arial 10 point font
WritableFont arial10font = new WritableFont(WritableFont.ARIAL, 10);
WritableCellFormat arial10format = new WritableCellFormat (arial10font);
// Create the label, specifying content and format
Label label2 = new Label(1,0, "Arial 10 point label", arial10format);
sheet.addCell(label2);
这样的话以后就可以复用这些样式了。
同时,WritableFont 也提供了多个重载的方法,以便适应不同的格式
// Create a cell format for Times 16, bold and italic
WritableFont times16font = new WritableFont(WritableFont.TIMES, 16, WritableFont.BOLD, true);
WritableCellFormat times16format = new WritableCellFormat (times16font);
// Create the label, specifying content and format
Label label4 = new Label(3,0, "Times 16 bold italic label", times16format);
sheet.addCell(label4);
格式化数字
数字类型的格式化结构是类似的,不同类型的格式已经定义好了
WritableCellFormat integerFormat = new WritableCellFormat (NumberFormats.INTEGER);
Number number2 = new Number(0, 4, 3.141519, integerFormat);
sheet.addCell(number2);
WritableCellFormat floatFormat = new WritableCellFormat (NumberFormats.FLOAT);
Number number3 = new Number(1, 4, 3.141519, floatFormat);
sheet.addCell(number3);
上面的例子是分别在A5和B5写入3.141519数字,但是因为格式类型不同,那么在A5展示的是3,而B5展示的是3.14
那么你也可以自定义格式的,下面例子就是自定义展示的数字位数
NumberFormat fivedps = new NumberFormat("#.#####");
WritableCellFormat fivedpsFormat = new WritableCellFormat(fivedps);
Number number4 = new Number(2, 4, 3.141519, fivedpsFormat);
sheet.addCell(number4);
当然,你也可以和我们定义文本的格式对象一块使用:
WritableCellFormat fivedpsFontFormat = new WritableCellFormat (times16font, fivedps);
Number number5 = new Number(3, 4, 3.141519, fivedpsFontFormat);
sheet.addCell(number5);
格式化日期
日期格式化也是类似数字类型格式化,使用自带的ava.text.SimpleDateFormat类格式化,同时jxl也预置了几个格式,定在在 jxl.write.DateFormat里面
// Get the current date and time from the Calendar object
Date now = Calendar.getInstance().getTime();
DateFormat customDateFormat = new DateFormat ("dd MMM yyyy hh:mm:ss");
WritableCellFormat dateFormat = new WritableCellFormat (customDateFormat);
DateTime dateCell = new DateTime(0, 6, now, dateFormat);
sheet.addCell(dateCell);
和数字格式化一样,文本格式化对象也可以应用在日期对象格式上
如果想要学习更多的扩展,那么去学习实例的Write.java吧面包括背景、颜色等的定义
复制和修改excel
这一部分是教你怎么更新excel里面的内容的
第一步还是读取excel
import java.io.File;
import java.util.Date;
import jxl.*;
import jxl.write.*;
...
Workbook workbook = Workbook.getWorkbook(new File("myfile.xls"));
下面这一步会创建一个上一部打开的excel副本,并转为可写的workbook对象
WritableWorkbook copy = Workbook.createWorkbook(new File("output.xls"), workbook);
那么使用上面的方法去复制一个副本修改excel表格,是很有效率的,因为不会把一些格式化的类型加载进来,但是这个方法会在内存创建两个workbook对象,会占用两倍的内存。
一旦我们转成可写的workbook对象,我们会就能够得到可写的cell对象。下面的代码就告诉你怎么修改cell了
WritableSheet sheet2 = copy.getSheet(1);
WritableCell cell = sheet2.getWritableCell(1, 2);
if (cell.getType() == CellType.LABEL)
{
Label l = (Label) cell;
l.setString("modified cell");
}
我们不需要调用add()方法,一旦cell加载到sheet内,那么里面内容就是可以修改了的,通过setXXX方法去修改。
然而,cell的格式化是不可变的,下面就是从新定义一个格式化对象咯
WritableSheet sheet2 = copy.getSheet(1);
WritableCell cell = sheet2.getWritableCell(2, 4);
NumberFormat fivedps = new NumberFormat("#.#####");
WritableCellFormat cellFormat = new WritableCellFormat(fivedps);
cell.setFormat(cellFormat);
一旦是可修改的workbook对象,那么也可以新增加cell。
最后别忘记了写和关闭的操作
...
// All cells modified/added. Now write out the workbook
copy.write();
copy.close();
嗯,官方还给我们提供了写的例子,在ReadWrite.java里面,但是不要修改jxlrwtest.xls这个文件,不然会运行不了。