ฉันจะอ่านสตริงตัวเลขในเซลล์ 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.