Poi3.7 XSSFWorkbook 用来操作MS03以后的Excel
1. HSSFWorkbook类(创建excel表)
首先从Workbook开始我们的POI编程之旅。要生成一个Workbook,需要用到HSSFWorkbook类文件,类定义如下:
- java.lang.Object
- org.apache.poi.hssf.usermodel.HSSFWorkbook
- public class HSSFWorkbook extends java.lang.Object
它有五个构造方法:
构建器 |
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文件作为数据流来进行传入传出。
- java.lang.Object
- org.apache.poi.poifs.filesystem.POIFSFileSystem
- public class POIFSFileSystem extends java.lang.Object implements POIFSViewable
「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」类,它的类定义如下。
- java.lang.Object
- org.apache.poi.hssf.usermodel.HSSFSheet
- public class HSSFSheet extends java.lang.Object
它有两个构造方法。
构建器 |
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
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」类关系图
- java.lang.Object
- org.apache.poi.hssf.util.Region
- public class Region extends java.lang.Object implements java.lang.Comparable
「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
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」类,它的类定义如下。
- java.lang.Object
- org.apache.poi.hssf.usermodel.HSSFRow
- public class HSSFRow extends java.lang.Object implements java.lang.Comparable
它的构造方法有三个。
构造方法 |
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 POISample12{
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 POISample13{
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 POISample14{
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 POISample15{
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」类,类定义如下。
- java.lang.Object
- org.apache.poi.hssf.usermodel.HSSFCell
- public class HSSFCell extends java.lang.Object
该类包含三个构造方法。
构造方法 |
protected HSSFCell(Workbook book, Sheet sheet, int row, CellValueRecordInterface |
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 POISample16{
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,实际是第2行)的第二列(列号是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 POISample17{
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表格
像下面那样准备一个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 POISample18{
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 POISample20{
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 POISample21{
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 POISample23{
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 POISample24{
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 POISample25{
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 POISample26{
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文件读取单元格信息
再来看看如何从现有的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」类,关于它的类定义如下:
- java.lang.Object
- org.apache.poi.hssf.usermodel.HSSFCellStyle
- public class HSSFCellStyle extends java.lang.Object
它有一个构造方法。
构造方法 |
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类定义如下:
- java.lang.Object
- org.apache.poi.hssf.util.HSSFColor
- public class HSSFColor extends java.lang.Object
而各种顔色又是作为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」类定义的。其定义如下:
- java.lang.Object
- org.apache.poi.hssf.usermodel.HSSFPalette
- public class HSSFPalette extends java.lang.Object
构造方法虽然有一个,但仍然是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);
}
}
运行结果如下: