Java POI组件——读、筛选、写Excel

接上一篇《Java POI组件——写Excel》http://blog.csdn.net/chy555chy/article/details/52739711

假设有这么一个需求——领导挑出了一些员工的名字(准备评先进),只需要这些员工的部分信息。需要你从员工表中找出它们和这些员工相应的某些信息。

  • 员工表如下
    Java POI组件——读、筛选、写Excel_第1张图片

  • 评先进的人是:”陈七”, “张三”, “林八”, “钱二”, “东方不败”

  • 需要的字段要按如下顺序排序:”姓名”,”员工号”,”部门”,”年龄”,”入岗时间”
  • 另外需要在首列生成索引,自动排序

结果如下
Java POI组件——读、筛选、写Excel_第2张图片

则本次读写Excel需要使用到的jar为

poi-3.15.jar
poi-ooxml-3.15.jar
poi-ooxml-schemas-3.15.jar
commons-collections4-4.1.jar
xmlbeans-2.6.0.jar

package com.example.pkg;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.Format;
import java.util.ArrayList;
import java.util.Date;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.extractor.ExcelExtractor;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class PoiExcelClass {
/**
     * 筛选并重组表格(自动生成索引),只筛选第一个sheet
     * 
     * @params originFileName 源文件名
     * @params targetFileName 目标文件名
     * @params columns 只提取原表格中出现过的列(不包括索引)
     * @params filterItems 筛选条件,只提取出现该项的行
     */
    private static void filter(String originFileName, String targetFileName, String[] columns, String filterColumn, String[] filterItems) {
        InputStream inp = null;
        Workbook workbook = null;
        ArrayList columnIndexList = new ArrayList(columns.length);
        int filterColumnIndex = -1;
        Workbook workbook_w = null;
        FileOutputStream fos = null;
        try {
            inp = new FileInputStream(originFileName);
            workbook = WorkbookFactory.create(inp);
            FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
            Sheet sheet = workbook.getSheetAt(0);
            Row row = sheet.getRow(0);
            // 如果未发现有行,则返回
            if (row == null)
                return;
            // 第一行规定必须是标题
            for (Cell cell : row) {
                if (cell.getCellTypeEnum() == CellType.STRING) {
                    for (String str : columns) {
                        String value = cell.getStringCellValue();
                        if (str.equals(value)) {
                            int index = cell.getColumnIndex();
                            columnIndexList.add(index);
                            if(filterColumnIndex == -1 && filterColumn.equals(value)) {
                                filterColumnIndex = index;
                            }
                            break;
                        }
                    }
                }
            }
            // 如果待筛选的字段一个也没找到就返回
            if (columnIndexList.size() == 0 || filterColumnIndex == -1)
                return;
            if (targetFileName.endsWith(SUFFIX_XSSF)) {
                workbook_w = new XSSFWorkbook();
            } else {
                workbook_w = new HSSFWorkbook();
            }
            Sheet sheet_w = workbook_w.createSheet("Sheet1");
            int rowIndex = 1;
            //添加标题行
            Row row_w = sheet_w.createRow(0);
            row_w.createCell(0).setCellValue("索引");
            for (int i = 0; i < columnIndexList.size(); i++) {
                String value = row.getCell(columnIndexList.get(i)).getStringCellValue();
                row_w.createCell(i+1).setCellValue(value);
            }
            for (Row r : sheet) {
                if(r.getRowNum() == 0) continue;
                Cell cell = r.getCell(filterColumnIndex);
                if(cell.getCellTypeEnum() == CellType.STRING) {
                     String value = cell.getStringCellValue();
                     for(String str : filterItems) {
                         if(str.equals(value)) {
                             //该行满足筛选条件
                             row_w = sheet_w.createRow(rowIndex);
                             row_w.createCell(0).setCellFormula("ROW()-1");
                             for (int i = 0; i < columnIndexList.size(); i++) {
                                 int index = columnIndexList.get(i);
                                 Cell c = r.getCell(index);
                                 Cell c_w = row_w.createCell(i+1, c.getCellType());
                                 //从原单元格中继承单元格格式,包括内容格式、边框、颜色、字体。注意:这里必须先create,不能直接设置其他单元格的格式
                                 CellStyle cs = workbook_w.createCellStyle();
                                 cs.cloneStyleFrom(c.getCellStyle());
                                 c_w.setCellStyle(cs);
                                 //以下是错误的方法,Error:This Style does not belong to the supplied Workbook Stlyes Source. Are you trying to assign a style from one workbook to the cell of a differnt workbook?
                                 //c_w.setCellStyle(c.getCellStyle());
                                 switch (c.getCellTypeEnum()) {
                                case _NONE:
                                    break;
                                case BLANK:
                                    break;
                                case BOOLEAN:
                                    c_w.setCellValue(c.getBooleanCellValue());
                                    break;
                                case ERROR:
                                    c_w.setCellErrorValue(c.getErrorCellValue());
                                    break;
                                case FORMULA:
                                    //唯一的问题就是公式由于是根据单元格计算,新表可能相应的单元格存放不同的数据,造成计算结果不同
//                                  c_w.setCellFormula(c.getCellFormula());
                                    CellValue cellValue = evaluator.evaluate(c);
                                    c_w.setCellType(cellValue.getCellType());
                                    switch (cellValue.getCellTypeEnum()) {
                                    case BOOLEAN:
                                        c_w.setCellValue(cellValue.getBooleanValue());
                                        break;
                                    case ERROR:
                                        c_w.setCellErrorValue(cellValue.getErrorValue());
                                        break;
                                    case NUMERIC:
                                        if(DateUtil.isCellDateFormatted(c)) {
                                            c_w.setCellValue(c.getDateCellValue());
                                        } else {
                                            c_w.setCellValue(c.getNumericCellValue());
                                        }
                                        break;
                                    case STRING:
                                        c_w.setCellValue(c.getRichStringCellValue());
                                        break;
                                    default:
                                        break;
                                    }
                                    break;
                                case NUMERIC:
                                    if(DateUtil.isCellDateFormatted(c)) {
                                        c_w.setCellValue(c.getDateCellValue());
                                    } else {
                                        c_w.setCellValue(c.getNumericCellValue());
                                    }
                                    break;
                                case STRING:
                                    c_w.setCellValue(c.getRichStringCellValue());
                                    break;
                                }
                             }
                             rowIndex++;
                             break;
                         }
                     }
                }
            }
            fos = new FileOutputStream(targetFileName);
            workbook_w.write(fos);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (EncryptedDocumentException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inp != null) {
                try {
                    inp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (workbook_w != null) {
                try {
                    workbook_w.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        filter(EXCEL_PATH, "filter.xlsx", new String[] {"姓名","员工号","部门","年龄","入岗时间"}, "姓名", new String[] {"陈七", "张三", "林八", "钱二", "东方不败"});
    }


虽然能基本完成这个任务,但这里还有一个不完美的地方,那就是公式单元格。
这里公式单元格的处理方式为:计算出该值,然后将其值填入对应单元。
其实更好的做法应该是将公式中的字段进行映射,映射到新的字段中。

你可能感兴趣的:(——,Java,POI,操作,Office)