Discussion:
Calc: Makro beim Verlassen einer Zelle starten
(zu alt für eine Antwort)
Chris
2006-08-05 10:14:33 UTC
Permalink
Hallo da draußen,

ich möchte in Calc ein Makro starten, wenn die Eingabe in einer
Tabellenzelle in einer bestimmten Spalte beendet ist
Konkret also: Jemand gibt in eine Tabellenzelle der Spalte B etwas ein
und springt dann mit ENTER oder TAB weiter - genau das ist der Moment,
in dem das Makro mit dem Inhalt der soeben verlassenen Zelle etwas
anstellen soll.
Das Makro an ENTER bzw. TAB bzw. beide binden möchte ich nicht, weil in
anderen Spalten andere Dinge eingetragen werden können, und die Tasten
dort ja auch noch gebraucht werden.

Gibt es diese Möglichkeit?
Eike Rathke
2006-08-05 11:46:47 UTC
Permalink
Post by Chris
ich möchte in Calc ein Makro starten, wenn die Eingabe in einer
Tabellenzelle in einer bestimmten Spalte beendet ist
Das geht ueber Spalte markieren und Menue Daten.Gueltigkeit: unter
Kriterien Textlaenge gleich 0 setzen, und unter Fehlermeldung als Aktion
dein Makro zuweisen.
Post by Chris
Konkret also: Jemand gibt in eine Tabellenzelle der Spalte B etwas ein
und springt dann mit ENTER oder TAB weiter - genau das ist der Moment,
in dem das Makro mit dem Inhalt der soeben verlassenen Zelle etwas
anstellen soll.
Der Fallstrick mit der Gueltigkeit in diesem Fall ist, dass der zu dem
Zeitpunkt aktuelle Zellwert noch der vorherige ist, weil die Eingabe
eben noch nicht abgeschlossen ist, weswegen nicht beliebige Makros
aufgerufen werden koennen, die sich per API den Wert aus dieser Zelle
besorgen wollen. Dein aufgerufenes Makro muss eine Funktion mit zwei
Parametern sein:

function checkValidity( CellValue as String, CellAddress as String ) as boolean
msgbox( CellValue & " in " & CellAddress)
checkValidity = true
end function

Die Argumente werden von der Gueltigkeitsueberpruefung automatisch
uebergeben. Wenn die Rueckgabe checkValidity=false statt true lautet,
wird die Eingabe abgewiesen. Der Rueckgabetyp muss dazu als boolean
deklariert sein.

Eike
--
PGP/OpenPGP/GnuPG encrypted mail preferred in all private communication.
Key ID: 0x293C05FD - 997A 4C60 CE41 0149 0DB3 9E96 2F1A D073 293C 05FD
Andreas Säger
2006-08-05 17:28:18 UTC
Permalink
Post by Eike Rathke
function checkValidity( CellValue as String, CellAddress as String ) as boolean
msgbox( CellValue & " in " & CellAddress)
checkValidity = true
end function
Wenn die Funktion nicht zur Validierung benötigt wird, einfach auf jeden
Fall True zurückgeben (aktzeptiere die Eingabe) und als Bedingung
Textlänge = 0 setzen weil es sonst nicht aufgerufen wird. Ok, mit dieser
Bedingung wird es nicht Aufgerufen, wenn der Inhalt im Eingabemodus
entfernt wird.
Das ganze funktioniert gar nicht wenn die Zelle nicht im Eingabemodus
verändert wird (Paste, Inhalte löschen, andere Makros(?)).

Hier ist ein Beispiel in Basic mit einer Funktion, die aus dem 2.
Post by Eike Rathke
http://www.oooforum.org/forum/viewtopic.phtml?t=38124
Dort wird bei fehlerhafter Eingabe (Bedingung: 0 - 24) die Zelle
zurückgesetzt (returnvalue = False) und bei richtiger Eingabe ein
Stundenwert in dieselbe Zelle geschrieben.
Eike Rathke
2006-08-05 20:06:55 UTC
Permalink
Post by Andreas Säger
Post by Eike Rathke
function checkValidity( CellValue as String, CellAddress as String ) as boolean
msgbox( CellValue & " in " & CellAddress)
checkValidity = true
end function
Wenn die Funktion nicht zur Validierung benötigt wird, einfach auf jeden
Fall True zurückgeben (aktzeptiere die Eingabe) und als Bedingung
Textlänge = 0 setzen weil es sonst nicht aufgerufen wird.
Hab ich auch geschrieben.
Post by Andreas Säger
Ok, mit dieser Bedingung wird es nicht Aufgerufen, wenn der Inhalt im
Eingabemodus entfernt wird.
Wenn das gewuenscht wird "Leerzellen zulassen" ausschalten.
Post by Andreas Säger
Das ganze funktioniert gar nicht wenn die Zelle nicht im Eingabemodus
verändert wird (Paste, Inhalte löschen, andere Makros(?)).
Das ist wahr. Dafuer muesste ein util::XModifyListener per
util::XModifyBroadcaster interface des Zellobjekts angemeldet werden,
addModifyListener(). Problem dabei ist die Persistenz, um nach dem Laden
des Dokuments wieder korrekt aufzusetzen.
Post by Andreas Säger
Hier ist ein Beispiel in Basic mit einer Funktion, die aus dem 2.
Post by Eike Rathke
http://www.oooforum.org/forum/viewtopic.phtml?t=38124
Dort wird bei fehlerhafter Eingabe (Bedingung: 0 - 24) die Zelle
zurückgesetzt (returnvalue = False) und bei richtiger Eingabe ein
Stundenwert in dieselbe Zelle geschrieben.
Das funktioniert aber nicht, wie dort auch beschrieben ist. Bei
fehlerhafter Eingabe sowieso nicht, weil ReplaceHours kein boolean false
zurueckliefert und damit die Eingabe angenommen wird, was leicht zu
aendern ist. Abgesehen davon, dass es, so wie es z.Zt. mit
oCell.formulalocal = "" ist, in dem Fall den vorherigen Wert loeschen
wuerde. Bei richtiger Eingabe nicht, weil die Gueltigkeitspruefung
aufgerufen wird bevor der neue Zellinhalt an der Zelle gesetzt wird, der
dann den vom Makro gesetzten Wert wieder ueberschreibt.

Eike
--
PGP/OpenPGP/GnuPG encrypted mail preferred in all private communication.
Key ID: 0x293C05FD - 997A 4C60 CE41 0149 0DB3 9E96 2F1A D073 293C 05FD
Michael Dannenhöfer
2006-08-05 12:34:56 UTC
Permalink
Hallo,
Post by Chris
Hallo da draußen,
ich möchte in Calc ein Makro starten, wenn die Eingabe in einer
Tabellenzelle in einer bestimmten Spalte beendet ist
Konkret also: Jemand gibt in eine Tabellenzelle der Spalte B etwas ein
und springt dann mit ENTER oder TAB weiter - genau das ist der Moment,
in dem das Makro mit dem Inhalt der soeben verlassenen Zelle etwas
anstellen soll.
Das Makro an ENTER bzw. TAB bzw. beide binden möchte ich nicht, weil in
anderen Spalten andere Dinge eingetragen werden können, und die Tasten
dort ja auch noch gebraucht werden.
Gibt es diese Möglichkeit?
Das kann man über einen EventListener lösen.
Der Zelle muss per Makro beim Start ein EventListener zugewiesen
werden. In Deinem Fall am besten:
com.sun.star.chart.XChartDataChangeEventListener

Sub addeventlistener
oDoc = thisComponent
oSheets = oDoc.getSheets()
oSheet = oSheets.getByName("Tabelle1")
oCell = oSheet.getCellRangeByName("A1")
oListener = CreateUnoListener( "CELL_",
"com.sun.star.chart.XChartDataChangeEventListener" )
oCell.addChartDataChangeEventListener(oListener)
End Sub

Dieses Makro muss bei öffnen des Dokumentes geladen werden.
Dann kannst Du in einem Makro auf die Änderung in der Zelle reagieren.

Sub CELL_chartDataChanged
oDoc = oDoc = thisComponent
oSheets = oDoc.getSheets()
oSheet = oSheets.getByName("Tabelle1")
oCell = oSheet.getCellRangeByName("A1")
msgbox oCell.string
end sub



mfg
Michael

--
FAQ zu Starbasic -> http://www.starbasicfaq.de/
StopenSuchTool zur Suche in StarOffice/OpenOffice-Dateien -> http://www.dannenhoefer.de/down/
music.funplayer 2006 mp3-Datenbank und Player -> http://www.dannenhoefer.de/funplayer
Eike Rathke
2006-08-05 14:05:25 UTC
Permalink
Post by Michael Dannenhöfer
Das kann man über einen EventListener lösen.
Der Zelle muss per Makro beim Start ein EventListener zugewiesen
com.sun.star.chart.XChartDataChangeEventListener
[...]
Dieses Makro muss bei öffnen des Dokumentes geladen werden.
Dann kannst Du in einem Makro auf die Änderung in der Zelle reagieren.
Das funktioniert zwar prinzipiell, hat jedoch folgende Nachteile:

- Die Anzahl der ChartListener je Dokument ist auf 64k begrenzt.

- Die Verwaltung von massig ChartListener Objekten, z.B. 64k bei einem
listener je Zelle in einer Spalte, erzeugt unnoetigen overhead.

- Die Benachrichtigung erfolgt erst wenn der Benutzer eine Sekunde
lang nichts getippt hat, weil wie der Name schon sagt das eigentlich
fuer das update von charts gedacht ist. Wenn also mehrere Werte
schnell nacheinander eingegeben werden, werden erst am Ende alle
listener benachrichtigt.

- Um die listener beim Oeffnen des Dokuments korrekt anmelden zu
koennen, muss ein Mechanismus geschaffen werden, der einfuegen und
loeschen von Spalten mitprotokolliert und auch irgendwie speichert.
Das ist nicht trivial. Alternativ koennte ein "tag" in einer
Spaltenueberschrift vergeben werden, nach dem gesucht wird um
erstmalig die Spalte zu bestimmen. Das erfordert allerdings eine
gewisse Kooperation des Benutzers, diese Zelle nicht zu veraendern..

Ich halte den von mir beschriebenen Ansatz mit der
Gueltigkeitsueberpruefung fuer besser geeignet.

Eike
--
PGP/OpenPGP/GnuPG encrypted mail preferred in all private communication.
Key ID: 0x293C05FD - 997A 4C60 CE41 0149 0DB3 9E96 2F1A D073 293C 05FD
Michael Dannenhöfer
2006-08-06 10:25:11 UTC
Permalink
Post by Eike Rathke
Post by Michael Dannenhöfer
Das kann man über einen EventListener lösen.
Der Zelle muss per Makro beim Start ein EventListener zugewiesen
com.sun.star.chart.XChartDataChangeEventListener
[...]
Dieses Makro muss bei öffnen des Dokumentes geladen werden.
Dann kannst Du in einem Makro auf die Änderung in der Zelle reagieren.
- Die Anzahl der ChartListener je Dokument ist auf 64k begrenzt.
Ist es sinnvoll etwas auszugrenzen bevor man die Grenze erreicht hat?
Post by Eike Rathke
- Die Verwaltung von massig ChartListener Objekten, z.B. 64k bei einem
listener je Zelle in einer Spalte, erzeugt unnoetigen overhead.
Mein Fehler, ich dachte es geht nur um eine Zelle. Es geht auch über
die ganze Spalte

oColumn = oSheet.getColumns().getByName("E")
oListener = CreateUnoListener( "CELL_",
"com.sun.star.chart.XChartDataChangeEventListener" )
oColumn.addChartDataChangeEventListener(oListener)
Post by Eike Rathke
- Die Benachrichtigung erfolgt erst wenn der Benutzer eine Sekunde
lang nichts getippt hat, weil wie der Name schon sagt das eigentlich
fuer das update von charts gedacht ist. Wenn also mehrere Werte
schnell nacheinander eingegeben werden, werden erst am Ende alle
listener benachrichtigt.
Wenn mehrere Werte nacheineinander eingeben werden, wird der Ablauf
durch Makros immer eingeschränkt. Ob dies an dieser Stelle stört oder
nicht liegt an der gewünschten Anwendung.
Post by Eike Rathke
- Um die listener beim Oeffnen des Dokuments korrekt anmelden zu
koennen, muss ein Mechanismus geschaffen werden, der einfuegen und
loeschen von Spalten mitprotokolliert und auch irgendwie speichert.
Das ist nicht trivial. Alternativ koennte ein "tag" in einer
Spaltenueberschrift vergeben werden, nach dem gesucht wird um
erstmalig die Spalte zu bestimmen. Das erfordert allerdings eine
gewisse Kooperation des Benutzers, diese Zelle nicht zu veraendern..
Das ist vollkommen überflüssig. Der zugewiesene Listenter bleibt
automatisch an der richtigen Stelle (Telle oder Spalte). Auch nach dem
Eingfügen von neuen Spalten oder Zeilen. Die Zuweisungen innerhalb
Basic erfolgen auf die Zelle oder Spalte nicht auf die Position.
Post by Eike Rathke
Post by Michael Dannenhöfer
Das ganze funktioniert gar nicht wenn die Zelle nicht im Eingabemodus
verändert wird (Paste, Inhalte löschen, andere Makros(?)).
Das ist wahr. Dafuer muesste ein util::XModifyListener per
<util::XModifyBroadcaster interface des Zellobjekts angemeldet werden,
addModifyListener(). Problem dabei ist die Persistenz, um nach dem Laden
des Dokuments wieder korrekt aufzusetzen.
Und auch dass ist bei Verwendung des Eventlisteners vollkommen
überflüssig, da auf jedes dieser Ereignisse reagiert wird.
Post by Eike Rathke
Ich halte den von mir beschriebenen Ansatz mit der
Gueltigkeitsueberpruefung fuer besser geeignet.
Ist das hier seit neuesten ein Wetbewerb?


Mfg
Michael



--
FAQ zu Starbasic -> http://www.starbasicfaq.de/
StopenSuchTool zur Suche in StarOffice/OpenOffice-Dateien -> http://www.dannenhoefer.de/down/
music.funplayer 2006 mp3-Datenbank und Player -> http://www.dannenhoefer.de/funplayer
Eike Rathke
2006-08-06 11:42:42 UTC
Permalink
Post by Michael Dannenhöfer
Post by Eike Rathke
- Die Anzahl der ChartListener je Dokument ist auf 64k begrenzt.
Ist es sinnvoll etwas auszugrenzen bevor man die Grenze erreicht hat?
Nein, aber diese Grenze ist bei einer kompletten Spalte von Einzelzellen
bereits erreicht. Ich wollte es nur erwaehnt haben.
Post by Michael Dannenhöfer
Post by Eike Rathke
- Die Verwaltung von massig ChartListener Objekten, z.B. 64k bei einem
listener je Zelle in einer Spalte, erzeugt unnoetigen overhead.
Mein Fehler, ich dachte es geht nur um eine Zelle. Es geht auch über
die ganze Spalte
oColumn = oSheet.getColumns().getByName("E")
oListener = CreateUnoListener( "CELL_",
"com.sun.star.chart.XChartDataChangeEventListener" )
oColumn.addChartDataChangeEventListener(oListener)
Der listener erfaehrt damit z.Zt. aber nicht, welche Zelle geaendert
wurde.
Post by Michael Dannenhöfer
Post by Eike Rathke
- Die Benachrichtigung erfolgt erst wenn der Benutzer eine Sekunde
lang nichts getippt hat, weil wie der Name schon sagt das eigentlich
fuer das update von charts gedacht ist. Wenn also mehrere Werte
schnell nacheinander eingegeben werden, werden erst am Ende alle
listener benachrichtigt.
Wenn mehrere Werte nacheineinander eingeben werden, wird der Ablauf
durch Makros immer eingeschränkt. Ob dies an dieser Stelle stört oder
nicht liegt an der gewünschten Anwendung.
Ok. Dieser Punkt hat andere Makro-Autoren jedenfalls schon gestoert.
Post by Michael Dannenhöfer
Post by Eike Rathke
- Um die listener beim Oeffnen des Dokuments korrekt anmelden zu
koennen, muss ein Mechanismus geschaffen werden, der einfuegen und
loeschen von Spalten mitprotokolliert und auch irgendwie speichert.
Das ist nicht trivial. Alternativ koennte ein "tag" in einer
Spaltenueberschrift vergeben werden, nach dem gesucht wird um
erstmalig die Spalte zu bestimmen. Das erfordert allerdings eine
gewisse Kooperation des Benutzers, diese Zelle nicht zu veraendern..
Das ist vollkommen überflüssig. Der zugewiesene Listenter bleibt
automatisch an der richtigen Stelle (Telle oder Spalte). Auch nach dem
Eingfügen von neuen Spalten oder Zeilen. Die Zuweisungen innerhalb
Basic erfolgen auf die Zelle oder Spalte nicht auf die Position.
Und wie bekommt der Basic code mit, dass er nach dem Speichern und neu
Laden des Dokuments nicht mehr auf Spalte E sondern auf Spalte F horchen
muss, wenn vor dem Speichern eine Spalte eingefuegt wurde?
Post by Michael Dannenhöfer
Post by Eike Rathke
Post by Andreas Säger
Das ganze funktioniert gar nicht wenn die Zelle nicht im Eingabemodus
verändert wird (Paste, Inhalte löschen, andere Makros(?)).
Das ist wahr. Dafuer muesste ein util::XModifyListener per
<util::XModifyBroadcaster interface des Zellobjekts angemeldet werden,
addModifyListener(). Problem dabei ist die Persistenz, um nach dem Laden
des Dokuments wieder korrekt aufzusetzen.
Und auch dass ist bei Verwendung des Eventlisteners vollkommen
überflüssig, da auf jedes dieser Ereignisse reagiert wird.
Wieder: speichern und laden von geaenderten Bezuegen. Das ist hier mit
Persistenz gemeint. Da unterscheidet sich der
XChartDataChangeEventListener in nichts von dem XModifyListener.
Letzterer wurde eigentlich fuer den hier angepeilten Zweck geschaffen.

Solange sich der Benutzer kooperativ verhaelt und die Spaltenanordnung
nicht aendert, ist das alles kein Problem. Was man ja auch mit
geschuetzten Tabellen forcieren kann, und wiederum ein Vorteil
gegenueber der Gueltigkeitsueberpruefung ist. Ob das im konkreten Fall
aber ueberhaupt moeglich ist, muss der OP entscheiden.
Post by Michael Dannenhöfer
Post by Eike Rathke
Ich halte den von mir beschriebenen Ansatz mit der
Gueltigkeitsueberpruefung fuer besser geeignet.
Ist das hier seit neuesten ein Wetbewerb?
Nein, der Versuch, gangbare Loesungen aufzuzeigen. Das Grundproblem
listener an Zelle gibt es immer wieder. Beide Varianten haben Vor- und
Nachteile, der OP muss entscheiden, was besser in sein Konzept passt,
und welche Nachteile er eher in Kauf nehmen kann.

Eike
--
PGP/OpenPGP/GnuPG encrypted mail preferred in all private communication.
Key ID: 0x293C05FD - 997A 4C60 CE41 0149 0DB3 9E96 2F1A D073 293C 05FD
Chris
2006-08-05 18:37:42 UTC
Permalink
An alle:

Danke für die schnelle Hilfe. Ich werde mich gleich mal dranbegeben.
Loading...