Encoding Fehler bei Exceltabelle auslesen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
alpha
User
Beiträge: 195
Registriert: Freitag 23. Mai 2003, 23:24
Wohnort: Ulm

Encoding Fehler bei Exceltabelle auslesen

Beitragvon alpha » Montag 8. Januar 2007, 09:48

Hallo Pythonfreunde,

ich bekomme in folgender Zeile:

Code: Alles auswählen

    wert = str(MyWorkSheet.Cells(1,spalte)).encode("utf-8")

diesen Fehler:

Traceback (most recent call last):
File "N:\scripts\Python\excellesen.py", line 32, in <module>
wert = str(MyWorkSheet.Cells(1,spalte)).encode("utf-8")
File "C:\programme\Python25\Lib\site-packages\win32com\client\dynamic.py", lin
e 187, in __str__
return str(self.__call__())
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 18:
ordinal not in range(128)

Ich hab jetzt schon ewig mit den Encodings rumexperimentiert aber komme zu keinem brauhcbaren Ergebnis. Könnt ihr mir weiterhelfen?

Grüße
alpha[/code]
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Re: Encoding Fehler bei Exceltabelle auslesen

Beitragvon gerold » Montag 8. Januar 2007, 10:18

alpha hat geschrieben:Könnt ihr mir weiterhelfen?

Hi alpha!

http://www.python-forum.de/topic-5095.html

Ich glaube nicht, dass du nach dieser Lektüre noch Fragen hast. Wenn doch -- einfach melden!

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

Beitragvon BlackJack » Montag 8. Januar 2007, 10:22

`str()` wandelt ein Objekt in eine Zeichenkette. Bei einer Unicode-Zeichenkette als Argument muss diese irgendwie kodiert werden. Da wird als kleinster gemeinsamer Nenner ASCII genommen, was wie man sieht fehlschlägt, wenn die Unicode-Zeichenkette Zeichen ausserhalb von ASCII enthält.

Danach versuchst Du ein `encode()`, was aber für Zeichensatz-Kodierungen nur auf Unicode-Zeichenketten Sinn macht.
alpha
User
Beiträge: 195
Registriert: Freitag 23. Mai 2003, 23:24
Wohnort: Ulm

Beitragvon alpha » Montag 8. Januar 2007, 13:00

Hi Blackjack,

aber wie kodiere ich dann ein Objekt? Encode geht ja nur auf strings.

Thx
alpha
BlackJack

Beitragvon BlackJack » Montag 8. Januar 2007, 13:07

Ich dachte das wäre schon eine Unicode-Zeichenkette!? Was ist das denn für ein Objekt und was kommt beim Aufruf der `str()`-Funktion mit diesem Objekt als Argument als Ergebnis heraus?
alpha
User
Beiträge: 195
Registriert: Freitag 23. Mai 2003, 23:24
Wohnort: Ulm

Beitragvon alpha » Montag 8. Januar 2007, 13:32

Hi Blackjack,

hier der Programmausschnitt

Code: Alles auswählen

MyApp = win32com.client.Dispatch("Excel.Application")
MyWorkbook = MyApp.Workbooks.Open("c:/temp/Legende_HMI_CANtrol.xls")
MyWorkSheet = MyWorkbook.Worksheets("Legende_HMI_CANtrol")

tabelle = []
spalte = 0
while True:
    spalte += 1
    print spalte
    #wert = ConvertText(str(MyWorkSheet.Cells(1,spalte)))
    print type(MyWorkSheet.Cells(1,spalte))
    wert = str(MyWorkSheet.Cells(1,spalte)).encode("iso-8859-1")
    print wert
    if wert is None or spalte > 255:
        break
    tabelle.append(MyWorkSheet.Cells(1,spalte))
print tabelle[9]


und hier die Ausgabe:


N:\scripts\Python>excellesen.py
1
<type 'instance'>
OPC-Item
2
<type 'instance'>
Einheit
3
<type 'instance'>
Beschreibung
deutsch / englisch
4
<type 'instance'>
Bemerkungen deutsch / englisch
5
<type 'instance'>
Beschreibung
deutsch
6
<type 'instance'>
Bemerkungen deutsch
7
<type 'instance'>
Beschreibung
englisch
8
<type 'instance'>
Bemerkungen englisch
9
<type 'instance'>
Traceback (most recent call last):
File "N:\scripts\Python\excellesen.py", line 33, in <module>
wert = str(MyWorkSheet.Cells(1,spalte)).encode("iso-8859-1")
File "C:\programme\Python25\Lib\site-packages\win32com\client\dynamic.py", lin
e 187, in __str__
return str(self.__call__())
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 18:
ordinal not in range(128)


Bei "Bemerkung französisch" steigt er wegen dem ö aus.

Gruß
alpha
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Re: Encoding Fehler bei Exceltabelle auslesen

Beitragvon gerold » Montag 8. Januar 2007, 13:34

alpha hat geschrieben:ich bekomme in folgender Zeile:

Code: Alles auswählen

wert = str(MyWorkSheet.Cells(1,spalte)).encode("utf-8")

diesen Fehler:

Traceback (most recent call last):
File "N:\scripts\Python\excellesen.py", line 32, in <module>
wert = str(MyWorkSheet.Cells(1,spalte)).encode("utf-8")
File "C:\programme\Python25\Lib\site-packages\win32com\client\dynamic.py", lin
e 187, in __str__
return str(self.__call__())
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 18:
ordinal not in range(128)

Hi alpha!

Um einen Text in eine besondere Codierung (z.B. utf-8) umzuwandeln, musst du zuerst herausfinden, in welcher Codierung der Quelltext vorhanden ist, oder ob dieser evt. bereits in Unicode vorliegt.

Ob Unicode oder nicht, sagt dir ``type``:

Code: Alles auswählen

print type(MyWorkSheet.Cells(1,spalte))

Wenn der Text im Unicode vorliegt, dann kannst du mit ``encode("utf-8")`` nach UTF-8 umwandeln.

Liegt der Text aber nicht im Unicode vor, musst du herausfinden, in welchem Coding dein Text vorliegt.

Unter einem deutschsprachigen Windows gibt es nicht viele mögliche Encodings. cp1252, iso-8859-1, iso-8859-15, mbcs und cp850. Die Reihenfolge entspricht in etwa der Wahrscheinlichkeit, da ein Encoding nicht sicher festgestellt, sondern nur nach Wahrscheinlichkeit erraten werden kann.

Am besten, du nimmst dir dafür eine Python-Shell zur Hand, die mit Umlauten umgehen kann. Ich verwende dafür gerne die PyShell, die beim wxPython-Demo mit dabei ist. Du kannst aber auch Idle verwenden.

UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 18:
ordinal not in range(128)

Dann lass uns mal herausfinden, mit welchem Buchstaben es ein Problem gibt.

In Idle::

Code: Alles auswählen

>>> print "\xf6"
ö
>>>

Es handelt sich also um das kleine "ö".

Ich setzte das mal ein bischen fort:

Code: Alles auswählen

>>> u"ö"
u'\xf6'
>>> u"ö".encode("cp1252")
'\xf6'
>>> u"ö".encode("utf-8")
'\xc3\xb6'
>>>

Der wahrscheinlichste Fall ist, vorausgesetzt, dass der Typ den du beim Prüfen mit ``type`` zurück bekommst nicht ``<type 'unicode'>`` ist, dass dein Text im Coding "cp1252" an Python übergeben wurde. Vielleicht auch in einem der anderen Encodings. Das musst du dann ausprobieren.

Die Umwandlung passiert, wie in http://www.python-forum.de/topic-5095.html aufgezeigt, über Unicode.

Code: Alles auswählen

text_cp1252 = MyWorkSheet.Cells(1,spalte)
text_unicode = text_cp1252.decode("cp1252")
text_utf8 = text_unicode.encode("utf-8")

# oder kurz
text_utf8 = MyWorkSheet.Cells(1,spalte).decode("cp1252").encode("utf-8")

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
alpha
User
Beiträge: 195
Registriert: Freitag 23. Mai 2003, 23:24
Wohnort: Ulm

Beitragvon alpha » Montag 8. Januar 2007, 13:51

Hallo Gerold,

wie oben beschrieben ist der Typ leider "instance" also irgendein Excel Objekt (meiner bescheidenen Meinung nach). Daher muss ich bevor ich .decode oder .encode verwende eine Stringwandlung machen. Kann ich eine Stringwandlung machen bei der immer ein Unicodestring herauskommt? Das sollte doch helfen. Dann müsste ich danach nur noch eine .encode machen und es sollte gehen, oder?

alpha
BlackJack

Beitragvon BlackJack » Montag 8. Januar 2007, 14:02

Kannst Du `str()` eventuell durch `unicode()` ersetzen? Excel müsste doch intern mittlerweile auch mit Unicode arbeiten.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Montag 8. Januar 2007, 14:07

alpha hat geschrieben:wie oben beschrieben ist der Typ leider "instance"

Hi alpha!

Code: Alles auswählen

# dann gehts entweder so
text_unicode = unicode(MyWorkSheet.Cells(1,spalte))
text_utf8 = text_unicode.encode("utf-8")

# oder so
text_unicode = unicode(MyWorkSheet.Cells(1,spalte), "cp1252")
text_utf8 = text_unicode.encode("utf-8")

``unicode()`` ist so etwas wie ``str()``. Kann also als Ersatz für ``"ööö".decode()`` verwendet werden.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
alpha
User
Beiträge: 195
Registriert: Freitag 23. Mai 2003, 23:24
Wohnort: Ulm

Beitragvon alpha » Montag 8. Januar 2007, 17:33

Hi Gerold,

danke für Deine Antworten. Leider funktionieren beide Varianten nciht.

Bei der ersten Variante krachts bei der Spalte mit dem ö:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 18:
ordinal not in range(128)

Bei der 2. Variante krachts gleich weil der Rückgabetyp 'type instance' ist und die Wandlung nur für Strings oder Unicodeobjekte funktioniert.

Irgendwie komm ich nicht weiter :?

alpha
BlackJack

Beitragvon BlackJack » Montag 8. Januar 2007, 18:23

Dann musst Du entweder einen Weg finden von so einem Zellenobjekt den Inhalt als Unicode zu bekommen, so eine Zelle hat sicher Attribute und Methoden, oder eben herausfinden in welcher Kodierung die Zeichenkette vorliegt, die man mit `str()` erhält, um sie umkodieren zu können.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Montag 8. Januar 2007, 18:25

...hier ist die Lösung:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import os
import win32com.client


filename = os.path.abspath("aaa.xls")

excel_app = win32com.client.dynamic.Dispatch("Excel.Application")
excel_workbook = excel_app.Workbooks.Open(filename)
excel_sheet = excel_workbook.Worksheets("bbb")

print repr(excel_sheet.Cells(1, 1))
print repr(excel_sheet.Range("A1"))

print "Formula:", repr(excel_sheet.Cells(1, 1).Formula)
print "Text:", repr(excel_sheet.Range("A1").Text)
print "Value:", repr(excel_sheet.Range("A1").Value)

utf8_string = excel_sheet.Range("A1").Text.encode("utf-8")
print "UTF-8:", repr(utf8_string)

excel_workbook.Close()
excel_app.Quit()

del excel_sheet
del excel_workbook
del excel_app

Ausgabe, wenn in "A1" der Text "öäüß" steht:
[code=]<COMObject <unknown>>
<COMObject Range>
Formula: u'\xf6\xe4\xfc\xdf'
Text: u'\xf6\xe4\xfc\xdf'
Value: u'\xf6\xe4\xfc\xdf'
UTF-8: '\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f'[/code]
Ausgabe, wenn in "A2" der Wert 1.12345 steht, und in "A1" die Formel "=A2":
[code=]<COMObject <unknown>>
<COMObject Range>
Formula: u'=A2'
Text: u'1,2345'
Value: 1.2344999999999999
UTF-8: '1,2345'[/code]
Und hier die Ausgabe, wenn in "A1" direkt der Wert 1.2345 steht:
[code=]<COMObject <unknown>>
<COMObject Range>
Formula: u'1.2345'
Text: u'1,2345'
Value: 1.2344999999999999
UTF-8: '1,2345'
[/code]
Du bekommst also Unicode-Strings zurück, und solltes aufpassen, was du dir zurück geben lässt. Formula, Text oder Value liefern je nach art der Zelle etwas komplett anderes zurück. "Text" ist besonders irritierend, da damit bei Zahlen je nach Ländereinstellung etwas anderes zurück gegeben wird.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Montag 8. Januar 2007, 18:46

Falls du immer UTF-8 brauchst, auch wenn eine Zahl in der Zelle steht:

Code: Alles auswählen

retval = excel_sheet.Range("A1").Value
print "Original:", repr(retval)
retval = unicode(retval)
utf8_string = retval.encode("utf-8")
print "Unicode:", repr(retval)
print "UTF8:", repr(utf8_string)

Ausgabe:
[code=]Original: 1.2344999999999999
Unicode: u'1.2345'
UTF8: '1.2345'[/code]
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
alpha
User
Beiträge: 195
Registriert: Freitag 23. Mai 2003, 23:24
Wohnort: Ulm

Beitragvon alpha » Dienstag 9. Januar 2007, 14:11

Danke Leute. Das .Text war wohl die Lösung. So gehts :D

Super Hilfe wie immer.

alpha

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]