java - 如何在 Java 中从 Excel 中的列名中读取值

标签 java excel

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

Column Names 是我的 Excel Sheet 的第一行。
value 是以 Y 作为单元格值的行。

我的输入只是 Column Name ,
我需要值为“Y”的列名和行的值

Below is the Excel Sheet

在这里,如果将列名输入为 "Names",它应该返回值 "Jose"
而“年龄”应该返回 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); 

}

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

但是对于行,如果它之前有一个空白单元格,我会在线程“main”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); 

最佳答案

Apache POI 不支持这种东西。
您可能需要将您的 EXCEL 文件读取为您自己编写的抽象结构。
我会推荐类似 Document 模型的东西,其中包含您的标题和内容。
如果您的目的只是按列名收集值,那么您可以将每个值作为 {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);
    }
}

关于java - 如何在 Java 中从 Excel 中的列名中读取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37626709/

相关文章:

Java - 为什么我的插入速度这么慢?

excel - VLOOKUP 找不到数据的问题

excel - 如何从另一张纸上的数据透视表计算 COUNTIF "=#N/A"?

python - 如何使用python计算excel每列中填充单元格的数量

excel - 列表中带有 #N/A 的排名数字

python - 将多个excel文件导入python pandas并将它们连接到一个数据帧中

java - 如何获取任意按下的键值

java - 在线java编译显示这样的错误

java - 为什么在调用该方法时会出现 NullPointerException?

java - 如何在浏览器中自动化 Java applet