如何使用Apache POI读取具有日期的Excel单元格?

89

我正在使用Apache POI 3.6,我想读取一个包含日期的Excel文件,日期格式为8/23/1991

 switch (cell.getCellType()) {

   ...
   ...

   case HSSFCell.CELL_TYPE_NUMERIC:
     value = "NUMERIC value=" + cell.getNumericCellValue();
     break;

   ...

 }

但它接受数字值类型,并返回像这样的值:33473.0

我尝试使用数字单元格类型,但没有成功。

dbltemp=row.getCell(c, Row.CREATE_NULL_AS_BLANK).getNumericCellValue();

if (c == 6 || c == 9) {
    strTemp= new String(dbltemp.toString().trim());

    long tempDate = Long.parseLong(strTemp);
    Date date = new Date(tempDate);

    strVal = date.toString();
}

我该如何解决我的问题?


为了我的个人项目,我将它更改为 Excel 表格中的“文本”列以规避此问题。 - N00b Pr0grammer
10个回答

128

注意:HSSFDateUtil已被弃用

如果你知道每行中哪个单元格,例如第0列将是日期,那么你可以直接使用row.getCell(0).getDateCellValue()
http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFCell.html#getDateCellValue()

更新:这里有一个例子 - 你可以将它应用于上面的switch case代码中。我检查并打印数字和日期值。在这种情况下,我的表格的第一列是日期,因此我使用row.getCell(0)

你可以直接使用if (HSSFDateUtil.isCellDateFormatted .. 代码块在你的switch case中。

if (row.getCell(0).getCellType() == HSSFCell.CELL_TYPE_NUMERIC)
    System.out.println ("Row No.: " + row.getRowNum ()+ " " +
        row.getCell(0).getNumericCellValue());

    if (HSSFDateUtil.isCellDateFormatted(row.getCell(0))) {
        System.out.println ("Row No.: " + row.getRowNum ()+ " " + 
            row.getCell(0).getDateCellValue());
    }
}
输出结果为:
Row No.: 0 39281.0
Row No.: 0 Wed Jul 18 00:00:00 IST 2007
Row No.: 1 39491.0
Row No.: 1 Wed Feb 13 00:00:00 IST 2008
Row No.: 2 39311.0
Row No.: 2 Fri Aug 17 00:00:00 IST 2007

18
调用 DateUtil.isCellDateFormatted() 方法将有助于从 HSSF 和 XSSF 中解放代码。通过使用全局父项而不是依赖于特定于 XLS/XLSX 的 HSSF/XSSF 子项,您可以使代码更具普适性。 - Aram Paronikyan
请调整或删除第二个链接。它返回404错误。 - Daniel T. Sobrosa
1
HSSFDateUtil在4.1.2版本中已被弃用。 - Aldo Canepa
4
不要使用 HSSFDateUtil,而是使用 DateUtilHSSFDateUtil 的父类)。 - Remigius Stalder
1
请使用CellType.NUMERIC而不是HSSFCell.CELL_TYPE_NUMERIC。 - S. Florin
显示剩余6条评论

25

是的,我理解了你的问题。识别单元格是否具有数字或数据值是困难的。

如果您希望以Excel中显示的格式获取数据,只需使用DataFormatter类格式化单元格即可。

DataFormatter dataFormatter = new DataFormatter();
String cellStringValue = dataFormatter.formatCellValue(row.getCell(0));
System.out.println ("Is shows data as show in Excel file" + cellStringValue);  // Here it automcatically format data based on that cell format.
// No need for extra efforts 

1
如何以ISO格式(YYYY-MM-DD)获取格式化日期? - golimar
它总是显示数字。 - MathematicsBeginner

13
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;


Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
if(cell.getCellTypeEnum() == CellType.NUMERIC||cell.getCellTypeEnum() == CellType.FORMULA)
   {
    

 String cellValue=String.valueOf(cell.getNumericCellValue());
     if(HSSFDateUtil.isCellDateFormatted(cell))
      {
          DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
          Date date = cell.getDateCellValue();
          cellValue = df.format(date);
       }
          System.out.println(cellValue);
    }

请为您的回答添加更多上下文信息。仅仅写代码作为回答可能不够清晰,对于所有阅读您的回答的人来说。 - uzilan
它使用getDateCellValue作为其他答案,但还使用SimpleDateFormat来格式化日期值,这是大多数用户想要的。 - golimar

4

Apache Poi 有一个 DateUtil.isCellDateFormatted(XSSFCell) 方法,它非常有效。

Object objData = switch (cell.getCellType()){
   case NUMERIC ->{
      if(DateUtil.isCellDateFormatted(cell)){
         yield cell.getDateCellValue();
      }else{
         yield cell.getNumericCellValue();
      }
  } //The rest of the cellTypes need to be implemented.
}

现在可以测试objData是否为日期或双精度浮点数。


2

到目前为止,这种方法已经被证明在读取日期单元格方面非常健壮:

Original Answer翻译成:"最初的回答"

private LocalDate readCellAsDate(final Row row, final int pos) {
    if (pos == -1) {
        return null;
    }
    final Cell cell = row.getCell(pos - 1);
    if (cell != null) {
        cell.setCellType(CellType.NUMERIC);
    } else {
        return null;
    }
    if (DateUtil.isCellDateFormatted(cell)) {
        try {
            return cell.getDateCellValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        } catch (final NullPointerException e) {
            logger.error(e.getMessage());
            return null;
        }
    }
    return null;
}

1
你需要使用DateUtils:详细信息请参见这篇文章
或者,更好的选择是使用Andy Khan的JExcel而不是POI。

我已经在POI中实现了很多东西,很抱歉因为这个我不能去做其他事情。一定有什么问题...还是谢谢你Duffymo。 - Venkat
1
如果你无法切换到JExcel,DateUtils将为您解决问题。 - duffymo
那个链接已经失效了,但仍然可以通过WayBack访问。即便如此,我也没有看到任何关于DateUtils的提及。 - beldaz
我想,DateUtil 应该是指 HSSFDateUtil。 - Evgeny Semionov

0

试试这段代码。

XSSFWorkbook workbook = new XSSFWorkbook(new File(result));
    XSSFSheet sheet = workbook.getSheetAt(0);

    // Iterate through each rows one by one
    Iterator<Row> rowIterator = sheet.iterator();
    while (rowIterator.hasNext()) {
        Row row = rowIterator.next();
        // For each row, iterate through all the columns
        Iterator<Cell> cellIterator = row.cellIterator();

        while (cellIterator.hasNext()) {
            Cell cell = cellIterator.next();
            switch (cell.getCellType()) {
            case Cell.CELL_TYPE_NUMERIC:
                if (cell.getNumericCellValue() != 0) {
                    //Get date
                    Date date = row.getCell(0).getDateCellValue();



                    //Get datetime
                    cell.getDateCellValue()


                    System.out.println(date.getTime());
                }
                break;
            }
        }
    }

希望能够帮到你。


0
如果您知道单元格编号,我建议使用getDateCellValue()方法。以下是一个对我有效的示例 - java.util.Date date = row.getCell().getDateCellValue(); System.out.println(date);

0
您可以使用CellDateFormatter来获取与Excel单元格中相同格式的日期。请参考以下代码:
CellValue cv = formulaEv.evaluate(cell);
double dv = cv.getNumberValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
    Date date = HSSFDateUtil.getJavaDate(dv);

    String df = cell.getCellStyle().getDataFormatString();

    strValue = new CellDateFormatter(df).format(date); 
}

0
 public void readExcel() {
        try {
            String path = String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
            File file = new File(path + "/myexcelsheet.xlsx");
            FileInputStream fileInputStream = new FileInputStream(file);
            XSSFWorkbook wb = new XSSFWorkbook(fileInputStream);
            XSSFSheet sheet = wb.getSheetAt(0);

            Iterator<Row> rowIter = sheet.iterator();
            int rowno = 1;
            if (rowno !=0){
                while (rowIter.hasNext()) {
                    Row row = rowIter.next();
                    Iterator<Cell> cellIterator = row.cellIterator();
                    textView4.append("\n");
                    for (int i = 0; i < row.getRowNum(); i++) {
                        while (cellIterator.hasNext()) {
                            Cell cell = cellIterator.next();
                            switch (cell.getCellType()) {
                                case Cell.CELL_TYPE_STRING:    //field that represents string cell type
                                    textView4.append(cell.getStringCellValue() + "" + "\t\t" + "");

                                break;
                                case Cell.CELL_TYPE_NUMERIC:    //field that represents number cell type
                                    if (DateUtil.isCellDateFormatted(cell)){
                                        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
                                        Date date = cell.getDateCellValue();
                                        textView4.append(dateFormat.format(date) + "" + "\t\t" + "");
                                    }else{
                                        textView4.append(cell.getNumericCellValue() + "" + "\t\t" + "");
                                    }
                                break;
                            }
                            textView4.append("");
                        }
                        i++;
                    }
                }
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

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