【问题标题】:Getting specific data from an excel sheet JAVA从 Excel 表 JAVA 获取特定数据
【发布时间】:2015-03-15 15:40:23
【问题描述】:

我正在尝试从 Excel 工作表中获取特定数据,数据是动态的。它可以是任何东西。列标题是我唯一可以用作占位符的东西,但列标题在工作表中的位置可能会有所不同。

例如,我有一张这样的表格:

|名称|姓氏|价值|

|酒吧 |便便 | 5|

|巴兹|富 | 7|

但是例如,我需要遍历工作表以获取姓氏列,然后如果我找到 surname = 'poo' 我必须拉取其对应的值,该值在工作表中位于下一个列中,但这是动态的。 surname 和 value 列并不总是彼此相邻,它们可以位于顶部的任何位置。但是,如果我在 surname 列中找到特定的“东西”,我需要提取它的值。

我已经设法遍历工作表并将所有数据存储在二维数组中并显示该数据。根据我所做的研究,这不是一种有效的方法,因为从工作表中遍历和存储大量数据会占用大量内存。我读过您可以阅读 excel 表,而不是将这些值存储在数组中,如果它们符合特定条件,您可以立即将它们写入另一张表。 EG:(伪) If(columnheader == surname && surname == foo ) 然后获取相应的值,然后将该值写入新工作表。

好的,我的问题是:

1.如何实现对工作表的迭代而不是将其存储在数组中并在匹配条件时将其直接写入另一个工作表?

2.从我下面的代码中,我如何实现对数组中的数据进行排序并查找surname = foo是否得到其对应的值?

就像我说的那样,表格中的数据是动态的,除了列标题,但作为标题的位置是动态的。

抱歉,帖子太长了,任何帮助将不胜感激。

package demo.poi;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.Cell;
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.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


public class test  {

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

        File excel = new File("test.xlsx");
        FileInputStream fis = new FileInputStream(excel);

        XSSFWorkbook wb = new XSSFWorkbook(fis);
        XSSFSheet ws = wb.getSheetAt(0);
        ws.setForceFormulaRecalculation(true);

        int rowNum = ws.getLastRowNum() + 1;
        int colNum = ws.getRow(0).getLastCellNum();
        int surnameHeaderIndex = -1, valueHeaderIndex = -1;

        //Read the headers first. Locate the ones you need
        XSSFRow rowHeader = ws.getRow(0);
        for (int j = 0; j < colNum; j++) {
            XSSFCell cell = rowHeader.getCell(j);
            String cellValue = cellToString(cell);
            if("SURNAME".equalsIgnoreCase(cellValue)) {
                surnameHeaderIndex = j;
            } else if("VALUE".equalsIgnoreCase(cellValue)) {
                valueHeaderIndex = j;
            }
        }

        if(surnameHeaderIndex == -1 || valueHeaderIndex == -1) {
            throw new Exception("Could not find header indexes\nSurname : " + surnameHeaderIndex + " | Value : " + valueHeaderIndex);
        }
        //createnew workbook
        XSSFWorkbook workbook = new XSSFWorkbook(); 		
		//Create a blank sheet
		XSSFSheet sheet = workbook.createSheet("data");
		
        for (int i = 1; i < rowNum; i++) {
            XSSFRow row = ws.getRow(i);
           row = sheet.createRow(rowNum++);
            String surname = cellToString(row.getCell(surnameHeaderIndex));
            String value = cellToString(row.getCell(valueHeaderIndex));
            int cellIndex = 0;
            row.createCell(cellIndex++).setCellValue(surname);
            row.createCell(cellIndex++).setCellValue(value);
            

            
        }
        FileOutputStream fos = new FileOutputStream(new File("test1.xlsx"));
        workbook.write(fos);
        fos.close();
    }

    public static String cellToString(XSSFCell cell) {

        int type;
        Object result = null;
        type = cell.getCellType();

        switch (type) {

        case XSSFCell.CELL_TYPE_NUMERIC:
            result = BigDecimal.valueOf(cell.getNumericCellValue())
                    .toPlainString();

            break;
        case XSSFCell.CELL_TYPE_STRING:
            result = cell.getStringCellValue();
            break;
        case XSSFCell.CELL_TYPE_BLANK:
            result = "";
            break;
        case XSSFCell.CELL_TYPE_FORMULA:
            result = cell.getCellFormula();
        }

        return result.toString();
    }
}

【问题讨论】:

  • 给出一个完整的例子和想要的输出。你提到排序,但我不完全明白你的意思。
  • 嗨,所以基本上来自那个 excel 表。我想迭代并找到特定的值。例如,现在我得到了数组中的所有数据,我需要用它做一些事情例如:我正在寻找的输出是一旦我找到 Surname 列,找到值“foo”,当你找到 foo 时,转到值列并得到相应的数字。如果您查看演示表,“foo”的值为“7”。但是,如果列标题位置是动态的,我如何获取 foo 的位置并将其与 7 的值相关联?

标签: java excel apache apache-poi xssf


【解决方案1】:

这样的事情应该是一个很好的起点。 基本上,您解析标题所在的第一行。 您找到所需标题的位置并保留它们。 在这个例子中,只需要两个标题(姓氏,值),所以我只保留两个变量。如果还有更多,那么解决方案是将这些标题的位置保留在HashMap 中,其中键是标题的名称。之后,行的迭代开始。该程序解析所需列的值 (row.getCell(index))。现在你有了你需要的值,而且只有它们。你可以做任何你想做的事,你可以打印它们或写一个文件或诸如此类的东西。

这是一个例子。错误处理取决于您。这只是一个例子。

package POIParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigDecimal;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class MainPoi {

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

        File excel = new File("test.xlsx");
        FileInputStream fis = new FileInputStream(excel);

        XSSFWorkbook wb = new XSSFWorkbook(fis);
        XSSFSheet ws = wb.getSheetAt(0);
        ws.setForceFormulaRecalculation(true);

        int rowNum = ws.getLastRowNum() + 1;
        int colNum = ws.getRow(0).getLastCellNum();
        int surnameHeaderIndex = -1, valueHeaderIndex = -1;

        // Read the headers first. Locate the ones you need
        XSSFRow rowHeader = ws.getRow(0);
        for (int j = 0; j < colNum; j++) {
            XSSFCell cell = rowHeader.getCell(j);
            String cellValue = cellToString(cell);
            if ("SURNAME".equalsIgnoreCase(cellValue)) {
                surnameHeaderIndex = j;
            } else if ("VALUE".equalsIgnoreCase(cellValue)) {
                valueHeaderIndex = j;
            }
        }

        if (surnameHeaderIndex == -1 || valueHeaderIndex == -1) {
            throw new Exception("Could not find header indexes\nSurname : "
                    + surnameHeaderIndex + " | Value : " + valueHeaderIndex);
        }
        // createnew workbook
        XSSFWorkbook workbook = new XSSFWorkbook();
        // Create a blank sheet
        XSSFSheet sheet = workbook.createSheet("data");

        for (int i = 1; i < rowNum; i++) {
            XSSFRow row = ws.getRow(i);
            String surname = cellToString(row.getCell(surnameHeaderIndex));
            String value = cellToString(row.getCell(valueHeaderIndex));
            int cellIndex = 0;
            //Create a newRow object for the output excel. 
            //We begin for i = 1, because of the headers from the input excel, so we go minus 1 in the new (no headers).
            //If for the output we need headers, add them outside this for loop, and go with i, not i-1
            XSSFRow newRow = sheet.createRow(i-1);  
            newRow.createCell(cellIndex++).setCellValue(surname);
            newRow.createCell(cellIndex++).setCellValue(value);
        }

        FileOutputStream fos = new FileOutputStream(new File("test1.xlsx"));
        workbook.write(fos);
        fos.close();
    }

    public static String cellToString(XSSFCell cell) {

        int type;
        Object result = null;
        type = cell.getCellType();

        switch (type) {

        case XSSFCell.CELL_TYPE_NUMERIC:
            result = BigDecimal.valueOf(cell.getNumericCellValue())
                    .toPlainString();

            break;
        case XSSFCell.CELL_TYPE_STRING:
            result = cell.getStringCellValue();
            break;
        case XSSFCell.CELL_TYPE_BLANK:
            result = "";
            break;
        case XSSFCell.CELL_TYPE_FORMULA:
            result = cell.getCellFormula();
        }

        return result.toString();
    }
}

【讨论】:

  • 谢谢你,alkis,这对我来说绝对是一个好的开始,感激不尽。您对问题 1 有什么建议吗?
  • 没问题。玩得开心。
  • 嗨,我用我迄今为止所做的代码更改更新了我的原始帖子。我无法将数据写入新工作簿。这些是我在 demo.poi.test.main(test.java:56) 的 demo.poi.test.cellToString(test.java:80) 的线程“main”java.lang.NullPointerException 中获取异常的错误
  • 好的,为了您的方便,我用一些额外的 cmets 更新了我的代码。但请注意,这超出了 SO 的规则。调试问题,无效。玩得开心
猜你喜欢
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 2019-05-15
  • 2019-04-21
  • 2013-09-02
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多