2009-09-11 37 views
14

我正在使用HSSF-POI來讀取excel數據。問題是我有一個單元格中的值,看起來像一個數字,但確實是字符串。如果我在Excel中查看格式單元格,它說類型是「文本」。 HSSF Cell仍然認爲它是數字。我怎樣才能得到一個字符串的值?從HSSF中讀取Excel中的字符串值,但它是雙重的

如果我嘗試使用cell.getRichStringValue,我會得到異常;如果cell.toString,它與Excel工作表中的值不同。

編輯:直到得到解決,我將使用

new BigDecimal(cell.getNumericCellValue()).toString() 
+0

您是否可以從xls文件中去除任何不相關或私有的數據並將其用於測試? – 2009-09-15 20:34:49

回答

6

你的意思是HSSF-POI說

cell.getCellType() == Cell.CELL_TYPE_NUMERIC

Cell.CELL_TYPE_STRING,因爲它應該是什麼?

我認爲這是POI中的一個錯誤,但每個單元格都包含一個變體,並且變體有一個類型。在那裏犯一個bug很難,所以我認爲Excel使用一些額外的數據或啓發式來將該字段報告爲文本。通常的MS方式,唉。

P.S.你不能在包含數字的Variant上使用任何getString(),因爲Variant數據的二進制表示取決於它的類型,並且試圖從實際上是數字的字符中獲取字符串將導致垃圾 - 因此是例外。

+0

是的,POI說它是Cell.CELL_TYPE_NUMERIC。當我重新開始工作時,我必須進一步調查。我沒有意識到它可能只是一些啓發式的_Excel_。 (我只是快速瀏覽數據,我自己並沒有創建電子表格。)感謝您的評論。 – egaga 2009-09-14 19:32:13

+0

工作中的啓發式似乎是正確的。就在今天,我與excel進行了一次小小的鬥爭,讓它在「合適的」語言環境中愉快地停止將數據從數字更改爲日期。 – NomeN 2009-09-15 00:12:34

+0

謝謝。我現在使用返回新的BigDecimal(cell.getNumericCellValue())。toString()。 – egaga 2009-09-15 07:23:35

2

Excel將從字符串轉換任何看起來像數字或日期或時間的東西。見MS Knowledge base article,基本上建議輸入一個額外的字符,使其成爲一個字符串。

+0

+1,用於指出關於已經懷疑Excel的啓發式的官方確認/解釋。 – 2009-09-17 01:02:56

1

您可能正在處理Excel問題。當您創建電子表格時,默認的單元格類型是Generic。使用這種類型,Excel根據輸入猜測類型,並將此類型與每個單元一起保存。

當您稍後將單元格格式更改爲文本時,您只是更改默認值。 Excel不會自動更改每個單元格的類型。我還沒有找到自動執行此操作的方法。

要確認這一點,您可以轉到Excel並重新鍵入其中一個數字,看看它是否是HSSF中的文本。

你也可以看看真正的細胞類型使用此功能,

@Cell("type", A1) 

A1是數字的單元格。它顯示文字「l」,數字顯示「v」。

10

如果您正在解析的文檔始終處於特定佈局,您可以隨時將單元格類型更改爲「字符串」,然後檢索該值。例如,如果第2列應始終爲字符串數據,請將其單元格類型設置爲字符串,然後使用字符串類型的get方法讀取它。

cell.setCellType(Cell.CELL_TYPE_STRING); 

在我的測試中,改變細胞類型沒有修改單元格的內容,但並允許它與以下任一方式獲得:

cell.getStringCellValue(); 

cell.getRichStringCellValue().getString(); 

沒有的一個例子沒有正確轉換的值,很難知道它的行爲與描述中描述的cell.toString()方法有什麼不同。

+0

謝謝你,真的讓我的一天。 – Ron 2011-12-09 01:45:52

+0

@jt。 :謝謝,我有同樣的問題 – 2012-05-16 06:14:22

+0

謝謝,它解決了我的問題。 – grep 2015-05-13 15:58:19

1

Excel的問題在於默認格式是通用的。使用這種格式,Excel將單元格中輸入的數字存儲爲數字。您必須在輸入值之前將格式更改爲文字。更改格式後重新輸入數值也將起作用。
如果內容看起來像Excel的編號,那麼會導致單元左上角的綠色三角形很少。如果是這種情況,則該值實際上存儲爲文本。

使用新的BigDecimal(cell.getNumericCellValue())。toString(),您仍然會遇到很多問題。例如,如果您有識別號碼(例如零件號碼或分類號碼),則可能有前導零的情況,這會成爲getNumericCellValue()方法的問題。

我嘗試徹底地解釋如何正確地創建Excel到創建我必須用POI處理的文件的聚會。如果文件是由最終用戶上傳的,我甚至已經創建了一個驗證程序來檢查預期的單元格類型,如果我事先知道列的話。作爲副產品,您還可以檢查提供的文件的各種其他內容(例如提供的正確列或強制值)。

+0

這似乎解決了我的問題。謝謝。 – egaga 2009-09-29 10:08:46

0

「問題是我在單元格中的值看起來像一個數字」=>在Excel中查看時看起來像數字嗎?

「但真的是字符串」=>這是什麼意思?你怎麼知道他們真的是字符串?

「如果我看格式單元格」=>什麼是「格式單元格」?

'...在Excel中,它表示類型是「text」=>請解釋。

「仍然HSSF細胞認爲它是數字。」 =>你的意思是the_cell.getCellType()返回Cell.CELL_TYPE_NUMERIC?

「我怎樣才能得到一個字符串的價值?」 =>如果它是NUMERIC,請使用the_cell.getNumericCellValue()獲取數值,然後將其格式化爲任意字符串。

「如果我嘗試使用cell.getRichStringValue,我會得到異常;」 =>所以它不是一個字符串。

「if cell.toString,它與Excel工作表中的值不同。」 =>所以cell.toString()不會像Excel格式化它的格式。

無論啓發式Excel用什麼來確定類型與您無關。它是存儲在文件中並由getCellType()顯示的重要決定的結果。

+0

我的意思是它們在語義上是字符串;他們的表示很重要(01與1不同),不同於數字(01與1相同) 我的意思是「格式單元格」功能,當我右鍵單擊單元格時,選擇「文本」作爲類型。 – egaga 2009-09-29 09:57:05

4

這下面的代碼工作正常讀取任何單元格類型但單元格應包含數值

new BigDecimal(cell.getNumericCellValue())); 

例如

ase.setGss(new BigDecimal(hssfRow.getCell(3).getNumericCellValue())); 

其中變量gss是BigDecimal類型。

11

你在POI尋找類是DataFormatter

當Excel寫到文件中,部分細胞被存儲爲文本字符串,而另一些則存儲爲數字。對於後者,代表單元的浮點值被存儲在文件中,所以當你向POI詢問實際上具有的單元值時。

雖然有時候,特別是在進行文本提取(但並非總是)時,您希望使單元格的值看起來像在Excel中一樣。它並不總是可以在String中完全得到(例如,非全空間填充),但DataFormatter類將使您關閉。

如果你是小區的字符串後,遠遠望去,你必須尋找它在Excel中,只是做:

// Create a formatter, do this once 
DataFormatter formatter = new DataFormatter(Locale.US); 

..... 

for(Cell cell : row) { 
    CellReference ref = new CellReference(cell); 
    // eg "The value of B12 is 12.4%" 
    System.out.println("The value of " + ref.formatAsString() + " is " + formatter.formatCellValue(cell)); 
} 

格式化將返回字符串細胞原樣,併爲數字細胞將將樣式上的格式化規則應用於單元格的編號

+0

我想這是更好的,因爲「雙」不能準確地代表一些值。 – codeplay 2013-01-10 02:04:04