2011-06-28 15 views
21

Tôi nhận ra câu hỏi hơi khó hiểu một chút, nhưng tôi không biết làm cách nào khác để nói. Dù sao, đây là mã gốc:Khi nhận nội dung ô bằng Thư viện Apache-POI, tôi nhận được cả hai "Không thể nhận được giá trị số từ ô văn bản" và ngược lại. Làm thế nào để tôi sửa chữa nó?

private void readFile(String excelFileName) throws FileNotFoundException, IOException { 
    XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(excelFileName)); 
    if (workbook.getNumberOfSheets() > 1){ 
     System.out.println("Please make sure there is only one sheet in the excel workbook."); 
    } 
    XSSFSheet sheet = workbook.getSheetAt(0); 
    int numOfPhysRows = sheet.getPhysicalNumberOfRows(); 
    XSSFRow row; 
    XSSFCell num; 
    for(int y = 1;y < numOfPhysRows;y++){ //start at the 2nd row since 1st should be category names 
     row = sheet.getRow(y); 
     poNum = row.getCell(1); 
     item = new Item(Integer.parseInt(poNum.getStringCellValue()); 
     itemList.add(item); 
     y++; 
    } 
} 

private int poiConvertFromStringtoInt(XSSFCell cell){ 
    int x = Integer.parseInt(Double.toString(cell.getNumericCellValue())); 
    return x; 
} 

Tôi nhận được lỗi sau:

Exception in thread "main" java.lang.IllegalStateException: Cannot get a numeric value from a text cell 
    at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781) 
    at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199) 

Thậm chí nếu tôi thay đổi nó để có được hoặc là một chuỗi sử dụng XSSFCell.getStringCellValue() hoặc thậm chí XFFSCell.getRichTextValue, tôi nhận được sự đảo ngược của thông báo lỗi ở trên (và tôi đảm bảo cuối cùng sẽ biến nó thành int bằng cách sử dụng Integer.parseInt(XSSFCell.getStringCellValue()).

Các lỗi sau đó đọc:

Exception in thread "main" java.lang.IllegalStateException: Cannot get a text value from a numeric cell 
    at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781) 
    at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199) 

Tôi biết một thực tế rằng các bảng tính excel cột là trong thực tế một chuỗi. Tôi không thể thay đổi bảng excel vì nó được tải lên ở nơi khác luôn luôn sử dụng cùng một định dạng và định dạng mỗi cột đầu tiên sẽ mất nhiều thời gian xử lý.

Mọi đề xuất?

[Giải pháp] Đây là mã giải pháp tôi đã đưa ra từ @ giúp đỡ Wivani của:

private long poiGetCellValue(XSSFCell cell){ 
    long x; 
    if(cell.getCellType() == 0) 
     x = (long)cell.getNumericCellValue(); 
    else if(cell.getCellType() == 1) 
     x = Long.parseLong(cell.getStringCellValue()); 
    else 
     x = -1; 
    return x; 
} 
+0

kiểm tra API; có các phương pháp để truy vấn loại cột, vì vậy bạn có thể sử dụng để kiểm tra xem bạn có phải chuyển đổi hay không. PS Đoạn mã đó là không đủ để thực sự giúp bạn gỡ lỗi. – Wivani

+0

Để cho mọi người biết điều gì đã xảy ra, tôi phát hiện ra rằng 100 số đầu tiên có số 0 dẫn đầu. Điều này khiến cho excel tự động tạo chuỗi này. Vì vậy, tôi đã phải viết một phương pháp để kiểm tra loại đầu tiên và sau đó định dạng cho phù hợp. Cảm ơn bạn @Wivani – crstamps2

+0

Thú vị có lẽ để tham khảo trong tương lai để thêm 'mã giải pháp' của bạn? – Wivani

Trả lời

50
Use This as reference 

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; 
       default: 
        System.out.println(); 
      } 
+0

Cảm ơn nhưng các trường hợp phải là 'XSSFCell.CELL_TYPE _...' –

+0

@Mayank Thêm một diễn viên trên System.out.println (cell.getNumericCellValue()); để lấy giá trị số nguyên bởi vì câu lệnh avove trả về giá trị gấp đôi. Vì vậy, câu trả lời đúng cho giá trị interger là System.out.println ((int) cell.getNumericCellValue()); –

+0

@Mayank Chuyển đổi RichStringCellValue thành chuỗi bình thường bằng cách sử dụng toString() để lấy giá trị chuỗi có thể được lưu trữ bên trong biến chuỗi. Vì vậy, câu trả lời sẽ là System.out.println (cell.getRichStringCellValue(). GetString(). ToString()); –

21

Chỉ cần sử dụng cell.setCellType (1); trước khi đọc giá trị ô và nhận nó dưới dạng Chuỗi luôn, sau đó bạn có thể sử dụng nó theo định dạng của riêng bạn (loại).

Ravi

+1

Điều này không được khuyến khích vì nó sẽ mất tất cả thông tin định dạng ô – Gagravarr

+0

Tôi nghĩ rằng việc thực hiện điều này có thể khiến nó không trả lại các trường ngày theo cách bạn có thể muốn ... một vấn đề. – BVernon

0

giải pháp Ravi của hoạt động: Chỉ cần sử dụng cell.setCellType (1); trước khi đọc giá trị ô và nhận nó dưới dạng Chuỗi luôn, sau đó bạn có thể sử dụng nó theo định dạng của riêng bạn (loại).

21

Bạn có thể nhận được giá trị như String bằng cách sử dụng định dạng xác định cho các tế bào này:

final DataFormatter df = new DataFormatter(); 
final XSSFCell cell = row.getCell(cellIndex); 
String valueAsString = df.formatCellValue(cell); 

Nhờ this answer.

+0

cảm ơn, đã làm việc như một sự quyến rũ cho meee! –

3

Sử dụng mã bên dưới để đọc bất kỳ loại dữ liệu từ xcels sử dụng poi.

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.util.Iterator; 
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; 

/** 
* 
* @author nirmal 
*/ 
public class ReadWriteExcel { 

    public static void main(String ar[]) { 
     ReadWriteExcel rw = new ReadWriteExcel(); 
     rw.readDataFromExcel(); 

    } 
    Object[][] data = null; 

    public File getFile() throws FileNotFoundException { 
     File here = new File("test/com/javaant/ssg/tests/test/data.xlsx"); 
     return new File(here.getAbsolutePath()); 

    } 

    public Object[][] readDataFromExcel() { 
     final DataFormatter df = new DataFormatter(); 
     try { 

      FileInputStream file = new FileInputStream(getFile()); 
      //Create Workbook instance holding reference to .xlsx file 
      XSSFWorkbook workbook = new XSSFWorkbook(file); 

      //Get first/desired sheet from the workbook 
      XSSFSheet sheet = workbook.getSheetAt(0); 

      //Iterate through each rows one by one 
      Iterator<Row> rowIterator = sheet.iterator(); 

      int rownum = 0; 
      int colnum = 0; 
      Row r=rowIterator.next(); 

      int rowcount=sheet.getLastRowNum(); 
      int colcount=r.getPhysicalNumberOfCells(); 
      data = new Object[rowcount][colcount]; 
      while (rowIterator.hasNext()) { 
       Row row = rowIterator.next(); 

       //For each row, iterate through all the columns 
       Iterator<Cell> cellIterator = row.cellIterator(); 
       colnum = 0; 
       while (cellIterator.hasNext()) { 

        Cell cell = cellIterator.next(); 
        //Check the cell type and format accordingly 
        data[rownum][colnum] = df.formatCellValue(cell); 
        System.out.print(df.formatCellValue(cell)); 
        colnum++; 
        System.out.println("-"); 
       } 
       rownum++; 
       System.out.println(""); 
      } 
      file.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return data; 
    } 
} 
2

Tôi cũng gặp lỗi này với phiên bản POI 3.12final.
Tôi nghĩ rằng lỗi được đăng ký ở đó: https://bz.apache.org/bugzilla/show_bug.cgi?id=56702 và tôi đưa ra nhận xét ở đó với phân tích của tôi.

Đây là giải pháp thay thế mà tôi đã sử dụng: Ngoại lệ được tăng lên bởi HSSFCell.getNumericCellValue được gọi bởi DateUtil.isCellDateFormatted. DateUtil.isCellDateFormatted thực hiện 2 điều:
1) kiểm tra kiểu giá trị của ô bằng cách gọi HSSFCell.getNumericCellValue và sau đó DateUtil.isValidExcelDate(), gần như vô nghĩa ở đây tôi nghĩ.
2) kiểm tra xem định dạng của các tế bào là một định dạng ngày

tôi sao chép mã của chủ đề 2) ở trên trong một chức năng mới 'myIsADateFormat' và sử dụng nó thay vì DateUtil.isCellDateFormatted (có nghĩa là khá bẩn để sao chép mã thư viện, nhưng nó hoạt động ...):

private boolean myIsADateFormat(Cell cell){ 
    CellStyle style = cell.getCellStyle(); 
    if(style == null) return false; 
    int formatNo = style.getDataFormat(); 
    String formatString = style.getDataFormatString(); 
    boolean result = DateUtil.isADateFormat(formatNo, formatString); 
    return result; 
} 

Nếu bạn cần phải kiểm tra các loại giá trị đầu tiên, bạn có thể sử dụng này quá:

CellValue cellValue = evaluator.evaluate(cell); 
int cellValueType = cellValue.getCellType(); 
if(cellValueType == Cell.CELL_TYPE_NUMERIC){ 
    if(myIsADateFormat(cell){ 
     .... 
    } 
} 
Các vấn đề liên quan