java控制Office套件API(POI加JXL)网上摘录留工作备查
在Java中,已经有很多对于Word、Excel的开源的解决方案,其中比较出色的是 Apache的Jakata项目的POI子项目。该项目的官方网站是http://jakarta.apache.org/poi/。POI包括一系列的API,它们可以操作基于 MicroSoft OLE 2 Compound Document Format的各种格式文件,可以通过这些API在Java中读写Excel、Word等文件。POI是完全的Java Excel和Java Word解决方案。POI子项目包括:POIFS、HSSF、HDF、HPSF。
|
子项目名 |
说明 |
|
POIFS(POI File System) |
POIFS是POI项目中最早的最基础的一个模块,是Java到OLE 2 Compound Document Format的接口,支持读写功能,所有的其他项目都依赖与该项目。 |
|
HSSF(Horrible Spreadsheet Format) |
HSSF是Java到Microsoft Excel 97(-2002)文件的接口,支持读写功能 |
|
HWPF(Horrible Word Processing Format) |
HWPF是Java到Microsoft Word 97文件的接口,支持读写功能,但目前该模块还处于刚开始开发阶段,只能实现一些简单文件的操作,在后续版本中,会提供更强大的支持 |
|
HPSF(Horrible Property Set Format) |
HPSF 是Java到OLE 2 Compound Document Format文件的属性设置的接口,属性设置通常用来设置文档的属性(标题,作者,最后修改日期等),还可以设置用户定义的属性。HPSF支持读写功能,当前发布版本中直支持读功能。 |
7.3.1 对Excel的处理类
下面通过HSSF提供的接口对Excel文件经 行处理。首先需要下载POI的包,可以到apache的官方网站下载,地址为:http://apache.justdn.org/jakarta /poi/,本书采用的是poi-2.5.1-final-20040804.jar,读者可以下载当前的稳定版本。把下载的包按照前面介绍的方式加入 Build Path,然后新建一个ch7.poi包,并创建一个ExcelReader类。
ExcelReader类可以读取一个XLS文件,然后将其内容逐行提取出来,写入文本文件。其代码如下。
代码7.6
public class ExcelReader {
// 创建文件输入流
private BufferedReader reader = null;
// 文件类型
private String filetype;
// 文件二进制输入流
private InputStream is = null;
// 当前的Sheet
private int currSheet;
// 当前位置
private int currPosition;
// Sheet数量
private int numOfSheets;
// HSSFWorkbook
HSSFWorkbook workbook = null;
// 设置Cell之间以空格分割
private static String EXCEL_LINE_DELIMITER = " ";
// 设置最大列数
private static int MAX_EXCEL_COLUMNS = 64;
// 构造函数创建一个ExcelReader
public ExcelReader(String inputfile) throws IOException, Exception {
// 判断参数是否为空或没有意义
if (inputfile == null || inputfile.trim().equals("")) {
throw new IOException("no input file specified");
}
// 取得文件名的后缀名赋值给filetype
this.filetype = inputfile.substring(inputfile.lastIndexOf(".") + 1);
// 设置开始行为0
currPosition = 0;
// 设置当前位置为0
currSheet = 0;
// 创建文件输入流
is = new FileInputStream(inputfile);
// 判断文件格式
if (filetype.equalsIgnoreCase("txt")) {
// 如果是txt则直接创建BufferedReader读取
reader = new BufferedReader(new InputStreamReader(is));
}
else if (filetype.equalsIgnoreCase("xls")) {
// 如果是Excel文件则创建HSSFWorkbook读取
workbook = new HSSFWorkbook(is);
// 设置Sheet数
numOfSheets = workbook.getNumberOfSheets();
}
else {
throw new Exception("File Type Not Supported");
}
}
// 函数readLine读取文件的一行
public String readLine() throws IOException {
// 如果是txt文件则通过reader读取
if (filetype.equalsIgnoreCase("txt")) {
String str = reader.readLine();
// 空行则略去,直接读取下一行
while (str.trim().equals("")) {
str = reader.readLine();
}
return str;
}
// 如果是XLS文件则通过POI提供的API读取文件
else if (filetype.equalsIgnoreCase("xls")) {
// 根据currSheet值获得当前的sheet
HSSFSheet sheet = workbook.getSheetAt(currSheet);
// 判断当前行是否到但前Sheet的结尾
if (currPosition > sheet.getLastRowNum()) {
// 当前行位置清零
currPosition = 0;
// 判断是否还有Sheet
while (currSheet != numOfSheets - 1) {
// 得到下一张Sheet
sheet = workbook.getSheetAt(currSheet + 1);
// 当前行数是否已经到达文件末尾
if (currPosition == sheet.getLastRowNum()) {
// 当前Sheet指向下一张Sheet
currSheet++;
continue;
} else {
// 获取当前行数
int row = currPosition;
currPosition++;
// 读取当前行数据
return getLine(sheet, row);
}
}
return null;
}
// 获取当前行数
int row = currPosition;
currPosition++;
// 读取当前行数据
return getLine(sheet, row);
}
return null;
}
// 函数getLine返回Sheet的一行数据
private String getLine(HSSFSheet sheet, int row) {
// 根据行数取得Sheet的一行
HSSFRow rowline = sheet.getRow(row);
// 创建字符创缓冲区
StringBuffer buffer = new StringBuffer();
// 获取当前行的列数
int filledColumns = rowline.getLastCellNum();
HSSFCell cell = null;
// 循环遍历所有列
for (int i = 0; i < filledColumns; i++) {
// 取得当前Cell
cell = rowline.getCell((short) i);
String cellvalue = null;
if (cell != null) {
// 判断当前Cell的Type
switch (cell.getCellType()) {
// 如果当前Cell的Type为NUMERIC
case HSSFCell.CELL_TYPE_NUMERIC: {
// 判断当前的cell是否为Date
if (HSSFDateUtil.isCellDateFormatted(cell)) {
// 如果是Date类型则,取得该Cell的Date值
Date date = cell.getDateCellValue();
// 把Date转换成本地格式的字符串
cellvalue = cell.getDateCellValue().toLocaleString();
}
// 如果是纯数字
else {
// 取得当前Cell的数值
Integer num = new Integer((int) cell
.getNumericCellValue());
cellvalue = String.valueOf(num);
}
break;
}
// 如果当前Cell的Type为STRIN
case HSSFCell.CELL_TYPE_STRING:
// 取得当前的Cell字符串
cellvalue = cell.getStringCellValue().replaceAll("'", "''");
break;
// 默认的Cell值
default:
cellvalue = " ";
}
} else {
cellvalue = "";
}
// 在每个字段之间插入分割符
buffer.append(cellvalue).append(EXCEL_LINE_DELIMITER);
}
// 以字符串返回该行的数据
return buffer.toString();
}
// close函数执行流的关闭操作
public void close() {
// 如果is不为空,则关闭InputSteam文件输入流
if (is != null) {
try {
is.close();
} catch (IOException e) {
is = null;
}
}
// 如果reader不为空则关闭BufferedReader文件输入流
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
reader = null;
}
}
}
}
7.3.2 ExcelReader的运行效果
下面创建一个main函数,用来测试上面的ExcelReader类,代码如下。
代码7.7
public static void main(String[] args) {
try{
ExcelReader er=new ExcelReader("c:\\xp.xls");
String line=er.readLine();
while(line != null){
System.out.println(line);
line=er.readLine();
}
er.close();
}catch(Exception e){
e.printStackTrace();
}
}
main函数先创建一个ExcelReader类,然后调用它提供的接口readLine,对XLS文件进行读取,打印到控制台,处理前的XLS文件。
写文件
package IO.file;
imp
ort java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.Region;
public class ExcelFile {
public void writeExcel(String fileName) {
// 目标文件
File file = new File(fileName);
FileOutputStream fOut = null;
// 创建excel工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
// 在excel工作簿中创建一个工作表,其名是默认
// 也可以指定工作表的名字
HSSFSheet sheet = workbook.createSheet("Test_Table");
// 创建字体,红色、粗体
HSSFFont font = workbook.createFont();
font.setColor(HSSFFont.COLOR_RED);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 设置字体
HSSFFont font = workbook.createFont();
font.setFontHeightInPoints(( short ) 20 ); // 字体高度
font.setColor(HSSFFont.COLOR_RED); // 字体颜色
font.setFontName( " 黑体 " ); // 字体
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 宽度
font.setItalic( true ); // 是否使用斜体
font.setStrikeout(true); // 是否使用划线
// 设置单元格类型
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFont(font);
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平布局:居中
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); //垂直居中
cellStyle.setWrapText( true );
// 添加单元格注释
// 创建HSSFPatriarch对象,HSSFPatriarch是所有注释的容器.
HSSFPatriarch patr = sheet.createDrawingPatriarch();
// 定义注释的大小和位置,详见文档
HSSFComment comment = patr.createComment( new HSSFClientAnchor( 0 , 0 , 0 , 0 , ( short ) 4 , 2 , ( short ) 6 , 5 ));
// 设置注释内容
comment.setString( new HSSFRichTextString( " 可以在POI中添加注释! " ));
// 设置注释作者. 当鼠标移动到单元格上是可以在状态栏中看到该内容.
comment.setAuthor( " Xuys. " );
// 创建单元格
HSSFCell cell = row.createCell(( short ) 1 );
HSSFRichTextString hssfString = new HSSFRichTextString( " Hello World! " );
cell.setCellValue(hssfString); // 设置单元格内容
cell.setCellStyle(cellStyle); // 设置单元格样式
cell.setCellType(HSSFCell.CELL_TYPE_STRING); // 指定单元格格式:数值、公式或字符串
cell.setCellComment(comment); // 添加注释
// 格式化数据
row = sheet.createRow(( short ) 2 );
cell = row.createCell(( short ) 2 );
cell.setCellValue( 11111.25 );
cellStyle = workbook.createCellStyle();
cellStyle.setDataFormat(format.getFormat( " 0.0 " ));
cell.setCellStyle(cellStyle);
row = sheet.createRow(( short ) 3 );
cell = row.createCell(( short ) 3 );
cell.setCellValue( 9736279.073 );
cellStyle = workbook.createCellStyle();
cellStyle.setDataFormat(format.getFormat( " #,##0.0000 " ));
cell.setCellStyle(cellStyle);
sheet.autoSizeColumn(( short ) 0 ); // 调整第一列宽度
sheet.autoSizeColumn(( short ) 1 ); // 调整第二列宽度
sheet.autoSizeColumn(( short ) 2 ); // 调整第三列宽度
sheet.autoSizeColumn(( short ) 3 ); // 调整第四列宽度
// 创建单元格的格式,如居中、左对齐等
HSSFCellStyle cellStyle = workbook.createCellStyle();
// 水平方向居中对齐
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 垂直方向居中对齐
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 设置字体
cellStyle.setFont(font);
// 下面将建立一个4行3列的表,第一行是表头
int rowNum = 0; // 行标
int colNum = 0; // 列标
// 设置表头信息
HSSFRow row = sheet.createRow(rowNum);
HSSFCell cell = null; // 创建单元格
for(colNum = 0; colNum < 5; colNum++) {
// 在当前行的colNum列上创建单元格
cell = row.createCell((short)colNum);
// 定义单元格为字符类型,也可以指定为日期类型、数字类型等
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
// 定义编码方面,为了支持中文,这里使用utf-16
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellStyle(cellStyle);
cell.setCellValue("表头名" + colNum);
}
rowNum++;
for(; rowNum < 5; rowNum++) {
// 新建第rowNum行
row = sheet.createRow(rowNum);
for(colNum = 0; colNum < 5; colNum++) {
cell = row.createCell((short)colNum);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellStyle(cellStyle);
cell.setCellValue("值-" + rowNum + "-" + colNum);
}
}
// 合并单元格
// 先创建2行5列的单元格,然后将这些单元格合并成2个大的单元格
rowNum = 5;
for(; rowNum < 7; rowNum++) {
row = sheet.createRow((short)rowNum);
for(colNum = 0; colNum < 5; colNum++)
cell = row.createCell((short)colNum);
}
// 建立第一个大单元格,高度是2,宽度也是2
rowNum = 5;
colNum = 0;
Region region = new Region(rowNum, (short)colNum, (rowNum + 1), (short)(colNum + 1));
sheet.addMergedRegion(region);
// 获得第一个大单元格
cell = sheet.getRow(rowNum).createCell((short)colNum);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellStyle(cellStyle);
cell.setCellValue("第一个大单元格");
// 建立第二个大单元格,高度是2,宽度是3
colNum = 2;
region = new Region(rowNum, (short)colNum, (rowNum + 1), (short)(colNum + 2));
sheet.addMergedRegion(region);
// 获得第二个大单元格
cell = sheet.getRow(rowNum).createCell((short)colNum);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellStyle(cellStyle);
cell.setCellValue("第二个大单元格");
// 工作簿建立完成,下面将工作簿存入文件
// 建立一个文件输出流
try {
fOut = new FileOutputStream(file);
workbook.write(fOut);
fOut.flush();
System.out.println("Excel文件生成成功!文件名:" + file.getAbsolutePath());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fOut != null)
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void readExcel(String fileName) {
File file = new File(fileName);
FileInputStream in = null;
try {
// 创建Excel工作簿文件的引用
in = new FileInputStream(file);
HSSFWorkbook workbook = new HSSFWorkbook(in);
// 创建对工作表的引用
// 这里使用按名引用
HSSFSheet sheet = workbook.getSheet("Test_Table");
// 也可以使用getSheetAt(int index)按索引引用
// 在Excel文档中,第一张工作表的默认引用是0,其语句是
// HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = null;
HSSFCell cell = null;
int rowNum = 0;
int colNum = 0;
for(; rowNum < 5; rowNum++) {
row = sheet.getRow(rowNum);
for(colNum = 0; colNum < 5; colNum++) {
cell = row.getCell(colNum);
System.out.print(cell.getStringCellValue() + "\t");
}
System.out.println();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExcelFile excel = new ExcelFile();
String fileName = "c:/temp.xls";
excel.writeExcel(fileName);
excel.readExcel(fileName);
}
}
jxl是一个韩国人写的java操作excel的工具, 在开源世界中,有两套比较有影响的API可供使用,一个是POI,一个是 jExcelAPI。其中功能相对POI比较弱一点。但jExcelAPI对中文支持非常好,API是纯Java的, 并不依赖Windows系统,即使 运行在Linux下,它同样能够正确的处理Excel文件。 另外需要说明的是,这套API对图形和图表的支持很有限,而且仅仅识别PNG格式。
使用如下:
搭建环境
将下载后的文件解包,得到jxl.jar,放入classpath,安装就完成了。
基本操作
一、创建文件
拟生成一个名为“test.xls”的Excel文件,其中第一个工作表被命名为
“第一页”,大致效果如下:
基本操作
一、创建文件
拟生成一个名为“test.xls”的Excel文件,其中第一个工作表被命名为
“第一页”,大致效果如下:
package test;
//生成Excel的类
import java.io.File;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
public class CreateExcel {
public static void main(String args[]) {
try {
// 打开文件
WritableWorkbook book = Workbook.createWorkbook(new File("test.xls"));
// 生成名为“第一页”的工作表,参数0表示这是第一页
WritableSheet sheet = book.createSheet("第一页", 0);
// 在Label对象的构造子中指名单元格位置是第一列第一行(0,0)
// 以及单元格内容为test
Label label = new Label(0, 0, "test");
// 将定义好的单元格添加到工作表中
sheet.addCell(label);
/*
* 生成一个保存数字的单元格 必须使用Number的完整包路径,否则有语法歧义 单元格位置是第二列,第一行,值为789.123
*/
jxl.write.Number number = new jxl.write.Number(1, 0, 555.12541);
sheet.addCell(number);
// 写入数据并关闭文件
book.write();
book.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
编译执行后,会产生一个Excel文件。
三、读取文件
以刚才我们创建的Excel文件为例,做一个简单的读取操作,程序代码如下:
package test;
//读取Excel的类
import java.io.File;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
public class ReadExcel {
public static void main(String args[]) {
try {
Workbook book = Workbook.getWorkbook(new File("test.xls"));
// 获得第一个工作表对象
Sheet sheet = book.getSheet(0);
// 得到第一列第一行的单元格
Cell cell1 = sheet.getCell(0, 0);
String result = cell1.getContents();
System.out.println(result);
book.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
程序执行结果:test
四、修改文件
利用jExcelAPI可以修改已有的Excel文件,修改Excel文件的时候,除了打开文件的方式不同之外,
其他操作和创建Excel是一样的。下面的例子是在我们已经生成的Excel文件中添加一个工作表:
package test;
import java.io.File;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
public class UpdateExcel {
public static void main(String args[]) {
try {
// Excel获得文件
Workbook wb = Workbook.getWorkbook(new File("test.xls"));
// 打开一个文件的副本,并且指定数据写回到原文件
WritableWorkbook book = Workbook.createWorkbook(new File("test.xls"),
wb);
// 添加一个工作表
WritableSheet sheet = book.createSheet("第二页", 1);
sheet.addCell(new Label(0, 0, "第二页的测试数据"));
book.write();
book.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
其他操作
一、 数据格式化
在Excel中不涉及复杂的数据类型,能够比较好的处理字串、数字和日期已经能够满足一般的应用。
1、 字串格式化
字符串的格式化涉及到的是字体、粗细、字号等元素,这些功能主要由WritableFont和
WritableCellFormat类来负责。假设我们在生成一个含有字串的单元格时,使用如下语句,
为方便叙述,我们为每一行命令加了编号:
WritableFont font1=
new WritableFont(WritableFont.TIMES,16,WritableFont.BOLD); ①
WritableCellFormat format1=new WritableCellFormat(font1); ②
Label label=new Label(0,0,”data 4 test”,format1) ③

其中①指定了字串格式:字体为TIMES,字号16,加粗显示。WritableFont有非常丰富的
构造子,供不同情况下使用,jExcelAPI的java-doc中有详细列表,这里不再列出。
②处代码使用了WritableCellFormat类,这个类非常重要,通过它可以指定单元格的各种
属性,后面的单元格格式化中会有更多描述。
③处使用了Label类的构造子,指定了字串被赋予那种格式。
在WritableCellFormat类中,还有一个很重要的方法是指定数据的对齐方式,比如针对我们
上面的实例,可以指定:
//把水平对齐方式指定为居中
format1.setAlignment(jxl.format.Alignment.CENTRE);
//把垂直对齐方式指定为居中
format1.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE);
二、单元格操作
Excel中很重要的一部分是对单元格的操作,比如行高、列宽、单元格合并等,所幸jExcelAPI
提供了这些支持。这些操作相对比较简单,下面只介绍一下相关的API。
1、 合并单元格
WritableSheet.mergeCells(int m,int n,int p,int q); 
//作用是从(m,n)到(p,q)的单元格全部合并,比如:
WritableSheet sheet=book.createSheet(“第一页”,0);
//合并第一列第一行到第六列第一行的所有单元格
sheet.mergeCells(0,0,5,0);
合并既可以是横向的,也可以是纵向的。合并后的单元格不能再次进行合并,否则会触发异常。
2、 行高和列宽
WritableSheet.setRowView(int i,int height);
//作用是指定第i+1行的高度,比如:
//将第一行的高度设为200
sheet.setRowView(0,200);
WritableSheet.setColumnView(int i,int width);
//作用是指定第i+1列的宽度,比如:
//将第一列的宽度设为30
sheet.setColumnView(0,30);
jExcelAPI还有其他的一些功能,比如插入图片等,这里就不再一一介绍,读者可以自己探索。
其中:如果读一个excel,需要知道它有多少行和多少列,如下操作:
Workbook book = Workbook.getWorkbook(new File("测试1.xls"));
// 获得第一个工作表对象
Sheet sheet = book.getSheet(0);
// 得到第一列第一行的单元格
int columnum = sheet.getColumns();// 得到列数
int rownum = sheet.getRows();// 得到行数
System.out.println(columnum);
System.out.println(rownum);
for (int i = 0; i < rownum; i++)// 循环进行读写
{
for (int j = 0; j < columnum; j++) {
Cell cell1 = sheet.getCell(j, i);
String result = cell1.getContents();
System.out.print(result);
System.out.print("\t");
}
System.out.println();
}
book.close();
浙公网安备 33010602011771号