#Java--POI之HSSF操作

一、POI的概念
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对MicrosoftOffice格式档案读和写的功能。

二、基本功能

HSSF - 提供读写Microsoft Excel格式档案的功能。

XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。

HWPF - 提供读写Microsoft Word格式档案的功能。

HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

HDGF - 提供读写Microsoft Visio格式档案的功能。

三、HSSF介绍

1、依赖

在使用HSSF之前,你需要引入以下依赖:

<dependency>

       <groupId>org.apache.poi</groupId>

       <artifactId>poi</artifactId>

       <version>3.15</version>

</dependency>

2、基本要素
(1)HSSFWorkbook :Excel文档,是一个顶层类

创建一个HSSFWorkbook对象,意味着拥有了一个空白的Excel文件。
我们可以这样来创建一个顶层类,并导出一张空白的Excel文档:
HSSFWorkbook wb  = newHSSFWorkbook();
方式1:
//1.创建File
File file = new File("C:\\Users\\Administrator\\Desktop\\test\\first.xls");
//2.调用write方法导出xls文件
try {
    wb.write(file);
} catch(IOException e) {
    e.printStackTrace();
}

方式2:
HSSFWorkbook wb  = newHSSFWorkbook();
//1.创建File
File file = new File("C:\\Users\\Administrator\\Desktop\\test\\second.xls");
OutputStream out = null;
try {
    out = newFileOutputStream(file);
    //2.调用write方法导出xls文件
    wb.write(out);
} catch(IOException e) {
    e.printStackTrace();
}finally{
    if(null != out){
        try {
            out.flush();
            out.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

(2)HSSFSheet :Excel文档的sheet页(也就是工作薄)

HSSFSheet虽然是一个类,但却是一个final类,final是java中的一个关键字,可以用来修饰变量、方法和类。用关键词final修饰的域成为最终域。用关键词final修饰的变量一旦赋值,就不能改变,也称为修饰的标识为常量。如果一个类的域被关键字final所修饰,它的取值在程序的整个执行过程中将不会改变。

假如说整个类都是final,就表明自己不希望从这个类继承,或者不答应其他任何人采取这种操作。换言之,出于这样或那样的原因,我们的类肯定不需要进行任何改变;或者出于安全方面的理由,我们不希望进行子类化(子类处理)。

然而,我们并不能实例化HSSFSheet类,我们查看底层代码发现,该类是一个被protected所修饰的类,我们知道,以下情况是无法进行实例化的:

. 抽象类 abstract class
. 接口 interface
.无公开的构造方法的类 private(单例模式)

.其他包下非public修饰的构造器的类

尤其是地三种和第四种在实际开发中应用得比较广泛,对于第四种方式在源码中比较常见,源码中的类设置成protected时,由于源码是第三方类,因此也就和当前调用类处于不同包下,所以在当前类中不能实例化被protected修饰的第三方类。我们可以理解为一种设计模式,是类封装性的体现,也是一种比较常用的设计模式。例如:

packagecom.yx.yzh.test;

public class B {

    //会覆盖B()构造器

    protected B(A a){}

}

 

packagecom.yx.yzh.test;

public class A {

    public BcreateB(){

    B a = new B(this);

    return a;

    };
}

说明:在上面的代码中,我们将B类的构造器设置成了protected修饰类,因此其他包下的类无法通过new B()的方式创建一个B类的实例,因此我在A类中设计了一个createB()方法,该方法将返回一个B类的实例(在同一个包下,protected能够访问另一个类)。因此,创建一个sheet对象如下。
HSSFWorkbook wb  = newHSSFWorkbook();
HSSFSheet st = wb.createSheet();
当我们调用createSheet()方法时,这意味着我们在Excel中插入了一个sheet页,如果想同时创建多张sheet页,那么可以多次调用createSheet(),例如,下面我们就向Excel文件中插入了两个sheet页:
HSSFWorkbook wb  = newHSSFWorkbook();
wb.createSheet();
wb.createSheet();
对于HSSFSheet对象的创建,我们可以这样来理解:因为sheet页所属于Excel文件,因此可以使用HSSFWorkbook对象来创建一个sheet页。

(3)HSSFRow:sheet页的行

我们可以通过通过HSSFSheet对象的createRow()方法来创建一个有效行。createRow()方法有一个int类型的参数,用于定位创建的有效行所在的行位置(使用数字0表示第一行)。例如:

HSSFWorkbook wb  = newHSSFWorkbook();

HSSFSheet st = wb.createSheet();

HSSFRow row = st.createRow(0);

从图中我们可以看出,一个sheet页拥有多行。对于HSSFRow对象的创建,我们可以这样来理解:因为一个sheet页拥有多行,因此可以使用HSSFSheet对象来创建一个有效行。

(4)HSSFCell:单元格
我们可以通过HSSFRow的createRow(int num)方法来获得单元格对象。其中参数num表示单元格所在行的位置,我们知道,一行拥有多个单元格。对于HSSFCell对象的创建,我们可以这样来理解:因为一行拥有多个单元格,因此可以使用HSSFRow对象来创建一个单元格。

四、HSSF与数据操作

1、分析

一个UserInfo对象对应数据表中的某一行数据,数据表的某一行数据对应sheet工作薄中的某一行数据,因此可以推出对象的字段值对应sheet工作薄中的单元格数据。因此,我们在查询得到一个范型为UserInfo的List后。遍历List,从而获得UserInfo的实体类对象,并通过该对象的getXXX方法获得每一个字段的值,再通过HSSFCell对象的setCellValue()方法为Excel的单元格赋值。

2、实现过程

(1)添加表格标题

表格标题的主要特点是:在第一行、居中、独占一个单元格成为一行(合并等表宽的行部分)等等。

第一步:合并单元格

表格标题在第一行,而且我们看到,UserInfo表字段一共有7个,因此需要合并7个单元格。因此你可以这样做:

HSSFWorkbook wb = newHSSFWorkbook();

HSSFSheet st = wb.createSheet();

//合并单元格

st.addMergedRegion(newCellRangeAddress(0, 0, 0, 6)); //起始行,结束行,起始列,终止列(6表示第七列)

第二步:创建样式(居中、字体)

//获取表格标题样式对象

HSSFCellStyle headStyle = wb.createCellStyle();

//设置内容居中

headStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

第三步:为表格标题所在的合并单元格设置样式

HSSFCell cell = row.createCell(0);

//设置表格标题内容

cell.setCellValue(“用户信息表”);

//为单元格设置样式

cell.setCellStyle(headStyle);

完整的代码如下所示:


HSSFWorkbook wb  = newHSSFWorkbook();

HSSFSheet st = wb.createSheet("用户列表");

//HSSFRow row =st.createRow(2);//第3行,0表示第一行

//1、设置表格标题

st.addMergedRegion(newCellRangeAddress(0, 0, 0, 6));//起始行,结束行,起始列,终止列

//获取表格标题样式对象

HSSFCellStyle tabTitleStyle= wb.createCellStyle();

//设置内容居中

tabTitleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

//将表格标题设置在第一行(0)

HSSFRow tableTitlerow=st.createRow(0);

//选中合并后的单元格作为表格标题信息存储的那个单元格

HSSFCell cell = tableTitlerow.createCell(0);

//设置表格标题内容

cell.setCellValue("用户信息表");

//为单元格设置样式

cell.setCellStyle(tabTitleStyle);

(2)表头设计

一张表应该像数据库表那样拥有一个表头才算完整,当然我们不能直接将字段作为表头,而需要将这些字段翻译为中文。由于表格标题占了第一行,因此表头应将第二行作为表头行。下面是表头的实现过程:

//获取表格标题样式对象

HSSFCellStyle tabHeadStyle =  wb.createCellStyle();

//设置内容水平居中

tabHeadStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

//设置内容垂直居中

tabHeadStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

HSSFRow tableHeadRow = st.createRow(1);

//表头第一列所在的单元格

HSSFCell cell1 = tableHeadRow.createCell(0);

//设置表头第一列所在的单元格的值

cell1.setCellValue("ID");

//设置表头单元格样式

cell1.setCellStyle(tabHeadStyle);

HSSFCell cell2 = tableHeadRow.createCell(1);

cell2.setCellValue("用户名");

cell2.setCellStyle(tabHeadStyle);

HSSFCell cell3 = tableHeadRow.createCell(2);

cell3.setCellValue("密码");

cell3.setCellStyle(tabHeadStyle);

HSSFCell cell4 = tableHeadRow.createCell(3);

cell4.setCellValue("年龄");

cell4.setCellStyle(tabHeadStyle);

HSSFCell cell5 = tableHeadRow.createCell(4);

cell5.setCellValue("性别");

cell5.setCellStyle(tabHeadStyle);

HSSFCell cell6 = tableHeadRow.createCell(5);

cell6.setCellValue("手机号");

cell6.setCellStyle(tabHeadStyle);

HSSFCell cell7 = tableHeadRow.createCell(6);

cell7.setCellValue("邮箱");

cell7.setCellStyle(tabHeadStyle);

(3)设置表数据


表数据是最重要的部分,由于表标题与表头各占了一行,因此表数据需要从第三行开始算起。代码如下所示。

String sql = "select* from userinfo";

String DBType = "SQLServer2008";

List<UserInfo> list = dBHandleUtils.findAll(sql, DBType,UserInfo.class);

//获取表格标题样式对象

HSSFCellStyle tabDataStyle =  wb.createCellStyle();

//设置内容水平居中

tabDataStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

//设置内容垂直居中

tabDataStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

//表格数据从第三行开始

int dataRow = 2;

HSSFRow tableDataRow = null;

//遍历出每一个对象

for(UserInfo u : list){

tableDataRow = st.createRow(dataRow);

Field[] fArr = u.getClass().getDeclaredFields();

HSSFCell dataCell = null;

for(int i = 0;i<fArr.length;i++){

try{

Field f = fArr[i];

//设置私有变量可操作

f.setAccessible(true);

//获取字段的值

String value = f.get(u).toString();

dataCell = tableDataRow.createCell(i);

//设置单元格数据

dataCell.setCellValue(value);

dataCell.setCellStyle(tabDataStyle);

}catch(Exceptione){

e.printStackTrace();

}

}
dataRow++;
}

4、设置样式

1)创建表头单元格格式

HSSFCellStyleheadStyle = wb.createCellStyle();

HSSFFont font =wb.createFont();

font.setFontName("黑体");

font.setFontHeightInPoints((short)16);//设置字体大小

headStyle.setFont(font);

headStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);//下边框

headStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框

headStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

headStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

2)创建Excel数据单元格样式

HSSFCellStylecellStyle = wb.createCellStyle();

cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);//下边框

cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框

cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

3)单元格数字格式

HSSFDataFormat df =wb.createDataFormat();

HSSFCellStyledfCellStyle = wb.createCellStyle();

dfCellStyle.setDataFormat(df.getFormat("#,#0.00"));//保留两位小数

dfCellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER_SELECTION);

dfCellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

dfCellStyle.setWrapText(true);

dfCellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);// 下边框

dfCellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框

dfCellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

dfCellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

5、完整案例

HSSFWorkbook wb  = newHSSFWorkbook();

HSSFSheet st = wb.createSheet("用户列表");

//HSSFRow row =st.createRow(2);//第3行,0表示第一行

//1、设置表格标题

st.addMergedRegion(newCellRangeAddress(0, 0, 0, 6));//起始行,结束行,起始列,终止列

//获取表格标题样式对象

HSSFCellStyle tabTitleStyle =  wb.createCellStyle();

//设置内容居中

tabTitleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

HSSFFont tabTitleFont = wb.createFont();

tabTitleFont.setFontName("黑体");

tabTitleFont.setFontHeightInPoints((short) 16);//设置字体大小

tabTitleStyle.setFont(tabTitleFont);

tabTitleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);//下边框

tabTitleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框

tabTitleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

tabTitleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

 

//将表格标题设置在第一行(0)

HSSFRow tableTitlerow = st.createRow(0);

//选中合并后的单元格作为表格标题信息存储的那个单元格

HSSFCell cell = tableTitlerow.createCell(0);

//设置表格标题内容

cell.setCellValue("用户信息表");

//为单元格设置样式

cell.setCellStyle(tabTitleStyle);

 

//2、设置表头

//获取表格标题样式对象

HSSFCellStyle tabHeadStyle =  wb.createCellStyle();

//设置内容水平居中

tabHeadStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

//设置内容垂直居中

tabHeadStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

HSSFFont tabHeadFont = wb.createFont();

tabHeadFont.setFontName("黑体");

tabHeadFont.setFontHeightInPoints((short) 14);//设置字体大小

tabHeadStyle.setFont(tabHeadFont);

tabHeadStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);//下边框

tabHeadStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框

tabHeadStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

tabHeadStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

HSSFRow tableHeadRow = st.createRow(1);

//表头第一列所在的单元格

HSSFCell cell1 = tableHeadRow.createCell(0);

//设置表头第一列所在的单元格的值

cell1.setCellValue("ID");

//设置表头单元格样式

cell1.setCellStyle(tabHeadStyle);

HSSFCell cell2 = tableHeadRow.createCell(1);

cell2.setCellValue("用户名");

cell2.setCellStyle(tabHeadStyle);

HSSFCell cell3 = tableHeadRow.createCell(2);

cell3.setCellValue("密码");

cell3.setCellStyle(tabHeadStyle);

HSSFCell cell4 = tableHeadRow.createCell(3);

cell4.setCellValue("性别");

cell4.setCellStyle(tabHeadStyle);

HSSFCell cell5 = tableHeadRow.createCell(4);

cell5.setCellValue("年龄");

cell5.setCellStyle(tabHeadStyle);

HSSFCell cell6 = tableHeadRow.createCell(5);

cell6.setCellValue("手机号");

cell6.setCellStyle(tabHeadStyle);

HSSFCell cell7 = tableHeadRow.createCell(6);

cell7.setCellValue("邮箱");

cell7.setCellStyle(tabHeadStyle);

 

//3、设置表格数据

String sql = "select* from userinfo";

String DBType = "SQLServer2008";

List<UserInfo> list = dBHandleUtils.findAll(sql, DBType,UserInfo.class);

//获取表格标题样式对象

HSSFCellStyle tabDataStyle =  wb.createCellStyle();

//设置内容水平居中

tabDataStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

//设置内容垂直居中

tabDataStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

tabDataStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);//下边框

tabDataStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框

tabDataStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

tabDataStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框

//创建一个DataFormat对象

HSSFDataFormat format = wb.createDataFormat();

//设置为文本格式(可以防止单元格文本太长而溢出)

tabDataStyle.setDataFormat(format.getFormat("@"));

//设置自动换行

//tabDataStyle.setWrapText(true);

//表格数据从第三行开始

int dataRow = 2;

HSSFRow tableDataRow = null;

//遍历出每一个对象

for(UserInfo u : list){

tableDataRow = st.createRow(dataRow);

Field[] fArr = u.getClass().getDeclaredFields();

HSSFCell dataCell = null;

//防止最后一列溢出,所以这里需要比字段数目多一列

for(int i = 0;i<fArr.length+1;i++){

try{

if(i<fArr.length){

Field f = fArr[i];

//设置私有变量可操作

f.setAccessible(true);

//获取字段的值

String value = f.get(u).toString();

dataCell = tableDataRow.createCell(i);

//设置单元格数据

dataCell.setCellValue(value);

dataCell.setCellStyle(tabDataStyle);

//防止最后一列溢出

}else{

dataCell = tableDataRow.createCell(i);

//设置单元格数据

dataCell.setCellValue("");

}

}catch(Exception e){

e.printStackTrace();

}

}

dataRow++;

}

 

//4、设置宽度自适应

// 工作薄单元格平均宽度

int sumSheetColumnWidth = 0;

//获取Excel空白文档默认的列数

int sheetDefaultColumnNums =  st.getLastRowNum();

//获取Excel空白文档默认的列宽,由于这里获取的单字符的长度,因此需要*256,以便与getColumnWidth的单位保持一致

int sheetDefaultWidth = st.getDefaultColumnWidth()*256;

//获取Excel空白文档默认的总宽宽

double totalSheetWidth = sheetDefaultColumnNums*sheetDefaultWidth;

 

for (int m = 0; m < 7; m++) {

//设置自适应列宽

st.autoSizeColumn((short)m);

//获取自适应列宽后的列宽

//getColumnWidth(intcolumnIndex)get the width (in units of 1/256th of a character width )以一个字符的1/256的字母宽度作为一个单位

sumSheetColumnWidth += st.getColumnWidth(m);

}

//获取数据部分的列平均宽度

//获取sheet页默认宽度相对于数据部分宽度的倍数

double rate = totalSheetWidth*1.0/sumSheetColumnWidth;

for (int m = 0; m < 7; m++) {

//重置宽度

st.setColumnWidth(m,(int) (st.getColumnWidth(m)*rate*1.1211));

}

 

//5、导出Excel文件

File file = new File("C:\\Users\\Administrator\\Desktop\\test\\third.xls");

OutputStream out = null;

try {

out = new FileOutputStream(file);

//2.调用write方法导出xls文件

wb.write(out);

} catch(IOException e) {

e.printStackTrace();

}finally{

if(null != out){

try {

out.flush();

out.close();

} catch(IOException e) {

e.printStackTrace();

}

}

}

}
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值