繁体   English   中英

按列名读取 excel java POI

[英]read excel by column name java POI

下午好,专家们有一个问题,我需要按列名而不是索引来读取整个 excel 文件,例如:

Column1 | Column2 | Column3
data1      data 2    data 3

POI 允许我通过返回Column1 = 0, Column2= 1 etc,的方法getColumnIndex()读取列索引,但我需要通过列名Column1Column2等读取它,有什么办法可以做到这一点?

我需要按列名读取行和列的所有字段。 附上我阅读文件的代码:

更新代码:

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class example {

    DataFormatter fmt = new DataFormatter();

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws FileNotFoundException, IOException {
        example softMarti = new example();
        FileInputStream file = new FileInputStream(new File("C:archive.xlsx"));
        XSSFWorkbook workbook = new XSSFWorkbook(file);
        XSSFSheet sheet = workbook.getSheetAt(0);
        Iterator<Row> rowIterator = sheet.iterator();
        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();
            int rowIndex = row.getRowNum();
            if (rowIndex < 1) {
                continue;
            }
            Iterator<Cell> cellIterator = row.cellIterator();

            while (cellIterator.hasNext()) {
                Cell cell = cellIterator.next();
                int columnIndex = cell.getColumnIndex();
                if (columnIndex != 0 && columnIndex != 1 && columnIndex != 4) {
                    continue;
                }
                String columnName = "";
                switch (columnIndex) {
                    case 0:
                        columnName = "column1";
                        break;
                    case 1:
                        columnName = "column2";
                        break;
                    case 4:
                        columnName = "column 4";
                        break;
                }
                String value = example.getValue(cell);
                boolean valid = example.isValid(columnIndex, value);
                if (valid) {
                    continue;
                }
                System.out.print(columnName + rowIndex);
                System.out.println(" -> " + value);

            }

        }

        // TODO code application logic here
    }

    private String getValue(Cell cell) {
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_BLANK:
                return null;
            case Cell.CELL_TYPE_BOOLEAN:
                return "CELL_TYPE_BOOLEAN";
            case Cell.CELL_TYPE_ERROR:
                return "CELL_TYPE_ERROR";
            case Cell.CELL_TYPE_FORMULA:
                return "CELL_TYPE_FORMULA";
            case Cell.CELL_TYPE_NUMERIC:
                return fmt.formatCellValue(cell);
            case Cell.CELL_TYPE_STRING:
                return cell.getStringCellValue();
            default:
                return "none";

        }

    }

    boolean isValid(int column, String value) {
        if (value == null) {
            return false;
        }
        String pattern = "";
        switch (column) {
            case 0:
                pattern = "[A-Za-z0-9_\\- ]{1,20}";
                break;
            case 1:
                pattern = "[A-Za-z0-9_\\- ]{1,80}";
                break;
            case 4:
                pattern = "[0-9]{1,8}";
                break;
        }
        Pattern pat = Pattern.compile(pattern);
        Matcher mat = pat.matcher(value);
        return mat.matches();
    }
}

此代码有效,但我需要验证列名,因为对于我的项目,列可能会更改 position,这是我的目标

为什么不读取第一行(0)单元格值(0-n)(又名列名)并将(列名,列索引)放入字符串/整数映射中。 然后您可以按名称引用列索引。

下面是一个例子:

Map<String, Integer> map = new HashMap<String,Integer>(); //Create map
HSSFRow row = sheet.getRow(0); //Get first row
//following is boilerplate from the java doc
short minColIx = row.getFirstCellNum(); //get the first column index for a row
short maxColIx = row.getLastCellNum(); //get the last column index for a row
for(short colIx=minColIx; colIx<maxColIx; colIx++) { //loop from first to last index
   HSSFCell cell = row.getCell(colIx); //get the cell
   map.put(cell.getStringCellValue(),cell.getColumnIndex()) //add the cell contents (name of column) and cell index to the map
 }

在此之后,您将获得 columnName ---> 索引中的映射。 然后你可以这样做:

int idx = map.get("ColumnName");

....并且您可以在 row.getCell(idx) 中使用它来获取所有其他行中的单元格。

阅读下面代码中的注释。 除了这个,我帮不了你。 您需要阅读文档并弄清楚如何去做。

Workbook workbook = WorkbookFactory.create(new FileInputStream("C:\\file.xlsx"));

Sheet sheet = workbook.getSheetAt(0);
totalRows = sheet.getPhysicalNumberOfRows();

Map<String, Integer> map = new HashMap<String,Integer>(); //Create map
HSSFRow row = sheet.getRow(0); //Get first row
//following is boilerplate from the java doc
short minColIx = row.getFirstCellNum(); //get the first column index for a row
short maxColIx = row.getLastCellNum(); //get the last column index for a row
for(short colIx=minColIx; colIx<maxColIx; colIx++) { //loop from first to last index
HSSFCell cell = row.getCell(colIx); //get the cell
map.put(cell.getStringCellValue(),cell.getColumnIndex()) //add the cell contents (name of column) and cell index to the map
}

List<ReportRow> listOfDataFromReport = new ArrayList<ReportRow>();
for(int x = 1; x<=totalRows; x++){
 ReportRow rr = new ReportRow(); //Data structure to hold the data from the xls file.
 HSSFRow dataRow = sheet.getRow(x); //get row 1 to row n (rows containing data)

 int idxForColumn1 = map.get("Column1"); //get the column index for the column with header name = "Column1"
 int idxForColumn2 = map.get("Column2"); //get the column index for the column with header name = "Column2"
 int idxForColumn3 = map.get("Column3"); //get the column index for the column with header name = "Column3"

 HSSFCell cell1 = dataRow.getCell(idxForColumn1) //Get the cells for each of the indexes
 HSSFCell cell2 = dataRow.getCell(idxForColumn2) 
 HSSFCell cell3 = dataRow.getCell(idxForColumn3)  

 //NOTE THAT YOU HAVE TO KNOW THE DATA TYPES OF THE DATA YOU'RE EXTRACTING.
 //FOR EXAMPLE I DON'T THINK YOU CAN USE cell.getStringCellValue IF YOU'RE TRYING TO GET A NUMBER
 rr.setColumn1(cell1.getStringCellValue()); //Get the values out of those cells and put them into the report row object
 rr.setColumn2(cell2.getStringCellValue());
 rr.setColumn3(cell3.getStringCellValue());

 listOfDataFromReport.add(rr);

}

//Now you have a list of report rows
for(int j = 0; j< listOfDataFromReport.size();j++){
   System.out.println("Column 1 Value: " +   listOfDataFromReport.get(j).getColumn1())
//etc...    
}

//This class holds the values from the xls file.  You may not need it
// I have no idea what you're doing with the data.  If you simply wanted to 
//print the data to console you wouldn't need it.
public static class ReportRow{
private String column1;
private String column2;
private String column3;

public String getColumn1(){
    return this.column1;
}
public void setColumn1(String column1){
    this.column1 = column1;
}   

public String getColumn2(){
    return this.column2;
}
public void setColumn2(String column2){
    this.column2 = column2;
}       
public String getColumn3(){
    return this.column3;
}
public void setColumn3(String column3){
    this.column3 = column3;
}   
}

我写了一个方法

public static int columnName(String a) throws EncryptedDocumentException, InvalidFormatException, IOException {

    int coefficient = 0;
    String excelFilePath = ConfigurationReader.getProperty("pathToYourFile"); // or specify the path directly
    FileInputStream inputStream = new FileInputStream(new File(excelFilePath));
    Workbook wb = WorkbookFactory.create(inputStream);
    Sheet sh = wb.getSheet("Sheet1");
    Row row = sh.getRow(0);
    int cellNum = row.getPhysicalNumberOfCells();
    for (int i = 0; i < cellNum; i++) {
        if ((row.getCell(i).toString()).equals(a)) {
            coefficient = i;
        }
    }

    return coefficient;
}

然后在我的代码中调用它:

Cell anyCellName = row.getCell(columnName("NameOfColumnInMyExcell"));

像这样的任何列名。 现在我可以按任何顺序移动我的列并且代码有效。

这是我的方法,希望对你有帮助

首先让我们获取列名并将其放入 map

 Map<String, Integer> requiredHeaders = new HashMap<>();
        FileInputStream file = new FileInputStream(new File("filename.xlsx"));
        Workbook workbook = new XSSFWorkbook(file);
        DataFormatter formatter = new DataFormatter();
        Sheet sheet = workbook.getSheetAt(0);
 for (Cell cell : sheet.getRow(0)) {
        requiredHeaders.put(cell.getStringCellValue(), cell.getColumnIndex());
    }

然后我们可以使用列索引循环查找行以获取所需的行

    for (int i = 1; i <= sheet.getLastRowNum(); i++) {
        Row row = sheet.getRow(i);
        System.out.println("serial = " + formatter.formatCellValue(row.getCell(requiredHeaders.get("serial"))));
        System.out.println("pin = " + formatter.formatCellValue(row.getCell(requiredHeaders.get("pin"))));
    }

现在完整代码如下:

private void readFile() throws FileNotFoundException, IOException {
    Map<String, Integer> requiredHeaders = new HashMap<>();
    FileInputStream file = new FileInputStream(new File("filename.xlsx"));
    Workbook workbook = new XSSFWorkbook(file);
    DataFormatter formatter = new DataFormatter();
    Sheet sheet = workbook.getSheetAt(0);
    for (Cell cell : sheet.getRow(0)) {
        requiredHeaders.put(cell.getStringCellValue(), cell.getColumnIndex());
    }

    for (int i = 1; i <= sheet.getLastRowNum(); i++) {
        Row row = sheet.getRow(i);
        System.out.println("serial = " + formatter.formatCellValue(row.getCell(requiredHeaders.get("serial"))));
        System.out.println("pin = " + formatter.formatCellValue(row.getCell(requiredHeaders.get("pin"))));
    }
    workbook.close();
}

这就是我的工作表的样子

现在这里是 output 代码输出

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM