Seite 1 von 1

Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: So 17. Aug 2014, 15:09
von BastiL
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.

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: So 17. Aug 2014, 20:48
von karolus
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

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: So 17. Aug 2014, 21:41
von BastiL
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.

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: So 17. Aug 2014, 22:26
von karolus
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

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: Mo 25. Aug 2014, 22:07
von BastiL
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.

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: Di 26. Aug 2014, 15:44
von karolus
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

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: Di 26. Aug 2014, 19:57
von BastiL
( 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.

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: Sa 13. Sep 2014, 23:21
von BastiL
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.

Re: Python Calc-Makro: Sortieren von Tabellenbereichen

Verfasst: So 14. Sep 2014, 07:01
von karolus
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