Bagaimana saya bisa membaca string numerik dalam sel Excel sebagai string (bukan angka)?

146
  1. Saya punya file excel dengan konten seperti ini:

    • A1: SomeString

    • A2: 2

    Semua bidang diatur ke format String.

  2. Ketika saya membaca file dalam java menggunakan POI, ia memberi tahu bahwa A2 dalam format sel numerik.

  3. Masalahnya adalah bahwa nilai dalam A2 bisa 2 atau 2.0 (dan saya ingin bisa membedakannya) jadi saya tidak bisa begitu saja menggunakan .toString().

Apa yang bisa saya lakukan untuk membaca nilai sebagai string?

pengumpul sukacita
sumber

Jawaban:

319

Saya memiliki masalah yang sama. Saya lakukan cell.setCellType(Cell.CELL_TYPE_STRING);sebelum membaca nilai string, yang memecahkan masalah terlepas dari bagaimana pengguna memformat sel.

wil
sumber
Saya menggunakan poi-3.8-beta4, dan ini berfungsi seperti yang diharapkan! Mengapa TS tidak menerima ini sebagai jawabannya?
swdev
Perlu diketahui bahwa POI numerik ke String konversi tidak mempertimbangkan sistem lokal, selalu menggunakan titik sebagai pemisah desimal. Misalnya, jika sistem Anda menggunakan ",", dan dalam angka Excel terlihat seperti "1,9", POI akan mengembalikan "1,9".
Alexey Berezkin
53
Perhatikan bahwa javadocs Apache POI secara eksplisit mengatakan tidak melakukan ini! Saat mereka menjelaskan, Anda harus menggunakan DataFormatter sebagai gantinya
Gagravarr
6
Peringatan Gagravarr untuk tidak melakukan ini benar! Dari dokumen: "Jika yang ingin Anda lakukan adalah mendapatkan nilai String untuk sel numerik Anda, hentikan !. Ini bukan cara untuk melakukannya. Sebaliknya, untuk mengambil nilai string sel numerik atau boolean atau tanggal, gunakan DataFormatter sebagai gantinya. " poi.apache.org/apidocs/org/apache/poi/ss/usermodel/... Saya menggunakan teknik ini sendiri sampai saya secara tidak sengaja mengubah data yang tidak ingin saya ubah. (Setel tipe ke String, baca nilai, setel kembali ke numerik, baca lagi dan dapatkan nilai numerik yang berbeda!)
Chris Finley
6
Gunakan DataFormatter. Javadoc memperingatkan kita untuk tidak menggunakan metode di atas.
Balu SKT
96

Saya tidak berpikir kita memiliki kelas ini kembali ketika Anda mengajukan pertanyaan, tetapi hari ini ada jawaban yang mudah.

Apa yang ingin Anda lakukan adalah menggunakan kelas DataFormatter . Anda melewatkan sel ini, dan ia melakukan yang terbaik untuk mengembalikan Anda sebuah string yang berisi apa yang akan ditunjukkan Excel kepada Anda untuk sel itu. Jika Anda memberikannya sel string, Anda akan mendapatkan string kembali. Jika Anda memberikannya sel numerik dengan aturan pemformatan yang diterapkan, itu akan memformat angka berdasarkan pada mereka dan memberikan Anda string kembali.

Untuk kasus Anda, saya berasumsi bahwa sel numerik memiliki aturan pemformatan bilangan bulat yang diterapkan padanya. Jika Anda meminta DataFormatter untuk memformat sel-sel itu, itu akan memberi Anda kembali string dengan string integer di dalamnya.

Juga, perhatikan bahwa banyak orang menyarankan melakukan cell.setCellType(Cell.CELL_TYPE_STRING), tetapi Apache POI JavaDocs cukup jelas menyatakan bahwa Anda tidak boleh melakukan ini ! Melakukan setCellTypepanggilan akan kehilangan pemformatan, karena javadocs menjelaskan satu-satunya cara untuk mengkonversi ke String dengan pemformatan yang tersisa adalah dengan menggunakan kelas DataFormatter .

Gagravarr
sumber
Terima kasih @Gravagarr hanya jawaban Anda yang berfungsi untuk saya, <code> cell.setCellType (Cell.CELL_TYPE_STRING); <code> dalam mengkonversi nilai 2.2 sebagai 2.2000000000000002, tetapi saya ingin 2.2. mengembalikan apa pun dalam format string, terima kasih
ankush yadav
dataformatter tampaknya tidak berfungsi untuk sel Formula, ia mengembalikan representasi string dari rumus alih-alih nilainya
gaurav5430
1
Hanya satu catatan kecil: Harap berikan cuplikan kode pendek untuk jawaban seperti itu, juga jika itu dinyatakan dalam tautan yang disediakan
BAERUS
@ gaurav5430 Ya, itu tidak cocok dengan formula ... Menurut doc,When passed a null or blank cell, this method will return an empty String (""). Formulas in formula type cells will not be evaluated.
SaratBhaswanth
53

Kode di bawah ini berfungsi untuk saya untuk semua jenis sel.

InputStream inp =getClass().getResourceAsStream("filename.xls"));
Workbook wb = WorkbookFactory.create(inp);
DataFormatter objDefaultFormat = new DataFormatter();
FormulaEvaluator objFormulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) wb);

Sheet sheet= wb.getSheetAt(0);
Iterator<Row> objIterator = sheet.rowIterator();

while(objIterator.hasNext()){

    Row row = objIterator.next();
    Cell cellValue = row.getCell(0);
    objFormulaEvaluator.evaluate(cellValue); // This will evaluate the cell, And any type of cell will return string value
    String cellValueStr = objDefaultFormat.formatCellValue(cellValue,objFormulaEvaluator);

}
Vinayak Dornala
sumber
4
Bekerja dengan baik! Saran saya adalah mengubah cara FormulaEvaluator diambil. Kelas Workbook menyediakan evaluator rumus melalui getCreationHelper().createFormulaEvaluator()metode ini. Dengan cara ini kode Anda tidak akan digabungkan dengan kelas HSSFFormulaEvaluator.
Vitor Santos
Ini harus menjadi jawaban yang diterima. Terima kasih @Vinayak
Phas1c
Bisakah FormulaEvaluatordihapus dari solusi ini? Apakah itu melayani tujuan?
P.Brian.Mackey
1
panggilan ke objFormulaEvaluator.evaluate tidak perlu. Nilai pengembalian yang tidak digunakan di sini.
Radu Simionescu
32

Saya akan merekomendasikan pendekatan berikut ketika memodifikasi tipe sel tidak diinginkan:

if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
    String str = NumberToTextConverter.toText(cell.getNumericCellValue())
}

NumberToTextConverter dapat dengan benar mengkonversi nilai ganda ke teks menggunakan aturan Excel tanpa kehilangan presisi.

Stanislav Mamontov
sumber
Saran yang sangat menarik! Terima kasih! Hal ini memungkinkan mendapatkan nilai yang tidak dikonversi berbeda dengan pengaturan cellType ke String.
Gleb Egunov
Saya mendapatkan 44.007 sebagai output untuk nilai sel 25/06/2020. Apa yang saya lakukan salah?
Vinay
10

Ya, ini bekerja dengan sempurna

direkomendasikan:

        DataFormatter dataFormatter = new DataFormatter();
        String value = dataFormatter.formatCellValue(cell);

tua:

cell.setCellType(Cell.CELL_TYPE_STRING);

bahkan jika Anda memiliki masalah dengan mengambil nilai dari cellmemiliki rumus, tetap ini berfungsi.

Rajesh Mbm
sumber
5
Tetapi Anda harus berhati-hati menggunakan ini untuk nilai ganda. Bagi saya itu mengubah nilai 7,9 menjadi 7,8999956589965 ...
Chris
2
The Apache POI javadocs sangat jelas bahwa Anda tidak harus melakukan seperti itu : Jika apa yang Anda ingin lakukan adalah mendapatkan nilai String untuk sel numerik Anda, berhenti !. Ini bukan cara untuk melakukannya. Sebagai gantinya, untuk mengambil nilai string sel numerik atau boolean atau tanggal, gunakan DataFormatter sebagai gantinya.
Gagravarr
4

Mencoba:

new java.text.DecimalFormat("0").format( cell.getNumericCellValue() )

Haruskah memformat nomor dengan benar.

saya ambil
sumber
Seperti yang saya pahami, si penanya ingin bisa membedakan antara 2dan 2.0. Solusi Anda tidak akan melakukan ini. (Tapi tetap saja, selamat datang di Stack Overflow!)
Paŭlo Ebermann
1

Selama sel dalam format teks sebelum pengguna mengetikkan angka, POI akan memungkinkan Anda untuk mendapatkan nilai sebagai string. Salah satu kuncinya adalah bahwa jika ada segitiga hijau kecil di sudut kiri atas sel yang diformat sebagai Teks, Anda akan dapat mengambil nilainya sebagai string (segitiga hijau muncul setiap kali sesuatu yang tampaknya berupa angka dipaksa ke dalam format teks). Jika Anda memiliki sel yang diformat Teks yang berisi angka, tetapi POI tidak akan membiarkan Anda mengambil nilai-nilai itu sebagai string, ada beberapa hal yang bisa Anda lakukan untuk data Spreadsheet agar memungkinkan:

  • Klik dua kali pada sel sehingga kursor pengeditan hadir di dalam sel, lalu klik Enter (yang dapat dilakukan hanya satu sel pada satu waktu).
  • Gunakan fungsi konversi teks Excel 2007 (yang dapat dilakukan pada banyak sel sekaligus).
  • Potong nilai yang menyinggung ke lokasi lain, format ulang sel spreadsheet sebagai teks, lalu tempel ulang nilai yang sebelumnya dipotong sebagai Nilai Tidak Terformat kembali ke area yang tepat.

Satu hal terakhir yang bisa Anda lakukan adalah jika Anda menggunakan POI untuk mendapatkan data dari spreadsheet Excel 2007, Anda bisa menggunakan metode kelas 'getRawValue ()'. Ini tidak peduli apa formatnya. Ini hanya akan mengembalikan string dengan data mentah.

Mark Farnsworth
sumber
0

Ketika kita membaca nilai sel numerik MS Excel menggunakan perpustakaan Apache POI, itu membacanya sebagai angka. Tetapi kadang-kadang kita ingin itu dibaca sebagai string (mis. Nomor telepon, dll.). Beginilah cara saya melakukannya:

  1. Masukkan kolom baru dengan sel pertama = CONCATENATE ("!", D2). Saya menganggap D2 adalah id sel dari kolom nomor telepon Anda. Seret sel baru ke ujung.

  2. Sekarang jika Anda membaca sel menggunakan POI, itu akan membaca rumus, bukan nilai yang dihitung. Sekarang lakukan yang berikut:

  3. Tambahkan kolom lain

  4. Pilih kolom lengkap yang dibuat pada langkah 1. dan pilih Edit-> COPY

  5. Pergi ke sel atas kolom yang dibuat pada langkah 3. dan Pilih Edit-> Tempel Spesial

  6. Di jendela yang terbuka, Pilih tombol radio "Nilai"

  7. Pilih "OK"

  8. Sekarang baca menggunakan POI API ... setelah membaca di Jawa ... hapus saja karakter pertama yaitu "!"

Asif Shahzad
sumber
Solusi Anda tampaknya tidak dapat digunakan jika seseorang tidak menghasilkan file excel sendiri, bukan? (Juga, dapatkah Anda memberikan ekstrak ke jawaban Anda? Tidak terlalu lama.)
Paŭlo Ebermann
Ya, itu tidak dapat digunakan ketika seseorang tidak menghasilkan file excel sendiri.
Asif Shahzad
0

Saya juga memiliki masalah serupa pada kumpulan data ribuan angka dan saya pikir saya telah menemukan cara sederhana untuk menyelesaikannya. Saya perlu memasukkan tanda kutip sebelum angka sehingga impor DB terpisah selalu melihat angka sebagai teks. Sebelum ini angka 8 akan diimpor sebagai 8.0.

Larutan:

  • Simpan semua pemformatan sebagai Umum.
  • Di sini saya mengasumsikan angka disimpan dalam Kolom A mulai dari Baris 1.
  • Masukkan 'di Kolom B dan salin baris sebanyak yang diperlukan. Tidak ada yang muncul di lembar kerja tetapi mengklik sel Anda dapat melihat apostophe di bilah Formula.
  • Di Kolom C: = B1 & A1.
  • Pilih semua Sel di Kolom C dan lakukan Tempel Spesial ke dalam Kolom D menggunakan opsi Nilai.

Hai Presto semua angka tetapi disimpan sebagai Teks.

Mark Holmes
sumber
0

getStringCellValue mengembalikan NumberFormatException jika jenis selnya numerik. Jika Anda tidak ingin mengubah jenis sel menjadi string, Anda bisa melakukan ini.

String rsdata = "";
try {
    rsdata = cell.getStringValue();
} catch (NumberFormatException ex) {
    rsdata = cell.getNumericValue() + "";
}
zawhtut
sumber
0

Banyak dari jawaban ini merujuk pada dokumentasi dan kelas POI lama. Dalam POI 3.16 terbaru, Cell dengan tipe int telah ditinggalkan

Cell.CELL_TYPE_STRING

masukkan deskripsi gambar di sini

Sebaliknya enum CellType dapat digunakan.

CellType.STRING 

Pastikan untuk memperbarui pom Anda dengan dependensi poi serta ketergantungan poi-ooxml ke versi 3.16 yang baru jika tidak Anda akan terus mendapatkan pengecualian. Satu keuntungan dengan versi ini adalah Anda dapat menentukan jenis sel pada saat sel dibuat menghilangkan semua langkah ekstra yang dijelaskan dalam jawaban sebelumnya:

titleRowCell = currentReportRow.createCell(currentReportColumnIndex, CellType.STRING);
Nelda.techspiress
sumber
0

Saya lebih suka pergi ke rute jawaban wil atau Vinayak Dornala, sayangnya mereka mempengaruhi kinerja saya jauh ke banyak. Saya mencari solusi HACKY dari casting implisit:

for (Row row : sheet){
String strValue = (row.getCell(numericColumn)+""); // hack
...

Saya tidak menyarankan Anda melakukan ini, karena situasi saya berhasil karena sifat dari bagaimana sistem bekerja dan saya memiliki sumber file yang dapat diandalkan.

Footnote: numericColumn Adalah int yang dihasilkan dari membaca header file yang diproses.

KeaganFouche
sumber
0
public class Excellib {
public String getExceldata(String sheetname,int rownum,int cellnum, boolean isString) {
    String retVal=null;
    try {
        FileInputStream fis=new FileInputStream("E:\\Sample-Automation-Workspace\\SampleTestDataDriven\\Registration.xlsx");
        Workbook wb=WorkbookFactory.create(fis);
        Sheet s=wb.getSheet(sheetname);
        Row r=s.getRow(rownum);
        Cell c=r.getCell(cellnum);
        if(c.getCellType() == Cell.CELL_TYPE_STRING)
        retVal=c.getStringCellValue();
        else {
            retVal = String.valueOf(c.getNumericCellValue());
        }

Saya Mencoba Ini dan Ini Berhasil untuk Saya

Prasanna
sumber
-1

Apakah Anda tetap mengendalikan lembar kerja excel? Apakah ada template yang dimiliki pengguna untuk memberi Anda input? Jika demikian, Anda dapat meminta kode memformat sel input untuk Anda.

datatoo
sumber
-1

Ini bekerja sempurna untuk saya.

Double legacyRow = row.getCell(col).getNumericCellValue();
String legacyRowStr = legacyRow.toString();
if(legacyRowStr.contains(".0")){
    legacyRowStr = legacyRowStr.substring(0, legacyRowStr.length()-2);
}
Rama Krishna
sumber
-2

Kami memiliki masalah yang sama dan memaksa pengguna kami untuk memformat sel sebagai 'teks' sebelum memasukkan nilainya. Dengan cara itu Excel dengan benar menyimpan angka genap sebagai teks. Jika format diubah setelahnya, Excel hanya mengubah cara nilai ditampilkan tetapi tidak mengubah cara nilai disimpan kecuali nilainya dimasukkan lagi (misalnya dengan menekan kembali ketika di dalam sel).

Baik atau tidaknya Excel menyimpan nilai sebagai teks ditunjukkan oleh segitiga hijau kecil yang ditampilkan Excel di sudut kiri atas sel jika dianggap sel berisi angka tetapi diformat sebagai teks.

Turismo
sumber
-3

dilemparkan ke int lalu lakukan a .toString(). Itu jelek tapi berhasil.

WolfmanDragon
sumber
Masalahnya adalah bahwa jika ada 2.0 dalam A2 saya harus mendapatkan string "2.0", dan jika 2 maka string "2".
joycollector