如何从Java中的Excel列中读取值

时间:2016-06-04 05:27:38

标签: java excel

如何在Excel(xlsx)中使用Apache POI读取与特定列名相关的值。

列名是Excel表的第一行。 value是以Y作为单元格值的行。

我的输入只是列名, 我需要列名称和行的值,其值为#34; Y"

Below is the Excel Sheet

这里我输入列名为"姓名" ,它应该回报价值"何塞"  而且"年龄"它应该返回23

我尝试过发现两个不同循环系统的代码,但是出现了一些错误

public static void main(String[] args) throws Exception {

    File file =    new File("D:\\xcel.xlsx");
    FileInputStream inputStream = new FileInputStream(file);


     Workbook wb = new XSSFWorkbook(inputStream);
     Sheet sh = wb.getSheet("Sheet1");

    //  Find the Column number Which has column name and row number 0

     Row row1 = sh.getRow(0);       
     int colNum = -1;
     for (int i = 0 ;i<=row1.getLastCellNum();i++){
         Cell cell1 = row1.getCell(i,Row.CREATE_NULL_AS_BLANK);
         String cellValue1 = cell1.getStringCellValue();
         if ("Employee".equals(cellValue1)){
              colNum = i ;
              break;}
        }



    //  Find the Row number Which is "Y" and column number 1

     int rowNum = -1;        
     for (int j = 0 ;j<=sh.getLastRowNum()+1;j++){           
         Row row2 = sh.getRow(j); 
         Cell cell2 = row2.getCell(1,Row.CREATE_NULL_AS_BLANK);       
         String cellValue2 = cell2.getStringCellValue();
            if ("Y".equals(cellValue2))
            { rowNum = j ;
            break;}                     
        }



    Row r = sh.getRow(rowNum);
     String val = r.getCell(colNum).getStringCellValue();

     System.out.println("Row number is "+rowNum);
     System.out.println("Last row number :"+sh.getLastRowNum());
     System.out.println("Column number is "+colNum);
     System.out.println("Last Column number :"+sh.getRow(0).getLastCellNum());
     System.out.println("Value is "+val); 

}

当我运行上面的代码时,即使在它之前有空白单元格,我也会得到列号,

但是对于行,如果在它之前存在空白单元格,我会在线程&#34; main&#34;中得到错误异常。显示java.lang.NullPointerException 但如果没有黑细胞,它就能正常工作。

再次在下面的代码中,我没有收到任何错误

但如果我的列名存在于最后一个单元格中,那么最后一个单元格编号和我的列编号应该相同,但是我的列编号比最后一个单元格编号小一个。

但是对于行号,它很好,我得到相同的数字。

此问题也适用于第一个代码

public static void main(String[] args) throws Exception {

    File file =    new File("D:\\xcel.xlsx");
    FileInputStream inputStream = new FileInputStream(file);


     Workbook wb = new XSSFWorkbook(inputStream);
     Sheet sh = wb.getSheet("Sheet1");

    //  Find the Column number Which has column name and row number 0

     Row row1 = sh.getRow(0);       

     int colNum = -1;
     for (Cell cell : row1) {
            if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                if (cell.getRichStringCellValue().getString().trim().equals("Employee")) {
                    colNum =  cell.getColumnIndex();                                   }
                                                             }
                                }

    //  Find the Row number Which is "Y" and column number 1


     int rowNum = -1;
     for (Row row : sh) {
            for (Cell cell : row) {
                if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                    if (cell.getRichStringCellValue().getString().trim().equals("Y")) {
                        rowNum =  row.getRowNum();                                     }
                                                                 }
                                    }
                        }               


 // Get the required value
    Row r = sh.getRow(rowNum);
     String val = r.getCell(colNum).getStringCellValue();

     System.out.println("Row number is "+rowNum);
     System.out.println("Last row number :"+sh.getLastRowNum());
     System.out.println("Column number is "+colNum);
     System.out.println("Last Column number :"+sh.getRow(0).getLastCellNum());
     System.out.println("Value is "+val); 

1 个答案:

答案 0 :(得分:0)

Apache POI不支持此类事情。 您可能需要将EXCEL文件读取为您自己写入的抽象结构。

我建议使用包含标题和内容的文档模型。

如果您的目的只是按列名收集值,并且有一些数据冗余,则可以将每个值存储为{column name:row value}的映射条目,列在所有行的列表中。

拥有这样的结构时,您可以轻松地按列值进行搜索。

例如:

import java.util.ArrayList;
import java.util.List;

public class Document {

    private List<String> headers;

    private List<DataRow> contents;

    public Document(List<String> headers, List<DataRow> contents) {
        this.headers = headers;
        this.contents = contents;
    }

    public List<DataRow> findAllWhere(String column, String value) {
        List<DataRow> result = new ArrayList<>();
        for (DataRow content : contents) {
            if (content.get(column).equals(value)) {
                result.add(content);
            }
        }
        return result;
    }

    public List<DataRow> getContents() {
        return contents;
    }

    public void setContents(List<DataRow> contents) {
        this.contents = contents;
    }

    public List<String> getHeaders() {
        return headers;
    }

    public void setHeaders(List<String> headers) {
        this.headers = headers;
    }

    @Override
    public String toString() {
        return "Document{" +
                "headers=" + headers +
                ", contents=" + contents +
                '}';
    }

}

对于行,我们可以这样:

import java.util.HashMap;
import java.util.Map;

public class DataRow {

    private Map<String, String> values = new HashMap<>();
    private Integer index;

    public String put(String columnName, String value) {
        return values.put(columnName, value);
    }

    public String get(String columnName) {
        return values.get(columnName);
    }

    public Integer getIndex() {
        return index;
    }

    public void setIndex(Integer index) {
        this.index = index;
    }


    @Override
    public String toString() {
        return "DataRow{" +
                "values=" + values +
                ", index=" + index +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        DataRow dataRow = (DataRow) o;

        if (values != null ? !values.equals(dataRow.values) : dataRow.values != null) return false;
        return !(index != null ? !index.equals(dataRow.index) : dataRow.index != null);

    }

    @Override
    public int hashCode() {
        int result = values != null ? values.hashCode() : 0;
        result = 31 * result + (index != null ? index.hashCode() : 0);
        return result;
    }

}

如何解析它的示例:

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Parser {

    private InputStream stream;

    public Parser(InputStream stream) {
        this.stream = stream;
    }

    public Document parse() {
        try {
            Workbook wb = WorkbookFactory.create(stream);

            //TODO better sheet searching
            Sheet sheet = wb.getSheetAt(0);
            Iterator<Row> rows = sheet.rowIterator();

            List<String> headers = new ArrayList<>();
            if (rows.hasNext()) {
                Row row = rows.next();
                for (Cell cell : row) {
                    headers.add(cell.getStringCellValue());
                }
            }

            List<DataRow> contents = new ArrayList<>();
            while (rows.hasNext()) {
                Row row = rows.next();
                DataRow dataRow = new DataRow();
                dataRow.setIndex(row.getRowNum());
                for (Cell cell : row) {
                    //TODO safeguard for header resolving, cell column index might be out of bound of header array
                    dataRow.put(
                            headers.get(cell.getColumnIndex()),
                            cell.getStringCellValue()
                    );
                }
                contents.add(dataRow);
            }

            return new Document(headers, contents);
        } catch (IOException | InvalidFormatException e) {
            throw new RuntimeException(e);
        }
    }

}

示例使用方法:

 Parser parser = new Parser(getClass().getResourceAsStream("resource.xlsx"));
 List<DataRow> data = parser.parse().findAllWhere("FLAG", "Y");

完整模拟可用here

这是你在找什么? 我必须警告你,每次你需要搜索整个excel时,这不是一个好主意。

public static String findFirstExecute(String excelPath, String sheetName, String columnName) {
    return findFirstValue(excelPath, sheetName, columnName, "Execute", "Y");
}

public static String findFirstValue(String excelPath, String sheetName, String columnName, String filterColumnName, String filterColumnValue) {
    try {
        Workbook wb = WorkbookFactory.create(new FileInputStream(new File(excelPath)));

        Sheet sheet = wb.getSheet(sheetName);
        Iterator<Row> rows = sheet.rowIterator();

        Map<String, Integer> headers = new HashMap<>();
        if (rows.hasNext()) {
            Row row = rows.next();
            for (Cell cell : row) {
                headers.put(cell.getStringCellValue(), cell.getColumnIndex());
            }
        }

        while (rows.hasNext()) {
            Row row = rows.next();
            String executeValue = row.getCell(headers.get(filterColumnName)).getStringCellValue();
            if (executeValue.equals(filterColumnValue)) {
                return row.getCell(headers.get(columnName)).getStringCellValue();
            }
        }
        return null;
    } catch (IOException | InvalidFormatException e) {
        throw new RuntimeException(e);
    }
}