原文:【开源库推荐】 #4 Poi-办公文档处理库 - Stars-One的杂货小窝

github仓库apache/poi

Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。.NET的开发人员则可以利用NPOI (POI for .NET) 来存取 Microsoft Office文档的功能。

提示:下文代码示例有Java和Kotlin形式

PS: 目前不确定此库能否在Android平台上使用,但从Github上的搜索结果来看,应该需要移植

POI结构说明

包名称说明

目前只研究了读写表格的相关操作,至于Word等其他文件还没有细致研究,之后有研究了再补充了..

读写Excel

首先,先引入依赖

<!--xls(03)-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.0.0</version>
</dependency>
<!--xlsx(07)-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.0.0</version>
</dependency>

poi是只支持xls格式,而poi-ooxml则可以支持xlsx格式

1.读取excel文件数据

上面我们也是知道,由于存在两种格式,所以我们的写法上得注意一下

由于XSSFWorkbookHSSFWorkbook都是实现的Workbook接口,所以可利用到多态的原理来编写代码,达到兼容写法

fun main(args: Array<String>) {
    val file = File("D:\\download\\test.xlsx")
    var workbook: Workbook? = null
    if (file.extension.toLowerCase() == "xlsx") {
        //xlsx
        workbook = XSSFWorkbook(file)
    }
    if (file.extension.toLowerCase() == "xls") {
        //xls
        workbook = HSSFWorkbook(FileInputStream(file))
    }
    workbook?.let {
        val sheet = workbook.getSheetAt(0)
        //读取第一行第一列单元格数据
        val firstColumn = sheet.getRow(0).first()
        //需要判断一下但单元格的类型
        if (firstColumn.cellType == CellType.STRING) {
            println(firstColumn.stringCellValue)
        }
        workbook.close()
    }
}

PS:就是觉得有些神奇的是,XSSFWorkbook构造函数可以接收File类型的对象参数,而HSSFWorkbook只能接收FileInputSteam

2.创建execl文件数据

val file = File("D:\\download\\myoutput.xlsx")
val workbook: Workbook = XSSFWorkbook()
//val workbook: Workbook =  HSSFWorkbook()
val sheet = workbook.createSheet("sheet0")
val row = sheet.createRow(0)
val cell = row.createCell(0)
cell.cellType = CellType.STRING
cell.setCellValue("hello world")
//输出到文件
workbook.write(FileOutputStream(file))
workbook.close()

效果:

【开源库推荐】#4 Poi-办公文档处理库

读写Word

可以查看此教程Apache POI Word(docx) 入门示例教程

暂无需求,还没有细研究

除此之外,可以选择Word模板然后注入对应的数据进去,推荐使用Poi-tl Documentation

补充-EXCEL常用操作方法

1、得到Excel常用对象

POIFSFileSystem fs=newPOIFSFileSystem(new FileInputStream("d:/test.xls"));
//得到Excel工作簿对象 
HSSFWorkbook wb = new HSSFWorkbook(fs); 
//得到Excel工作表对象 
HSSFSheet sheet = wb.getSheetAt(0); 
//得到Excel工作表的行 
HSSFRow row = sheet.getRow(0); 
//得到Excel工作表指定行的单元格 
HSSFCell cell = row.getCell(0); 
//得到单元格样式
cellStyle = cell.getCellStyle();

2、建立Excel常用对象

HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
HSSFRow row = sheet.createRow((short)0); 
HSSFCell cell = sheet.createCell((short)0); 
cellStyle = wb.createCellStyle(); 
//指定单元格样式和值
cell.setCellStyle(cellStyle); 
cell.setCellValue(1);

3、sheet相关

//设置sheet名称
wb.setSheetName(0, "12" + "月合同到期");
//取得sheet的数目 
wb.getNumberOfSheets();
//新建名称为Output的sheet
HSSFSheet sheet = wb.createSheet("Output"); 
//根据index取得sheet对象
HSSFSheet sheet = wb.getSheetAt(0); 
//选中指定的工作表
sheet.setSelected(true);

4、有效的行,单元格个数

//取得有效的行数
int rowcount = sheet.getLastRowNum(); 
//取得一行的有效单元格个数
row.getLastCellNum();

5、单元格值类型读写

//根据单元格不同属性返回字符串数值
public String getCellStringValue(HSSFCell cell) { 
    String cellValue = ""; 
    switch (cell.getCellType()) { 
        case HSSFCell.CELL_TYPE_STRING://字符串类型 
            cellValue = cell.getStringCellValue(); 
            if(cellValue.trim().equals("")||cellValue.trim().length()<=0) {
                cellValue=" "; 
            }
            break; 
        case HSSFCell.CELL_TYPE_NUMERIC: //数值类型 
            cellValue = String.valueOf(cell.getNumericCellValue()); 
            break; 
        case HSSFCell.CELL_TYPE_FORMULA: //公式 
            cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); 
            cellValue = String.valueOf(cell.getNumericCellValue()); 
            break; 
        case HSSFCell.CELL_TYPE_BLANK: 
            cellValue=" "; 
            break; 
        case HSSFCell.CELL_TYPE_BOOLEAN: 
            break; 
        case HSSFCell.CELL_TYPE_ERROR: 
            break; 
        default: 
            break; 
    } 
    return cellValue; 
}
//设置单元格为STRING类型
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
//设置单元格的值---有重载
cell.setCellValue(value);

【开源库推荐】#4 Poi-办公文档处理库

POI CellType类型有以下几种

CellType类型
CELL_TYPE_NUMERIC 数值型 0
CELL_TYPE_STRING 字符串型 1
CELL_TYPE_FORMULA 公式型 2
CELL_TYPE_BLANK 空值 3
CELL_TYPE_BOOLEAN 布尔型 4
CELL_TYPE_ERROR 错误 5

使用POI读取单元格的数据有两种方式:

  1. 通过setCellType将单元格类型设置为字符串,然后通过getRichStringCellValue读取该单元格数据,然后将读取到的字符串转换为对应的类型,
  2. 通过getCellType获取单元格类型,然后通过对应的getcellvalue方法读取该单元格数据,如:getNumericCellValue

6、设置列宽、行高

sheet.setColumnWidth((short)column,(short)width);
row.setHeight((short)height);
//POI设置自适应列宽sheet.autoSizeColumn(i); (版本不能太老)
sheet.autoSizeColumn(i, true);(合并的单元格使用)
sheet.setColumnWidth(i, “列名”.getBytes().length*2*256);(中文适用)
公式单元格自适应的是公式,将值算出后再设置:
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet.getWorkbook());
CellValue cell71Val = evaluator.evaluate(cell71);
cell71.setCellValue(cell71Val.getNumberValue());
//调整单元格宽度
sheet.setAutobreaks(true); 
sheet.setColumnWidth((short)i,colsWidth[i]); //设定单元格长度 
sheet.autoSizeColumn((short) i);//自动根据长度调整单元格长度

7、添加区域,合并单元格

//合并从第rowFrom行columnFrom列
Region region = new Region((short)rowFrom,(short)columnFrom,(short)rowTo ,(short)columnTo);
sheet.addMergedRegion(region);// 到rowTo行columnTo的区域 
// 获得一个 sheet 中合并单元格的数量
int sheetmergerCount = sheet.getNumMergedRegions();

8、常用单元格边框格式

HSSFCellStyle style = wb.createCellStyle();
style.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);//下边框 
style.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);//左边框 
style.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框 
style.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

其中边框类型分为以下几种:

边框范例图 对应的静态值
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_DOTTED
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_HAIR
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_DASH_DOT_DOT
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_DASH_DOT
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_DASHED
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_THIN
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_MEDIUM_DASH_DOT_DOT
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_SLANTED_DASH_DOT
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_MEDIUM_DASH_DOT
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_MEDIUM_DASHED
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_MEDIUM
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_THICK
【开源库推荐】#4 Poi-办公文档处理库 HSSFCellStyle. BORDER_DOUBLE

9、设置字体和内容位置

HSSFFont font = wb.createFont();
font.setFontName("华文行楷");//设置字体名称
font.setFontHeightInPoints((short) 11);                    //字号 
font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); //加粗 
font.setColor(HSSFColor.RED.index);               //设置字体颜色
font.setUnderline(FontFormatting.U_SINGLE);  //设置下划线
font.setTypeOffset(FontFormatting.SS_SUPER);//设置上标下标
font.setStrikeout(true);                                   //设置删除线
style.setFont(font); 
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中 
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中 
style.setRotation(short rotation);//单元格内容的旋转的角度 
Style.setWrapText(true); //设置excel单元格中的内容换行
HSSFDataFormat df = wb.createDataFormat(); 
style1.setDataFormat(df.getFormat("0.00%"));//设置单元格数据格式 
cell.setCellStyle(style);

10、在工作单中清空行数据,调整行位置

HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("row sheet"); 
// Create various cells and rows for spreadsheet. 
// Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5) 
sheet.shiftRows(5, 10, -5);

11、填充和颜色设置

HSSFCellStyle style = wb.createCellStyle();
style.setFillBackgroundColor(HSSFColor.AQUA.index); 
style.setFillPattern(HSSFCellStyle.BIG_SPOTS); 
HSSFCell cell = row.createCell((short) 1); 
cell.setCellValue("X"); 
style = wb.createCellStyle(); 
style.setFillForegroundColor(HSSFColor.ORANGE.index); 
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); 
cell.setCellStyle(style);

12、工作表的放大缩小

sheet.setZoom(1,2); // 50 percent magnification
sheet.setZoom(75); //75% scale

13. 使用公式

cell.setCellType(XSSFCell.CELL_TYPE_FORMULA);
cell.setCellFormula("SUM(C2:C3)" ); //给单元格设公式 

14. 设置超链接

cell.setCellFormula("hyperlink(\"http://www.yiibai.com/testng/\",\"testng\")");

15、插入图片

public static void test1(){
    FileOutputStream fileOut = null;     
    BufferedImage bufferImg = null;     
   try {  
       ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();  
     //加载图片  
       bufferImg = ImageIO.read(new File(picture));     
       ImageIO.write(bufferImg, "jpg", byteArrayOut);  
       HSSFWorkbook wb = new HSSFWorkbook();     
       HSSFSheet sheet = wb.createSheet("sheet1");    
       HSSFPatriarch patriarch = sheet.createDrawingPatriarch();     
          HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,255,(short) 0,0,(short)4,37);    
       //插入图片 1   
       patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));      
       //图片2  
       anchor = new HSSFClientAnchor(500, 0, 0, 0,(short) 5, 1, (short) 9, 38);  
       patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));  
       fileOut = new FileOutputStream( filepath+"/excel.xls");     
       // 输出文件   
        wb.write(fileOut);  
        System.out.println("test1");
   } catch (Exception e) {  
       e.printStackTrace();  
   }          
}  
public static void test3(){
    FileOutputStream fileOut = null;     
    BufferedImage bufferImg = null;     
   try {  
       ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();  
     //加载图片  
       bufferImg = ImageIO.read(new File(picture));     
       ImageIO.write(bufferImg, "jpg", byteArrayOut);  
       XSSFWorkbook wb = new XSSFWorkbook();     
       XSSFSheet sheet1 = wb.createSheet("sheet1");    
       XSSFDrawing drawing = sheet1.createDrawingPatriarch();     
          XSSFClientAnchor anchor = new XSSFClientAnchor(0,0,1023,255,(short) 0,0,(short)10,10);          
       //插入图片 1   
          drawing.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));      
       fileOut = new FileOutputStream( filepath+ "/excel2.xlsx");     
       // 输出文件   
        wb.write(fileOut);  
        System.out.println("test3");
   } catch (Exception e) {  
       e.printStackTrace();  
   }          
}  

16. 从Excel文件提取图片

public static void testread(){
    InputStream inp;
    try {
        inp = new FileInputStream(filepath+"/excel.xls");
        HSSFWorkbook workbook = new HSSFWorkbook(inp);//读取现有的Excel文件
        List<HSSFPictureData> pictures = workbook.getAllPictures();
        for(int i=0;i<pictures.size();i++){
            HSSFPictureData pic=pictures.get(i);
            String ext = pic.suggestFileExtension();
            if (ext.equals("jpeg"))//判断文件格式,依照实际图片格式设置
            {
                FileOutputStream png=new FileOutputStream(filepath +"\\Apache.jpg");
                png.write(pic.getData());
                png.close();//保存图片
                System.out.println("test11");
            }
        }
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

参考

发表回复