Pytanie w sprawie excel, java, apache-poi – Jak mogę odczytać ciągi liczbowe w komórkach Excela jako łańcuch (nie liczby)?

130

Mam plik programu Excel z takimi treściami:

A1: SomeString

A2: 2

Wszystkie pola są ustawione na format String.

Kiedy czytam plik w java za pomocą POI, informuje on, że A2 jest w formacie numerycznym.

Problem polega na tym, że wartość w A2 może wynosić 2 lub 2.0 (i chcę móc je odróżnić), więc nie mogę po prostu użyć.toString().

Co mogę zrobić, aby odczytać wartość jako ciąg?

Twoja odpowiedź

19   odpowiedzi
1

zanim użytkownik wpisze liczbę, POI pozwoli uzyskać wartość jako ciąg. Jednym z nich jest to, że jeśli w lewym górnym rogu komórki jest sformowany mały zielony trójkąt, który jest sformatowany jako Tekst, będzie można pobrać jego wartość jako ciąg (zielony trójkąt pojawia się, gdy coś wydaje się być liczbą jest wymuszony w formacie tekstowym). Jeśli masz komórki sformatowane w formacie Tekst, które zawierają liczby, ale POI nie pozwolą ci pobrać tych wartości jako ciągów, istnieje kilka rzeczy, które możesz zrobić w danych Arkusza kalkulacyjnego, aby to umożliwić:

Kliknij dwukrotnie komórkę, aby kursor edycji znajdował się w komórce, a następnie kliknij Enter (można to zrobić tylko w jednej komórce na raz).Użyj funkcji konwersji tekstu Excel 2007 (która może być wykonana na wielu komórkach jednocześnie).Wytnij obraźliwe wartości do innej lokalizacji, przeformatuj komórki arkusza kalkulacyjnego jako tekst, a następnie ponownie wklej poprzednio wycięte wartości jakoNiesformatowane wartości z powrotem do właściwego obszaru.

Ostatnią rzeczą, którą możesz zrobić, jest to, że jeśli używasz POI do uzyskiwania danych z arkusza kalkulacyjnego Excel 2007, możesz użyć metody Cell klasy 'getRawValue ()'. To nie obchodzi, jaki jest format. Po prostu zwróci łańcuch z surowymi danymi.

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

0

W najnowszym punkcie POI 3.16Komórka z typami int został przestarzały

Cell.CELL_TYPE_STRING

Zamiast tegoWyliczenie CellType może być użyty.

CellType.STRING 

Po prostu zaktualizuj swój pom o zależność poi, a także zależność poi-ooxml od nowej wersji 3.16, w przeciwnym razie nadal będziesz otrzymywać wyjątki. Jedną z zalet tej wersji jest możliwość określenia typu komórki w momencie tworzenia komórki, eliminując wszystkie dodatkowe kroki opisane w poprzednich odpowiedziach:

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

pożądane:

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

NumberToTextConverter może poprawnie przekonwertować podwójną wartość na tekst przy użyciu reguł programu Excel bez precyzyjnej utraty.

-1

To działało dla mnie idealnie.

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

jeśli typ komórki jest numeryczny. Jeśli nie chcesz zmienić typu komórki na łańcuch, możesz to zrobić.

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

Jak już wspomniano w JavaDocs Poi (https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType%28int%29) nie używaj:

cell.setCellType(Cell.CELL_TYPE_STRING);

ale użyj:

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

Więcej przykładówhttp://massapi.com/class/da/DataFormatter.html

-1

że nie można tego zrobić w obecnej wersji POI, w oparciu o fakt, że ten błąd:

https://issues.apache.org/bugzilla/show_bug.cgi?id=46136

jest wciąż wybitny.

44

Poniższy kod działał dla mnie dla każdego typu komórki.

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

}
Pracował dobrze! Moją sugestią byłoby zmienić sposób pobierania FormulaEvaluator. Klasa skoroszytu dostarcza ewaluatora formuł przezgetCreationHelper().createFormulaEvaluator() metoda. W ten sposób twój kod nie zostanie połączony z klasą HSSFFormulaEvaluator. Vitor Santos
wywołanie objFormulaEvaluator.evaluate nie jest konieczne. Zwracana wartość tego nie jest tutaj używana. Radu Simionescu
MogąFormulaEvaluator po prostu usunąć z tego rozwiązania? Czy to służy celowi? P.Brian.Mackey
To powinna być zaakceptowana odpowiedź. Dzięki @Vinayak Phas1c
0

niestety znacznie wpłynęły na moje wyniki. Poszedłem naHACKY rozwiązanie niejawnego odlewania:

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

Nie sugeruję, abyś to robił, ponieważ w mojej sytuacji działał ze względu na naturę działania systemu i posiadałem niezawodne źródło plików.

Przypis: numericColumn Jest int, który jest generowany z odczytu nagłówka przetwarzanego pliku.

86

żebyśmy mieli tę klasę z powrotem, kiedy zadałeś to pytanie, ale dziś jest prosta odpowiedź.

Co chcesz zrobić, to użyćKlasa DataFormatter. Przekazujesz tę komórkę i robi wszystko, co w jej mocy, aby zwrócić ci ciąg zawierający to, co Excel pokaże ci dla tej komórki. Jeśli przekażesz mu komórkę ciągu, otrzymasz ciąg znaków. Jeśli przekażesz mu komórkę numeryczną z zastosowanymi regułami formatowania, sformatuje ona liczbę na ich podstawie i da ci łańcuch z powrotem.

W twoim przypadku zakładam, że komórki numeryczne mają zastosowaną do nich regułę formatowania liczb całkowitych. Jeśli poprosisz DataFormatter o sformatowanie tych komórek, otrzymasz z powrotem łańcuch z całkowitym łańcuchem znaków.

Zauważ też, że wiele osób sugeruje robienie tegocell.setCellType(Cell.CELL_TYPE_STRING), aleApache POI JavaDocs dość wyraźnie stwierdzają, że nie powinieneś tego robić! RobieniesetCellType wywołanie utraci formatowanie, jakojavadocs wyjaśnij jedynym sposobem konwersji na ciąg znaków z pozostałym formatowaniem jest użycieKlasa DataFormatter.

Tylko jedna drobna uwaga: proszę podać krótkie fragmenty kodu dla takich odpowiedzi, także jeśli są one podane w podanych linkach BAERUS
Dzięki @Gagravarr tylko twoja odpowiedź działa dla mnie, <code> cell.setCellType (Cell.CELL_TYPE_STRING); <code> w konwersji wartości 2.2 na 2.2000000000000002, ale chcę 2.2. zwraca wszystko w formacie string dzięki thank ankush yadav
@ gaurav5430 Tak, nie pasuje do formuł ... Według 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
dataformatter nie działa dla komórek Formula, zwraca ciąg znaków reprezentujący formułę zamiast wartości gaurav5430
-1

który użytkownicy mają do wprowadzenia? Jeśli tak, możesz sformatować kod wejściowy dla Ciebie.

Nie. To niemożliwe ... Stwórzcie sami xls ... joycollector
-1

wania komórek jako „tekst”przed wprowadzanie wartości. W ten sposób Excel poprawnie zapisuje liczby parzyste jako tekst. Jeśli format zostanie później zmieniony, Excel zmieni tylko sposób wyświetlania wartości, ale nie zmieni sposobu przechowywania wartości, chyba że wartość zostanie wprowadzona ponownie (np. Przez naciśnięcie powrotu w komórce).

To, czy program Excel prawidłowo zapisał wartość jako tekst, wskazuje mały zielony trójkąt, który program Excel wyświetla w lewym górnym rogu komórki, jeśli uważa, że ​​komórka zawiera liczbę, ale jest sformatowany jako tekst.

Miałem też problem Romain Hippeau
4

Próbować:

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

Należy poprawnie sformatować numer.

Jak rozumiem, pytający chce być w stanie odróżnić2 i2.0. Twoje rozwiązanie by tego nie zrobiło. (Ale nadal witaj w Stack Overflow!) Paŭlo Ebermann
-1

.toString(). Jest brzydki, ale działa.

Problem polega na tym, że jeśli w wersji A2 jest 2.0, muszę uzyskać ciąg „2.0”, a jeśli 2 to ciąg „2”. joycollector
5

Zalecana:

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

stary:

cell.setCellType(Cell.CELL_TYPE_STRING);

nawet jeśli masz problem z pobraniem wartości zcell mając wzór, nadal to działa.

TheJavadocs Apache POI są bardzo jasne, że nie powinieneś tego robić w ten sposób: Jeśli chcesz uzyskać wartość ciągu dla komórki numerycznej, zatrzymaj się! To nie jest sposób na to. Zamiast tego, w celu pobrania wartości ciągu z komórki numerycznej lub boolowskiej lub daty, użyj zamiast tego DataFormatter. Gagravarr
Ale musisz uważać, używając tego dla podwójnych wartości. Dla mnie wartość 7,9 zmieniła się na 7,8999956589965 ... Chris
stary powinno byćźle MiXT4PE
292

cell.setCellType(Cell.CELL_TYPE_STRING); przed odczytaniem wartości ciągu, która rozwiązała problem bez względu na to, jak użytkownik sformatował komórkę.

Nie może działać na poi-3.1-FINAL Vacker
@Wil cell.setCellType (Cell.CELL_TYPE_STRING); nie działa dla arkusza .xlsx. Jakieś inne rozwiązanie tego problemu? Meenaxi
Ostrzeżenie Gagravarra przed robieniem tego jest słuszne! Z dokumentów: „Jeśli chcesz uzyskać wartość String dla swojej komórki numerycznej, przestań! To nie jest sposób, aby to zrobić. Zamiast tego, do pobierania wartości ciągu liczbowego lub logicznego lub komórki daty, użyj Zamiast tego DataFormatter. ”poi.apache.org/apidocs/org/apache/poi/ss/usermodel/… Sam stosowałem tę technikę, dopóki nie zamknąłem przypadkowo zmieniających się danych, których nie zamierzałem zmienić. (Ustaw typ na String, odczytaj wartość, ustaw typ na numeryczny, przeczytaj ponownie i uzyskaj inną wartość liczbową!) Chris Finley
Zastanawiam się, czy to konto do formatowania? Jak gdyby plik Excel zawsze pokazywał do 2 miejsc po przecinku, czy wartość ciągu będzie dokładnie taka sama? ryvantage
0

że znalazłem prosty sposób rozwiązania. Musiałem wstawić apostrof przed numerem, aby osobny import DB zawsze postrzegał liczby jako tekst. Wcześniej numer 8 zostanie zaimportowany jako 8.0.

Rozwiązanie:

Zachowaj całe formatowanie jako ogólne.Tutaj zakładam, że liczby są przechowywane w kolumnie A, począwszy od rzędu 1.Wstaw „w kolumnie B i skopiuj tyle wierszy, ile potrzeba. Nic nie pojawia się w arkuszu roboczym, ale kliknięcie komórki pozwala zobaczyć apostophe na pasku Formuły.W kolumnie C: = B1 i A1.Zaznacz wszystkie komórki w kolumnie C i wklej specjalnie do kolumny D, używając opcji Wartości.

Hej Presto wszystkie liczby, ale zapisane jako tekst.

0

eki Apache POI, odczytujemy ją jako numeryczną. Ale czasami chcemy, aby odczytano go jako ciąg (np. Numery telefonów itp.). Tak to zrobiłem:

Wstaw nową kolumnę z pierwszą komórką = CONCATENATE ("!", D2). Zakładam, że D2 to identyfikator komórki w kolumnie numeru telefonu. Przeciągnij nową komórkę do końca.

Teraz, jeśli czytasz komórkę za pomocą POI, odczyta formułę zamiast obliczonej wartości. Teraz wykonaj następujące czynności:

Dodaj kolejną kolumnę

Wybierz pełną kolumnę utworzoną w kroku 1. i wybierz Edycja-> KOPIUJ

Przejdź do górnej komórki kolumny utworzonej w kroku 3. i wybierz Edycja-> Wklej specjalnie

W otwartym oknie wybierz przycisk opcji „Wartości”

Wybierz „OK”

Teraz przeczytaj za pomocą POI API ... po przeczytaniu w Javie ... po prostu usuń pierwszy znak, tj. "!"

Twoje rozwiązanie wydaje się nie nadawać do użytku, jeśli sam nie tworzysz plików Excela, prawda? (Czy mógłbyś umieścić w odpowiedzi fragment? To nie jest tak długie.) Paŭlo Ebermann
Tak, nie można go użyć, gdy sam nie tworzy się pliku Excel. Asif Shahzad

Powiązane pytania