🙏 Helfen Sie jetzt mit, unser LibreOffice Forum zu erhalten! 🙏
Mit Ihrer Spende sichern Sie den Fortbestand, den Ausbau und die laufenden Kosten dieses Forums. 🌱

🍀 Jeder Beitrag zählt – vielen Dank für Ihre Unterstützung!🍀

❤️ DANKE >> << DANKE ❤️

>> Dank Ihrer Unterstützung -> Keine Werbung für alle registrierten LibreOffice-Forum User! <<
🤗 Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet. 🤗

Python Calc-Makro: Sortieren von Tabellenbereichen

Alles zur Programmierung im LibreOffice.
Antworten
BastiL
Beiträge: 13
Registriert: So 3. Feb 2013, 10:52

Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von BastiL » So 17. Aug 2014, 15:09

Hallo zusammen,

ich versuche einen Tabellenbereich zu sortieren: LO 4.2.4.2 unter Linux, Python als Makroprogrammiersprache:

Code: Alles auswählen

from com.sun.star.beans import PropertyValue
from com.sun.star.table import TableSortField
from com.sun.star.table.TableSortFieldType import AUTOMATIC

def sort(object=object):
    thisComponent = XSCRIPTCONTEXT.getDocument()
    datasheet = thisComponent.Sheets.getByName('Tabelle1')

    # Sortierung der Tabelle sicherstellen
    sRange = datasheet.getCellRangeByPosition(0,2,18,100)
    SD = PropertyValue()
    SF = TableSortField()
    SF.Field = 9
    SF.IsAscending = True
    SD.Name = "SortFields"
    SD.Value = SF
    sRange.sort(SD)
Der Fehler tritt in der letzten Zeile auf: SD is not iterable. Ich habe mich an dem Beispiel für Base im Buch von Pitonyak (S. 490) orientiert, aber der Transfer nach Python gelingt mir nicht.

Danke.

Benutzeravatar
karolus
* LO-Experte *
Beiträge: 2539
Registriert: Fr 10. Dez 2010, 10:01

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von karolus » So 17. Aug 2014, 20:48

Hallo

Du musst das in Python nicht zwingend über die Api-methoden sortieren, sofern du keine unterschiedlichen Formatierungen innerhalb einer Spalte hast, kannst du ..DataArray mit nativen Python-methoden sortieren und wieder zurückschreiben, siehe:
http://www.libreoffice-forum.de/viewtop ... 876#p30235

Apropos Fehler - so funktionierts

Code: Alles auswählen

sRange.sort( (SD,) ) 
Die Api verlangt an der Stelle ein Array mit dem Argumentkonstrukt nicht das Argumenkonstrukt alleine, in Python wird das durch Übergabe eines tuple mit dem Argumenkonstrukt abgebildet.

Karolus
LO7.4.7.5 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO24.8.0.3 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)

BastiL
Beiträge: 13
Registriert: So 3. Feb 2013, 10:52

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von BastiL » So 17. Aug 2014, 21:41

Danke für die Antwort. Das Sortieren in Python hat Charme. Ich werde das testen. das bestätigt einmal mehr, dass ein direktes Interface zwischen Libreoffice Calc und pandas mega Sinn machen würde - gibt es dazu Ansätze?
Ich denke aber, dass ich in dem Fall die Api verwenden werde. Ich habe extreme Performanceprobleme beim Schreiben in calc-Sheets sobald die "etwas" größer sind. Das Sortieren in calc wird zwar auch langsamer aber nicht so viel.
Generell wird calc bei mir bei vielen Operationen exponentiell mit der Dateigröße langsamer (z.B. speichern, schreiben aus einem Python-Makro heraus, sortieren, ...). Sobald die Datei nur max 1,5MB groß ist geht alles super schnell, aber es wird alles sehr schnell sehr langsam - haben andere das Problem auch?

Edit: Ich habe festgestellt, dass die aus dem Python-Makro ins Libreoffice-Sheet Schreibperformance (setDataArray/setValue) VIEL besser wird, wenn man statt dem ods das xlsx-Format verwendet. Sofern man die Makros nicht im Dokument direkt speichern möchte, scheint das kein Problem zu sein.
Zuletzt geändert von BastiL am So 17. Aug 2014, 23:44, insgesamt 1-mal geändert.

Benutzeravatar
karolus
* LO-Experte *
Beiträge: 2539
Registriert: Fr 10. Dez 2010, 10:01

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von karolus » So 17. Aug 2014, 22:26

Hallo
BastiL hat geschrieben:Danke für die Antwort. Das Sortieren in Python hat Charme. Ich werde das testen. das bestätigt einmal mehr, dass ein direktes Interface zwischen Libreoffice Calc und pandas mega Sinn machen würde - gibt es dazu Ansätze?
Ich denke aber, dass ich in dem Fall die Api verwenden werde. Ich habe extreme Performanceprobleme beim Schreiben in calc-Sheets sobald die "etwas" größer sind. Das Sortieren in calc wird zwar auch langsamer aber nicht so viel.
Generell wird calc bei mir bei vielen Operationen exponentiell mit der Dateigröße langsamer (z.B. speichern, schreiben aus einem Python-Makro heraus, sortieren, ...). Sobald die Datei nur max 1,5MB groß ist geht alles super schnell, aber es wird alles sehr schnell sehr langsam - haben andere das Problem auch?
pandas wird u.a. auch in IPython Notebooks eingebunden respektive umgekehrt.
http://nbviewer.ipython.org/gist/wesm/4 ... Tour.ipynb
http://nbviewer.ipython.org/gist/4569783
Auf der anderen Seite entwickelt sich `IPython notebook` zu meiner favorisierten "Entwicklungsumgebung" für und mit LO.
Damit hätten wir doch schon das Interface für LO←→pandas ;)

Meine Empfehlung um viele Routinen zu beschleunigen von Datenoperationen in Calc: nimm frühzeitig ...DataArray operiere auf diesen Daten setze deine Ergebnissdaten wieder zusammen zu einem tuple( von gleichlangen tuple'n) und übergib das Ding an ein entsprechend dimensioniertes CellRange.setDataArray( out )

Karolus
LO7.4.7.5 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO24.8.0.3 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)

BastiL
Beiträge: 13
Registriert: So 3. Feb 2013, 10:52

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von BastiL » Mo 25. Aug 2014, 22:07

Auf der anderen Seite entwickelt sich `IPython notebook` zu meiner favorisierten "Entwicklungsumgebung" für und mit LO.
Da würde mich mal interessieren wie du genau arbeitest.
Was ich mit Interface meine: Ein paar Funktionen, um einen libreoffice-Calc-Ausschnitt in einen Pandas-Dataframe zu bekommen und umgekehrt. Ich habe vor einiger Zeit eine Handvoll Funktionen geschrieben, die Calc-Bereiche in python-Listen packen bzw. Python-Listen in ein Calc-Sheet packen. Für pandas Dataframes habe ich so etwas (noch) nicht.
nimm frühzeitig ...DataArray operiere auf diesen Daten setze deine Ergebnissdaten wieder zusammen zu einem tuple( von gleichlangen tuple'n) und übergib das Ding an ein entsprechend dimensioniertes CellRange.setDataArray( out )
Das mache ich schon. Im ods-Format qualend langsam, im xlsx bei mir massiv schneller, v.a. sobald die Dateien etwas größer werden.

Benutzeravatar
karolus
* LO-Experte *
Beiträge: 2539
Registriert: Fr 10. Dez 2010, 10:01

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von karolus » Di 26. Aug 2014, 15:44

Hallo
Im ods-Format qualend langsam, im xlsx bei mir massiv schneller, v.a. sobald die Dateien etwas größer werden.
Das kann ich jetzt nicht nachvollziehen wenn die Datei bereits geöffnet ist kann doch ein reines ...setDataArray( .... ) nicht unterschiedlich lang dauern. ( kann es sein das du das Speichern ins jeweilige Format mit einrechnest ) ??
- dabei dürfte der Export nach .xlsx tatsächlich besser abschneiden weil die zip-Komprimieralgorithmen wegfallen.

Karolus
LO7.4.7.5 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO24.8.0.3 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)

BastiL
Beiträge: 13
Registriert: So 3. Feb 2013, 10:52

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von BastiL » Di 26. Aug 2014, 19:57

( kann es sein das du das Speichern ins jeweilige Format mit einrechnest )
Leider nein. Ich habe hier zigfach Beispiele bei denen es massive Performanceunterschiede macht. Übrigens ist auch das Lesen (z.B. getString) massiv betroffen. Wenn es meine Zeit erlaubt werde ich einen Demonstrationsfall posten und auch die Zeiten auf meinem System mit angeben.

BastiL
Beiträge: 13
Registriert: So 3. Feb 2013, 10:52

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von BastiL » Sa 13. Sep 2014, 23:21

Ich habe erst jetzt Zeit gehbat mein Makro anzupassen. Der von Karolus vorgeschlagene Befehl:

Code: Alles auswählen

sRange.sort( (SD,) ) 
sorgt dafür, dass die Fehlermeldung verschwindet. Sortiert ist das Tabellenblatt hinterher aber nicht, obwohl das Makro fehlerfrei durchläuft ... Bei "Rückgängig" kann ich einen Sortiervorgang rückgängig machen, der aber keine Änderung bringt. Dabei sehe ich auch den Bereich der sortiert wird. Dieser ist korrekt und kann daher nicht das Problem sein. Wenn ich Daten manuell sortiere funktioniert alles wie es soll. Muss ich das Tabellenblatt vielleicht irgendwie aktualisieren?

Hier Beispielsheet: http://www73.zippyshare.com/v/40750806/file.html

Und hier das Makro das ich dazu verwende:

Code: Alles auswählen

from com.sun.star.beans import PropertyValue
from com.sun.star.table import TableSortField
from com.sun.star.table.TableSortFieldType import AUTOMATIC

def sort(object=object):
    thisComponent = XSCRIPTCONTEXT.getDocument()
    datasheet = thisComponent.Sheets.getByName('Tabelle1')

    # Sortierung der Tabelle sicherstellen
    sRange = datasheet.getCellRangeByPosition(0,0,1,9)
    SD = PropertyValue()
    SF = TableSortField()
    SF.Field = 1
    SF.IsAscending = True
    SD.Name = "SortFields"
    SD.Value = SF
    sRange.sort( (SD,) )
Die Erwartung wäre, dass der Test in Spalte A und die Zahlen in Spalte B nach Spalte B aufsteigend sortiert werden. Es passiert aber durch Ausführung des Makros nichts.

Benutzeravatar
karolus
* LO-Experte *
Beiträge: 2539
Registriert: Fr 10. Dez 2010, 10:01

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Beitrag von karolus » So 14. Sep 2014, 07:01

Hallo

Tut mir leid, ich hatte in der ersten Antwort lediglich geprüft, das kein Fehler geworfen wird, nicht aber darauf das überhaupt sortiert wird. Die API ist halt oft furchtbar kompliziert und umständlich-- siehe →→

Code: Alles auswählen

from com.sun.star.beans import PropertyValue
from com.sun.star.table import TableSortField
from com.sun.star.table.TableSortFieldType import AUTOMATIC
import uno

def sortieren(object=object):
    doc = XSCRIPTCONTEXT.getDocument()
    datasheet = doc.Sheets.getByName('Tabelle1')
    sRange = datasheet.getCellRangeByPosition(0,0,1,9)
    SF = TableSortField()
    SF.Field = 1
    SF.IsAscending = True
    SF.FieldType = AUTOMATIC
    
    sortfield= SF, #im tuple übergeben
    sortfield = uno.Any("[]com.sun.star.table.TableSortField", sortfield)
    sortdesc = []
    DescriptorSpecs = (("SortFields",sortfield),
                       ("IsSortColumns",False))
    for spec in DescriptorSpecs:
        SD = PropertyValue()   #einzeln initialisiesen     
        SD.Name, SD.Value = spec
        sortdesc.append(SD)
        
    sortdesc = tuple(sortdesc) #Liste→→Tuple    
    sRange.sort( sortdesc )
     
test_sortieren.ods
(19.26 KiB) 312-mal heruntergeladen
Du darfst deine Beispielsdokumente auch hier anhängen!

Karolus
LO7.4.7.5 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO24.8.0.3 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)


An alle, die das LibreOffice-Forum gern nutzen und unterstützen wollen:


Bitte helfen Sie uns mit 7 Euro pro Monat.
Durch Ihren Beitrag tragen Sie dazu bei, unsere laufenden Kosten für die kommenden Monate zu decken.
Unkompliziert per Kreditkarte oder PayPal.
Als ein kleines Dankeschön werden Sie im LO-Forum als SUPPORTER gekennzeichnet.



Antworten