一、 POI简介
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
二、 HSSF概况
HSSF 是Horrible SpreadSheet Format的缩写,通过HSSF,你可以用纯Java代码来读取、写入、修改Excel文件。HSSF 为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”。
三、 POI EXCEL文档结构类
HSSFWorkbook excel文档对象
HSSFSheet excel的sheet HSSFRow excel的行
HSSFCell excel的单元格 HSSFFont excel字体
HSSFName 名称 HSSFDataFormat 日期格式
HSSFHeader sheet头
HSSFFooter sheet尾
HSSFCellStyle cell样式
HSSFDateUtil 日期
HSSFPrintSetup 打印
HSSFErrorConstants 错误信息表
四、 EXCEL常用操作方法
1、 得到Excel常用对象
[c-sharp] view plaincopy
POIFSFileSystem fs=newPOIFSFileSystem(new FileInputStream("d:/test.xls"));
//得到Excel工作簿对象
HSSFWorkbook wb = new HSSFWorkbook(fs);
//得到Excel工作表对象
HSSFSheet sheet = wb.getSheetAt(0);
//得到Excel工作表的行
HSSFRow row = sheet.getRow(i);
//得到Excel工作表指定行的单元格
HSSFCell cell = row.getCell((short) j);
cellStyle = cell.getCellStyle();//得到单元格样式
2、建立Excel常用对象
[c-sharp] view plaincopy
HSSFWorkbook wb = new HSSFWorkbook();//创建Excel工作簿对象
HSSFSheet sheet = wb.createSheet("new sheet");//创建Excel工作表对象
HSSFRow row = sheet.createRow((short)0); //创建Excel工作表的行
cellStyle = wb.createCellStyle();//创建单元格样式
row.createCell((short)0).setCellStyle(cellStyle); //创建Excel工作表指定行的单元格
row.createCell((short)0).setCellValue(1); //设置Excel工作表的值
3、设置sheet名称和单元格内容
[c-sharp] view plaincopy
wb.setSheetName(1, "第一张工作表",HSSFCell.ENCODING_UTF_16);
cell.setEncoding((short) 1);
cell.setCellValue("单元格内容");
4、取得sheet的数目
[c-sharp] view plaincopy
wb.getNumberOfSheets()
5、 根据index取得sheet对象
[c-sharp] view plaincopy
HSSFSheet sheet = wb.getSheetAt(0);
6、取得有效的行数
[c-sharp] view plaincopy
int rowcount = sheet.getLastRowNum();
7、取得一行的有效单元格个数
[c-sharp] view plaincopy
row.getLastCellNum();
8、单元格值类型读写
[c-sharp] view plaincopy
cell.setCellType(HSSFCell.CELL_TYPE_STRING); //设置单元格为STRING类型
cell.getNumericCellValue();//读取为数值类型的单元格内容
9、设置列宽、行高
[c-sharp] view plaincopy
sheet.setColumnWidth((short)column,(short)width);
row.setHeight((short)height);
10、添加区域,合并单元格
[c-sharp] view plaincopy
Region region = new Region((short)rowFrom,(short)columnFrom,(short)rowTo
,(short)columnTo);//合并从第rowFrom行columnFrom列
sheet.addMergedRegion(region);// 到rowTo行columnTo的区域
//得到所有区域
sheet.getNumMergedRegions()
11、保存Excel文件
[c-sharp] view plaincopy
FileOutputStream fileOut = new FileOutputStream(path);
wb.write(fileOut);
12、根据单元格不同属性返回字符串数值
[c-sharp] view plaincopy
public String getCellStringValue(HSSFCell cell) {
String cellValue = "";
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING://字符串类型
cellValue = cell.getStringCellValue();
if(cellValue.trim().equals("")||cellValue.trim().length()<=0)
cellValue=" ";
break;
case HSSFCell.CELL_TYPE_NUMERIC: //数值类型
cellValue = String.valueOf(cell.getNumericCellValue());
break;
case HSSFCell.CELL_TYPE_FORMULA: //公式
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
cellValue = String.valueOf(cell.getNumericCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK:
cellValue=" ";
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
break;
case HSSFCell.CELL_TYPE_ERROR:
break;
default:
break;
}
return cellValue;
}
13、常用单元格边框格式
[c-sharp] view plaincopy
HSSFCellStyle style = wb.createCellStyle();
style.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);//下边框
style.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);//左边框
style.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框
style.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
14、设置字体和内容位置
[c-sharp] view plaincopy
HSSFFont f = wb.createFont();
f.setFontHeightInPoints((short) 11);//字号
f.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);//加粗
style.setFont(f);
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中
style.setRotation(short rotation);//单元格内容的旋转的角度
HSSFDataFormat df = wb.createDataFormat();
style1.setDataFormat(df.getFormat("0.00%"));//设置单元格数据格式
cell.setCellFormula(string);//给单元格设公式
style.setRotation(short rotation);//单元格内容的旋转的角度
15、插入图片
[c-sharp] view plaincopy
//先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
BufferedImage bufferImg = ImageIO.read(new File("ok.jpg"));
ImageIO.write(bufferImg,"jpg",byteArrayOut);
//读进一个excel模版
FileInputStream fos = new FileInputStream(filePathName+"/stencil.xlt");
fs = new POIFSFileSystem(fos);
//创建一个工作薄
HSSFWorkbook wb = new HSSFWorkbook(fs);
HSSFSheet sheet = wb.getSheetAt(0);
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,255,(short) 0,0,(short)10,10);
patriarch.createPicture(anchor , wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));
16、调整工作表位置
[c-sharp] view plaincopy
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("format sheet");
HSSFPrintSetup ps = sheet.getPrintSetup();
sheet.setAutobreaks(true);
ps.setFitHeight((short)1);
ps.setFitWidth((short)1);
17、设置打印区域
[c-sharp] view plaincopy
HSSFSheet sheet = wb.createSheet("Sheet1");
wb.setPrintArea(0, "$A$1:$C$2");
18、标注脚注
[c-sharp] view plaincopy
HSSFSheet sheet = wb.createSheet("format sheet");
HSSFFooter footer = sheet.getFooter()
footer.setRight( "Page " + HSSFFooter.page() + " of " + HSSFFooter.numPages() );
19、在工作单中清空行数据,调整行位置
[c-sharp] view plaincopy
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("row sheet");
// Create various cells and rows for spreadsheet.
// Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5)
sheet.shiftRows(5, 10, -5);
20、选中指定的工作表
[c-sharp] view plaincopy
HSSFSheet sheet = wb.createSheet("row sheet");
heet.setSelected(true);
21、工作表的放大缩小
[c-sharp] view plaincopy
HSSFSheet sheet1 = wb.createSheet("new sheet");
sheet1.setZoom(1,2); // 50 percent magnification
22、头注和脚注
[c-sharp] view plaincopy
HSSFSheet sheet = wb.createSheet("new sheet");
HSSFHeader header = sheet.getHeader();
header.setCenter("Center Header");
header.setLeft("Left Header");
header.setRight(HSSFHeader.font("Stencil-Normal", "Italic") +
HSSFHeader.fontSize((short) 16) + "Right w/ Stencil-Normal Italic font and size 16");
23、自定义颜色
[c-sharp] view plaincopy
HSSFCellStyle style = wb.createCellStyle();
style.setFillForegroundColor(HSSFColor.LIME.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
HSSFFont font = wb.createFont();
font.setColor(HSSFColor.RED.index);
style.setFont(font);
cell.setCellStyle(style);
24、填充和颜色设置
[c-sharp] view plaincopy
HSSFCellStyle style = wb.createCellStyle();
style.setFillBackgroundColor(HSSFColor.AQUA.index);
style.setFillPattern(HSSFCellStyle.BIG_SPOTS);
HSSFCell cell = row.createCell((short) 1);
cell.setCellValue("X");
style = wb.createCellStyle();
style.setFillForegroundColor(HSSFColor.ORANGE.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell.setCellStyle(style);
25、强行刷新单元格公式
[c-sharp] view plaincopy
HSSFFormulaEvaluator eval=new HSSFFormulaEvaluator((HSSFWorkbook) wb);
private static void updateFormula(Workbook wb,Sheet s,int row){
Row r=s.getRow(row);
Cell c=null;
FormulaEcaluator eval=null;
if(wb instanceof HSSFWorkbook)
eval=new HSSFFormulaEvaluator((HSSFWorkbook) wb);
else if(wb instanceof XSSFWorkbook)
eval=new XSSFFormulaEvaluator((XSSFWorkbook) wb);
for(int i=r.getFirstCellNum();i
if(c.getCellType()==Cell.CELL_TYPE_FORMULA)
eval.evaluateFormulaCell(c);
}
}
说明:FormulaEvaluator提供了evaluateFormulaCell(Cell cell)方法,计算公式保存结果,但不改变公式。而evaluateInCell(Cell cell) 方法是计算公式,并将原公式替换为计算结果,也就是说该单元格的类型不在是Cell.CELL_TYPE_FORMULA而是Cell.CELL_TYPE_NUMBERIC。HSSFFormulaEvaluator提供了静态方法evaluateAllFormu
laCells(HSSFWorkbook wb) ,计算一个Excel文件的所有公式,用起来很方便。
1. HSSFWorkbook类(创建excel表)
首先从Workbook开始我们的POI编程之旅。要生成一个Workbook,需要用到HSSFWorkbook类文件,类定义如下:
它有五个构造方法:
构建器 |
HSSFWorkbook() |
HSSFWorkbook(java.io.InputStream s) |
HSSFWorkbook(java.io.InputStream s, boolean preserveNodes) |
HSSFWorkbook(POIFSFileSystem fs) |
HSSFWorkbook(POIFSFileSystem fs, boolean preserveNodes) |
我们用第一个构建器来生成一个Workbook
HSSFWorkbook
public HSSFWorkbook()
Creates new HSSFWorkbook from scratch (start here!)
使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
接下来再来对生成的Workbook进行保存操作,保存操作用「HSSFWorkbook」类的「write」方法:
write
public void write(java.io.OutputStream stream) throws
java.io.IOException
Method write - write out this workbook to an Outputstream.
Constructs a new POI POIFSFileSystem, passes in the workbook
binary representation and writes it out.
Parameters:
stream - - the java OutputStream you wish to write the XLS to
Throws:
java.io.IOException - if anything can't be written.
参数是作为保存对象的输出流对象「OutputStream」。
示例程序
可以自己实际做一下啊。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();//创建一个空白的workbook
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);//调用HSSFWorkbook类的write方法写入到输出流
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
运行刚才的示例程序来生成一个Excel文件吧。
==========================================异常华丽的分割线=============================================================
2. POIFSFileSystem类(读取excel表格)
这次我们用POI打开一个已经存在的Workbook。因为没有现成的方法,所以只能再次利用HSSFWorkbook构造方法
HSSFWorkbook
public HSSFWorkbook(POIFSFileSystem fs) throws java.io.IOException
--
这个构建器虽然没什么说明,但可以看出它的参数是一个「POIFSFileSystem」这样的一个类对象。那我们再来看看「POIFSFileSystem」类定义。
POIFSFileSystem类定义
「POIFSFileSystem」类对象可以把Excel文件作为数据流来进行传入传出。
「POIFSFileSystem」类有两个构建器
构建器 |
POIFSFileSystem() |
POIFSFileSystem(java.io.InputStream stream) |
读取文件时使用第二个构建器。
POIFSFileSystem
public POIFSFileSystem(java.io.InputStream stream) throws
java.io.IOException
Create a POIFSFileSystem from an InputStream
Parameters:
stream - the InputStream from which to read the data
Throws:
java.io.IOException - on errors reading, or on invalid data
参数设定为读入Excel文件的流对象「InputStream」。使用方法如下。
FileInputStream in = new FileInputStream("sample.xls");//文件输入流
POIFSFileSystem fs = new POIFSFileSystem(in);//构建poifsfileSystem对象,根据输入流
HSSFWorkbook wb = new HSSFWorkbook(fs);
通过POIFSFileSystem读取Excel文件
下面就实际做一下如何读取Excel文件。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample1.xls");//将excel文件转为输入流
POIFSFileSystem fs = new POIFSFileSystem(in);//构建POIFSFileSystem类对象,用输入流构建
workbook = new HSSFWorkbook(fs);//创建个workbook,根据POIFSFileSystem对象
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
这个示例程序的作用是读取「sample1.xls」文件后再把它作为「sample2.xls」保存。
「sample1.xls」文件如下。
正在上传…重新上传取消
实行之后,会生成一模一样的文件「sample2.xls」。
打开如下。
正在上传…重新上传取消
==========================================异常华丽的分割线=============================================================
3. 关于Sheet
HSSFSheet类定义
用POI来作成一个Sheet,可以用「HSSFSheet」类,它的类定义如下。
它有两个构造方法。
构建器 |
protected HSSFSheet(Workbook book) |
protected HSSFSheet(Workbook book, Sheet sheet) |
虽然有两个构建器,但都是protected的,所以要新建Sheet,只能通过Workbook。
新建Sheet
在Workbook里新建Sheet时,还是使用「HSSFWorkbook」类的「createSheet」的方法,详细可以参照「在Workbook里创建Sheet」。
使用方法如下。
HSSFWorkbook workbook = new HSSFWorkbook();//创建个空白的workbook
HSSFSheet sheet = workbook.createSheet();//创建个空白的sheet
读取现有的Sheet
对于在Workbook已经存在的Sheet来说,可以用「HSSFWorkbook」类的「getSheet」方法来读取。
getSheet
public HSSFSheet getSheet(java.lang.String name)
Get sheet with the given name
Parameters:
name - of the sheet
Returns:
HSSFSheet with the name provided or null if it does not exist
(java.lang.String name)参数为Sheet名称。
使用方法如下。
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.getSheet("sheet1")//读取名称为sheet1的sheet
不用Sheet名而用Sheet的序列号来取得Sheet的话,可以用「HSSFWorkbook」类的「getSheetAt」方法。
getSheetAt
public HSSFSheet getSheetAt(int index)
Get the HSSFSheet object at the given index.
Parameters:
index - of the sheet number (0-based physical & logical)
Returns:
HSSFSheet at the provided index
(int index)参数为sheet的序号
使用方法如下。
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.getSheetAt(1);//读取序号为1的sheet(第二张sheet)
=================
Workbook创建Sheet
要在Workbook里创建一个Sheet,可以使用「HSSFWorkbook」类的「createSheet」方法。
createSheet
public HSSFSheet createSheet()
create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and
returns the high level representation. Use this to create new sheets.
Returns:
HSSFSheet representing the new sheet.
还有一个名称相同的「createSheet」方法,但可以指定Sheet名。
createSheet
public HSSFSheet createSheet(java.lang.String sheetname)
create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and
returns the high level representation. Use this to create new sheets.
Parameters:
sheetname - sheetname to set for the sheet.
Returns:
HSSFSheet representing the new sheet.
创建的Sheet作为「HSSFSheet」类对象返回。
示例程序
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
workbook.createSheet();//创建workbook的sheet
workbook.createSheet();
workbook.createSheet("test");
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
上面的示例程序执行后,会生成下面的「sample1.xls」文件。
如果没有设定Sheet名,会从0开始默认设定为Sheet0,Sheet1等,设定为test的话,则可以创建test这样的Sheet。
===================================
Workbook复制Sheet
要复制Workbook里现有的Sheet来创建新的Sheet,可以使用「HSSFWorkbook」类的「cloneSheet」方法。
cloneSheet
public HSSFSheet cloneSheet(int sheetNum)
create an HSSFSheet from an existing sheet in the HSSFWorkbook.
Returns:
HSSFSheet representing the cloned sheet.
指定要复制的Sheet序列号。
示例程序
再一次动手来做做吧。复制前Workbook如下。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
workbook.cloneSheet(0);
workbook.cloneSheet(1);
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
执行后打开「sample1.xls」文件看看。
可以看出,两个Sheet被成功复制。被复制的Sheet名格式是「原Sheet名(序列号)」。顺便一提的是,如果你手动在Excel里进行复制的话,被复制的Sheet名的格式是「原Sheet名 (序列号)」。也就是原Sheet名和(序列号)之间有一个半角空格。
=============
Workbook删除Sheet
要从Workbook里删除Sheet,可以使用「HSSFWorkbook」类的方法「removeSheetAt」。
removeSheetAt
public void removeSheetAt(int index)
removes sheet at the given index
Parameters:
index - of the sheet (0-based)
(int index)指定要删除Sheet的序列号。
如果不知道序列号的话,也可以通过「HSSFWorkbook」类的方法「getSheetIndex」,设定Sheet名来取得序列号。
getSheetIndex
public int getSheetIndex(java.lang.String name)
Returns the index of the sheet by his name
Parameters:
name - the sheet name
Returns:
index of the sheet (0 based)
(java.lang.String name)参数请指定要删除的Sheet名。
示例程序
生成一个Workbook,再在其中创建三个Sheet,最后再把名为「Sheet1」的Sheet删除。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
workbook.createSheet();
workbook.createSheet();
workbook.createSheet();
workbook.removeSheetAt(workbook.getSheetIndex("Sheet1"));
System.out.println("Sheet0 = " + workbook.getSheetIndex("Sheet0"));
System.out.println("Sheet2 = " + workbook.getSheetIndex("Sheet2"));
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
示例程序执行后,会生成「sample1.xls」这样的文件,打开来看看先。
从图中可以看出,Sheet1被删除了,那么这时候序列号又是怎么样的呢?你还是可以通过「HSSFWorkbook」类的方法「getSheetIndex」,设定Sheet名来取得序列号看看。
Sheet0 = 0
Sheet2 = 1
我们发现中间的Sheet被删除后,后面的Sheet序列号会往前移一个,总之会维持从0开始的整数顺序。
============
改变sheet的名称
要改变现有Sheet或刚新建Sheet的名称,可以用「HSSFWorkbook」类的「setSheetName」方法。
setSheetName
public void setSheetName(int sheet, java.lang.String name)
set the sheet name. Will throw IllegalArgumentException if the name
is greater than 31 chars or contains /\?*[]
Parameters:
sheet - number (0 based)
参数:(int sheet)指定要改变的Sheet的序列号。参数(java.lang.String name)为要改变的名称,设置名称时,最大长度是31个文字,还有「/\?*[]」这样的字符不能使用。
指定汉字Sheet名时,用第二个方法。
setSheetName
public void setSheetName(int sheet, java.lang.String name,
short encoding)
--
「encoding」的参数在「HSSFWorkbook」类里被定义成下面两种。
static byte ENCODING_COMPRESSED_UNICODE
static byte ENCODING_UTF_16 ---------------设置中文用
参数(int sheet, java.lang.String name,short encoding)
int sheet sheet号
java.lang.String name 改变的名字
short encoding 设定汉字时(包括日语),「encoding」的参数应该传入「HSSFWorkbook.ENCODING_UTF_16」。
示例程序
亲自动手做一做吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
workbook.createSheet();
workbook.createSheet();
workbook.setSheetName(0, "test");//更改sheet0的名字为test
workbook.setSheetName(1, "测试", HSSFWorkbook.ENCODING_UTF_16);//更改sheet1的名字为“测试”设置为utf-16
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
程序执行后,打开「sample1.xls」文件来看看。
可以看出,汉字Sheet名被正常设好了。
使用「createSheet」方法创建新的Sheet时,不能进行encoding设定。所以要设置汉字Sheet名时,只能先新建一个Sheet,然后再对该Sheet进行改名操作。
=====================
设定列宽度
如果想在工作表里指定列宽度的话,可以使用「HSSFSheet」类的「setColumnWidth」方法。
setColumnWidth
public void setColumnWidth(short column, short width)
set the width (in units of 1/256th of a character width)
Parameters:
column - - the column to set (0-based)
width - - the width in units of 1/256th of a character width
(short column)指定列的序列号, (short width)指定列的宽度。宽度如果指定1的话,那就是一个文字的1/256(也就是说一个文字占256的宽度),4个文字的宽度是1024。
另外,要取得列宽度可以使用「HSSFSheet」类的「getColumnWidth」方法。
getColumnWidth
public short getColumnWidth(short column)
get the width (in units of 1/256th of a character width )
Parameters:
column - - the column to set (0-based)
Returns:
width - the width in units of 1/256th of a character width
(short column)指定列的序列号
自己动手做一下吧。仍然按照下图准备一个Excel文件,取得从第0列到第2列的列宽、然后把第2列的列宽指定给第0列和第1列。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
short[] width = new short[3];
for (int i = 0 ; i < 3 ; i++){
width[i] = sheet.getColumnWidth((short)i);
System.out.println(i + "列宽度:" + width[i]);
}//循环获取0,1,2的宽度
//将第二列的宽度赋给第0,1列
sheet.setColumnWidth((short)0, width[2]);
sheet.setColumnWidth((short)1, width[2]);
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
打开新生成的Excel文件看看。
0列宽度:1865
1列宽度:3986
2列宽度:2048
一个Excel文件新生成时,有自己默认的列宽度,当然我们也可以用POI来指定默认的列宽度。
指定默认的列宽度用「HSSFSheet」类的「setDefaultColumnWidth」方法。
setDefaultColumnWidth
public void setDefaultColumnWidth(short width)
set the default column width for the sheet (if the columns do not define
their own width) in characters
Parameters:
width - default column width
(short width)参数,这里要注意的就是,和刚才的方法不一样,这里的列宽度单位是1个文字,而不是刚才的一个文字的1/256。
要取得原来的默认列宽度,使用「getDefaultColumnWidth」方法。
getDefaultColumnWidth
public short getDefaultColumnWidth()
get the default column width for the sheet (if the columns do not define
their own width) in characters
Returns:
default column width
这里的列宽度单位也是一个文字
动手做做看吧。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
sheet.setDefaultColumnWidth((short)5);//将默认的列宽设为5个文字大小
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
新生成的Excel文件打开来看看吧。
=================
调整工作表Sheet的显示比例
有时我们可能会手动去调整工作表Sheet的显示比例,用POI同样也能做到这一点。这时我们可以使用「HSSFSheet」类的「setZoom」方法。
setZoom
public void setZoom(int numerator, int denominator)
Sets the zoom magnication for the sheet. The zoom is expressed as a
fraction. For example to express a zoom of 75% use 3 for the
numerator and 4 for the denominator.
Parameters:
numerator - The numerator for the zoom magnification.
denominator - The denominator for the zoom magnification.
(int numerator, int denominator)参数,这样就可以指定显示比例了,指定方法是用”numerator”÷”denominator”,比方说,「setZoom(2, 1)」就是设定为200%的比例,「setZoom(3, 4)」就是设定为75%的比例。
动手做一下吧。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);//取得序号为0的sheet
sheet.setZoom(2, 1);//改变sheet的显示比例为200%
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
新生成的Excel文件如下图所示。
==========
合并单元格
现在再看看如果将指定的单元格进行合并操作。用POI进行合并操作,使用「HSSFSheet」类的「addMergedRegion」方法。
addMergedRegion
public int addMergedRegion(Region region)
adds a merged region of cells (hence those cells form one)
Parameters:
region - (rowfrom/colfrom-rowto/colto) to merge
Returns:
index of this region
参数(Region region),合并范围必须使用「Region」类来指定,关于「Region」类的介绍如下。
「Region」类关系图
「Region」类的构造方法
Region
public Region(int rowFrom, short colFrom, int rowTo, short colTo)// rowFrom起始行号, colFrom起始列号,rowTo结束行号,colTo结束列号
--
指定范围时,从左上的单元格到右下的单元格指定,比方像下面这样。
Region(1, (short)1, 2, (short)3)
示例程序
动手做做看,还是使用原来的Excel文件。
把上图选中的单元格进行合并操作时,看下面的程序。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.util.Region;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
sheet.addMergedRegion(new Region(1, (short)1, 2, (short)3));//从第2行第2列开始并到第3行,第4列
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
把刚作成的新的Excel文件打开看看吧
==========================================异常华丽的分割线=============================================================
4.关于SHEET中的行
HSSFRow类定义
用POI在工作表里作成一个行,可以用「HSSFRow」类,它的类定义如下。
它的构造方法有三个。
构造方法 |
protected HSSFRow() |
protected HSSFRow(Workbook book, Sheet sheet, int rowNum) |
protected HSSFRow(Workbook book, Sheet sheet, RowRecord record) |
虽然有三个,但每一个都是protected的,所以不能直接使用它的构造方法,而是用Sheet对象来创建行。
创建行
在工作表里创建行,使用「HSSFSheet」类的「createRow」方法,前面也讲过,你可以参照一下『Sheet里行的创建』。
使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(0);
取得已经存在的行
在工作表里取得行,使用「HSSFSheet」类的「getRow」方法,详细内容你可以参照一下『Sheet里行的读取』。
使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.getRow(0);
=============
A.获取行的状态
我们还可以用POI获取当前工作表的行的一些状态,比如获得第一行的序列号,使用「HSSFSheet」类的「getFirstRowNum」方法。
getFirstRowNum
public int getFirstRowNum()
gets the first row on the sheet
Returns:
the number of the first logical row on the sheet
还有,获得最后一行的序列号,使用「HSSFSheet」类的「getLastRowNum」方法。
getLastRowNum
public int getLastRowNum()
gets the last row on the sheet
Returns:
last row contained n this sheet.
还可以获得实际存在的行的总数,使用「HSSFSheet」类的「getPhysicalNumberOfRows」方法。
getPhysicalNumberOfRows
public int getPhysicalNumberOfRows()
Returns the number of phsyically defined rows (NOT the number of rows
in the sheet)
自己动手做做吧。
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
System.out.println("创建行之前的状态:");
System.out.println("First:" + sheet.getFirstRowNum());//sheet.getFirstRowNum()获取sheet的第一行行号
System.out.println("Last:" + sheet.getLastRowNum());//getLastRowNum()获取sheet的最后行行号
System.out.println("Total:" + sheet.getPhysicalNumberOfRows() + "\n");// getPhysicalNumberOfRows()获取sheet的行总数
sheet.createRow(1);
System.out.println("创建第一行后的状态:");
System.out.println("First:" + sheet.getFirstRowNum());
System.out.println("Last:" + sheet.getLastRowNum());
System.out.println("Total:" + sheet.getPhysicalNumberOfRows() + "\n");
sheet.createRow(3);
System.out.println("创建第三行后的状态:");
System.out.println("First:" + sheet.getFirstRowNum());
System.out.println("Last:" + sheet.getLastRowNum());
System.out.println("Total:" + sheet.getPhysicalNumberOfRows());
}
}
用上面的代码实行看看。
创建行之前的状态:
First:0
Last:0
Total:0
创建第一行后的状态:
First:0
Last:1
Total:1
创建第三行后的状态:
First:0
Last:3
Total:2
getPhysicalNumberOfRows() 取得是创建的总行数,即存在的行数
==================
B.行的创建
之前仅仅新建了Sheet,虽然可以看到新建的Sheet里有无数的单元格,但还不能直接往这些单元格设值。要想往这些单元格里设值,你还必须创建行。
因此,再来看看行创建的方法。
在Sheet里创建行,使用「HSSFSheet」类的「createRow」方法。
createRow
public HSSFRow createRow(int rownum)
Create a new row within the sheet and return the high
level representation
Parameters:
rownum - row number
Returns:
High level HSSFRow object representing a row in the sheet
(int rownum)创建指定行号的行。行号是从0开始的整数,最大是65535,可以支持65536行。创建行所返回的值是「HSSFRow」类对象,关于「HSSFRow」类定义的说明,以后再详细说。
创建方法很多,要说详细挺复杂。比方说,即使第一行(行号为0)和第二行不创建,也能直接创建第三行。
示例程序
亲自动手做一下吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();//创建个空白的workbook
HSSFSheet sheet = workbook.createSheet();//创建个空白的sheet
HSSFRow row = sheet.createRow(2);//创建行号为2的行,excel中的第三行
HSSFCell cell = row.createCell((short)0);//创建上面行的第一个单元格
cell.setCellValue("test");//将test写入单元格
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
在上面的程序里,生成一个Sheet,然后单独创建了第三行(行号为2),接着又创建了一个单元格,最后给这个单元格设了值。执行后,打开「sample.xls」文件看看。
可以看到,在第三行第一列,值已经被设定好了。
================
C.行的读取
要取得Sheet里的某一行,可以使用「HSSFSheet」类的「getRow」方法。
getRow
public HSSFRow getRow(int rownum)
Returns the logical row (not physical) 0-based. If you ask for a row
that is not defined you get a null. This is to say row 4 represents
the fifth row on a sheet.
Parameters:
rownum - row to get
Returns:
HSSFRow representing the rownumber or null if its not defined on the
sheet
利用行号取得指定的行。如果行不存在,则返回NULL。
示例程序
动手做做看。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);
for (int i = 0 ; i < 3 ; i++){
HSSFRow r = sheet.getRow(i);
if (r == null){
System.out.println("第" + i + "行不存在。");
}else{
System.out.println("第" + i + "行取得成功。");
}
}
}
}
上面的程序里,先创建一个Sheet,然后创建第二行(行号为1)。最后读取第一行到第三行的三行。结果如下。
第0行不存在。
第1行取得成功。
第2行不存在。
这和予想的一样。
读取有值的行
按照下图准备一个Excel文件。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);//读取序号为0的sheet
for (int i = 0 ; i < 3 ; i++){
HSSFRow r = sheet.getRow(i);
if (r == null){
System.out.println("第" + i + "行不存在。");
}else{
System.out.println("第" + i + "行取得成功。");
}
}
}
}
结果如下。
第0行取得成功。
第1行取得成功。
第2行不存在。
从上面的例子可以看出,如果当前行有值的话,那么读取这一行时肯定存在。
从取得的行里获取单元格的值。
这一次从已经取得的行里获取单元格的值。仍然使用刚才的Excel文件。用getRow方法先取得行对象,再从单元格里获取值。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);//读取序号为0的sheet
HSSFRow row = sheet.getRow(1);//取得sheet中第二行(行号1)
HSSFCell cell = row.getCell((short)1);//取得第二行,第二格(单元格号1)
System.out.println(cell.getStringCellValue());//cell.getStringCellValue()取值
}
}
结果如下。
sample
可以看出,把第二行第二列的值取出来了。
===================
在现有的行上创建行(貌似没什么用啊)
最后,再来试试看,在现有的行上,用「createRow」方法创建一行看看会是什么结果。还是使用刚才的Excel文件,在第二行上创建一行,再把值取出来。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);//取得0sheet
HSSFRow row = sheet.createRow(1);//在已经有第二行的情况下再建第二行
HSSFCell cell = row.getCell((short)1);//取得新建第二行的值
System.out.println(cell.getStringCellValue());
}
}
结果如下。
Exception in thread "main" java.lang.NullPointerException
at POISample.main(POISample.java:35)
发生了空指针异常。本来对于已经存在的行用「createRow」方法进行创建行操作,可能你会以为会复制原来的行,但事实并非如此。
让我们在原来程序的基础上再稍作一些变化,已经存在的行用「createRow」方法进行创建行操作后,再在该行的空白单元格设上值,保存为新的文件。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.createRow(1);
HSSFCell cell = row.createCell((short)3);
cell.setCellValue("news");
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
执行上面程序后,打开新的Excel文件如下。
对于已经存在的行再用「createRow」方法执行的话,那从原来行里有值的单元格取值时会发生空指针异常。但如果新创建一个单元格再设值的话,那之前单元格的值也会被保留下来。虽然是猜测,不过大家可以自己亲自动手来验证一下。
=======================
D.移动行
如果要移动某一行的话,可以使用「HSSFSheet」类的「shiftRows」方法。
shiftRows
public void shiftRows(int startRow, int endRow, int n)
Shifts rows between startRow and endRow n number of rows. If you use
a negative number, it will shift rows up. Code ensures that rows don't
wrap around. Calls shiftRows(startRow, endRow, n, false, false);
Additionally shifts merged regions that are completely defined in
these rows (ie. merged 2 cells on a row to be shifted).
Parameters:
startRow - the row to start shifting
endRow - the row to end shifting
n - the number of rows to shift
int startRow, int endRow:指定要移动的行的范围从「startRow」行到「endRow」行。
int n:「n」如果是正数就往下移动的行数,如果为负,就往上移动。
按下图准备一个Excel文件。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
sheet.shiftRows(1, 2, 2);//第二行和第三行向下移动两行
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
打开新建的Sample2.xls文件看看。
从上图可以看出,第二行和第三行的内容已经移动到第四行和第五行,并覆盖原第四行和第五行的内容。但第二行到第五行的行高却维持原样没有变化。
再来看看有没有办法可以既移动内容,又可以移动行高呢?从帮助文档里可以看出,对于「shiftRows」方法,还有另外一种用法。
shiftRows
public void shiftRows(int startRow, int endRow, int n,
boolean copyRowHeight, boolean resetOriginalRowHeight)
Shifts rows between startRow and endRow n number of rows. If you use
a negative number, it will shift rows up. Code ensures that rows don't
wrap around
Additionally shifts merged regions that are completely defined in
these rows (ie. merged 2 cells on a row to be shifted).
TODO Might want to add bounds checking here
Parameters:
startRow - the row to start shifting
endRow - the row to end shifting
n - the number of rows to shift
copyRowHeight - whether to copy the row height during the shift
resetOriginalRowHeight - whether to set the original row's height
to the default
前面3个参数和之前一样。如要使行高也一起移动的话,设置「copyRowHeight」参数为「true」。
还有,移动后,原来的行是保留原行高不变还是恢复到默认行高呢?可以设置「resetOriginalRowHeight」参数。为「true」时,则可以恢复到默认行高。反之则保留原行高不变。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
sheet.shiftRows(1, 2, 2, true, true);//第二行和第三行保留原来高度向下移动两行,原栏位恢复默认高度
FileOutputStream out = null;
try{
out = new FileOutputStream("sample2.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
再打开新生成的Sample2.xls文件来看看。
从上图可以看出,移动后,原行高也被移动了,而原行则恢复到默认行高。
===================
==========================================异常华丽的分割线=============================================================
关于单元格
HSSFCell类定义
这一章开始介绍单元格,其实前面一章已经提到过了,用POI创建单元格,使用「HSSFCell」类,类定义如下。
该类包含三个构造方法。
构造方法 |
protected HSSFCell(Workbook book, Sheet sheet, int row, CellValueRecordInterface cval) |
protected HSSFCell(Workbook book, Sheet sheet, int row, short col) |
protected HSSFCell(Workbook book, Sheet sheet, int row, short col, int type) |
同之前一样,虽然有三个构造方法,但都是protected类型的,所以直接用构造方法创建单元格行不通,只能通过行来创建单元格。
创建单元格
在一个工作表里创建一个单元格,必须用「HSSFRow」类的「createCell」方法,详细请参照『行里创建单元格』。
使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short)2);
读取现有单元格
要读取某一行现有的单元格,使用「HSSFRow」类的「getCell」方法,详细请参照『读取单元格』。
使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.getRow(0);
HSSFCell cell = row.getCell((short)2);
==========
行里创建单元格
下面来看看如何在取得现有行或者在新创建的行里,再创建一个单元格。用POI来创建的话,使用「HSSFRow」类的「createCell」方法。
createCell
public HSSFCell createCell(short column)
Use this to create new cells within the row and return it.
The cell that is returned is a CELL_TYPE_BLANK. The type can be
changed either through calling setCellValue or setCellType.
Parameters:
column - - the column number this cell represents
Returns:
HSSFCell a high level representation of the created cell.
(short column)创建指定列号的单元格。列号和行号一样,也是从0开始数的。创建的单元格以「HSSFCell」类的对象返回,关于「HSSFCell」类的介绍,我们放在下面几章进行。
自己动手做做看吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);//创建序号为1的行,第2行
HSSFCell cell = row.createCell((short)2);//创建序号为2的单元格,第二行第3格
cell.setCellValue("test");//写入test
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
上面的例子里,先创建一个工作表Sheet,然后在工作表里只创建第二行,最后再在这一行创建一个新的单元格,并设上一个值。实行这个程序会生成「sample.xls」这样的Excel文件,打开来看看吧。
从图中可以看到,第一行(行号为1,实际是第3行)的第二列(列号是2,实际是第3列)的单元格里,被赋上了值。
==============
读取单元格
如果要从现有的行里取得某一个单元格,POI提供了「HSSFRow」类的「getCell」方法。
getCell
public HSSFCell getCell(short cellnum)
get the hssfcell representing a given column (logical cell)
0-based.
If you ask for a cell that is not defined....you get a null.
Parameters:
cellnum - 0 based column number
Returns:
HSSFCell representing that column or null if undefined.
(short cellnum)取得指定列号的单元格。如果是不存在的单元格,会返回「null」。
再来动手做做吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);//创建第二行
HSSFCell cell = row.createCell((short)2);//创建第二行第三格
cell.setCellValue("test");//第二行第三格写入test
for (int i = 0 ; i < 3 ; i++){
HSSFCell c = row.getCell((short)i);
if (c == null){
System.out.println("第" + i + "列单元格不存在");
}else{
System.out.println("第" + i + "列单元格获取成功");
}
}
}
}
上面的例子里,先做成一行(行号为1),然后在这一行的第2列(行号为2)创建单元格,最后再从第0列到第2列依次取得单元格,结果如下:
第0列单元格不存在
第1列单元格不存在
第2列单元格获取成功
===============
像下面那样准备一个Excel表格来做做看。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);//取得第一张sheet
HSSFRow row = sheet.getRow(1);//第2行
for (int i = 0 ; i < 3 ; i++){
HSSFCell c = row.getCell((short)i);
if (c == null){
System.out.println("第" + i + "列单元格不存在");
}else{
System.out.println("第" + i + "列单元格取得成功");
System.out.println("单元格的值:" + c.getStringCellValue());//getStringCellValue()取得单元格的值
}
}
}
}
结果如下:
第0列单元格取得成功
单元格的值:cell a-2
第1列单元格不存在
第2列单元格取得成功
单元格的值:cell c-2
===========
POI向单元格写入值
前面介绍了如何用POI获取单元格的值,这一节介绍如何用POI向单元格里设定值。和之前获取值一样,对于不同类型的值,写入的方法也是不同的。
值 |
方法 |
boolean |
setCellValue(boolean value) |
date |
setCellValue(java.util.Calendar value) |
date |
setCellValue(java.util.Date value) |
numeric |
setCellValue(double value) |
string |
setCellValue(java.lang.String value) |
方法名称相同,但参数类型不同,这样的方法有5个。关于日期型的方法,有Calender型和Date型两种。
当然,POI也可以写入Error值和计算式。
值 |
方法 |
error value |
setCellErrorValue(byte value) |
Formula |
setCellFormula(java.lang.String formula) |
先统一看一下各种方法的Doc文档说明吧。
setCellValue(boolean value)
写入boolean型使用「setCellValue(boolean value)」方法。
setCellValue
public void setCellValue(boolean value)
set a boolean value for the cell
Parameters:
value - the boolean value to set this cell to. For formulas
we'll set the precalculated value, for booleans we'll set
its value. For other types we will change the cell to a
boolean cell and set its value.
如果对象单元格不是boolean型的话,则自动转换为boolean型写入。
setCellValue(java.util.Calendar value)
写入Calendar型使用「setCellValue(java.util.Calendar value)」方法。
setCellValue
public void setCellValue(java.util.Calendar value)
set a date value for the cell. Excel treats dates as numeric
so you will need to format the cell as a date.
Parameters:
value - the date value to set this cell to. For formulas
we'll set the precalculated value, for numerics we'll
set its value. For othertypes we will change the cell
to a numeric cell and set its value.
Calendar型的值是作为数值型写入的,如何想表示为日期型的话,需要做格式转换处理。如果对象单元格不是数值型的话,则自动转换为数值型写入。
setCellValue(java.util.Date value)
写入Date型使用「setCellValue(java.util.Date value)」方法。
setCellValue
public void setCellValue(java.util.Date value)
set a date value for the cell. Excel treats dates as numeric
so you will need to format the cell as a date.
Parameters:
value - the date value to set this cell to. For formulas
we'll set the precalculated value, for numerics we'll
set its value. For other types we will change the cell
to a numeric cell and set its value.
Date型的值是作为数值型写入的,如何想表示为日期型的话,需要做格式转换处理。如果对象单元格不是数值型的话,则自动转换为数值型写入。
setCellValue(double value)
写入数值型使用「setCellValue(double value)」方法。
setCellValue
public void setCellValue(double value)
set a numeric value for the cell
Parameters:
value - the numeric value to set this cell to. For formulas
we'll set the precalculated value, for numerics we'll
set its value. For other types we will change the cell
to a numeric cell and set its value.
如果对象单元格不是数值型的话,则自动转换为数值型写入。
setCellValue(java.lang.String value)
写入字符串型使用「setCellValue(java.lang.String value)」方法。
setCellValue
public void setCellValue(java.lang.String value)
set a string value for the cell. Please note that if you are
using full 16 bit unicode you should call setEncoding() first.
Parameters:
value - value to set the cell to. For formulas we'll set
the formula string, for String cells we'll set its value.
For other types we will change the cell to a string cell
and set its value. If value is null then we will change
the cell to a Blank cell.
要写入中文等文字的话,必须要先使用「setEncoding」方法进行转换。如果对象单元格不是字符串型的话,则自动转换为字符串型写入。还有,如果写入的值是”null”的话,则单元格为空白。
setCellErrorValue(byte value)
写入Error型使用「setCellErrorValue(byte value)」方法。
setCellErrorValue
public void setCellErrorValue(byte value)
set a error value for the cell
Parameters:
value - the error value to set this cell to. For formulas
we'll set the precalculated value ??? IS THIS RIGHT??? ,
for errors we'll set its value. For other types we will
change the cell to an error cell and set its value.
如果对象单元格不是Error型的话,则自动转换为Error型写入。
setCellFormula
写入计算式使用「setCellFormula」方法。
setCellFormula
public void setCellFormula(java.lang.String formula)
--
写入计算式方法的参数虽然是字符串,但Doc文档里一点说明也没有。
示例程序
下面仍然自己动手做一下吧。需要注意的是,对于日期型是作为数值写入的,而数值到底表示什么样的日期是看不出来的,这时只能通过另外指定日期格式。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import java.util.Calendar;
import java.util.Date;
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);//创建第二行
HSSFCell cell1 = row.createCell((short)0);//2,1格
cell1.setCellValue(true);//写入true
HSSFCell cell2 = row.createCell((short)1);//2,2格
Calendar cal = Calendar.getInstance();//Calendar???
cell2.setCellValue(cal);//写入Calendar型对象cal
HSSFCell cell3 = row.createCell((short)2);//2,3格
Date date = new Date(); //日期型
cell3.setCellValue(date);//写入日期型
HSSFCell cell4 = row.createCell((short)3);//2,4格
cell4.setCellValue(150);//写入150
HSSFCell cell5 = row.createCell((short)4);//2.5格
cell5.setCellValue("hello");//写入hello
HSSFRow row2 = sheet.createRow(2);//第三行
HSSFCell cell6 = row2.createCell((short)0);//3,1格
cell6.setCellErrorValue(HSSFErrorConstants.ERROR_NUM);//写入error型
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
运行结果如下:
关于计算式和中文文字的写入,下面几节里将会有具体介绍,还有包括日期型的格式指定。
===============
POI中写入中文
如果你现在下载最新版的POI开发包,你会发现,用POI向单元格里写入字符串时,如果是中文文字或者日文文字的话,已经不需要指定Unicode了,直接就可以显示汉字。之前版本存在的「HSSFCell」类的「setEncoding」方法已经被删除了。下面是被删除的方法说明。
setEncoding
public void setEncoding(short encoding)
set the encoding to either 8 or 16 bit. (US/UK use 8-bit,
rest of the western world use 16bit)
Parameters:
encoding - either ENCODING_COMPRESSED_UNICODE (0)
or ENCODING_UTF_16 (1)
用下面程序来做做看。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row1 = sheet.createRow(1);
HSSFCell cell1 = row1.createCell((short)0);
//cell1.setEncoding(HSSFCell.ENCODING_UTF_16);
cell1.setCellValue("使用中文");
HSSFCell cell2 = row1.createCell((short)1);
//cell2.setEncoding(HSSFCell.ENCODING_COMPRESSED_UNICODE);
cell2.setCellValue("日本語を使う");
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
运行结果如下:
=============
POI获取单元格类值类型
在获取单元格值的时候,不同类型,使用的方法也不一样,所以获取之前,必须要知道类型。这一节就来介绍如何知道单元格里的值是何类型。
要获取单元格值的类型,使用「HSSFCell」类的「getCellType」方法。
getCellType
public int getCellType()
get the cells type (numeric, formula or string)
下面就是类型和定义值的一览表。
Cell type |
定义值 |
值(int) |
Blank |
CELL_TYPE_BLANK |
3 |
Boolean |
CELL_TYPE_BOOLEAN |
4 |
Error |
CELL_TYPE_ERROR |
5 |
Formula |
CELL_TYPE_FORMULA |
2 |
Numeric |
CELL_TYPE_NUMERIC |
0 |
String |
CELL_TYPE_STRING |
1 |
示例程序
下面来实际动手做做看。按下图准备一个Excel文件。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(1);
HSSFCell cell = row.getCell((short)0);
System.out.println("A:2=" + getType(cell.getCellType()));
cell = row.getCell((short)1);
System.out.println("B:2=" + getType(cell.getCellType()));
cell = row.getCell((short)2);
System.out.println("C:2=" + getType(cell.getCellType()));
cell = row.getCell((short)3);
System.out.println("D:2=" + getType(cell.getCellType()));
cell = row.getCell((short)4);
System.out.println("E:2=" + getType(cell.getCellType()));
}
public static String getType(int type){
if (type == HSSFCell.CELL_TYPE_BLANK){
return "CELL_TYPE_BLANK";
}else if (type == HSSFCell.CELL_TYPE_BOOLEAN){
return "CELL_TYPE_BOOLEAN";
}else if (type == HSSFCell.CELL_TYPE_ERROR){
return "CELL_TYPE_ERROR";
}else if (type == HSSFCell.CELL_TYPE_FORMULA){
return "CELL_TYPE_FORMULA";
}else if (type == HSSFCell.CELL_TYPE_NUMERIC){
return "CELL_TYPE_NUMERIC";
}else if (type == HSSFCell.CELL_TYPE_STRING){
return "CELL_TYPE_STRING";
}else{
return "Not defined";
}
}
}
实行结果如下:
A:2=CELL_TYPE_NUMERIC
B:2=CELL_TYPE_STRING
C:2=CELL_TYPE_BOOLEAN
D:2=CELL_TYPE_NUMERIC
E:2=CELL_TYPE_ERROR
有一点要注意的是,数值型和日期型都是「CELL_TYPE_NUMERIC」。
日期型检查
到底是数值型还是日期型,可以通过「org.apache.poi.hssf.usermodel.HSSFDateUtil」类的「isCellDateFormatted」方法来检证。
isCellDateFormatted
public static boolean isCellDateFormatted(HSSFCell cell)
Check if a cell contains a date Since dates are
stored internally in Excel as double values we
infer it is a date if it is formatted as such.
因为这个方法是静态的,可以直接调用如下所示。
if (HSSFDateUtil.isCellDateFormatted(cell)){
/* 日期型 */
}
现在就把之前的示例程序稍微改动一下,再运行看看。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(1);
HSSFCell cell = row.getCell((short)0);
System.out.println("A:2=" + getType(cell));
cell = row.getCell((short)1);
System.out.println("B:2=" + getType(cell));
cell = row.getCell((short)2);
System.out.println("C:2=" + getType(cell));
cell = row.getCell((short)3);
System.out.println("D:2=" + getType(cell));
cell = row.getCell((short)4);
System.out.println("E:2=" + getType(cell));
}
public static String getType(HSSFCell cell){
int type = cell.getCellType();
if (type == HSSFCell.CELL_TYPE_BLANK){
return "CELL_TYPE_BLANK";
}else if (type == HSSFCell.CELL_TYPE_BOOLEAN){
return "CELL_TYPE_BOOLEAN";
}else if (type == HSSFCell.CELL_TYPE_ERROR){
return "CELL_TYPE_ERROR";
}else if (type == HSSFCell.CELL_TYPE_FORMULA){
return "CELL_TYPE_FORMULA";
}else if (type == HSSFCell.CELL_TYPE_NUMERIC){
//检查日期类型
if (HSSFDateUtil.isCellDateFormatted(cell)){
return "CELL_TYPE_DATE";
}else{
return "CELL_TYPE_NUMERIC";
}
}else if (type == HSSFCell.CELL_TYPE_STRING){
return "CELL_TYPE_STRING";
}else{
return "Not defined";
}
}
}
实行结果如下:
A:2=CELL_TYPE_NUMERIC
B:2=CELL_TYPE_STRING
C:2=CELL_TYPE_BOOLEAN
D:2=CELL_TYPE_DATE
E:2=CELL_TYPE_ERROR
这一次,日期型也可以被检查出来了。
=========
POI获取单元格类的值
这一节介绍如何获取单元格的值。在POI里,对于不同类型的单元格的值,所调用的方法是不一样的。
型 |
函数名 |
boolean型 |
getBooleanCellValue() |
java.util.Date型 |
getDateCellValue() |
byte型 |
getErrorCellValue() |
double型 |
getNumericCellValue() |
java.lang.String型 |
getStringCellValue() |
java.lang.String型 |
getCellFormula() |
如果单元格里是String型的值,调用方法「getStringCellValue」,数值型的话,则调用「getNumericCellValue」。再一起来看看其它方法。
getBooleanCellValue
获取boolean型的値,调用「getBooleanCellValue」方法。
getBooleanCellValue
public boolean getBooleanCellValue()
get the value of the cell as a boolean. For strings, numbers,
and errors, we throw an exception. For blank cells we return
a false.
如果调用这个方法来获取字符串,数值型的值的话,会发生Exception异常,如果对象单元格里不含值,则返回「false」。
getDateCellValue
获取日期Date型时,调用「getDateCellValue」方法。
getDateCellValue
public java.util.Date getDateCellValue()
get the value of the cell as a date. For strings we
throw an exception.
For blank cells we return a null.
如果用这个方法来获取字符串时,会有Exception异常发生,如果对象单元格里不含值,则返回「null」。
getErrorCellValue
单元格如果是Error值,比如#VALUE!等,这时可以使用「getErrorCellValue」方法。
getErrorCellValue
public byte getErrorCellValue()
get the value of the cell as an error code. For strings,
numbers, and booleans, we throw an exception. For blank
cells we return a 0.
字符串,数值型,布尔型的值用这个方法的话,会产生异常,而单元格里值为空时则返回「0」。
对于单元格的Error值类型,在POI里的「org.apache.poi.hssf.usermodel.HSSFErrorConstants」有定义列表如下:
常量名 |
错误代码 |
Excel里的Error值 |
public static final byte ERROR_DIV_0 |
7 |
#DIV/0! |
public static final byte ERROR_NA |
42 |
#N/A |
public static final byte ERROR_NAME |
29 |
#NAME? |
public static final byte ERROR_NULL |
0 |
#NULL! |
public static final byte ERROR_NUM |
36 |
#NUM! |
public static final byte ERROR_REF |
23 |
#REF! |
public static final byte ERROR_VALUE |
15 |
#VALUE! |
所以这里要注意了,Excel的ERROR.TYPE函数所返回的值,和POI所定义的是不一样的。
getNumericCellValue
读取数值型时,调用「getNumericCellValue」方法。
getNumericCellValue
public double getNumericCellValue()
get the value of the cell as a number. For strings
we throw an exception.
For blank cells we return a 0.
用这个方法来读取字符串类型时,会有Exception发生,如果单元格里值为空时则返回「0」。
getStringCellValue
字符串类型取得时,使用「getStringCellValue」方法。
getStringCellValue
public java.lang.String getStringCellValue()
get the value of the cell as a string - for numeric cells
we throw an exception.
For blank cells we return an empty string. For formulaCells
that are not string Formulas, we return empty String
同样的,用这个方法来读取数值型时,也会有异常Exception发生。单元格值为空时,则返回空白。
getCellFormula
读取单元格里的计算式时,使用「getCellFormula」方法。
getCellFormula
public java.lang.String getCellFormula()
--
单元格里如果是计算式的话,则把计算式作为字符串来获取。关于具体内容,在最新文档里,竟然没有,不知道为什么。
示例程序
下面我们就在一个Excel文件里,设定各种值,然后用上面的方法来读取。像下图一样准备一个Excel文件吧。
通过下面程序来获取各种类型的单元格的值。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(1);
HSSFCell cell = row.getCell((short)0);
System.out.println(cell.getNumericCellValue());
cell = row.getCell((short)1);
System.out.println(cell.getStringCellValue());
cell = row.getCell((short)2);
System.out.println(cell.getBooleanCellValue());
cell = row.getCell((short)3);
System.out.println(cell.getErrorCellValue());
cell = row.getCell((short)4);
System.out.println(cell.getDateCellValue());
}
}
运行结果如下:
125.0
你好
true
7
Tue Oct 27 00:00:00 JST 2009
和预想的一样吧
POI读取写入函数式
单元格里可以写入函数,自动进行计算操作,这也是Excel功能强大的一方面。前面也提到过,使用POI,往单元格里写入函数,使用「setCellFormula」方法,要获取单元格的函数则使用「getCellFormula」方法。
两个方法,在DOC文档里都没有详细说明,原因不明。总之,先动手做做看。首先来看看如何从单元格取出函数式。
上图中,在单元格「C:2」里的函数式是「=A2*B2」,「C:3」里的函数式是「=SUM(A3:B3)」。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row1 = sheet.getRow(1);
HSSFCell cell1 = row1.getCell((short)2);
System.out.println("C:2的函数式 " + cell1.getCellFormula());//getCellFormula()取得函数式
HSSFRow row2 = sheet.getRow(2);
HSSFCell cell2 = row2.getCell((short)2);
System.out.println("C:3的函数式 " + cell2.getCellFormula());
}
}
实行结果如下:
C:2的函数式 A2*B2
C:3的函数式 SUM(A3:B3)
如上所示,函数式被正常取出,只是函数式前的「=」被省略了。
下面再来看看如何向单元格写入函数式。还是利用之前的Excel文件,「C:2」单元格里写入「A2+B2」,「C:3」单元格里写入「AVERAGE(A3,B3)」这样的函数式。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row1 = sheet.getRow(1);
HSSFCell cell1 = row1.createCell((short)2);
cell1.setCellFormula("A2+B2");// setCellFormula写入函数式
HSSFRow row2 = sheet.getRow(2);
HSSFCell cell2 = row2.createCell((short)2);
cell2.setCellFormula("AVERAGE(A3,B3)");
FileOutputStream out = null;
try{
out = new FileOutputStream("sample3.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
实行结果如下:
到底什么样的函数式可以用,什么样的不能用,这一点还不是很明白,但至少一部分是可以用的。
最后要注意的就是,对于使用getCell方法获取的单元格,函数式是不能被写入的。因此对于已经存在的单元格,在写入函数式时,只能先通过createCell方法创建单元格,再写入函数式。
POI获取行单元格相关信息
有时可能你想要知道行里面单元格的具体信息,比方说,该行实际上有多少单元格,最初的单元格在什么位置,最后的单元格又在哪里?用POI也可以实现。
要取得某一行实际存在的单元格的总数,使用「HSSFRow」类的「getPhysicalNumberOfCells」方法。
getPhysicalNumberOfCells
public int getPhysicalNumberOfCells()
gets the number of defined cells (NOT number of cells in the
actual row!). That is to say if only columns 0,4,5 have values
then there would be 3.
Returns:
int representing the number of defined cells in the row.
要想知道最初的单元格的位置,可以使用「HSSFRow」类的「getFirstCellNum」方法。
getFirstCellNum
public short getFirstCellNum()
get the number of the first cell contained in this row.
Returns:
short representing the first logical cell in the row,
or -1 if the row does not contain any cells.
你也可以使用「HSSFRow」类的「getLastCellNum」方法来获取最后的单元格的位置,但这里要注意一点,如果单元格存在,如下面的API文档所说,获取的值是实际列号再加上1,在以前的版本可不是这样的。
getLastCellNum
public short getLastCellNum()
get the number of the last cell contained in this row.
Returns:
short representing the last logical cell in the row PLUS ONE,
or -1 if the row does not contain any cells.
需要注意的是,POI在获取最初单元格位置和最后单元格位置时,返回的值并不是某一行特有的,而是针对所有的行。也就是说,上面的两个方法,针对所有的行,返回一个最小的列号和最大的列号。因此,不管对于哪一行,实行上面的两个方法,返回的值都是一样的。
自己动手做做看吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);
System.out.println("创建单元格前的状态:");
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
row.createCell((short)1);
System.out.println("创建第二列(列号为1)单元格:");
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
row.createCell((short)3);
System.out.println("创建第四列(列号为3)单元格:");
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
}
}
结果如下:
创建单元格前的状态:
First:-1
Last:-1
Total:0
创建第二列(列号为1)单元格:
First:1
Last:2
Total:1
创建第四列(列号为3)单元格:
First:1
Last:4
Total:2
一行当中没有单元格的情况下,调用「getFirstCellNum」方法和「getLastCellNum」方法,返回值都是「-1」。有单元格时,调用「getLastCellNum」方法,返回的值总是实际列号再加上1(实际第几列)。
===============
再来看看如何从现有的Excel文件里读取单元格信息。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(1);
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
row = sheet.getRow(2);
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
}
}
结果如下:
First:0
Last:4
Total:2
First:0
Last:4
Total:2
接下来对这个Excel文件在另外的单元格里输入值,再用同样的程序(稍有变化)来运行看看。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
public class POISample{
public static void main(String[] args){
FileInputStream in = null;
HSSFWorkbook workbook = null;
try{
in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
workbook = new HSSFWorkbook(fs);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try{
in.close();
}catch (IOException e){
System.out.println(e.toString());
}
}
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow row = sheet.getRow(1);
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
row = sheet.getRow(2);
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
row = sheet.getRow(3);
System.out.println("First:" + row.getFirstCellNum());
System.out.println("Last:" + row.getLastCellNum());
System.out.println("Total:"
+ row.getPhysicalNumberOfCells() + "\n");
}
}
结果如下:
First:0
Last:5
Total:2
First:0
Last:5
Total:2
First:0
Last:5
Total:1
虽然对于不同的行,单元格的总数不一样,但不管哪一行,它的最小列号和最大列号都是一样的。
==========================================异常华丽的分割线=============================================================
POI样式的设定
HSSFCellStyle类定义
这一节开始介绍如何通过POI来进行单元格格式的设定。设定格式使用「HSSFCellStyle」类,关于它的类定义如下:
它有一个构造方法。
构造方法 |
protected HSSFCellStyle(short index, ExtendedFormatRecord rec) |
虽然有构造方法,但却是protected的,所以不能直接使用,要通过一个工作簿workbook来生成格式对象。
在POI里,格式好像是以workbook为单位来管理的,所以要先作成一个格式对象,保存在workbook里,然后再对已生成好的单元格进行设定。
在单元格里指定格式
要作成一个格式对象,可以使用「HSSFWorkbook」类的「createCellStyle」方法。
createCellStyle
public HSSFCellStyle createCellStyle()
create a new Cell style and add it to the workbook's style table
Returns:
the new Cell Style object
另外,要取出现有的格式对象的话,使用「HSSFWorkbook」类的「getCellStyleAt」方法,这个方法有参数,是被保存格式的INDEX号。
getCellStyleAt
public HSSFCellStyle getCellStyleAt(short idx)
get the cell style object at the given index
Parameters:
idx - index within the set of styles
Returns:
HSSFCellStyle object at the index
还有,对于某一个单元格,也可以取出它的格式对象。这时要使用「HSSFCell」类的「getCellStyle」方法。
getCellStyle
public HSSFCellStyle getCellStyle()
get the style for the cell. This is a reference to a cell style
contained in the workbook object.
这样的话,不管是新创建的或者是从现有的单元格里取出来的格式对象,都可以用来对某一个单元格进行格式的设定。设定方法使用「HSSFCell」类的「setCellStyle」方法。
setCellStyle
public void setCellStyle(HSSFCellStyle style)
set the style for the cell. The style should be an HSSFCellStyle
created/retreived from the HSSFWorkbook.
Parameters:
style - reference contained in the workbook
示例程序
关于格式的详细设定方法,下几节再讲,先做个示例程序来看看。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);//第二行
HSSFCell cell = row.createCell((short)0);//2,1格
cell.setCellValue("sample");//写入sample
HSSFCellStyle style = workbook.createCellStyle();//创建个workbook的HSSFCellStyle格式对象style
//设定格式
style.setFillBackgroundColor(HSSFColor.WHITE.index);
style.setFillForegroundColor(HSSFColor.LIGHT_ORANGE.index);
style.setFillPattern(HSSFCellStyle.THICK_HORZ_BANDS);
cell.setCellStyle(style);//对2,1格写入上面的格式
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
按上面程序,在某一个单元格里设定了顔色。运行结果如下:
好了,从下一节开始详细介绍单元格格式的设定。
===============
POI单元格颜色设定
先从单元格顔色设定开始介绍。单元格的顔色有前景色和背景色。
前景色的设定使用「HSSFCellStyle」类的「setFillForegroundColor」方法。
setFillForegroundColor
public void setFillForegroundColor(short bg)
set the foreground fill color
Parameters:
bg - color
背景色的设定则使用「HSSFCellStyle」类的「setFillBackgroundColor」方法。
setFillBackgroundColor
public void setFillBackgroundColor(short bg)
set the background fill color.
Parameters:
bg - color
两个方法都是通过参数来设定具体什么顔色。该参数类型为short型,在「HSSFColor」类里,准备了各种各样顔色的定义值。
HSSFColor类
HSSFColor类定义如下:
而各种顔色又是作为HSSFColor类的子类,定义一览表如下:
HSSFColor.AQUA |
HSSFColor.BLACK |
HSSFColor.BLUE |
HSSFColor.BLUE_GREY |
HSSFColor.BRIGHT_GREEN |
HSSFColor.BROWN |
HSSFColor.CORAL |
HSSFColor.CORNFLOWER_BLUE |
HSSFColor.DARK_BLUE |
HSSFColor.DARK_GREEN |
HSSFColor.DARK_RED |
HSSFColor.DARK_TEAL |
HSSFColor.DARK_YELLOW |
HSSFColor.GOLD |
HSSFColor.GREEN |
HSSFColor.GREY_25_PERCENT |
HSSFColor.GREY_40_PERCENT |
HSSFColor.GREY_50_PERCENT |
HSSFColor.GREY_80_PERCENT |
HSSFColor.INDIGO |
HSSFColor.LAVENDER |
HSSFColor.LEMON_CHIFFON |
HSSFColor.LIGHT_BLUE |
HSSFColor.LIGHT_CORNFLOWER_BLUE |
HSSFColor.LIGHT_GREEN |
HSSFColor.LIGHT_ORANGE |
HSSFColor.LIGHT_TURQUOISE |
HSSFColor.LIGHT_YELLOW |
HSSFColor.LIME |
HSSFColor.MAROON |
HSSFColor.OLIVE_GREEN |
HSSFColor.ORANGE |
HSSFColor.ORCHID |
HSSFColor.PALE_BLUE |
HSSFColor.PINK |
HSSFColor.PLUM |
HSSFColor.RED |
HSSFColor.ROSE |
HSSFColor.ROYAL_BLUE |
HSSFColor.SEA_GREEN |
HSSFColor.SKY_BLUE |
HSSFColor.TAN |
HSSFColor.TEAL |
HSSFColor.TURQUOISE |
HSSFColor.VIOLET |
HSSFColor.WHITE |
HSSFColor.YELLOW |
|
设定顔色时,用这些子类的静态常量「index」作为参数,使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(HSSFColor.LIME.index);
style.setFillBackgroundColor(HSSFColor.GREEN.index);
如果这些顔色还不够你用的话,那么下一节再介绍怎么设定自己想要的顔色。
填充模式
指定填充模式的话,使用「HSSFCellStyle」类的「setFillPattern」方法。
setFillPattern
public void setFillPattern(short fp)
setting to one fills the cell with the foreground color
... No idea about other values
Parameters:
fp - fill pattern (set to 1 to fill w/foreground color)
指定的填充模式,在「HSSFCellStyle」类里也有定义,类型为static short型,如下所示:
值 |
说明 |
NO_FILL |
No background |
SOLID_FOREGROUND |
Solidly filled |
FINE_DOTS |
Small fine dots |
ALT_BARS |
Wide dots |
SPARSE_DOTS |
Sparse dots |
THICK_HORZ_BANDS |
Thick horizontal bands |
THICK_VERT_BANDS |
Thick vertical bands |
THICK_BACKWARD_DIAG |
Thick backward facing diagonals |
THICK_FORWARD_DIAG |
Thick forward facing diagonals |
BIG_SPOTS |
Large spots |
BRICKS |
Brick-like layout |
THIN_HORZ_BANDS |
Thin horizontal bands |
THIN_VERT_BANDS |
Thin vertical bands |
THIN_BACKWARD_DIAG |
Thin backward diagonal |
THIN_FORWARD_DIAG |
Thin forward diagonal |
SQUARES |
Squares |
DIAMONDS |
Diamonds |
实际的使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(HSSFColor.LIME.index);
style.setFillBackgroundColor(HSSFColor.GREEN.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
示例程序
这就实际动手做做看吧,首先看一下定义的顔色到底是什么顔色,全部拉上来看看。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
public class POISample{
static HSSFWorkbook workbook;
public static void main(String[] args){
workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row[] = new HSSFRow[12];
for (int i = 0; i < 12 ; i++){
row[i] = sheet.createRow(i);
}
HSSFCell cell[][] = new HSSFCell[12][4];
for (int i = 0; i < 12; i++){
for (int j = 0; j < 4 ; j++){
cell[i][j] = row[i].createCell((short)j);
}
}
setStyle(cell[0][0], "AQUA", HSSFColor.AQUA.index);
setStyle(cell[0][1], "BLACK", HSSFColor.BLACK.index);
setStyle(cell[0][2], "BLUE", HSSFColor.BLUE.index);
setStyle(cell[0][3], "BLUE_GREY", HSSFColor.BLUE_GREY.index);
setStyle(cell[1][0], "BRIGHT_GREEN",
HSSFColor.BRIGHT_GREEN.index);
setStyle(cell[1][1], "BROWN", HSSFColor.BROWN.index);
setStyle(cell[1][2], "CORAL", HSSFColor.CORAL.index);
setStyle(cell[1][3], "CORNFLOWER_BLUE",
HSSFColor.CORNFLOWER_BLUE.index);
setStyle(cell[2][0], "DARK_BLUE", HSSFColor.DARK_BLUE.index);
setStyle(cell[2][1], "DARK_GREEN", HSSFColor.DARK_GREEN.index);
setStyle(cell[2][2], "DARK_RED", HSSFColor.DARK_RED.index);
setStyle(cell[2][3], "DARK_TEAL", HSSFColor.DARK_TEAL.index);
setStyle(cell[3][0], "DARK_YELLOW",
HSSFColor.DARK_YELLOW.index);
setStyle(cell[3][1], "GOLD", HSSFColor.GOLD.index);
setStyle(cell[3][2], "GREEN", HSSFColor.GREEN.index);
setStyle(cell[3][3], "GREY_25_PERCENT",
HSSFColor.GREY_25_PERCENT.index);
setStyle(cell[4][0], "GREY_40_PERCENT",
HSSFColor.GREY_40_PERCENT.index);
setStyle(cell[4][1], "GREY_50_PERCENT",
HSSFColor.GREY_50_PERCENT.index);
setStyle(cell[4][2], "GREY_80_PERCENT",
HSSFColor.GREY_80_PERCENT.index);
setStyle(cell[4][3], "INDIGO", HSSFColor.INDIGO.index);
setStyle(cell[5][0], "LAVENDER", HSSFColor.LAVENDER.index);
setStyle(cell[5][1], "LEMON_CHIFFON",
HSSFColor.LEMON_CHIFFON.index);
setStyle(cell[5][2], "LIGHT_BLUE",
HSSFColor.LIGHT_BLUE.index);
setStyle(cell[5][3], "LIGHT_CORNFLOWER_BLUE",
HSSFColor.LIGHT_CORNFLOWER_BLUE.index);
setStyle(cell[6][0], "LIGHT_GREEN",
HSSFColor.LIGHT_GREEN.index);
setStyle(cell[6][1], "LIGHT_ORANGE",
HSSFColor.LIGHT_ORANGE.index);
setStyle(cell[6][2], "LIGHT_TURQUOISE",
HSSFColor.LIGHT_TURQUOISE.index);
setStyle(cell[6][3], "LIGHT_YELLOW",
HSSFColor.LIGHT_YELLOW.index);
setStyle(cell[7][0], "LIME", HSSFColor.LIME.index);
setStyle(cell[7][1], "MAROON", HSSFColor.MAROON.index);
setStyle(cell[7][2], "OLIVE_GREEN",
HSSFColor.OLIVE_GREEN.index);
setStyle(cell[7][3], "ORANGE", HSSFColor.ORANGE.index);
setStyle(cell[8][0], "ORCHID", HSSFColor.ORCHID.index);
setStyle(cell[8][1], "PALE_BLUE", HSSFColor.PALE_BLUE.index);
setStyle(cell[8][2], "PINK", HSSFColor.PINK.index);
setStyle(cell[8][3], "PLUM", HSSFColor.PLUM.index);
setStyle(cell[9][0], "RED", HSSFColor.RED.index);
setStyle(cell[9][1], "ROSE", HSSFColor.ROSE.index);
setStyle(cell[9][2], "ROYAL_BLUE",
HSSFColor.ROYAL_BLUE.index);
setStyle(cell[9][3], "SEA_GREEN", HSSFColor.SEA_GREEN.index);
setStyle(cell[10][0], "SKY_BLUE", HSSFColor.SKY_BLUE.index);
setStyle(cell[10][1], "TAN", HSSFColor.TAN.index);
setStyle(cell[10][2], "TEAL", HSSFColor.TEAL.index);
setStyle(cell[10][3], "TURQUOISE",
HSSFColor.TURQUOISE.index);
setStyle(cell[11][0], "VIOLET", HSSFColor.VIOLET.index);
setStyle(cell[11][1], "WHITE", HSSFColor.WHITE.index);
setStyle(cell[11][2], "YELLOW", HSSFColor.YELLOW.index);
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
public static void setStyle(HSSFCell cell, String col, short fg){
HSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(fg);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell.setCellStyle(style);
cell.setCellValue(col);
}
}
上面程序只指定了「ForegroundColor」,填充模式是「SOLID_FOREGROUND」,因此顔色应该是全部充满整个单元格的。运行结果如下:
下面再对填充模式进行各种修改来看看。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
public class POISample{
static HSSFWorkbook workbook;
public static void main(String[] args){
workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row[] = new HSSFRow[5];
for (int i = 0; i < 5 ; i++){
row[i] = sheet.createRow(i);
}
HSSFCell cell[][] = new HSSFCell[5][4];
for (int i = 0; i < 5; i++){
for (int j = 0; j < 4 ; j++){
cell[i][j] = row[i].createCell((short)j);
}
}
setStyle(cell[0][0], "NO_FILL", HSSFCellStyle.NO_FILL);
setStyle(cell[0][1], "SOLID_FOREGROUND",
HSSFCellStyle.SOLID_FOREGROUND);
setStyle(cell[0][2], "FINE_DOTS", HSSFCellStyle.FINE_DOTS);
setStyle(cell[0][3], "ALT_BARS", HSSFCellStyle.ALT_BARS);
setStyle(cell[1][0], "SPARSE_DOTS", HSSFCellStyle.SPARSE_DOTS);
setStyle(cell[1][1], "THICK_HORZ_BANDS",
HSSFCellStyle.THICK_HORZ_BANDS);
setStyle(cell[1][2], "THICK_VERT_BANDS",
HSSFCellStyle.THICK_VERT_BANDS);
setStyle(cell[1][3], "THICK_BACKWARD_DIAG",
HSSFCellStyle.THICK_BACKWARD_DIAG);
setStyle(cell[2][0], "THICK_FORWARD_DIAG",
HSSFCellStyle.THICK_FORWARD_DIAG);
setStyle(cell[2][1], "BIG_SPOTS", HSSFCellStyle.BIG_SPOTS);
setStyle(cell[2][2], "BRICKS", HSSFCellStyle.BRICKS);
setStyle(cell[2][3], "THIN_HORZ_BANDS",
HSSFCellStyle.THIN_HORZ_BANDS);
setStyle(cell[3][0], "THIN_VERT_BANDS",
HSSFCellStyle.THIN_VERT_BANDS);
setStyle(cell[3][1], "THIN_BACKWARD_DIAG",
HSSFCellStyle.THIN_BACKWARD_DIAG);
setStyle(cell[3][2], "THIN_FORWARD_DIAG",
HSSFCellStyle.THIN_FORWARD_DIAG);
setStyle(cell[3][3], "SQUARES", HSSFCellStyle.SQUARES);
setStyle(cell[4][0], "DIAMONDS", HSSFCellStyle.DIAMONDS);
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
public static void setStyle(HSSFCell cell, String fps,
short fp){
HSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(HSSFColor.WHITE.index);
style.setFillForegroundColor(HSSFColor.LIGHT_ORANGE.index);
style.setFillPattern(fp);
cell.setCellStyle(style);
cell.setCellValue(fps);
}
}
上面固定了「ForegroundColor」和「BackgroundColor」,而填充模式则做了各种尝试。运行结果如下:
================
POI调色板操作
上一节介绍了如何设定POI里已经准备好的顔色,但有时你想要的顔色不在这个范围内,怎么办呢?这一节就来介绍如何使用调色板的RGB的值来设定你喜欢的顔色。
要创建一个新的颜色,在调色板里如果有这个对应值那当然没问题。那有没有可能你想要的顔色在调色板里也没有呢?关于这个解决办法还不知道。总之,先从有对应值的来做做看吧。
首先取出现在正在使用的调色板。调色板是由「HSSFPalette」类定义的。其定义如下:
构造方法虽然有一个,但仍然是protected的,所以也不能直接使用,而要用「HSSFWorkbook」类的「getCustomPalette」方法来取得调色板对象。
getCustomPalette
public HSSFPalette getCustomPalette()
--
非常遗憾,该方法也是没有任何说明,原因不明。先按下面的方法使用吧。
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFPalette palette = workbook.getCustomPalette();
调色板取得后,就可以使用「HSSFPalette」类的「setColorAtIndex」方法设定自己想要的顔色了。
setColorAtIndex
public void setColorAtIndex(short index,
byte red, byte green, byte blue)
Sets the color at the given offset
Parameters:
index - the palette index, between 0x8 to
0x40 inclusive
red - the RGB red component, between 0
and 255 inclusive
green - the RGB green component, between 0
and 255 inclusive
blue - the RGB blue component, between 0
and 255 inclusive
第一个参数设定你想要顔色的主色调的index号,如上一节一样,使用「HSSFColor」类的子类。
HSSFColor.RED.index
剩下的三个参数,通过设定RGB值来调节你想要的顔色。每一个都可以设定0~255的值。
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFPalette palette = workbook.getCustomPalette();
palette.setColorAtIndex(HSSFColor.RED.index,
(byte)100, (byte)0, (byte)0);
示例程序
自己做做看吧,首先要确定你想要顔色的主色调。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);
HSSFCell cell = row.createCell((short)1);
HSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(HSSFColor.RED.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell.setCellStyle(style);
cell.setCellValue("RED");
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
上面程序对一个单元格设定了红色「HSSFColor.RED」的主色调,运行结果如下:
下面就对这个顔色通过RGB值来做一些改动吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.usermodel.HSSFPalette;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFPalette palette = workbook.getCustomPalette();
palette.setColorAtIndex(HSSFColor.RED.index,
(byte)128, (byte)0, (byte)0);
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);
HSSFCell cell = row.createCell((short)1);
HSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(HSSFColor.RED.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
cell.setCellStyle(style);
cell.setCellValue("RED");
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
上面程序使用调色板对红色「HSSFColor.RED」进行了一些改动,之后用前面一个例子的方法同样设定红色,但得到的结果却是不一样的。运行结果如下:
因为调色板在一个workbook里是共有的,所以如果用调色板改变了某一种顔色,下次使用时,相同的顔色就全部改变了。
===============
POI设置边框
在做一个电子表格时,边框的设置有时是必不可少的。这一节就来介绍边框,设置时,可以指定边框的位置,边框的种类,边框的顔色。
首先是边框的位置和种类。对单元格设置边框时,有上下左右位置之分,所以POI也准备了四个不同的方法。
上部的边框:
setBorderTop
public void setBorderTop(short border)
set the type of border to use for the top
border of the cell
Parameters:
border - type
下部的边框:
setBorderBottom
public void setBorderBottom(short border)
set the type of border to use for the
bottom border of the cell
Parameters:
border - type
左侧的边框:
setBorderLeft
public void setBorderLeft(short border)
set the type of border to use for the
left border of the cell
Parameters:
border - type
右侧的边框:
setBorderRight
public void setBorderRight(short border)
set the type of border to use for the
right border of the cell
Parameters:
border - type
参数通过表示边框种类的short型值来指定。下面是定义在「HSSFCellStyle」类里可以被指定值的一览表。
值 |
说明 |
BORDER_DASH_DOT |
dash-dot border |
BORDER_DASH_DOT_DOT |
dash-dot-dot border |
BORDER_DASHED |
dash border |
BORDER_DOTTED |
dot borderhair-line border |
BORDER_DOUBLE |
double-line border |
BORDER_HAIR |
hair-line border |
BORDER_MEDIUM |
Medium border |
BORDER_MEDIUM_DASH_DOT |
medium dash-dot border |
BORDER_MEDIUM_DASH_DOT_DOT |
medium dash-dot-dot border |
BORDER_MEDIUM_DASHED |
Medium dashed border |
BORDER_NONE |
No border |
BORDER_SLANTED_DASH_DOT |
slanted dash-dot border |
BORDER_THICK |
Thick border |
BORDER_THIN |
Thin border |
比如要在单元格下边框设置两重线的边框时,按如下方法:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFCellStyle style = workbook.createCellStyle();
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
下面再看看指定边框顔色。同样也分为上下左右边框来操作。
上部的边框:
setTopBorderColor
public void setTopBorderColor(short color)
set the color to use for the top border
Parameters:
color -
下部的边框:
setBottomBorderColor
public void setBottomBorderColor(short color)
set the color to use for the bottom border
Parameters:
color -
左侧的边框:
setLeftBorderColor
public void setLeftBorderColor(short color)
set the color to use for the left border
Parameters:
color -
右侧的边框:
setRightBorderColor
public void setRightBorderColor(short color)
set the color to use for the right border
Parameters:
color -
仍然是通过参数来指定顔色,而且使用方法和前面一节也是一样。具体如下:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFCellStyle style = workbook.createCellStyle();
style.setRightBorderColor(HSSFColor.RED.index);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
示例程序
实际动手做做吧。首先看看如何设置上下左右的边框。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.usermodel.HSSFPalette;
public class POISample{
public static void main(String[] args){
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(1);
HSSFCell cell1 = row.createCell((short)1);
HSSFCell cell2 = row.createCell((short)2);
HSSFCellStyle style1 = workbook.createCellStyle();
style1.setBorderTop(HSSFCellStyle.BORDER_DOUBLE);
style1.setBorderLeft(HSSFCellStyle.BORDER_DOUBLE);
style1.setTopBorderColor(HSSFColor.GOLD.index);
style1.setLeftBorderColor(HSSFColor.PLUM.index);
cell1.setCellStyle(style1);
HSSFCellStyle style2 = workbook.createCellStyle();
style2.setBorderBottom(HSSFCellStyle.BORDER_DOUBLE);
style2.setBorderRight(HSSFCellStyle.BORDER_DOUBLE);
style2.setBottomBorderColor(HSSFColor.ORANGE.index);
style2.setRightBorderColor(HSSFColor.SKY_BLUE.index);
cell2.setCellStyle(style2);
cell1.setCellValue("U & L");
cell2.setCellValue("B & R");
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
}
上面程序既改了顔色,也设置了上和左的边框各一个,右和下的边框各一个。
下面再对边框种类进行各种各样的顔色改变来看看效果。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.util.HSSFColor;
public class POISample{
static HSSFWorkbook workbook;
public static void main(String[] args){
workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row[] = new HSSFRow[5];
for (int i = 0; i < 5 ; i++){
row[i] = sheet.createRow(i);
}
HSSFCell cell[][] = new HSSFCell[5][3];
for (int i = 0; i < 5; i++){
for (int j = 0; j < 3 ; j++){
cell[i][j] = row[i].createCell((short)j);
}
}
setStyle(cell[0][0], "DASH_DOT",
HSSFCellStyle.BORDER_DASH_DOT);
setStyle(cell[0][1], "DASH_DOT_DOT",
HSSFCellStyle.BORDER_DASH_DOT_DOT);
setStyle(cell[0][2], "DASHED",
HSSFCellStyle.BORDER_DASHED);
setStyle(cell[1][0], "DOTTED",
HSSFCellStyle.BORDER_DOTTED);
setStyle(cell[1][1], "DOUBLE",
HSSFCellStyle.BORDER_DOUBLE);
setStyle(cell[1][2], "HAIR",
HSSFCellStyle.BORDER_HAIR);
setStyle(cell[2][0], "MEDIUM",
HSSFCellStyle.BORDER_MEDIUM);
setStyle(cell[2][1], "MEDIUM_DASH_DOT",
HSSFCellStyle.BORDER_MEDIUM_DASH_DOT);
setStyle(cell[2][2], "MEDIUM_DASH_DOT_DOT",
HSSFCellStyle.BORDER_MEDIUM_DASH_DOT_DOT);
setStyle(cell[3][0], "MEDIUM_DASHED",
HSSFCellStyle.BORDER_MEDIUM_DASHED);
setStyle(cell[3][1], "NONE",
HSSFCellStyle.BORDER_NONE);
setStyle(cell[3][2], "SLANTED_DASH_DOT",
HSSFCellStyle.BORDER_SLANTED_DASH_DOT);
setStyle(cell[4][0], "THICK", HSSFCellStyle.BORDER_THICK);
setStyle(cell[4][1], "THIN", HSSFCellStyle.BORDER_THIN);
FileOutputStream out = null;
try{
out = new FileOutputStream("sample.xls");
workbook.write(out);
}catch(IOException e){
System.out.println(e.toString());
}finally{
try {
out.close();
}catch(IOException e){
System.out.println(e.toString());
}
}
}
public static void setStyle(HSSFCell cell,
String bn, short border){
HSSFCellStyle style = workbook.createCellStyle();
style.setBorderBottom(border);
style.setBottomBorderColor(HSSFColor.ORANGE.index);
cell.setCellStyle(style);
cell.setCellValue(bn);
}
}
运行结果如下:
==========================================异常华丽的分割线=============================================================
添加 POI 支持
鉴于现在大部分应用是以 Maven 作为构建,可在 pom.xml 中加入 POI 的 maven 依赖,但是 maven 现在只支持到 3.1 版本,对 3.5 版本还不提供支持。
因此可以直接在 Apache 官网下载 POI3.5 版本,作为 reference library 加入 工程中
创建新工作簿 Workbook wb = new HSSFWorkbook(); FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
Workbook wb = new XSSFWorkbook(); FileOutputStream fileOut = new FileOutputStream("workbook.xlsx"); wb.write(fileOut); fileOut.close();
创建新 sheet 页 Workbook wb = new HSSFWorkbook(); //Workbook wb = new XSSFWorkbook(); Sheet sheet1 = wb.createSheet("new sheet"); Sheet sheet2 = wb.createSheet("second sheet"); FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
创建单元格 Workbook wb = new HSSFWorkbook(); //Workbook wb = new XSSFWorkbook(); CreationHelper createHelper = wb.getCreationHelper(); Sheet sheet = wb.createSheet("new sheet");
//创建一列,在其中加入多个单元格,列索引号从 0 开始,单元格的索引号也是从 0 //开始
POI3.5 HSSF&XSSF Excel 操作快速入门
6
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
Row row = sheet.createRow((short)0);1 //创建一个单元格,并在其中加入内容. Cell cell = row.createCell(0); cell.setCellValue(1);
// 上面的多行代码可以采用下面的一行代码的方式完成 row.createCell(1).setCellValue(1.2); row.createCell(2).setCellValue( createHelper.createRichTextString("This is a string")); row.createCell(3).setCellValue(true);
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
新建一个时间格式的单元格 //Workbook wb = new XSSFWorkbook(); CreationHelper createHelper = wb.getCreationHelper(); Sheet sheet = wb.createSheet("new sheet");
//创建一列,在其中加入多个单元格,列索引号从 0 开始,单元格的索引号也是从 0 //开始 Row row = sheet.createRow(0);
//创建一个单元格,并在其中加入内容. 第一个单元格的内容不设置为日期时间格式 Cell cell = row.createCell(0); cell.setCellValue(new Date());
//我们将第二个单元格设置成日期(和时间)格式。对这个文件来说创建一个新的单 //元格格式非常重要,除非您能够不用内置的格式来渲染所有的单元格 CellStyle cellStyle = wb.createCellStyle(); cellStyle.setDataFormat( createHelper.createDataFormat().getFormat("m/d/yy h:mm")); cell = row.createCell(1); cell.setCellValue(new Date()); cell.setCellStyle(cellStyle);
//也可以用 java.util.Calendar 来设置单元格格式 cell = row.createCell(2); cell.setCellValue(Calendar.getInstance());
1 很多方法的参数是 short 而不是 int 所以需要做一次类型转换 --译者注
POI3.5 HSSF&XSSF Excel 操作快速入门
7
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
cell.setCellStyle(cellStyle);
// 将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
处理不同内容格式的单元格 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet"); Row row = sheet.createRow((short)2); row.createCell(0).setCellValue(1.1); row.createCell(1).setCellValue(new Date()); row.createCell(2).setCellValue(Calendar.getInstance()); row.createCell(3).setCellValue("a string"); row.createCell(4).setCellValue(true); row.createCell(5).setCellType(HSSFCell.CELL_TYPE_ERROR);
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
遍历列和单元格 有些时候您仅希望遍历一个 sheet 页中所有的列或是一列中所有的单元格。这可以用 一个简单的 for 循环来实现。
幸运的是,这非常简单。Row 对象定义了一个 CellIterator 内部类用来处理单元格的 遍历(可以通过调用 row.cellIterator() 来获得 Iterator 对象),另外,Sheet 对象提供 了一个 rowIterator()方法对所有列进行遍历
除此之外,Sheet 和 Row 对象都实现了 java.lang.Iterable 接口,因此如果您用的 是 Java 1.5 及以上版本,您可以简单的调用内置的“foreach”来实现。请看:
Sheet sheet = wb.getSheetAt(0); for (Iterator
POI3.5 HSSF&XSSF Excel 操作快速入门
8
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
} 使用 J ava1.5 foreach 循环遍历列和单元格
有时候您仅希望遍历一个 sheet 页中所有的列或是一列中所有的单元格。如果您使用的是 java1.5 或是以上版本,那么这将十分的方便,因为它支持新的 foreach 循环。
幸运的是,这非常的简单。Sheet 和 Row 对象都实现了 java.lang.Iterable 接口支持 foreach 循环。对 Row 对象来说它支持通过调用 CellIterator 内部类用来处理单元格的 遍历,对于 Sheet 对象来说它提供了一个 rowIterator()方法对所有列进行遍历。
Sheet sheet = wb.getSheetAt(0); for (Row row : sheet) { for (Cell cell : row) { // Do something here } }
获得单元格内的内容
要想获得单元格内的内容,您首先要要知道单元格内容的格式(比如您想获得从字符 格式的单元格内获得一个数字,您将得到的是 NumberFormatException 错误)。因此, 您将希望能够切换到该单元格格式,然后为获得该单元格内容调用合适的 getter 方法。
在以下的代码中我们将对一个 sheet 页中的所有单元格进行遍历,并打印出单元格的引用 和内容。
// import org.apache.poi.ss.usermodel.*;
Sheet sheet1 = wb.getSheetAt(0); for (Row row : sheet1) { for (Cell cell : row) { CellReference cellRef = new CellReference(row.getRowNum(), cell.getCellNum()); System.out.print(cellRef.formatAsString()); System.out.print(" - "); switch(cell.getCellType()) { case Cell.CELL_TYPE_STRING: System.out.println(cell.getRichStringCellValue().getString()); break; case Cell.CELL_TYPE_NUMERIC: if(DateUtil.isCellDateFormatted(cell)) { System.out.println(cell.getDateCellValue()); } else { System.out.println(cell.getNumericCellValue());
POI3.5 HSSF&XSSF Excel 操作快速入门
9
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
} break; case Cell.CELL_TYPE_BOOLEAN: System.out.println(cell.getBooleanCellValue()); break; case Cell.CELL_TYPE_FORMULA: System.out.println(cell.getCellFormula()); break; default: System.out.println(); } } }
文本提取
对于大多数的文本提取需求,标准的 ExcelExtractor 类应该能够满足您所有的需求。
InputStream inp = new FileInputStream("workbook.xls"); HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(inp)); ExcelExtractor extractor = new ExcelExtractor(wb);
extractor.setFormulasNotResults(true); extractor.setIncludeSheetNames(false); String text = extractor.getText();
对于特殊的文本提取,比如将 xls 文件内容写入 csv 文件,可以参考: /src/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSV mra.java 文件
单元格的各种对齐方式 public static void main(String[] args) throws Exception { Workbook wb = new XSSFWorkbook(); //或者是 new HSSFWorkbook();
Sheet sheet = wb.createSheet(); Row row = sheet.createRow((short) 2); row.setHeightInPoints(30);
createCell(wb, row, (short) 0, XSSFCellStyle.ALIGN_CENTER, XSSFCellStyle.VERTICAL_BOTTOM); createCell(wb, row, (short) 1, XSSFCellStyle.ALIGN_CENTER_SELECTION, XSSFCellStyle.VERTICAL_BOTTOM); createCell(wb, row, (short) 2, XSSFCellStyle.ALIGN_FILL, XSSFCellStyle.VERTICAL_CENTER);
POI3.5 HSSF&XSSF Excel 操作快速入门
10
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
createCell(wb, row, (short) 3, XSSFCellStyle.ALIGN_GENERAL, XSSFCellStyle.VERTICAL_CENTER); createCell(wb, row, (short) 4, XSSFCellStyle.ALIGN_JUSTIFY, XSSFCellStyle.VERTICAL_JUSTIFY); createCell(wb, row, (short) 5, XSSFCellStyle.ALIGN_LEFT, XSSFCellStyle.VERTICAL_TOP); createCell(wb, row, (short) 6, XSSFCellStyle.ALIGN_RIGHT, XSSFCellStyle.VERTICAL_TOP);
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("xssf-align.xlsx"); wb.write(fileOut); fileOut.close();
}
/** *创建一个单元格并为其设定指定的对齐方式. * * @param wb 工作簿 * @param row 单元格所在的列 * @param column 单元格所在的行索引号 * @param halign 单元格的水平对齐方式. */ private static void createCell(Workbook wb, Row row, short column, short halign, short valign) { Cell cell = row.createCell(column); cell.setCellValue(new XSSFRichTextString("Align It")); CellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(halign); cellStyle.setVerticalAlignment(valign); cell.setCellStyle(cellStyle); }
如何处理边框 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet");
//创建一列,在其中加入多个单元格,列索引号从 0 开始,单元格的索引号也是从 0 //开始. Row row = sheet.createRow(1);
POI3.5 HSSF&XSSF Excel 操作快速入门
11
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
//创建一个单元格,并在其中加入内容. Cell cell = row.createCell(1); cell.setCellValue(4);
//设置单元格边框为四周环绕. CellStyle style = wb.createCellStyle(); style.setBorderBottom(CellStyle.BORDER_THIN); style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); style.setBorderLeft(CellStyle.BORDER_THIN); style.setLeftBorderColor(IndexedColors.GREEN.getIndex()); style.setBorderRight(CellStyle.BORDER_THIN); style.setRightBorderColor(IndexedColors.BLUE.getIndex()); style.setBorderTop(CellStyle.BORDER_MEDIUM_DASHED); style.setTopBorderColor(IndexedColors.BLACK.getIndex()); cell.setCellStyle(style);
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
填充色和颜色操作 Workbook wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet");
//创建一列,在其中加入多个单元格,列索引号从 0 开始,单元格的索引号也是从 0 //开始 Row row = sheet.createRow((short) 1);
// 浅绿色背景色 CellStyle style = wb.createCellStyle(); style.setFillBackgroundColor(IndexedColors.AQUA.getIndex()); style.setFillPattern(CellStyle.BIG_SPOTS); Cell cell = row.createCell((short) 1); cell.setCellValue("X"); cell.setCellStyle(style);
//橙色前景色。前景色:前景色是指正在使用的填充颜色,而非字体颜色 style = wb.createCellStyle(); style.setFillForegroundColor(IndexedColors.ORANGE.getIndex()); style.setFillPattern(CellStyle.SOLID_FOREGROUND); cell = row.createCell((short) 2); cell.setCellValue("X");
POI3.5 HSSF&XSSF Excel 操作快速入门
12
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
cell.setCellStyle(style);
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
合并单元格 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet");
Row row = sheet.createRow((short) 1); Cell cell = row.createCell((short) 1); cell.setCellValue("This is a test of merging");
sheet.addMergedRegion(new CellRangeAddress( 1, //first row (0-based) 1, //last row (0-based) 1, //first column (0-based) 2 //last column (0-based) ));
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
字体的处理 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet");
//创建一列,在其中加入多个单元格,列索引号从 0 开始,单元格的索引号也是从 0 //开始 Row row = sheet.createRow(1);
// 创建一个字体并修改它的样式. Font font = wb.createFont(); font.setFontHeightInPoints((short)24); font.setFontName("Courier New"); font.setItalic(true); font.setStrikeout(true);
POI3.5 HSSF&XSSF Excel 操作快速入门
13
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
//字体在样式(style)中载入才能使用,因此创建一个 style 来使用该字体 CellStyle style = wb.createCellStyle(); style.setFont(font);
//创建一个单元格,并在其中加入内容. Cell cell = row.createCell(1); cell.setCellValue("This is a test of fonts"); cell.setCellStyle(style);
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close(); 注意: 一个工作簿中最大的自定义字体数目为 32767(short 类型最大正数)。您应当复用这些字 体,而不是为每一个单元格新建一个字体。比如:
错误的用法:
for (int i = 0; i < 10000; i++) { Row row = sheet.createRow(i); Cell cell = row.createCell((short) 0);
CellStyle style = workbook.createCellStyle(); Font font = workbook.createFont(); font.setBoldweight(Font.BOLDWEIGHT_BOLD); style.setFont(font); cell.setCellStyle(style); }
正确的用法 :
CellStyle style = workbook.createCellStyle(); Font font = workbook.createFont(); font.setBoldweight(Font.BOLDWEIGHT_BOLD); style.setFont(font); for (int i = 0; i < 10000; i++) { Row row = sheet.createRow(i); Cell cell = row.createCell((short) 0); cell.setCellStyle(style); }
POI3.5 HSSF&XSSF Excel 操作快速入门
14
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
自定义颜色
HSSF:
HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(); HSSFRow row = sheet.createRow((short) 0); HSSFCell cell = row.createCell((short) 0); cell.setCellValue("Default Palette");
//就像上面一个例子一样从标准调色板上获得几种颜色 //我们将在石灰色的背景上应用红色字体
HSSFCellStyle style = wb.createCellStyle(); style.setFillForegroundColor(HSSFColor.LIME.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
HSSFFont font = wb.createFont(); font.setColor(HSSFColor.RED.index); style.setFont(font);
cell.setCellStyle(style);
//替换保存为默认调色板 FileOutputStream out = new FileOutputStream("default_palette.xls"); wb.write(out); out.close();
//现在然我们把橙色和石灰色的组合替换成更有吸引力的组合 // 还是比较喜欢 freebsd.org 提供的色彩方案
cell.setCellValue("Modified Palette");
//为该工作簿新建一个调色板 HSSFPalette palette = wb.getCustomPalette();
//替换标准红色为 freebsd.org 上的红色 palette.setColorAtIndex(HSSFColor.RED.index, (byte) 153, //RGB red (0-255) (byte) 0, //RGB green (byte) 0 //RGB blue ); //替换石灰色为 freebsd.org 上的金色
POI3.5 HSSF&XSSF Excel 操作快速入门
15
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
palette.setColorAtIndex(HSSFColor.LIME.index, (byte) 255, (byte) 204, (byte) 102);
//将其保存为“修改过的调色板” // 注意,不论我们以前在哪里用到了红色和石灰色,都会奇迹般的换上现在的颜色 out = new FileOutputStream("modified_palette.xls"); wb.write(out); out.close();
XSSF:
XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet(); XSSFRow row = sheet.createRow(0); XSSFCell cell = row.createCell( 0); cell.setCellValue("custom XSSF colors");
XSSFCellStyle style1 = wb.createCellStyle(); style1.setFillForegroundColor(new XSSFColor(new java.awt.Color(128, 0, 128))); style1.setFillPattern(CellStyle.SOLID_FOREGROUND);
读取和重写工作簿 InputStream inp = new FileInputStream("workbook.xls"); //InputStream inp = new FileInputStream("workbook.xlsx");
Workbook wb = WorkbookFactory.create(inp); Sheet sheet = wb.getSheetAt(0); Row row = sheet.getRow(2); Cell cell = row.getCell(3); if (cell == null) cell = row.createCell(3); cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue("a test");
//将输出流写入一个文件 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
在单元格中使用换行 Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
POI3.5 HSSF&XSSF Excel 操作快速入门
16
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(2); Cell cell = row.createCell(2); cell.setCellValue("Use \n with word wrap on to create a new line");
//为了能够使用换行,您需要设置单元格的样式 wrap=true CellStyle cs = wb.createCellStyle(); cs.setWrapText(true); cell.setCellStyle(cs);
//增加单元格的高度已能够容纳两行文字 row.setHeightInPoints((2*sheet.getDefaultRowHeightInPoints()));
// 调整列宽以使用内容长度 sheet.autoSizeColumn((short)2);
FileOutputStream fileOut = new FileOutputStream("ooxml-newlines.xlsx"); wb.write(fileOut); fileOut.close();
创建用户自定义数据格式 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("format sheet"); CellStyle style; DataFormat format = wb.createDataFormat(); Row row; Cell cell; short rowNum = 0; short colNum = 0;
row = sheet.createRow(rowNum++); cell = row.createCell(colNum); cell.setCellValue(11111.25); style = wb.createCellStyle(); style.setDataFormat(format.getFormat("0.0")); cell.setCellStyle(style);
row = sheet.createRow(rowNum++); cell = row.createCell(colNum); cell.setCellValue(11111.25);
POI3.5 HSSF&XSSF Excel 操作快速入门
17
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
style = wb.createCellStyle(); style.setDataFormat(format.getFormat("#,##0.0000")); cell.setCellStyle(style);
FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
Sheet 页自适应页面大小 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("format sheet"); PrintSetup ps = sheet.getPrintSetup();
sheet.setAutobreaks(true);
ps.setFitHeight((short)1); ps.setFitWidth((short)1);
//为电子表格创建多行多列. 。。。。。。。 FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
设定打印区域 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("Sheet1"); //为第一个 sheet 页设定打印区域 wb.setPrintArea(0, "$A$1:$C$2"); //也可以这样实现: wb.setPrintArea( 0, //sheet 页标 0, //开始列标 1, //结束列标 0, //开始行标 0 //结束行标 );
FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut);
POI3.5 HSSF&XSSF Excel 操作快速入门
18
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
fileOut.close();
设置脚注页码 HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet("format sheet"); HSSFFooter footer = sheet.getFooter()
footer.setRight( "Page " + HSSFFooter.page() + " of " + HSSFFooter.numPages() );
//为电子表格创建多行多列 。。。。。。
FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
使用便捷函数
便捷函数存在于 contrib2中,并提供许多实用功能如不用明确的新建一个样式就能够为合 并区域设置边框和改变样式。
HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet1 = wb.createSheet( "new sheet" );
//创建一个合并区域 HSSFRow row = sheet1.createRow( (short) 1 ); HSSFRow row2 = sheet1.createRow( (short) 2 ); HSSFCell cell = row.createCell( (short) 1 ); cell.setCellValue( "This is a test of merging" ); Region region = new Region( 1, (short) 1, 4, (short) 4 ); sheet1.addMergedRegion( region );
// 设置边框和边框颜色 final short borderMediumDashed = HSSFCellStyle.BORDER_MEDIUM_DASHED; HSSFRegionUtil.setBorderBottom( borderMediumDashed, region, sheet1, wb ); HSSFRegionUtil.setBorderTop( borderMediumDashed, region, sheet1, wb );
2Contrib:外围爱好者根据需要自行编译并贡献的软件 —译者注
POI3.5 HSSF&XSSF Excel 操作快速入门
19
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
HSSFRegionUtil.setBorderLeft( borderMediumDashed, region, sheet1, wb ); HSSFRegionUtil.setBorderRight( borderMediumDashed, region, sheet1, wb ); HSSFRegionUtil.setBottomBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); HSSFRegionUtil.setTopBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); HSSFRegionUtil.setLeftBorderColor(HSSFColor.AQUA.index, region, sheet1, wb); HSSFRegionUtil.setRightBorderColor(HSSFColor.AQUA.index, region, sheet1, wb);
//展示 HSSFCellUtil 的一些用法 HSSFCellStyle style = wb.createCellStyle(); style.setIndention((short)4); HSSFCellUtil.createCell(row, 8, "This is the value of the cell", style); HSSFCell cell2 = HSSFCellUtil.createCell( row2, 8, "This is the value of the cell"); HSSFCellUtil.setAlignment(cell2, wb, HSSFCellStyle.ALIGN_CENTER);
//输出工作簿 FileOutputStream fileOut = new FileOutputStream( "workbook.xls" ); wb.write( fileOut ); fileOut.close();
上下移动一行 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("row sheet");
//为电子表格创建多行多列 。。。。。。 // 将第 6 到 第 11 行移至顶端 第 0 到 第 5 行 sheet.shiftRows(5, 10, -5);
将 sheet 页设定为默认选中 Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("row sheet"); sheet.setSelected(true);
POI3.5 HSSF&XSSF Excel 操作快速入门
20
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
设置 sheet 页放大倍率
放大倍率是用分数来表示的,比如,如果放大倍率是 75%,那么可以用 3/4 来表示
Workbook wb = new HSSFWorkbook(); Sheet sheet1 = wb.createSheet("new sheet"); sheet1.setZoom(3,4); // 75%放大倍率
拆分和冻结窗格
您可以创建两种窗格:冻结窗格和拆分窗格
冻结窗格是由行和列来分隔的。您可以采用以下的方式来创建冻结窗格:
sheet1.createFreezePane( 3, 2, 3, 2 ); 3
The first two parameters are the columns and rows you wish to split by. The second two parameters indicate the cells that are visible in the bottom right quadrant.
前两个参数是您想分隔开的列数和行数,后两个参数表示在右下部分中可见的单元格。其 中第三个参数是右边区域可见的左边列数,第四个参数是下面区域可见的首行。
拆分窗格看起来和冻结窗格很不一样。拆分窗格被分成了 4 个单独的工作区域。拆分是像 素级别的,用户可以通过改变拆分点来调整拆分的效果。
拆分窗格可以通过调用以下方法实现:
sheet2.createSplitPane( 2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT );
第一个参数是拆分点在 X 轴上的坐标。单位是 1/20 个点。在这里可以把一个点看成一个 像素。第二个参数是拆分点在 Y 轴上的坐标,单位同样也是 1/20 个点。第三个参数是右边 区域可见的左边列数,第四个参数是下面区域可见的首行
最后一个参数指定了该拆分点落在了哪个窗格中。一共有四种选项 Sheet.PANE_LOWER_LEFT, PANE_LOWER_RIGHT, PANE_UPPER_RIGHT 或者 PANE_UPPER_LEFT.
Workbook wb = new HSSFWorkbook(); Sheet sheet1 = wb.createSheet("new sheet"); Sheet sheet2 = wb.createSheet("second sheet"); Sheet sheet3 = wb.createSheet("third sheet"); Sheet sheet4 = wb.createSheet("fourth sheet");
// 冻结第一行 sheet1.createFreezePane( 0, 1, 0, 1 );
3 createFreezePane 方法有两种 createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) 和 createFreezePane(int colSplit, int rowSplit) 在冻结整行整列时第二种方法更为简便 –译者注
POI3.5 HSSF&XSSF Excel 操作快速入门
21
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
// 冻结第一列 sheet2.createFreezePane( 1, 0, 1, 0 ); //冻结列和行(这里可以忽略右下方的滚动条的位置) sheet3.createFreezePane( 2, 2 ); //拆分窗口并且使左下方有焦点 sheet4.createSplitPane( 2000, 2000, 0, 0, Sheet.PANE_LOWER_LEFT );
FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
重复列和行
在打印时,可以通过 HSSFWorkbook 类的 setRepeatingRowsAndColumns()方法设 置重复的列和行。
这个方法包含五个参数。第一个参数是 sheet 页的索引(0 代表第一个 sheet 页)。第二 和第三个参数指定了重复列的范围,如果不想重复列的话,可以用-1 代替。第四和第五 个参数指定了重复行的范围,同样如果不想重复行可以用-1 替代起止索引号。
Workbook wb = new HSSFWorkbook(); Sheet sheet1 = wb.createSheet("new sheet"); Sheet sheet2 = wb.createSheet("second sheet");
//设置第一张 sheet 页中的第一到第三列重复 wb.setRepeatingRowsAndColumns(0,0,2,-1,-1); // 为第二张 sheet 页设置重复列和行 wb.setRepeatingRowsAndColumns(1,4,5,1,2);
FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
页眉和页脚
这是一个页眉的例子,但页脚也同样适用
Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet");
Header header = sheet.getHeader(); header.setCenter("Center Header"); header.setLeft("Left Header"); header.setRight(HSSFHeader.font("Stencil-Normal", "Italic") +
POI3.5 HSSF&XSSF Excel 操作快速入门
22
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
HSSFHeader.fontSize((short) 16) + "Right w/ Stencil-Normal Italic font and size 16");
FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
绘制图形
POI 支持调用 MS-Office 绘图工具进行图形的绘制。一张 sheet 页上的图形是按照有层 级的图形组和图形来安排的。最顶层的图形是 patriarch,它在 sheet 页上是不可见的。 在开始绘制图形之前,您需要在 HSSFSheet 对象中调用 createPatriarch 方法。调 用这个方法会清除在该 sheet 页中储存的所有的图形信息。默认情况下只要这个方法不 被调用,POI 不会将图形数据清除。
要创建一个图形,您需要做以下几步:
1. 创建一个 patriarch 对象
2. 创建一个锚点以供图形在 sheet 页上定位
3. 调用 patriarch 对象创建一个图形
4. 设置图形类型(直线,椭圆,矩形等等)
5. 设置图形的其他样式细节(例如:线条粗细等等)
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 ); HSSFSimpleShape shape1 = patriarch.createSimpleShape(a1); shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
文本框的创建方式如下:
HSSFTextbox textbox1 = patriarch.createTextbox( new HSSFClientAnchor(0,0,0,0,(short)1,1,(short)2,2)); textbox1.setString(new HSSFRichTextString("This is a test") );
在同一文本框中设置不同的字体样式也是可以实现的
HSSFFont font = wb.createFont(); font.setItalic(true); font.setUnderline(HSSFFont.U_DOUBLE); HSSFRichTextString string = new HSSFRichTextString("Woo!!!");
POI3.5 HSSF&XSSF Excel 操作快速入门
23
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
string.applyFont(2,5,font); textbox.setString(string );
Just as can be done manually using Excel, it is possible to group shapes together. This is done by calling createGroup() and then creating the shapes using those groups.
如同 Excel 中可以手动设置组一样,调用 createGroup()方法,用新建的组创建图形 也可以实现。组中也可以嵌套其他组。
注意
任何一个组中必须至少包含两个不同图形或是其他的子组。
创建图片组可以参考下面的例子: // 创建一个图片组. HSSFShapeGroup group = patriarch.createGroup( new HSSFClientAnchor(0,0,900,200,(short)2,2,(short)2,2));
//在图片组中创建多条直线. HSSFSimpleShape shape1 = group.createShape(new HSSFChildAnchor(3,3,500,500)); shape1.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); ( (HSSFChildAnchor) shape1.getAnchor() ).setAnchor((short)3,3,500,500); HSSFSimpleShape shape2 = group.createShape(new HSSFChildAnchor((short)1,200,400,600)); shape2.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE);
如果您足够细心,您将会发下,在图形组中添加的图形使用的是一个新类型的锚点对象 HSSFChildAnchor。这是因为新创建的组会有自己的坐标空间。在 POI 中,这个 坐标 空间默认为(0,0,1023,255),但是您也可以根据自己的意愿进行修改。
myGroup.setCoordinates(10,10,20,20); // top-left, bottom-right
如果您在一个图片组中加入了另外一个图片组,同样该子图片组也有自己的坐标空间。
设置图形样式
默认的图片演示看起来有些平常。为图形设置不同的样式也可以通过 POI 来实现。不过现 在仅能支持以下几种图形样式改变:
变换填充色
POI3.5 HSSF&XSSF Excel 操作快速入门
24
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
去除填充色
改变线条粗细
改变线条样式 比如:虚线,点线等等
改变线条颜色
以下是如何实现
HSSFSimpleShape s = patriarch.createSimpleShape(a); s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_OVAL); s.setLineStyleColor(10,10,10); s.setFillColor(90,10,200); s.setLineWidth(HSSFShape.LINEWIDTH_ONE_PT * 3); s.setLineStyle(HSSFShape.LINESTYLE_DOTSYS);
图形和 Graphics2d 类
虽然推荐使用本地 POI 命名来创建图形,但有时我们也希望调用标准 AIP 获得和外部库 的兼容性。处于这目的我们对 Graphics 和 Graphics2d 类进行了扩充。
注意:
在开始使用之前,您需要知道 Graphics2d 对 MS-office 绘图命令的支持不是很好,虽 然 Graphics 类比起来对 MS-office 绘图命令更加兼容,但仍然差强人意。
所有的绘图指令都封装在 HSSFShapeGroup 类中。以下是它们的用法:
a = new HSSFClientAnchor( 0, 0, 1023, 255, (short) 1, 0, (short) 1, 0 ); group = patriarch.createGroup( a ); group.setCoordinates( 0, 0, 80 * 4 , 12 * 23 ); float verticalPointsPerPixel = a.getAnchorHeightInPoints(sheet) / (float)Math.abs(group.getY2() - group.getY1()); g = new EscherGraphics( group, wb, Color.black, verticalPointsPerPixel ); g2d = new EscherGraphics2d( g ); drawChemicalStructure( g2d );
首先我们做的是为我们将要进行的绘制创建一个组并设置它的坐标。接下来,我们计算出 一个合理的 fontSizeMultipler 创建一个 EscherGraphics 对象。因为我们想得到的是 Graphics2d 对象,所以我们我们新建一个 EscherGraphics2d 对象并把它传入一个创 建好的 Graphics 对 象 中 。 最 后 我 们 会 通 过 一 系 列 流 程 将 它 绘 制 成 一 个 EscherGraphics2d 对象。
在垂直方向上每个点的像素值还需要再深入说明一下。在将 Graphics 对象调用转化成
POI3.5 HSSF&XSSF Excel 操作快速入门
25
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
Escher 对象调用中遇到的一个困难是,在 Excel 中没有明确的对绝对位置的像素定义。 在 Excel 中,单元格的宽度是用“字符”宽度,高度是用“点”来度量的。不幸的是,在 Excel 中并没有明确的定义被用来度量的字符的类型。估计是由于 Excel 想在不同的平台 上或是在同一平台上使用不同的字体造成的。
因为这些限制,我们必须要实现一个标准 verticalPointsPerPixel 用来度量每个垂直方 向点所占的像素。当您调用像是 drawString()这样的方法时,所用到的字体的 verticalPointsPerPixel 度量值必须明确。
计算 verticalPointsPerPixel 值的公式如下:
multipler = groupHeightInPoints / heightOfGroup
图形组的高度可以通过简单的计算不同图形边界盒的 Y 轴坐标来得到。 获得图新组的高 度也可以简单的调用以下这个方法:
HSSFClientAnchor.getAnchorHeightInPoints().
许多 Graphic 类支持的方法还没有实现,现在已知实现的方法是:
fillRect() fillOval() drawString() drawOval() drawLine() clearRect()
现在还不支持的方法会调用 POI 日志机制返回并记录日志信息(默认为 disabled)
提纲
提纲对将不同部分的信息聚合在一起非常重要。它可以用 POI 提供的 API 简单的这样实 现:
Workbook wb = new HSSFWorkbook(); Sheet sheet1 = wb.createSheet("new sheet");
sheet1.groupRow( 5, 14 ); sheet1.groupRow( 7, 14 ); sheet1.groupRow( 16, 19 );
sheet1.groupColumn( (short)4, (short)7 ); sheet1.groupColumn( (short)9, (short)12 ); sheet1.groupColumn( (short)10, (short)11 );
FileOutputStream fileOut = new FileOutputStream(filename);
POI3.5 HSSF&XSSF Excel 操作快速入门
26
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
wb.write(fileOut); fileOut.close(); 折叠(或展开)一个提纲,可以用以下的方法: sheet1.setRowGroupCollapsed( 7, true ); sheet1.setColumnGroupCollapsed( (short)4, true );
被选中的行或列必须包含一个已经创建好的组,可以是组内的任意位置。
图像处理
图像是绘图支持的一部分。提价一张图片可以用最高级别的 Drawing 对象调用 createPicture()。现在支持的图片格式有:
PNG JPG DIB
应当值得注意的是任何已经存在的绘图可能会因为您添加一张图片到 sheet 页上而被清 除
插入图片
//创建一个新的工作簿 Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
//为工作簿添加图片. InputStream is = new FileInputStream("image1.jpeg"); byte[] bytes = IOUtils.toByteArray(is); int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG); is.close();
CreationHelper helper = wb.getCreationHelper();
//创建 sheet 页 Sheet sheet = wb.createSheet();
// 创建顶层的 Drawing 对象,它是所有图形和图像的载体 Drawing drawing = sheet.createDrawingPatriarch();
//添加一个图片图形 ClientAnchor anchor = helper.createClientAnchor();
POI3.5 HSSF&XSSF Excel 操作快速入门
27
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
//设置图形左上角的位置 //然后调用 Picture 的 resize() 方法,自动关联到新坐标 anchor.setCol1(3); anchor.setRow1(2); Picture pict = drawing.createPicture(anchor, pictureIdx);
//自动关联到新坐标 pict.resize();
//保存到工作簿 String file = "picture.xls"; if(wb instanceof XSSFWorkbook) file += "x"; FileOutputStream fileOut = new FileOutputStream(file); wb.write(fileOut); fileOut.close(); 注意 Picture.resize() 现仅支持 JPEG 和 PNG 格式的图片,其他格式暂不支持
从工作簿中读取图片
List lst = workbook.getAllPictures(); for (Iterator it = lst.iterator(); it.hasNext(); ) { PictureData pict = (PictureData)it.next(); String ext = pict.suggestFileExtension(); byte[] data = pict.getData(); if (ext.equals("jpeg")){ FileOutputStream out = new FileOutputStream("pict.jpg"); out.write(data); out.close(); } }
关联范围和关联单元格
关联范围是用一个名字代表一组单元格的方式。关联单元格是关联范围的下一级一组单元 格中的一个。您可以用他们的关联范围创建或是得到对应的单元格。当要处理关联范围时 可 以 用 org.apache.poi.hssf.util.CellReference 和 org.apache.poi.hssf.util.AreaReference 两个类(除了包名不一样外,在 XSSF 和 HSSF 中同样有这两个类)
创建管理范围 / 关联单元格
POI3.5 HSSF&XSSF Excel 操作快速入门
28
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
// 准备数据 String sname = "TestSheet", cname = "TestName", cvalue = "TestVal"; Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet(sname); sheet.createRow(0).createCell((short) 0).setCellValue(cvalue);
//1.用空间引用为一个单元格创建关联范围 Name namedCell = wb.createName(); namedCell.setNameName(cname); String reference = sname+"!A1:A1"; // 空间引用 namedCell.setRefersToFormula(reference);
// 2.用单元格引用为一个单元格创建关联范围 Name namedCel2 = wb.createName(); namedCel2.setNameName(cname); String reference = sname+"!A1"; //单元格引用 namedCel2.setRefersToFormula(reference);
// 3. 用空间引用为一组单元格创建关联范围 Name namedCel3 = wb.createName(); namedCel3.setNameName(cname); String reference = sname+"!A1:C5"; // 空间引用 namedCel3.setRefersToFormula(reference);
// 4. 创建关联方程 Name namedCel4 = wb.createName(); namedCel4.setNameName("my_sum"); namedCel4.setRefersToFormula("SUM(sname+!$I$2:$I$6)");
从关联范围 / 关联单元格读取数据
// 准备数据 String cname = "TestName"; Workbook wb = getMyWorkbook(); // 获得工作簿
//获得关联范围 int namedCellIdx = wb.getNameIndex(cellName); Name aNamedCell = wb.getNameAt(namedCellIdx);
//在关联范围中获得单元格并检测它的内容 AreaReference aref = new AreaReference(aNamedCell.getRefersToFormula()); CellReference[] crefs = aref.getAllReferencedCells(); for (int i=0; i
29
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
Sheet s = wb.getSheet(crefs[i].getSheetName()); Row r = sheet.getRow(crefs[i].getRow()); Cell c = r.getCell(crefs[i].getCol()); //根据单元格数据格式取出单元格内容。。。。。。. } 从不连续的关联范围中读取数据 // 准备数据 String cname = "TestName"; Workbook wb = getMyWorkbook(); // retrieve workbook
// 获得关联范围 // Will be something like "$C$10,$D$12:$D$14"; int namedCellIdx = wb.getNameIndex(cellName); Name aNamedCell = wb.getNameAt(namedCellIdx);
//在关联范围中获得单元格并检测它的内容 //将会返回 C10 单元格和 D12 到 D14 单元格的空间引用 AreaReference[] arefs = AreaReference.generateContiguous(aNamedCell.getRefersToFormula()) ; for (int i=0; i
30
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
为单元格添加注释
注释是不同于单元格的内容是附属于或者从属与单元格的富文本。注释的内容是独立于单 元格独自存储的,并且是在绘制对象中展示的(比如一个文本框),因此它既独立于单元 格同时又与单元格紧密联系。
添加注释
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
CreationHelper factory = wb.getCreationHelper();
Sheet sheet = wb.createSheet(); Cell cell = sheet.createRow(3).createCell(5); cell.setCellValue("F4"); Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = factory.createClientAnchor(); Comment comment = drawing.createCellComment(anchor); RichTextString str = factory.createRichTextString("Hello, World!"); comment.setString(str); comment.setAuthor("Apache POI"); //将注释注册到单元格 cell.setCellComment(comment);
String fname = "comment-xssf.xls"; if(wb instanceof XSSFWorkbook) fname += "x"; FileOutputStream out = new FileOutputStream(fname); wb.write(out); out.close();
读取单元格的注释
Cell cell = sheet.get(3).getColumn((short)1); Comment comment = cell.getCellComment(); if (comment != null) { RichTextString str = comment.getString(); String author = comment.getAuthor(); } // 另外您也可以用 sheet.getCellComment(row, column)来获取内容 comment = sheet.getCellComment(3, 1);
POI3.5 HSSF&XSSF Excel 操作快速入门
31
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
根据内容调整单元格的宽度 Sheet sheet = workbook.getSheetAt(0); sheet.autoSizeColumn((short)0); //调整第一列的宽度 sheet.autoSizeColumn((short)1); //调整第二列的宽度 注意: 因为 HSSFSheet.autoSizeColumn 使用 Java2D 类来计算列的宽度,因此在图形环境 (graphical environment)不可用的情况下,调用会报错。如果图形环境不可用的情况 下,您必须告诉 java 您使用的是 headless 模式,请设置以下系统属性: java.awt.headless=true .
超级链接
获取超级链接
Sheet sheet = workbook.getSheetAt(0);
Cell cell = sheet.getRow(0).getCell((short)0); Hyperlink link = cell.getHyperlink(); if(link != null){ System.out.println(link.getAddress()); }
创建超级链接
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook(); CreationHelper createHelper = wb.getCreationHelper();
//设置单元格格式为超级链接 //默认情况下超级链接为下划线、蓝色字体 CellStyle hlink_style = wb.createCellStyle(); Font hlink_font = wb.createFont(); hlink_font.setUnderline(Font.U_SINGLE); hlink_font.setColor(IndexedColors.BLUE.getIndex()); hlink_style.setFont(hlink_font);
Cell cell; Sheet sheet = wb.createSheet("Hyperlinks"); //URL cell = sheet.createRow(0).createCell((short)0); cell.setCellValue("URL Link");
Hyperlink link =
POI3.5 HSSF&XSSF Excel 操作快速入门
32
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
createHelper.createHyperlink(Hyperlink.LINK_URL); link.setAddress("http://poi.apache.org/"); cell.setHyperlink(link); cell.setCellStyle(hlink_style);
//关联到当前目录的文件 cell = sheet.createRow(1).createCell((short)0); cell.setCellValue("File Link"); link = createHelper.createHyperlink(Hyperlink.LINK_FILE); link.setAddress("link1.xls"); cell.setHyperlink(link); cell.setCellStyle(hlink_style);
//e-mail 关联 cell = sheet.createRow(2).createCell((short)0); cell.setCellValue("Email Link"); link = createHelper.createHyperlink(Hyperlink.LINK_EMAIL); //注意:如果邮件主题中存在空格,请保证是按照 URL 格式书写的 link.setAddress("mailto:[email protected]?subject=Hyperlinks"); cell.setHyperlink(link); cell.setCellStyle(hlink_style);
//关联到工作簿中的位置
//创建一个目标 sheet 页和目标单元格 Sheet sheet2 = wb.createSheet("Target Sheet"); sheet2.createRow(0).createCell((short)0).setCellValue("Target Cell");
cell = sheet.createRow(3).createCell((short)0); cell.setCellValue("Worksheet Link"); Hyperlink link2 = createHelper.createHyperlink(Hyperlink.LINK_DOCUMENT); link2.setAddress("'Target Sheet'!A1"); cell.setHyperlink(link2); cell.setCellStyle(hlink_style);
FileOutputStream out = new FileOutputStream("hyperinks.xlsx"); wb.write(out); out.close();
POI3.5 HSSF&XSSF Excel 操作快速入门
33
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
数据验证
注意:
最新的 3.5 版本,XSSF 数据流不支持数据验证而且 HSSF 数据流也不支持从 sheet 页 中恢复数据的验证
检测用户输入是否与预定义的值相悖
以下的代码中,见限制用户在 A1 单元格中输入的数值仅为 10,20,30 中的一个
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("Data Validation"); CellRangeAddressList addressList = new CellRangeAddressList( 0, 0, 0, 0); DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint( new String[]{"10", "20", "30"}); HSSFDataValidation dataValidation = new HSSFDataValidation (addressList, dvConstraint); datavalidation.setSuppressDropDownArrow(true); sheet.addValidationData(dataValidation);
下拉列表
以下的代码将完成相同的功能,但是提供一个下拉列表供用户选择
HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("Data Validation"); CellRangeAddressList addressList = new CellRangeAddressList( 0, 0, 0, 0); DVConstraint dvConstraint = DVConstraint.createExplicitListConstraint( new String[]{"10", "20", "30"}); HSSFDataValidation dataValidation = new HSSFDataValidation (addressList, dvConstraint); datavalidation.setSuppressDropDownArrow(false); sheet.addValidationData(dataValidation);
错误提示信息
当用户输入非法值是弹出一个消息窗(Message box)告知用户
dataValidation.setErrorStyle(HSSFDataValidation.ErrorStyle.STOP); dataValidation.createErrorBox("Box Title", "Message Text");
POI3.5 HSSF&XSSF Excel 操作快速入门
34
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
替换“Box Title”为您想在消息框标题栏所显示的标题名称,替换“Message Text” 为您的错误提示信息
提示框( Prompt )
当需要验证的单元格被选中时弹出提示框(Prompt)提醒用户
dataValidation.createPromptBox("Title", "Message Text"); dataValidation.setShowPromptBox(true); createPromptBox() 中的第一个参数是提示框的标题,第二个参数是提示信息。 DVConstraint 对象的 createExplicitListConstraint() 传 入 的 参 数 可 以 是 表 示 Integer,floating point, date 或是文本的 String 数组。
高级数据校验
对输入的数据进行校验比如输入一个在 10 到 100 之间整型的值可以用
DVConstraint.createNumericConstraint(int, int, String, String)这个工厂方法
dvConstraint = DVConstraint.createNumericConstraint( DVConstraint.ValidationType.INTEGER, DVConstraint.OperatorType.BETWEEN, "10", "100");
如果查阅一下 javaDoc 可以看到其他的校验方法和可以支持的类型。请记住不是所有的 类型都支持校验 。通过两个 String 类型传入的参数可以是公式。“=”是一个公式的标 志。
dvConstraint = DVConstraint.createNumericConstraint( DVConstraint.ValidationType.INTEGER, DVConstraint.OperatorType.BETWEEN, "=SUM(A1:A3)", "100");
如果 createNumericConstraint()方法已经被调用,那将不能够创建一个下拉列表。同 时 setSuppressDropDownArrow(false)的调用也将被忽略。 时间和日期的约束可以 通 过 调 用 createDateConstraint(int, String, String, String) 或是 createTimeConstraint(int, String, String)来实现。两者的调用与上面的方法类似, javaDoc 中有很详细的解释。
用单元格中数据创建数据校验值
特 定 的 单 元 格 的 内 容 可 以 为 数据校验提 供 校 验 值 。 DVConstraint.createFormulaListConstraint(String)方法对这种校验方式提供支持。 指定从连续的单元格取得的内容作为校验值可以采用以下两种方法中的一种:
dvConstraint = DVConstraint.createFormulaListConstraint("$A$1:$A$3");
POI3.5 HSSF&XSSF Excel 操作快速入门
35
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
或者
HSSFNamedRange namedRange = workbook.createName(); namedRange.setNameName("list1"); namedRange.setRefersToFormula("$A$1:$A$3"); dvConstraint = DVConstraint.createFormulaListConstraint("list1");
在上面两个例子中,用户将可以从下拉列表中选择从 A1A2A3 单元格中取到的值。
所有的数据不一定都是校验值。然而从不同的 sheet 页中取得数据的话,这个 sheet 页 在创建的时候必须别赋予一个 sheet 名,并且这个名字应该在方程式中使用。那么,假设 存在一个名字是“Data Sheet”的 sheet 页,那可以这样操作:
HSSFNamedRange namedRange = workbook.createName(); namedRange.setNameName("list1"); namedRange.setRefersToFormula("'Data Sheet'!$A$1:$A$3"); dvConstraint = DVConstraint.createFormulaListConstraint("list1");
这样也是可以的:
dvConstraint = DVConstraint.createFormulaListConstraint("'Data Sheet'!$A$1:$A$3");
但这样是不行的:
HSSFNamedRange namedRange = workbook.createName(); namedRange.setNameName("list1"); namedRange.setRefersToFormula("'Sheet1'!$A$1:$A$3"); dvConstraint = DVConstraint.createFormulaListConstraint("list1");
这样也是不行的:
dvConstraint = DVConstraint.createFormulaListConstraint("'Sheet1'!$A$1:$A$3");
嵌入其他资源对象
可以对嵌入的 Excel、word、PowerPoint 文档或者其他类型的嵌入对象进行更加进行的 操作。
HSSF:
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("excel_with_embeded.xls")); HSSFWorkbook workbook = new HSSFWorkbook(fs); for (HSSFObjectData obj : workbook.getAllEmbeddedObjects()) { //该对象的 OLE2 类名
POI3.5 HSSF&XSSF Excel 操作快速入门
36
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
String oleName = obj.getOLE2ClassName(); if (oleName.equals("Worksheet")) { DirectoryNode dn = (DirectoryNode) obj.getDirectory(); HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(dn, fs, false); //System.out.println(entry.getName() + ": " + embeddedWorkbook.getNumberOfSheets()); } else if (oleName.equals("Document")) { DirectoryNode dn = (DirectoryNode) obj.getDirectory(); HWPFDocument embeddedWordDocument = new HWPFDocument(dn, fs); //System.out.println(entry.getName() + ": " + embeddedWordDocument.getRange().text()); } else if (oleName.equals("Presentation")) { DirectoryNode dn = (DirectoryNode) obj.getDirectory(); SlideShow embeddedPowerPointDocument = new SlideShow(new HSLFSlideShow(dn, fs)); //System.out.println(entry.getName() + ": " + embeddedPowerPointDocument.getSlides().length); } else { if(obj.hasDirectoryEntry()){ // 文件夹实体类(DirectoryEntry)是一个文档节点( DocumentNode) // 检查它的实体,获得它的内容 DirectoryNode dn = (DirectoryNode) obj.getDirectory(); for (Iterator entries = dn.getEntries(); entries.hasNext();) { Entry entry = (Entry) entries.next(); //System.out.println(oleName + "." + entry.getName()); } } else { // 如果没有文件夹实体类(DirectoryEntry) //从 HSSFObjectData 对象中恢复嵌入文档的数据 byte[] objectData = obj.getObjectData(); } } }
XSSF:
XSSFWorkbook workbook = new XSSFWorkbook("excel_with_embeded.xlsx"); for (PackagePart pPart : workbook.getAllEmbedds()) { String contentType = pPart.getContentType();
POI3.5 HSSF&XSSF Excel 操作快速入门
37
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
//Excel 工作簿 二进制或 OpenXML 格式 if (contentType.equals("application/vnd.ms-excel")) { HSSFWorkbook embeddedWorkbook = new HSSFWorkbook(pPart.getInputStream()); } //Excel 工作簿 OpenXML 格式 else if (contentType.equals("application/vnd.openxmlformats-officedocumen t.spreadsheetml.sheet")) { OPCPackage docPackage = OPCPackage.open(pPart.getInputStream()); XSSFWorkbook embeddedWorkbook = new XSSFWorkbook(docPackage); } // word 文档- 二进制 (OLE2CDF) 文件格式 else if (contentType.equals("application/msword")) { HWPFDocument document = new HWPFDocument(pPart.getInputStream()); } // word 文档 - OpenXML 文件格式 else if (contentType.equals("application/vnd.openxmlformats-officedocumen t.wordprocessingml.document")) { OPCPackage docPackage = OPCPackage.open(pPart.getInputStream()); XWPFDocument document = new XWPFDocument(docPackage); } //PPT 文档 –二进制文件格式 else if (contentType.equals("application/vnd.ms-powerpoint")) { HSLFSlideShow slideShow = new HSLFSlideShow(pPart.getInputStream()); } // PPT 文档 - OpenXML 文件格式 else if (contentType.equals("application/vnd.openxmlformats-officedocumen t.presentationml.presentation")) { OPCPackage docPackage = OPCPackage.open(pPart.getInputStream()); XSLFSlideShow slideShow = new XSLFSlideShow(docPackage); } //其他的嵌入文件格式. else { System.out.println("Unknown Embedded Document: " +
POI3.5 HSSF&XSSF Excel 操作快速入门
38
本文翻译自 http://poi.apache.org/spreadsheet/quick-guide.html
欢迎交流指正 岑坚 ( 高凯 )hellonickco.javaeye.com
contentType); InputStream inputStream = pPart.getInputStream(); } }