Apache POI

​ 实际开发中经常会遇到导入导出Excel的问题,既然涉及到了,就会有创建,修改和显示Office的需求,Apache开源基金使用Java开发使用POI,他的类和方法提供对用户输入数据或文件到Office文件的操作API.

Apache POI组件

​ Apache POI包含类和方法,来将MS Office所有OLE 2文档复合。此API组件的列表如下。

  • POIFS (较差混淆技术实现文件系统) : 此组件是所有其他POI元件的基本因素。它被用来明确地读取不同的文件。
  • HSSF (可怕的电子表格格式) : 它被用来读取和写入MS-Excel文件的xls格式。
  • XSSF (XML格式) : 它是用于MS-Excel中XLSX文件格式。
  • HPSF (可怕的属性设置格式) : 它用来提取MS-Office文件属性设置。
  • HWPF (可怕的字处理器格式) : 它是用来读取和写入MS-Word的文档扩展名的文件。
  • XWPF (XML字处理器格式) : 它是用来读取和写入MS-Word的docx扩展名的文件。
  • HSLF (可怕的幻灯片版式格式) : 它是用于读取,创建和编辑PowerPoint演示文稿。
  • HDGF (可怕的图表格式) : 它包含类和方法为MS-Visio的二进制文件。
  • HPBF (可怕的出版商格式) : 它被用来读取和写入MS-Publisher文件。

Apache POI发行版支持多种文档文件格式。这种支持是在几个Jar文件中提供的。并不是每种格式都需要所有的jar。下表显示了POI组件、Maven存储库标记和项目Jar文件之间的关系。

Component Application type Maven artifactId Notes
POIFS OLE2 Filesystem poi Required to work with OLE2 / POIFS based files
HPSF OLE2 Property Sets poi
HSSF Excel XLS poi For HSSF only, if common SS is needed see below
HSLF PowerPoint PPT poi-scratchpad
HWPF Word DOC poi-scratchpad
HDGF Visio VSD poi-scratchpad
HPBF Publisher PUB poi-scratchpad
HSMF Outlook MSG poi-scratchpad
HWMF WMF drawings poi-scratchpad
DDF Escher common drawings poi
OpenXML4J OOXML poi-ooxml plus either poi-ooxml-schemas or ooxml-schemas and ooxml-security See notes below for differences between these options
XSSF Excel XLSX poi-ooxml
XSLF PowerPoint PPTX poi-ooxml
XWPF Word DOCX poi-ooxml
XDGF Visio VSDX poi-ooxml
Common SL PowerPoint PPT and PPTX poi-scratchpad and poi-ooxml SL code is in the core POI jar, but implementations are in poi-scratchpad and poi-ooxml.
Common SS Excel XLS and XLSX poi-ooxml WorkbookFactory and friends all require poi-ooxml, not just core poi

需要什么导入相关类就可以了

POI各jar包的介绍

  • poi-version-yyyymmdd.jar 用于操作.xls文件,依赖于commons-logging、commons-codec、log4j。例如poi-3.9.jar
  • poi-ooxml-version-yyyymmdd.jar poi-ooxml-schemas-version-yyyymmdd.jar 用于操作.xlsx、.pptx、.docx文件;依赖于poi-version-yyyymmdd.jar、dom4j、xmlbeans、stax-api-1.0.1;操作Excel主要是指ss包、xssf包。
  • poi-examples-3.12-20150511.jar poi例子,开发不需要
  • poi-excelant-3.12-20150511.jar 不需要
  • poi-scratchpad-version-yyyymmdd.jar 用于操作.ppt、.doc、.vsd、.pub、.msg文件,依赖于poi-version-yyyymmdd.jar

Apache POI常用的类

  • HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
  • XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
  • HWPF - 提供读写Microsoft Word DOC97格式档案的功能。
  • XWPF - 提供读写Microsoft Word DOC2003格式档案的功能。
  • HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
  • HDGF - 提供读Microsoft Visio格式档案的功能。
  • HPBF - 提供读Microsoft Publisher格式档案的功能。
  • HSMF - 提供读Microsoft Outlook格式档案的功能。
  • 在开发中我们经常使用HSSF用来操作Excel处理表格数据,对于其它的不经常使用。
  • HSSF 是Horrible SpreadSheet Format的缩写,通过HSSF,你可以用纯Java代码来读取、写入、修改Excel文件。HSSF 为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”。

常用的类和方法

HSSFWorkbook :工作簿,代表一个excel的整个文档

  • HSSFWorkbook(); // 创建一个新的工作簿
  • HSSFWorkbook(InputStream inputStream); // 创建一个关联输入流的工作簿,可以将一个excel文件封装成工作簿
  • HSSFSheet createSheet(Stringsheetname); //创建一个新的Sheet
  • HSSFSheet getSheet(String sheetName);//通过名称获取Sheet
  • HSSFSheet getSheetAt(int index); // 通过索引获取Sheet,索引从0开始
  • HSSFCellStyle createCellStyle();//创建单元格样式
  • int getNumberOfSheets();//获取sheet的个数
  • setActiveSheet(int index); //设置默认选中的工作表
  • write();
  • write(FilenewFile);
  • write(OutputStream stream);
HSSFSheet:工作表
  • HSSFRow createRow(int rownum); //创建新行,需要指定行号,行号从0开始
  • HSSFRow getRow(int index);// 根据索引获取指定的行
  • int addMergedRegion(CellRangeAddress region);合并单元格
  • CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol); 单元格范围, 用于合并单元格,需要指定要合并的首行、最后一行、首列、最后一列。
  • autoSizeColumn(int column); //自动调整列的宽度来适应内容
  • getLastRowNum(); //获取最后的行的索引,没有行或者只有一行的时候返回0
  • setColumnWidth(int columnIndex, int width); //设置某一列的宽度,width=字符个数 256,例如20个字符的宽度就是20 256
HSSFRow :行
  • HSSFCell createCell(int column); //创建新的单元格
  • HSSFCell setCell(shot index);
  • HSSFCell getCell(shot index);
  • setRowStyle(HSSFCellStyle style); //设置行样式
  • short getLastCellNum();//获取最后的单元格号,如果单元格有第一个开始算,lastCellNum就是列的个数
  • setHeightInPoints(float height); //设置行的高度
HSSFCell:单元格
  • setCellValue(String value); //设置单元格的值
  • setCellType(); //设置单元格类型,如 字符串、数字、布尔等
  • setCellStyle(); //设置单元格样式
  • String getStringCellValue(); //获取单元格中的字符串值
  • setCellStyle(HSSFCellStyle style); //设置单元格样式,例如字体、加粗、格式化
  • setCellFormula(String formula);//设置计算公式,计算的结果作为单元格的值,也提供了异常常用的函数,如求和”sum(A1,C1)”、日期函数、字符串相关函数、CountIf和SumIf函数、随机数函数等
HSSFCellStyle :单元格样式
  • setFont(Font font); //为单元格设置字体样式
  • setAlignment(HorizontalAlignment align); // 设置水平对齐方式
  • setVerticalAlignment(VerticalAlignment align); // 设置垂直对齐方式
  • setFillPattern(FillPatternType fp);
  • setFillForegroundColor(short bg); //设置前景色
  • setFillBackgroundColor(short bg); //设置背景颜色
HSSFFont:字体
  • setColor(short color); // 设置字体颜色
  • setBold(boolean bold); // 设置是否粗体
  • setItalic(boolean italic); //设置倾斜
  • setUnderline(byte underline); //设置下划线
HSSFName:名称
  • HSSFDataFormat ://日期格式化
  • HSSFHeader : //Sheet的头部
  • HSSFFooter ://Sheet的尾部
  • HSSFDateUtil ://日期工具
  • HSSFPrintSetup ://打印设置
  • HSSFErrorConstants://错误信息表

Excel中的工作簿、工作表、行、单元格中的关系:

一个Excel文件对应于一个workbook(HSSFWorkbook)。 一个workbook可以有多个sheet(HSSFSheet)组成。 一个sheet是由多个row(HSSFRow)组成。 一个row是由多个cell(HSSFCell)组成。

基础示例

maven引入需要的依赖

<dependency>  
    <groupId>org.apache.poi</groupId>  
    <artifactId>poi</artifactId>  
    <version>3.8</version>  
</dependency>

在桌面上生成一个Excel文件

public static void createExcel() throws IOException{
	// 获取桌面路径
	FileSystemView fsv = FileSystemView.getFileSystemView();
	String desktop = fsv.getHomeDirectory().getPath();
	String filePath = desktop + "/template.xls";
	
	File file = new File(filePath);
	OutputStream outputStream = new FileOutputStream(file);
	HSSFWorkbook workbook = new HSSFWorkbook();
	HSSFSheet sheet = workbook.createSheet("Sheet1");
	HSSFRow row = sheet.createRow(0);
	row.createCell(0).setCellValue("id");
	row.createCell(1).setCellValue("订单号");
	row.createCell(2).setCellValue("下单时间");
	row.createCell(3).setCellValue("个数");
	row.createCell(4).setCellValue("单价");
	row.createCell(5).setCellValue("订单金额");
	row.setHeightInPoints(30); // 设置行的高度
	
	HSSFRow row1 = sheet.createRow(1);
	row1.createCell(0).setCellValue("1");
	row1.createCell(1).setCellValue("NO00001");
	
	// 日期格式化
	HSSFCellStyle cellStyle2 = workbook.createCellStyle();
	HSSFCreationHelper creationHelper = workbook.getCreationHelper();
	cellStyle2.setDataFormat(creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
	sheet.setColumnWidth(2, 20 * 256); // 设置列的宽度
	
	HSSFCell cell2 = row1.createCell(2);
	cell2.setCellStyle(cellStyle2);
	cell2.setCellValue(new Date());
	
	row1.createCell(3).setCellValue(2);
	
	
	// 保留两位小数
	HSSFCellStyle cellStyle3 = workbook.createCellStyle();
	cellStyle3.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
	HSSFCell cell4 = row1.createCell(4);
	cell4.setCellStyle(cellStyle3);
	cell4.setCellValue(29.5);
	
	
	// 货币格式化
	HSSFCellStyle cellStyle4 = workbook.createCellStyle();
	HSSFFont font = workbook.createFont();
	font.setFontName("华文行楷");
	font.setFontHeightInPoints((short)15);
	font.setColor(HSSFColor.RED.index);
	cellStyle4.setFont(font);
	
	HSSFCell cell5 = row1.createCell(5);
	cell5.setCellFormula("D2*E2");  // 设置计算公式
	
	// 获取计算公式的值
	HSSFFormulaEvaluator e = new HSSFFormulaEvaluator(workbook);
	cell5 = e.evaluateInCell(cell5);
	System.out.println(cell5.getNumericCellValue());

	
	workbook.setActiveSheet(0);
	workbook.write(outputStream);
	outputStream.close();
}

读取Excel,解析数据

public static void readExcel() throws IOException{
	FileSystemView fsv = FileSystemView.getFileSystemView();
	String desktop = fsv.getHomeDirectory().getPath();
	String filePath = desktop + "/template.xls";
	
	FileInputStream fileInputStream = new FileInputStream(filePath);
	BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
	POIFSFileSystem fileSystem = new POIFSFileSystem(bufferedInputStream);
	HSSFWorkbook workbook = new HSSFWorkbook(fileSystem);
	HSSFSheet sheet = workbook.getSheet("Sheet1");
	
	int lastRowIndex = sheet.getLastRowNum();
	System.out.println(lastRowIndex);
	for (int i = 0; i <= lastRowIndex; i++) {
		HSSFRow row = sheet.getRow(i);
		if (row == null) { break; }
		
		short lastCellNum = row.getLastCellNum();
		for (int j = 0; j < lastCellNum; j++) {
			String cellValue = row.getCell(j).getStringCellValue();
			System.out.println(cellValue);
		}
	}
	
	
	bufferedInputStream.close();
}