Seite 1 von 1

Python und Excel: Erste Gehversuche

Verfasst: Sonntag 3. Dezember 2006, 20:10
von JeanCantos
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: Alles auswählen

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
Wo liegt denn hier mein Denkfehler?

Gruß,

Jean

Verfasst: Sonntag 3. Dezember 2006, 20:17
von sape
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

Verfasst: Sonntag 3. Dezember 2006, 20:20
von sape

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

Re: Python und Excel: Erste Gehversuche

Verfasst: Sonntag 3. Dezember 2006, 22:56
von BlackJack
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.

Re: Python und Excel: Erste Gehversuche

Verfasst: Montag 4. Dezember 2006, 09:26
von gerold
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
:-)

Verfasst: Montag 4. Dezember 2006, 10:35
von BlackJack
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!

Verfasst: Montag 4. Dezember 2006, 10:53
von gerold
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
:-)

Verfasst: Montag 4. Dezember 2006, 23:47
von JeanCantos
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

Verfasst: Dienstag 5. Dezember 2006, 00:23
von BlackJack
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!?

Verfasst: Dienstag 5. Dezember 2006, 17:35
von JeanCantos
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: Alles auswählen

import string
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b
oder

Code: Alles auswählen

from string import strip
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b
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: Alles auswählen

7.5.6, 7.5.7 A
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. :-)

Verfasst: Dienstag 5. Dezember 2006, 18:27
von Leonidas
JeanCantos hat geschrieben:Demzufolge macht es also einen Unterschied, ob ich:

Code: Alles auswählen

import string
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b
oder

Code: Alles auswählen

from string import strip
a = '7.5.6, 7.5.7 A'
b = a.strip()
print b
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().

Verfasst: Mittwoch 6. Dezember 2006, 16:23
von JeanCantos
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

Verfasst: Mittwoch 6. Dezember 2006, 16:39
von BlackJack
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.

Verfasst: Mittwoch 6. Dezember 2006, 20:10
von JR
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-Mi ... 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