POI说明—Java操作EXCEL

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()
Creates new HSSFWorkbook from scratch (start here!)

HSSFWorkbook(java.io.InputStream s)  

HSSFWorkbook(java.io.InputStream s, boolean preserveNodes)
Companion to HSSFWorkbook(POIFSFileSystem), this constructs the POI filesystem around your inputstream.

HSSFWorkbook(POIFSFileSystem fs)  

HSSFWorkbook(POIFSFileSystem fs, boolean preserveNodes)
given a POI POIFSFileSystem object, read in its Workbook and populate the high and low level models.

我们用第一个构建器来生成一个Workbook

扫描二维码关注公众号,回复: 6137707 查看本文章

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()
Constructor, intended for writing

POIFSFileSystem(java.io.InputStream stream)
Create a POIFSFileSystem from an InputStream

读取文件时使用第二个构建器。

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)
Creates new HSSFSheet – called by HSSFWorkbook to create a sheet from scratch.

protected HSSFSheet(Workbook book, Sheet sheet)
Creates an HSSFSheet representing the given Sheet object.

虽然有两个构建器,但都是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」类关系图

  • 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)
Creates new HSSFRow from scratch.

protected HSSFRow(Workbook book, Sheet sheet, RowRecord record)
Creates an HSSFRow from a low level RowRecord object.

虽然有三个,但每一个都是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 cval)
Creates an HSSFCell from a CellValueRecordInterface.

protected HSSFCell(Workbook book, Sheet sheet, int row, short col)
Creates new Cell – Should only be called by HSSFRow.

protected HSSFCell(Workbook book, Sheet sheet, int row, short col, int type)
Deprecated. As of 22-Jan-2002 use @see org.apache.poi.hssf.usermodel.HSSFRow
#createCell(short) and use setCellValue to specify the type lazily.

同之前一样,虽然有三个构造方法,但都是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 

Boolean 

CELL_TYPE_BOOLEAN 

Error 

CELL_TYPE_ERROR 

Formula 

CELL_TYPE_FORMULA 

Numeric 

CELL_TYPE_NUMERIC 

String 

CELL_TYPE_STRING 

示例程序

下面来实际动手做做看。按下图准备一个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 

#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 

#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)
Creates new HSSFCellStyle why would you want to do this??

虽然有构造方法,但却是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);

}

}

运行结果如下:

==========================================异常华丽的分割线=============================================================

猜你喜欢

转载自blog.csdn.net/weixin_38519136/article/details/89880372