如何使用Apache POI读取特定的Excel列

23

在使用Apache POI时,我在Excel中遇到了一个问题。我可以跨行读取,但有时我想只读取特定的列。

所以是否可能只读取任何特定的列,例如仅A列或仅C列。

我正在使用Java语言进行此操作。

7个回答

28

heikkim是正确的,这里有一些来自我所拥有的代码的样例代码:

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;
...
for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
  row = sheet.getRow(rowIndex);
  if (row != null) {
    Cell cell = row.getCell(colIndex);
    if (cell != null) {
      // Found column and there is value in the cell.
      cellValueMaybeNull = cell.getStringCellValue();
      // Do something with the cellValueMaybeNull here ...
      // break; ???
    }
  }
}

对于colCount,请使用类似于row.getPhysicalNumberOfCells()的内容。


谢谢Christophe..但我有一个疑问..在col1中填充了4个单元格,但在col3中填充了8个单元格,所以当我运行代码时,它将运行8次,但我只想要col1中的4个,并且我只想要特定列中填充的单元格数,因为我正在将此计数和数据提供给我的测试输入..请帮忙..再次感谢您的时间和代码.. - selva
跳过单元格中没有值的行? - Gagravarr
我添加了一个 break,这经常容易被忘记掉 :) - Christophe Roussy
你本可以直接使用 cell = row.getCell(theColIndexYouWant); 而不必使用循环。 - backslashN
@backslashN 这是在2012年,我很快为问题的需要适应了我的一些代码,但你是对的,我更新了代码,因为这更有效率。 - Christophe Roussy

6
  Sheet sheet  = workBook.getSheetAt(0); // Get Your Sheet.

  for (Row row : sheet) { // For each Row.
      Cell cell = row.getCell(0); // Get the Cell at the Index / Column you want.
  }

我的解决方案,代码上更简单一些。


你似乎在迭代所有的列,然后忽略了你不需要的列。只获取给定行中感兴趣的单元格不是更简单吗? - Gagravarr
是的,这就是它正在做的事情。虽然对于大文件来说并不高效,但我不建议使用它,但对于小文件来说,它还是可以的。从代码角度来看,它确实使代码更简单/更易于维护,您不同意吗? - Jack
其实你是对的,那个很糟糕。我已经更新了更明显的选择。 - Jack

3

根据您的问题,您只需要读取特定列。因此,在迭代行及其单元格时,您可以简单地检查列的索引。

Iterator<Row> rowIterator = mySheet.iterator(); // Traversing over each row of XLSX file
        while (rowIterator.hasNext()) {
            Row row = rowIterator.next(); // For each row, iterate through each columns
            Iterator<Cell> cellIterator = row.cellIterator();
            while (cellIterator.hasNext()) {
                Cell cell = cellIterator.next();
                println "column index"+cell.getColumnIndex()//You will have your columns fixed in Excel file
                if(cell.getColumnIndex()==3)//for example of c
                {
                print "done"            
                }
          }
     }     

我正在使用POI 3.12-- 'org.apache.poi:poi:3.12' 希望对您有所帮助。干杯!

如果你只关心一列,为什么不仅获取那个单元格呢?为什么要遍历行中的所有单元格直到找到它呢? - Gagravarr
其实是的,我希望你指的是“CellReference”类? - 89n3ur0n
1
不用担心,只需使用 row.getCell(columnNumber) 即可! - Gagravarr

2
你可以循环行并从每行读取相同的单元格(这不就是组成列吗?)。

谢谢Brian的回复。是的,但是在col1有4个填充单元格而col5有6个填充单元格的情况下,我感到困惑,因为我正在将这些数据提供给我的测试输入值。所以你能告诉我如何找到列中填充的单元格数吗?请帮帮我。 - selva

2
import java.io.*;

import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.*;
import java.text.*;

public class XSLXReader {
    static DecimalFormat df = new DecimalFormat("#####0");

    public static void main(String[] args) {
        FileWriter fostream;
        PrintWriter out = null;
        String strOutputPath = "H:\\BLR_Team\\Kavitha\\Excel-to-xml\\";
        String strFilePrefix = "Master_5.2-B";

        try {
            InputStream inputStream = new FileInputStream(new File("H:\\BLR_Team\\Kavitha\\Excel-to-xml\\Stack-up 20L pure storage 11-0039-01 ISU_USA-A 1-30-17-Rev_exm.xls"));
            Workbook wb = WorkbookFactory.create(inputStream);
           // Sheet sheet = wb.getSheet(0);
            Sheet sheet =null;
            Integer noOfSheets= wb.getNumberOfSheets();

            for(int i=0;i<noOfSheets;i++){
                sheet = wb.getSheetAt(i);
                System.out.println("Sheet : "+i + " " + sheet.getSheetName());
                System.out.println("Sheet : "+i + " " + sheet.getFirstRowNum());
                System.out.println("Sheet : "+i + " " + sheet.getLastRowNum());

            //Column 29
            fostream = new FileWriter(strOutputPath + "\\" + strFilePrefix+i+ ".xml");
            out = new PrintWriter(new BufferedWriter(fostream));

            out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            out.println("<Bin-code>");

            boolean firstRow = true;
            for (Row row : sheet) {
                if (firstRow == true) {
                    firstRow = false;
                    continue;
                }
                out.println("\t<DCT>");
                out.println(formatElement("\t\t", "ID", formatCell(row.getCell(0))));
                out.println(formatElement("\t\t", "Table_name", formatCell(row.getCell(1))));
                out.println(formatElement("\t\t", "isProddaten", formatCell(row.getCell(2))));
                out.println(formatElement("\t\t", "isR3P01Data", formatCell(row.getCell(3))));

                out.println(formatElement("\t\t", "LayerNo", formatCell(row.getCell(29))));
                out.println("\t</DCT>");
            }
            CellReference ref = new CellReference("A13");
          Row r = sheet.getRow(ref.getRow());
          if (r != null) {
             Cell c = r.getCell(ref.getCol());
           System.out.println(c.getRichStringCellValue().getString());
          }

            for (Row row : sheet) {
                  for (Cell cell : row) {

                      CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex());


                      switch (cell.getCellType()) {
                      case Cell.CELL_TYPE_STRING:
                          System.out.println(cell.getRichStringCellValue().getString());
                          break;
                      case Cell.CELL_TYPE_NUMERIC:
                          if (DateUtil.isCellDateFormatted(cell)) {
                              System.out.println(cell.getDateCellValue());
                          } else {
                              System.out.println(cell.getNumericCellValue());
                          }
                          break;
                      case Cell.CELL_TYPE_BOOLEAN:
                          System.out.println(cell.getBooleanCellValue());
                          break;
                      case Cell.CELL_TYPE_FORMULA:
                          System.out.println(cell.getCellFormula());
                          break;
                      case Cell.CELL_TYPE_BLANK:
                          System.out.println();
                          break;
                      default:
                          System.out.println();
                  }
                  }

            }
            out.write("</Bin-code>");
            out.flush();
            out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String formatCell(Cell cell)
    {
        if (cell == null) {
            return "";
        }
        switch(cell.getCellType()) {
            case Cell.CELL_TYPE_BLANK:
                return "";
            case Cell.CELL_TYPE_BOOLEAN:
                return Boolean.toString(cell.getBooleanCellValue());
            case Cell.CELL_TYPE_ERROR:
                return "*error*";
            case Cell.CELL_TYPE_NUMERIC:
                return XSLXReader.df.format(cell.getNumericCellValue());
            case Cell.CELL_TYPE_STRING:
                return cell.getStringCellValue();
            default:
                return "<unknown value>";
        }
    }

    private static String formatElement(String prefix, String tag, String value) {
        StringBuilder sb = new StringBuilder(prefix);
        sb.append("<");
        sb.append(tag);
        if (value != null && value.length() > 0) {
            sb.append(">");
            sb.append(value);
            sb.append("</");
            sb.append(tag);
            sb.append(">");
        } else {
            sb.append("/>");
        }
        return sb.toString();
    }
}

这段代码有三个作用:

  1. 将Excel文件生成XML格式的文件。作者是Dong Kim。
  2. 打印特定单元格A13的内容。
  3. 将Excel文件的内容以普通文本格式打印出来。需要导入的JAR包:poi-3.9.jar, poi-ooxml-3.9.jar, poi-ooxml-schemas-3.9.jar, xbea‌​n-2.3.0.jar, xmlbeans‌​-xmlpublic-2.4.0.jar‌​, dom4j-1.5.jar。

3
你应该在回答中放置解释,而不是在评论中。 - Xpleria
@Neil Patrao:感谢您将评论移动到解释部分。 - Kavitha yadav
@Kavithayadav,我来到这个帖子,你的代码在我的端上运行良好。但是我需要知道如何定义代码以读取特定的工作表...你能给予建议吗? - user2201789

0

以下是按列读取Excel数据的代码。

public ArrayList<String> extractExcelContentByColumnIndex(int columnIndex){
        ArrayList<String> columndata = null;
        try {
            File f = new File("sample.xlsx")
            FileInputStream ios = new FileInputStream(f);
            XSSFWorkbook workbook = new XSSFWorkbook(ios);
            XSSFSheet sheet = workbook.getSheetAt(0);
            Iterator<Row> rowIterator = sheet.iterator();
            columndata = new ArrayList<>();

            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                Iterator<Cell> cellIterator = row.cellIterator();
                while (cellIterator.hasNext()) {
                    Cell cell = cellIterator.next();

                    if(row.getRowNum() > 0){ //To filter column headings
                        if(cell.getColumnIndex() == columnIndex){// To match column index
                            switch (cell.getCellType()) {
                            case Cell.CELL_TYPE_NUMERIC:
                                columndata.add(cell.getNumericCellValue()+"");
                                break;
                            case Cell.CELL_TYPE_STRING:
                                columndata.add(cell.getStringCellValue());
                                break;
                            }
                        }
                    }
                }
            }
            ios.close();
            System.out.println(columndata);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return columndata;
    }

0
请注意,使用行单元迭代器(Iterator<Cell> cellIterator = row.cellIterator();)迭代列可能会导致静默跳过列。我刚遇到了一个暴露这种行为的文档。
使用for循环中的索引进行迭代,并使用row.getCell(i)不会跳过列,并且会返回正确列索引处的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接