Python und Excel: Erste Gehversuche

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.
JeanCantos
User
Beiträge: 25
Registriert: Sonntag 26. November 2006, 17:08

Python und Excel: Erste Gehversuche

Beitragvon JeanCantos » Sonntag 3. Dezember 2006, 20:10

Hallo zusammen,

über mich gerade ein bissel in Pythonprogrammierung unter Excel. Bei folgendem Code komme ich jedoch nicht weiter:

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-

import win32com.client
import string

## Excel Anwendung öffnen
MyApplication = win32com.client.Dispatch("Excel.Application")
MyApplication.Visible = True

## Arbeitsmappe auswählen oder neue erstellen
MyWorkbook = MyApplication.Workbooks.Open("D:\my_excelfile.xls")
MyWorkSheet = MyWorkbook.Worksheets("Tabelle1")

## Ermittlung max.Spalten
MaxSpalten = 1
while not Inhalt == None:
    Inhalt = MyWorkSheet.Cells(1,MaxSpalten)
    MaxSpalten = MaxSpalten + 1
    print 'MaxSpalten = ',MaxSpalten
   
## Ermittlung max.Zeilen
   
# Zeilenweise auslesen des Tabellenblattes
MyString = {}
for Zeile in range(0,2):
    for Spalte in range(0,MaxSpalten):
        MyString[Zeile,Spalte] = MyWorkSheet.Cells(Zeile+1,Spalte +1)


for Zeile in range(0,2):
    for Spalte in range(0,4):
        print MyString[Zeile,Spalte],

##MyWorkbook.SaveAs(Filename=r"D:\my_excelfile.xls")

##MyWorkbook.Close()
##MyApplication.Quit()

del MyWorkSheet
del MyWorkbook
del MyApplication


Der Block "## Ermittlung max.Spalten" wird mir mit der Fehlermeldung kommentiert:
[code=]Traceback (most recent call last):
File "E:\Public\Programmierung\Python\Excel.py", line 16, in <module>
while not Inhalt == None:
NameError: name 'Inhalt' is not defined[/code]

Wo liegt denn hier mein Denkfehler?

Gruß,

Jean
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Beitragvon sape » Sonntag 3. Dezember 2006, 20:17

Hi.

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-

import win32com.client
import string

## Excel Anwendung öffnen
MyApplication = win32com.client.Dispatch("Excel.Application")
MyApplication.Visible = True

## Arbeitsmappe auswählen oder neue erstellen
MyWorkbook = MyApplication.Workbooks.Open("D:\my_excelfile.xls")
MyWorkSheet = MyWorkbook.Worksheets("Tabelle1")

## Ermittlung max.Spalten
MaxSpalten = 1
while not Inhalt == None: #Wo ist Inhalt definiert!?
[...]


Der Name ``Inhalt`` Existiert nicht! Du musst erstmal ``Inhalt`` definieren bevor du es in einer ``while`` schleife nutzen kannst.

lg
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Beitragvon sape » Sonntag 3. Dezember 2006, 20:20

Code: Alles auswählen

## Ermittlung max.Spalten
MaxSpalten = 1
Inhalt = False # oder sonst ein wert.
while not Inhalt == None:
    Inhalt = MyWorkSheet.Cells(1,MaxSpalten)
    MaxSpalten = MaxSpalten + 1
    print 'MaxSpalten = ',MaxSpalten


lg
BlackJack

Re: Python und Excel: Erste Gehversuche

Beitragvon BlackJack » Sonntag 3. Dezember 2006, 22:56

Deine Namen entsprechen nicht dem Style Guide. Da ist das `win32com`-Modul aber wohl auch ein schlechtes Vorbild.

JeanCantos hat geschrieben:

Code: Alles auswählen

## Ermittlung max.Spalten
MaxSpalten = 1
while not Inhalt == None:
    Inhalt = MyWorkSheet.Cells(1,MaxSpalten)
    MaxSpalten = MaxSpalten + 1
    print 'MaxSpalten = ',MaxSpalten


Das wäre in anderen Sprachen eher eine ``do``/``while``-Schleife. Die wird in Python durch eine "Endlosschleife" umgesetzt, die bei der Abbruchbedingung mit ``break`` verlassen wird:

Code: Alles auswählen

max_spaltennummer = 1
while True:
    inhalt = worksheet.Cells(1, max_spaltennummer)
    if inhalt is None:
        break
    max_spaltennummer += 1
    print 'max_spaltennummer =', max_spaltennummer


Die maximale Spaltennummer von Hand hochzuzählen macht den Quelltext allerdings ein bisschen unübersichtlich, dass liesse sich auch so schreiben:

Code: Alles auswählen

from itertools import count

for max_spaltennummer in count(1):
    inhalt = worksheet.Cells(1, max_spaltennummer)
    if inhalt is None:
        break
    print 'max_spaltennummer = ', max_spaltennummer


Wenn man die Daten aus der Tabelle in eine "zweidimensionale" Liste steckt, dann braucht man die Zeilen- und Spaltenanzahl nicht in extra Variablen speichern, weil Listen ihre Länge "kennen".

Code: Alles auswählen

del MyWorkSheet
del MyWorkbook
del MyApplication


Einfache Namen zu löschen ist in der Regel überflüssig. Das habe ich in den der Zeit, die ich Python schon verwende, noch nie machen müssen.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Re: Python und Excel: Erste Gehversuche

Beitragvon gerold » Montag 4. Dezember 2006, 09:26

BlackJack hat geschrieben:

Code: Alles auswählen

del MyWorkSheet
del MyWorkbook
del MyApplication

Einfache Namen zu löschen ist in der Regel überflüssig. Das habe ich in den der Zeit, die ich Python schon verwende, noch nie machen müssen.

Hi BlackJack!

Ich hatte schon öfter Probleme, wenn ich das bei der Ansteuerung von Excel NICHT gemacht habe. Es ist anscheinend wichtig, dass die Objekte in der richtigen Reihenfolge zerstört werden, sonst bleiben sie im Speicher hängen -- auch wenn das Python-Programm schon längst beendet ist.

Ich empfehle ``del`` nach dem Ansteuern von COM-Servern zu benutzen.

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

Beitragvon BlackJack » Montag 4. Dezember 2006, 10:35

Da klingt nach zirkulären Referenzen bei Objekten mit `__del__()`-Methode. Kranke Windows-Welt. :-)

Edit: Obwohl das eigentlich nicht sein kann. Ob die Namen mit ``del`` entfernt werden oder durch das verlassen der Funktion automatisch verschwinden, dürfte keinen Unterschied machen. Jetzt bin ich verwirrt!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Montag 4. Dezember 2006, 10:53

BlackJack hat geschrieben:Ob die Namen mit ``del`` entfernt werden oder durch das verlassen der Funktion automatisch verschwinden, dürfte keinen Unterschied machen.

Hi BlackJack!

Erklären -- kann ich es nicht. :K Es könnte evt. mit der Reihenfolge zusammenhängen.

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

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
JeanCantos
User
Beiträge: 25
Registriert: Sonntag 26. November 2006, 17:08

Beitragvon JeanCantos » Montag 4. Dezember 2006, 23:47

Hallo zusammen,

zunächst einmal recht herzlichen Dank für eure Antworten. Zunächst einmal verstehe ich nicht, warum ich bei dem Befehl

Code: Alles auswählen

import itertools
eine Fehlermeldung erhalte, dass "count" nicht bekannt sei, während ich bei dem Code

Code: Alles auswählen

from itertools import count
keine Fehlermeldung erhalte.

Importiere ich denn beim ersten Code nicht das komplette Modul, während ich im zweiten Teil nur die Methode "count()" importiere?

Dann habe ich versucht die Methode "count()" mit dem Code

Code: Alles auswählen

from itertools import count

for maxSpalte in count(1):
    print maxSpalte
    Inhalt = MyWorkSheet.Cells(1, maxSpalte)
    if Inhalt is None:
        break
    print 'Anzahl Spalten= ', maxSpalte
und der Hilfe im Pythonmanual zu vertehen

Die Methode count(n) zählt alo bei jedem Aufruf eins hoch, beginnend bei n. So weit, so gut.

Wenn eine leere Zelle auftaucht, der Ihalt also None ist, müsste die Schleife doch unterbrochen werden. Bei mir hingegen zählt die Schleife bis 256 hoch und wird dann mit einer Fehlermeldung beendet. Naja, klar, Excel hat ja auch nur 256 Spalten.

Tippe ich aber den Code

Code: Alles auswählen

Inhalt = MyWorkSheet.Cells(1, 5)
print Inhalt
ein, dann wird mir "None" ausgegeben. Ich habe die ersten vier Spalten in der ersten Zeile mit Text gefüllt, sodass ab der fünften Spalte alle weiteren leer sind.

Warum aber funktioniert das in meiner obigen Schleife nicht?

Code: Alles auswählen

Der Name ``Inhalt`` Existiert nicht!
Du musst erstmal ``Inhalt`` definieren bevor du es in einer ``while`` schleife nutzen kannst.

Aber ist denn nicht gerade der Vorzug bei Python, dass keinerlei Variablen deklariert sein müssen? So habe ich es zumindest des Öfteren gelesen.

Gruß,

Jean
BlackJack

Beitragvon BlackJack » Dienstag 5. Dezember 2006, 00:23

JeanCantos hat geschrieben:zunächst einmal recht herzlichen Dank für eure Antworten. Zunächst einmal verstehe ich nicht, warum ich bei dem Befehl

Code: Alles auswählen

import itertools
eine Fehlermeldung erhalte, dass "count" nicht bekannt sei, während ich bei dem Code

Code: Alles auswählen

from itertools import count
keine Fehlermeldung erhalte.

Importiere ich denn beim ersten Code nicht das komplette Modul, während ich im zweiten Teil nur die Methode "count()" importiere?


In beiden Fällen wird das Modul geladen, die Frage ist was in Deinem Modul an Namen gebunden wird. Bei ``import itertools`` wird das *Modul* an den Namen `itertools` gebunden und über diesen Namen kannst Du auf alle Namen *in* dem Modul zugreifen. Auf `count()` zum Beispiel so: ``itertools.count(1)``. Bei dem ``from``-Import kannst Du einzelne Objekte aus dem Modul in Deinem Modul an Namen binden, dann kannst Du auch ohne den Modulnamen darauf zugreifen. Ist in etwa äquivalent zu:

Code: Alles auswählen

import itertools
count = itertools.count
del itertools


Dann habe ich versucht die Methode "count()" mit dem Code

Code: Alles auswählen

from itertools import count

for maxSpalte in count(1):
    print maxSpalte
    Inhalt = MyWorkSheet.Cells(1, maxSpalte)
    if Inhalt is None:
        break
    print 'Anzahl Spalten= ', maxSpalte
und der Hilfe im Pythonmanual zu vertehen

Die Methode count(n) zählt alo bei jedem Aufruf eins hoch, beginnend bei n. So weit, so gut.

Wenn eine leere Zelle auftaucht, der Ihalt also None ist, müsste die Schleife doch unterbrochen werden. Bei mir hingegen zählt die Schleife bis 256 hoch und wird dann mit einer Fehlermeldung beendet. Naja, klar, Excel hat ja auch nur 256 Spalten.

Tippe ich aber den Code

Code: Alles auswählen

Inhalt = MyWorkSheet.Cells(1, 5)
print Inhalt
ein, dann wird mir "None" ausgegeben. Ich habe die ersten vier Spalten in der ersten Zeile mit Text gefüllt, sodass ab der fünften Spalte alle weiteren leer sind.

Warum aber funktioniert das in meiner obigen Schleife nicht?


Keine Ahnung. Das dürfte so nicht sein. Was bekommst Du wenn Du in der Schleife vor das ``if`` ein ``print repr(Inhalt)`` setzt? Das ``break`` verlässt auf jeden Fall die Schleife wenn es ausgeführt wird.

Code: Alles auswählen

Der Name ``Inhalt`` Existiert nicht!
Du musst erstmal ``Inhalt`` definieren bevor du es in einer ``while`` schleife nutzen kannst.

Aber ist denn nicht gerade der Vorzug bei Python, dass keinerlei Variablen deklariert sein müssen? So habe ich es zumindest des Öfteren gelesen.


Es geht hier nicht um *deklarieren*, sondern um *definieren*. Die Anweisung ``while Inhalt != None:`` heisst doch für Python: Nimm das Objekt das an den Namen `Inhalt` gebunden ist und vergleiche es mit `None`. Dazu muss aber ein Objekt an den Namen gebunden sein, wie sollte man es sonst vergleichen können!?
JeanCantos
User
Beiträge: 25
Registriert: Sonntag 26. November 2006, 17:08

Beitragvon JeanCantos » Dienstag 5. Dezember 2006, 17:35

Hallo BlackJack,

recht herzlichen Dank für deine ausführliche Antwort, die mir mal wieder gezeigt hat, dass ich vom Programmieren sehr wenig verstehe. :-)

Code: Alles auswählen

In beiden Fällen wird das Modul geladen, die Frage ist was in Deinem Modul an Namen gebunden wird. Bei ``import itertools`` wird das *Modul* an den Namen `itertools` gebunden und über diesen Namen kannst Du auf alle Namen *in* dem Modul zugreifen. Auf `count()` zum Beispiel so: ``itertools.count(1)``. Bei dem ``from``-Import kannst Du einzelne Objekte aus dem Modul in Deinem Modul an Namen binden, dann kannst Du auch ohne den Modulnamen darauf zugreifen.

Demzufolge macht es also einen Unterschied, ob ich:
[code=]import string
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b[/code]
oder [code=]from string import strip
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b[/code] schreibe.

Unabhängig davon, dass die strip-Methode nicht das macht, was ich von ihr nach Lesen der Dokumentation geglaubt habe, nämlich Leerzeichen aus einem String entfernen. :-)

Bei mir wird beides Mal [code=]7.5.6, 7.5.7 A[/code]ausgegeben, ergo der Inhalt der Variablen a.

Kann es sein, dass an meinem Interpreter etwas nicht stimmt?

Gruß,

Jean

PS: Den Fehler in Excelcode habe ich gefunden. Der Inhalt der Zelle wird mit

Code: Alles auswählen

    Inhalt = MyWorkSheet.Cells(1, max_spaltennummer).Value
ausgelesen und beschrieben. :-)
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 5. Dezember 2006, 18:27

JeanCantos hat geschrieben:Demzufolge macht es also einen Unterschied, ob ich:
[code=]import string
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b[/code]
oder [code=]from string import strip
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b[/code] schreibe.

Nein, macht es nicht. Denn du nutzt die Strip-Funktion des Moduls nicht, also kannst du dir den Import in beiden Fällten sparen. Du nutzt nämlich das strip() des Stringobjektes. Und ob du import string und dann string.strip(' a ') machst, oder from string import strip und dann strip(' a ') machst - das ist dann wiederrum äquivalent. In beiden Fällen nutzt du sie selbe Funktion. Der Unterschied ist nur, an welchen Namensraum die Funktion gebunden ist.

JeanCantos hat geschrieben:Unabhängig davon, dass die strip-Methode nicht das macht, was ich von ihr nach Lesen der Dokumentation geglaubt habe, nämlich Leerzeichen aus einem String entfernen. :-)

Dann hast du die Dokumentation falsch verstanden.
Dokumentation hat geschrieben:Return a copy of the string with leading and trailing characters removed.

Also es löscht nur die Zeichen am Anfang und am Ende des Strings. Also wenn dein String mit Leerzeichen oder Tabs beginnt oder endet. Du kannst als Parameter sogar angeben welche Zeichen, zum Beispiel wenn du überzählige 'a's am Anfang hast kannst du die durch strip() entfernen lassen.

JeanCantos hat geschrieben:Kann es sein, dass an meinem Interpreter etwas nicht stimmt?

Nö - verhält sich exakt so, wie in der Dokumentation beschrieben. Zum generellen Ersetzen von Zeichen in Strings gibt es ja replace().
My god, it's full of CARs! | Leonidasvoice vs Modvoice
JeanCantos
User
Beiträge: 25
Registriert: Sonntag 26. November 2006, 17:08

Beitragvon JeanCantos » Mittwoch 6. Dezember 2006, 16:23

Hallo Leonidas,

auch Dir einmal einen recht herzlichen Dank für deine Mühe.

Ich dachte bisher, die Strip()-Funktion gehört zum Modul STRING, jedoch muss ich mir eingestehen und Dir recht geben, dass sie sowohl eine STRING-Medthode ist, wie der Documentation auch zu entnehmen ist.

Jedoch verstehe ich den Sinn nicht ganz. Wozu wird die Strip-Funktion in ein Modul gepackt, wenn sie doch eh schon Bestandteil des Stringobjectes ist. Anmerken möchte ich noch, dass ich sehr unerfahren bin, was die objektorientierte Programmierung betrifft und des Öfteren nicht immer genau verstehe, warum das eine so gehandhabt wird und das andere nicht. Eventuell kannst Du mir ja auch diebezüglich gute Literatur empfehlen.

Gruß,

Jean
BlackJack

Beitragvon BlackJack » Mittwoch 6. Dezember 2006, 16:39

Es wurde nicht die Methode auf Zeichenketten auch noch mal in ein Modul gepackt, sondern umgekehrt: "früher" gab es nur die Funktion. Damit alte Software weiterhin läuft, gibt's die Funktion halt immer noch, wird in der Dokumentation aber als veraltet gekennzeichnet.
JR
User
Beiträge: 286
Registriert: Montag 20. Februar 2006, 16:43
Wohnort: Berlin

Beitragvon JR » Mittwoch 6. Dezember 2006, 20:10

Hi JeanCantos!

Du hast nach Literatur gefragt.
Ich beschäftige mich seit etwa einem halben Jahr mit Python und empfehle dir für den Einstieg das Buch:

Autor: Michael Weigend
Titel: Python GE-PACKT
ISBN-Nr. 3-8266-1512-3

Sehe gerade, gibt es schon ab 9,95 http://www.amazon.de/Python-Ge-Packt-Michael-Weigend/dp/3826615123

Solltest du vor haben, Oberflächen zu gestalten, empfehle ich wxPython. Habe mit TkInter angefangen und hab schnell eine Krise bekommen.

Aber hör dich lieber noch um oder lies dir die Meinungen anderer da durch.

Gruß
Jamil

Wer ist online?

Mitglieder in diesem Forum: Don Terremoto, SmombieTV