ฉันจะอ่านสตริงตัวเลขในเซลล์ Excel เป็นสตริงได้อย่างไร (ไม่ใช่ตัวเลข)


146
  1. ฉันมีไฟล์ excel พร้อมเนื้อหาดังกล่าว:

    • A1: SomeString

    • A2: 2

    ฟิลด์ทั้งหมดถูกตั้งค่าเป็นรูปแบบสตริง

  2. เมื่อฉันอ่านไฟล์ใน java โดยใช้ POI มันจะบอกว่า A2 อยู่ในรูปแบบเซลล์ตัวเลข

  3. ปัญหาคือค่าใน A2 สามารถเป็น 2 หรือ 2.0 (และฉันต้องการแยกแยะได้) ดังนั้นฉันจึงไม่สามารถใช้งาน.toString()ได้

ฉันจะทำอย่างไรเพื่ออ่านค่าเป็นสตริง

คำตอบ:


319

ฉันมีปัญหาเดียวกัน ฉันทำcell.setCellType(Cell.CELL_TYPE_STRING);ก่อนอ่านค่าสตริงซึ่งแก้ปัญหาโดยไม่คำนึงว่าผู้ใช้จัดรูปแบบเซลล์อย่างไร


ฉันใช้ poi-3.8-beta4 และทำงานตามที่คาดไว้! ทำไม TS ไม่ยอมรับคำตอบนี้เป็นคำตอบ?
— swdev

โปรดทราบว่าการแปลงตัวเลข POI เป็น String ไม่ได้คำนึงถึงสถานที่ของระบบ แต่จะใช้จุดเป็นตัวคั่นทศนิยมเสมอ ตัวอย่างเช่นหากระบบของคุณใช้ "," และในตัวเลข Excel ดูเหมือนว่า "1,9", POI จะส่งคืน "1.9" แทน
— Alexey Berezkin

53
โปรดทราบว่าApache POI javadocs พูดอย่างชัดเจนว่าอย่าทำเช่นนี้! ในฐานะที่พวกเขาอธิบายว่าคุณควรใช้ DataFormatter แทน
— Gagravarr

6
คำเตือนของ Gagravarr ต่อการทำเช่นนี้ถูกต้อง! จากเอกสาร: "ถ้าสิ่งที่คุณต้องการทำคือรับค่าสตริงสำหรับเซลล์ตัวเลขของคุณให้หยุด! นี่ไม่ใช่วิธีที่จะทำแทนการดึงค่าสตริงของเซลล์ตัวเลขหรือบูลีนหรือเซลล์วันที่แทนให้ใช้ DataFormatter แทน " poi.apache.org/apidocs/org/apache/poi/ss/usermodel/ ...... ฉันใช้เทคนิคนี้ด้วยตัวเองจนกระทั่งฉันได้รับข้อมูลที่เปลี่ยนแปลงโดยไม่ตั้งใจฉันไม่ได้ตั้งใจจะเปลี่ยนแปลง (ตั้งค่าชนิดเป็นสตริงอ่านค่าตั้งค่าประเภทกลับเป็นตัวเลขอ่านอีกครั้งและรับค่าตัวเลขที่แตกต่างกัน!)
— Chris Finley

6
ใช้ DataFormatter Javadoc เตือนเราจากการใช้วิธีการด้านบน
— Balu SKT

96

ฉันไม่คิดว่าเราจะได้ชั้นเรียนนี้คืนเมื่อคุณถามคำถาม แต่วันนี้มีคำตอบง่าย ๆ

สิ่งที่คุณต้องการจะทำคือใช้ระดับ DataFormatter คุณส่งผ่านเซลล์นี้และมันเป็นการดีที่สุดที่จะคืนสตริงให้คุณซึ่งมีสิ่งที่ Excel จะแสดงให้คุณเห็นสำหรับเซลล์นั้น หากคุณผ่านเซลล์สตริงคุณจะได้รับสตริงกลับ หากคุณผ่านเซลล์ตัวเลขโดยใช้กฎการจัดรูปแบบเซลล์จะจัดรูปแบบตัวเลขตามเซลล์นั้นและให้สตริงกลับมาให้คุณ

สำหรับกรณีของคุณฉันจะสมมติว่าเซลล์ที่เป็นตัวเลขมีกฎการจัดรูปแบบจำนวนเต็มที่ใช้กับพวกเขา ถ้าคุณขอให้ DataFormatter จัดรูปแบบเซลล์เหล่านั้นมันจะให้สตริงกลับมาพร้อมสตริงจำนวนเต็ม

นอกจากนี้โปรดทราบว่าผู้คนจำนวนมากแนะนำให้ทำcell.setCellType(Cell.CELL_TYPE_STRING)แต่Apache POI JavaDocs ค่อนข้างชัดเจนว่าคุณไม่ควรทำเช่นนี้ ! ทำsetCellTypeโทรจะหลวมการจัดรูปแบบเป็นjavadocs อธิบายวิธีเดียวที่จะแปลงเป็นสตริงที่มีการจัดรูปแบบที่เหลือคือการใช้ระดับ DataFormatter


ขอบคุณ @Gagravarr คำตอบของคุณใช้ได้ผลกับฉัน <code> cell.setCellType (Cell.CELL_TYPE_STRING); <code> ในการแปลงค่า 2.2 เป็น 2.2000000000000002 แต่ฉันต้องการ 2.2 มันจะคืนค่าทุกอย่างในรูปแบบสตริงขอบคุณ
— ankush yadav

Dataformatter ดูเหมือนจะไม่ทำงานกับเซลล์ Formula แต่จะส่งคืนการแทนสตริงของสูตรแทนค่า
— gaurav5430

1
เพียงบันทึกย่อหนึ่งฉบับ: โปรดให้ข้อมูลโค้ดสั้น ๆ สำหรับคำตอบดังกล่าวและหากมีการระบุไว้ในลิงก์ที่ให้ไว้
— BAERUS

@ gaurav5430 ใช่มันไม่เหมาะกับสูตร ... ตาม 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

รหัสด้านล่างทำงานสำหรับฉันสำหรับเซลล์ประเภทใดก็ได้

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);

}

4
ทำงานได้ดี! ข้อเสนอแนะของฉันจะเปลี่ยนวิธีดึง FormulaEvaluator คลาสเวิร์กบุ๊กจัดเตรียมสูตรการประเมินgetCreationHelper().createFormulaEvaluator()วิธี วิธีนี้โค้ดของคุณจะไม่ถูกผนวกเข้ากับคลาส HSSFFormulaEvaluator
— Vitor Santos

นี่ควรเป็นคำตอบที่ยอมรับได้ ขอบคุณ @Vinayak
— Phas1c

สามารถFormulaEvaluatorลบออกจากโซลูชันนี้ได้หรือไม่ มันมีจุดประสงค์หรือไม่?
— P.Brian.Mackey

1
ไม่จำเป็นต้องเรียกใช้ objFormulaEvaluator.evaluate ค่าส่งคืนของที่ไม่ได้ใช้ที่นี่
— Radu Simionescu

32

ฉันอยากจะแนะนำวิธีการต่อไปนี้เมื่อปรับเปลี่ยนประเภทของเซลล์ไม่พึงประสงค์:

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

NumberToTextConverter สามารถแปลงค่าคู่ให้เป็นข้อความได้อย่างถูกต้องโดยใช้กฎของ Excel โดยไม่สูญเสียความแม่นยำ


คำแนะนำที่น่าตื่นเต้นจริงๆ! ขอบคุณ! อนุญาตให้รับค่าที่ไม่กลับในทางตรงกันข้ามกับการตั้งค่า cellType เป็น String
— Gleb Egunov

ฉันได้รับ 44007 เป็นผลลัพธ์สำหรับค่าเซลล์ของ 25/06/2020 ผมทำอะไรผิดหรือเปล่า?
— Vinay

17

ตามที่ได้กล่าวถึงแล้วใน JavaDocs ของ Poi ( https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType%28int%29 ) อย่าใช้:

cell.setCellType(Cell.CELL_TYPE_STRING);

แต่ใช้:

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

ตัวอย่างเพิ่มเติมเกี่ยวกับhttp://massapi.com/class/da/DataFormatter.html


10

ใช่มันทำงานได้อย่างสมบูรณ์

แนะนำ:

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

อายุ:

cell.setCellType(Cell.CELL_TYPE_STRING);

แม้ว่าคุณจะมีปัญหาในการเรียกคืนค่าจากcellการมีสูตร แต่ก็ยังใช้งานได้


5
แต่คุณต้องระวังการใช้สิ่งนี้เพื่อค่าสองเท่า สำหรับฉันแล้วมันเปลี่ยนค่า 7.9 เป็น 7.8999956589965 ...
— Chris

2
javadocs Apache POI มีความชัดเจนมากที่คุณไม่ควรทำมันเหมือนว่า : หากสิ่งที่คุณต้องการจะทำคือการได้รับค่าสายอักขระสำหรับเซลล์ตัวเลขของคุณหยุด !. นี่ไม่ใช่วิธีที่จะทำ แต่สำหรับการดึงค่าสตริงของเซลล์ตัวเลขหรือบูลีนหรือวันที่ให้ใช้ DataFormatter แทน
— Gagravarr

4

ลอง:

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

ควรจัดรูปแบบตัวเลขให้ถูกต้อง


ที่ผมเข้าใจผู้ถามต้องการเพื่อให้สามารถแยกแยะความแตกต่างระหว่างและ2 2.0ทางออกของคุณจะไม่ทำเช่นนี้ (แต่ยังยินดีต้อนรับสู่ Stack Overflow!)
— Paŭlo Ebermann

1

ตราบใดที่เซลล์อยู่ในรูปแบบข้อความก่อนที่ผู้ใช้จะพิมพ์ตัวเลข POI จะอนุญาตให้คุณรับค่าเป็นสตริง กุญแจสำคัญคือถ้ามีสามเหลี่ยมสีเขียวขนาดเล็กที่มุมซ้ายบนของเซลล์ที่จัดรูปแบบเป็นข้อความคุณจะสามารถเรียกคืนค่าเป็นสตริงได้ (สามเหลี่ยมสีเขียวปรากฏขึ้นเมื่อใดก็ตามที่ปรากฏเป็นตัวเลข ถูกบังคับในรูปแบบข้อความ) หากคุณมีเซลล์ที่จัดรูปแบบข้อความที่มีตัวเลข แต่จุดที่น่าสนใจจะไม่อนุญาตให้คุณดึงค่าเหล่านั้นเป็นสตริงมีบางสิ่งที่คุณสามารถทำได้กับข้อมูลสเปรดชีตเพื่อให้:

  • ดับเบิลคลิกที่เซลล์เพื่อให้มีเคอร์เซอร์แก้ไขอยู่ในเซลล์จากนั้นคลิกที่ Enter (ซึ่งสามารถทำได้ครั้งละหนึ่งเซลล์เท่านั้น)
  • ใช้ฟังก์ชันแปลงข้อความ Excel 2007 (ซึ่งสามารถทำได้ในหลายเซลล์พร้อมกัน)
  • ตัดออกจากค่าการกระทำผิดกฎหมายไปยังตำแหน่งอื่นฟอร์แมตเซลล์สเปรดชีตเป็นข้อความแล้ว repaste ก่อนหน้านี้ตัดออกเป็นค่ายังไม่ฟอร์แมตค่ากลับเข้ามาในพื้นที่ที่เหมาะสม

สิ่งสุดท้ายที่คุณสามารถทำได้คือถ้าคุณใช้ POI เพื่อรับข้อมูลจากสเปรดชีต Excel 2007 คุณสามารถใช้เมธอด 'getRawValue ()' คลาสเซลล์ได้ นี่ไม่สนใจว่ารูปแบบคืออะไร มันก็จะส่งกลับสตริงที่มีข้อมูลดิบ


0

เมื่อเราอ่านค่าตัวเลขเซลล์ของ MS Excel โดยใช้ไลบรารี Apache POI มันจะอ่านค่าเป็นตัวเลข แต่บางครั้งเราต้องการให้อ่านเป็นสตริง (เช่นหมายเลขโทรศัพท์ ฯลฯ ) นี่คือวิธีที่ฉันทำ:

  1. แทรกคอลัมน์ใหม่ด้วยเซลล์แรก = CONCATENATE ("!", D2) ฉันถือว่า D2 เป็นรหัสเซลล์ของคอลัมน์หมายเลขโทรศัพท์ของคุณ ลากเซลล์ใหม่ขึ้นจนจบ

  2. ตอนนี้ถ้าคุณอ่านเซลล์โดยใช้จุดที่น่าสนใจมันจะอ่านสูตรแทนค่าที่คำนวณได้ ตอนนี้ทำดังนี้:

  3. เพิ่มคอลัมน์อื่น

  4. เลือกคอลัมน์สมบูรณ์ที่สร้างในขั้นตอนที่ 1 และเลือกแก้ไข -> คัดลอก

  5. ไปที่เซลล์ด้านบนของคอลัมน์ที่สร้างในขั้นตอนที่ 3 และเลือกแก้ไข -> วางแบบพิเศษ

  6. ในหน้าต่างที่เปิดขึ้นเลือกปุ่มตัวเลือก "ค่า"

  7. เลือก "ตกลง"

  8. ตอนนี้อ่านโดยใช้ POI API ... หลังจากอ่านใน Java ... เพียงลบตัวอักษรตัวแรกเช่น "!"


วิธีแก้ปัญหาของคุณดูเหมือนจะไม่สามารถใช้งานได้ถ้าไม่มีใครสร้างไฟล์ excel ด้วยตัวเองใช่ไหม? (นอกจากนี้คุณสามารถใส่สารสกัดลงในคำตอบของคุณได้หรือไม่ไม่นาน)
— Paŭlo Ebermann

ใช่มันไม่สามารถใช้งานได้เมื่อไม่มีคนสร้างไฟล์ excel ด้วยตัวเอง
— Asif Shahzad

0

ฉันยังมีปัญหาที่คล้ายกันในชุดข้อมูลของตัวเลขหลายพันและฉันคิดว่าฉันได้พบวิธีง่ายๆในการแก้ไข ฉันต้องการแทรกเครื่องหมายอัญประกาศเดี่ยวก่อนตัวเลขเพื่อให้การนำเข้าฐานข้อมูลแยกต่างหากเห็นตัวเลขเป็นข้อความเสมอ ก่อนหน้านี้หมายเลข 8 จะถูกนำเข้าเป็น 8.0

สารละลาย:

  • คงรูปแบบทั้งหมดเป็นทั่วไป
  • ที่นี่ฉันสมมติว่าตัวเลขถูกเก็บไว้ในคอลัมน์ A เริ่มต้นที่แถว 1
  • ใส่ใน 'ในคอลัมน์ B และคัดลอกแถวได้มากเท่าที่ต้องการ ไม่มีสิ่งใดปรากฏในแผ่นงาน แต่การคลิกที่เซลล์คุณสามารถเห็นเครื่องหมายอัญประกาศเดี่ยวในแถบสูตร
  • ในคอลัมน์ C: = B1 & A1
  • เลือกเซลล์ทั้งหมดในคอลัมน์ C และวางแบบพิเศษลงในคอลัมน์ D โดยใช้ตัวเลือกค่า

เฮ้ Presto ตัวเลขทั้งหมด แต่เก็บไว้เป็นข้อความ


0

getStringCellValue ส่งคืน NumberFormatException หากประเภทเซลล์เป็นตัวเลข หากคุณไม่ต้องการเปลี่ยนประเภทเซลล์เป็นสตริงคุณสามารถทำได้

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

0

หลายคำตอบเหล่านี้อ้างอิงเอกสารประกอบ POI และคลาสเก่า ใน POI 3.16 ใหม่ล่าสุดเซลล์ที่มีประเภท intนั้นเลิกใช้แล้ว

Cell.CELL_TYPE_STRING

ป้อนคำอธิบายรูปภาพที่นี่

สามารถใช้CellType enumแทนได้

CellType.STRING 

เพียงแค่ให้แน่ใจว่าได้อัพเดท pom ของคุณด้วยการพึ่งพา poi เช่นเดียวกับการพึ่งพา poi-ooxml เป็นเวอร์ชั่น 3.16 ใหม่มิฉะนั้นคุณจะได้รับการยกเว้นต่อไป ข้อดีอย่างหนึ่งของรุ่นนี้คือคุณสามารถระบุประเภทของเซลล์ได้ในเวลาที่สร้างเซลล์โดยกำจัดขั้นตอนพิเศษทั้งหมดที่อธิบายไว้ในคำตอบก่อนหน้า:

titleRowCell = currentReportRow.createCell(currentReportColumnIndex, CellType.STRING);

0

ฉันอยากจะไปตามเส้นทางของคำตอบของวิลหรือ Vinayak Dornala โชคไม่ดีที่พวกเขาส่งผลต่อการแสดงของฉันไปมาก ผมไปหาhackyวิธีการแก้ปัญหาของการหล่อโดยปริยาย:

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

ฉันไม่แนะนำให้คุณทำเช่นนี้เพราะสถานการณ์ของฉันทำงานได้เนื่องจากลักษณะของการทำงานของระบบและฉันมีแหล่งไฟล์ที่เชื่อถือได้

เชิงอรรถ: numericColumn เป็น int ซึ่งสร้างขึ้นจากการอ่านส่วนหัวของไฟล์ที่ประมวลผล


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());
        }

ฉันลองสิ่งนี้และมันก็ใช้ได้ผลสำหรับฉัน


-1

คุณสามารถควบคุมแผ่นงาน excel ได้หรือไม่ มีเทมเพลตที่ผู้ใช้มีให้อินพุตหรือไม่ ถ้าเป็นเช่นนั้นคุณสามารถมีรูปแบบรหัสเซลล์อินพุตให้คุณได้




-1

สิ่งนี้ทำงานได้สมบูรณ์แบบสำหรับฉัน

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

-2

เรามีปัญหาเดียวกันและบังคับให้ผู้ใช้จัดรูปแบบเซลล์เป็น 'ข้อความ' ก่อนป้อนค่า ด้วยวิธีนี้ Excel จัดเก็บตัวเลขให้เป็นข้อความได้อย่างถูกต้อง หากรูปแบบมีการเปลี่ยนแปลงหลังจากนั้น Excel จะเปลี่ยนวิธีการแสดงค่าเท่านั้น แต่จะไม่เปลี่ยนวิธีการจัดเก็บค่าเว้นแต่จะมีการป้อนค่าอีกครั้ง (เช่นโดยการกดย้อนกลับเมื่ออยู่ในเซลล์)

Excel เก็บค่าไว้อย่างถูกต้องหรือไม่ตามที่ข้อความจะถูกระบุโดยสามเหลี่ยมสีเขียวเล็ก ๆ ที่ Excel แสดงที่มุมซ้ายบนของเซลล์ถ้าคิดว่าเซลล์มีตัวเลข แต่ถูกจัดรูปแบบเป็นข้อความ


-3

หล่อเป็น int .toString()แล้วทำ มันน่าเกลียด แต่ก็ใช้งานได้


ปัญหาคือว่าถ้ามี 2.0 ใน A2 ฉันต้องได้รับสตริง "2.0" และถ้า 2 จากนั้นสตริง "2"
— joycollector
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.