dim Feld()
ein eigener listener muss alle vorgesehen funktionen aufweisen!
siehe Bsp04.odb http://members.aon.at/schardinger/openo ... piele.html
servus, günther
Listener will nicht so wie ich
Moderator: Moderatoren
Re: Listener will nicht so wie ich
Versuche das Problem und den derzeitigen Stand der Lösung erneut zusammenzufassen, inklusiv Code.Keiner mehr eine Idee?
Kann doch nicht so ein kompliziertes Problem sein...?
Stelle vorzugsweise eine Testdatei mit integriertem Code zur Verfügung.
WArum?
Das Problem ist wohl nicht unlösbar, aber z.B. ich verstehe erstens nicht was Du im DEtail willst und zum Zweiten überblicke ich zwar das Ganze insgesamt, weiß aber das das ausgetestet werden müßte was zeitaufwendig ist und wozu noch weniger Lust seitens der Helfer besteht wenn sie sich erst noich alles zum Testen (letzlich also eine Beispieldatei) selbst zusammenstellen müssen.
Ob das hilft weiß ich nicht, nur Du solltest immer bedenken das Du es den Helfern so bequem machen solltest wie möglich da das ggf. die Antwortschance erhöht.
Gruß
Stephan
Re: Listener will nicht so wie ich
Aloha
Der Listener bietet seine Funktionalität so oder so, ob nun einer oder mehrere - es kommt nur darauf an, dass der betroffene Zellbereich überhaupt weiss, dass er einen Listener benachrichtigen soll und welchen.
Als globale Variablen musst Du also die Referenz auf den Listener sowie auf die mit einem Listener versehenen Zellbereiche haben.
Was Du benötigen würdest, wäre ein "ReDim Preserve", welches bewirkt, dass die alten Inhalte / Referenzen des Arrays erhalten bleiben.

Dort sieht man, dass das Interface die Methode "modified" zur Verfügung stellt.
Zusätzlich erbt das XModifyListener-Interface noch (wie alle Listener) vom com.sun.star.lang.XEventListener die Methode "disposing".
Für einen Einsteiger sicher nicht wirklich überschaubar, aber für die Zukunft möglicherweise ja irgendwann gut, das mal gehört zu haben.
Fazit: Dein Listener muss also die Methoden "disposing" und "modified" bereithalten.
Damit haben wir eigentlich alles, was Du benötigst:
-Du musst dem Listener die Methoden "disposing" und "modified" zur Verfügung stellen
-Du musst die Referenz auf den Listener global hinterlegen
-Du musst die Zellbereiche global hinterlegen, vornehmlich in einem Array
Schau mal, ob Du mit dem Beispielcode hier was anfangen kannst:
Bei Fragen dazu einfach nochmal melden.
Dafür muss man den Listener nicht unbedingt beenden, das lässt sich auch mit einer Hilfsvariable umsetzen.Jason hat geschrieben:Da mein Code aber selbst auch etwas in eine überwachte Zelle schreiben soll, ist es unerlässlich den ModifyListener davor zu beenden, weil er sich sonst selbst wieder aufruft.
Es reicht ein einziger Listener, der auf mehrere Zellbereiche angesetzt wird.Jason hat geschrieben:Da mein Makro universell einsetzbar sein soll, weis ich vorher nicht, für wie viele Tabellen ich einen XModifyListener öffnen muss.
Der Listener bietet seine Funktionalität so oder so, ob nun einer oder mehrere - es kommt nur darauf an, dass der betroffene Zellbereich überhaupt weiss, dass er einen Listener benachrichtigen soll und welchen.
Als globale Variablen musst Du also die Referenz auf den Listener sowie auf die mit einem Listener versehenen Zellbereiche haben.
Ein Redim erzeugt ein neues leeres Array mit der neuen Dimension.Jason hat geschrieben:aber wie definiert man ein unbestimmtes Array? Wenn ich ein bestimmtes globales Array versuche mit redim zu ergänzen, so scheinen alle neuen Einträge des Arrays nicht als Global zu gelten und werden dem entsprechend nicht gespeichert.
Was Du benötigen würdest, wäre ein "ReDim Preserve", welches bewirkt, dass die alten Inhalte / Referenzen des Arrays erhalten bleiben.
Eine Google-Suche mit dem Suchbegriff "com.sun.star.util.XModifyListener" spuckt direkt als erstes einen Verweis auf die API aus, in der die Methoden (in diesem Fall nur die Methode) zu finden istJason hat geschrieben:und ich hab wirklich eine Stunde gesucht -, welche Funktionen, bzw. Events der "com.sun.star.util.XModifyListener"

Dort sieht man, dass das Interface die Methode "modified" zur Verfügung stellt.
Zusätzlich erbt das XModifyListener-Interface noch (wie alle Listener) vom com.sun.star.lang.XEventListener die Methode "disposing".
Für einen Einsteiger sicher nicht wirklich überschaubar, aber für die Zukunft möglicherweise ja irgendwann gut, das mal gehört zu haben.
Fazit: Dein Listener muss also die Methoden "disposing" und "modified" bereithalten.
Damit haben wir eigentlich alles, was Du benötigst:
-Du musst dem Listener die Methoden "disposing" und "modified" zur Verfügung stellen
-Du musst die Referenz auf den Listener global hinterlegen
-Du musst die Zellbereiche global hinterlegen, vornehmlich in einem Array
Schau mal, ob Du mit dem Beispielcode hier was anfangen kannst:
Code: Alles auswählen
Global myModLis as Object REM Der Listener
Global myCellArray(0) as Object REM Globales Array für die betroffenen Zellbereiche
Global bManuallyCalled as Boolean REM Hilfsvariable, damit man den Listener nicht durch seine eigenen Änderungen aufruft
Global bListenerAlreadyAdded as Boolean REM Um zu verhindern, dass der Listener möglicherweise mehrmals gestartet wird
Private Const sCellRange as String = "A1:A10" REM Zellbereich, der überwacht werden soll
Private Const sLookupTable as String = "Lookup" REM Tabelle, in der nach möglichen Vorschlägen gesucht werden soll
Private Const nSearchColumn as Integer = 3 REM In welcher Spalte soll in der Tabelle nach dem Begriff gesucht werden
Private Const nStartRow as Integer = 8 REM Ab wecher Zeile gibt es Ergebnisse?
Private Const nEndRow as Integer = 41 REM Bis zu welcher Zeile?
Sub AddMyListener
bManuallyCalled = False
If bListenerAlreadyAdded Then Exit Sub
oDoc = thisComponent
nSheetCount = oDoc.Sheets.Count-1
ReDim myCellArray(nSheetCount) as Object
myModLis = CreateUnoListener( "MyListener_", "com.sun.star.util.XModifyListener" )
For x = 0 To nSheetCount
oSheet = oDoc.Sheets(x)
myCellArray(x) = oSheet.getCellRangeByName(sCellRange)
myCellArray(x).addModifyListener(myModLis)
Next x
bListenerAlreadyAdded = True
MsgBox "ModifyListener gestartet für Bereich " & sCellRange & " in allen Tabellen"
End Sub
Sub AutoComplete(Cell as Object)
If NOT Cell.supportsService("com.sun.star.sheet.SheetCell") Then Exit Sub REM Mehrere Zellen markiert
oSheet = thisComponent.Sheets.getByName(sLookupTable)
oSD = oSheet.createSearchDescriptor
sSearch = Cell.String
With oSD
.SearchString = "^" & sSearch
.SearchRegularExpression = True
End With
oSearchArea = oSheet.getCellRangeByPosition(nSearchColumn,nStartRow,nSearchColumn,nEndRow)
oResult = oSearchArea.findAll(oSD)
If isNull(oResult) Then REM Kein Ergebnis
MsgBox("Der Zauber konnte nicht gefunden werden. Eine Eigenkreation?")
Exit Sub
End If
If oResult.Count > 1 Then REM Mehrere Ergebnisse, nicht unbedingt zusammenhängend
MsgBox("Sorry, aber das reicht nicht. Der Zaubername muss genauer angegeben werd.")
Exit Sub
End If
nRow = oResult.RangeAddresses(0).StartRow
If nRow <> oResult.RangeAddresses(0).EndRow Then REM Mehrere Ergebnisse, die direkt aufeinanderfolgen in der Lookup-Tabelle
MsgBox("Sorry, aber das reicht nicht. Der Zaubername muss genauer angegeben werd.")
Exit Sub
End If
nCol = oResult.RangeAddresses(0).StartColumn
sNewString = oSheet.getCellByPosition(nCol,nRow).String
If MsgBox("Zauber" & Chr(13) & sNewString & Chr(13) & "gefunden, soll der Rest ergänzt werden?", 3, "Jason's Frage:") = 6 Then
bManuallyCalled = True
Cell.String = sNewString
End If
End Sub
Sub MyListener_disposing(oEvent)
End Sub
Sub MyListener_modified(oEvent)
If bManuallyCalled Then
bManuallyCalled = False
Exit Sub
End If
AutoComplete(thisComponent.CurrentSelection(0))
End Sub
Sub RemoveMyListener
If isNull(myModLis) Then Exit Sub
oDoc = thisComponent
nSheetCount = oDoc.Sheets.Count-1
For x = 0 To nSheetCount
myCellArray(x).removeModifyListener(myModLis)
Next x
bListenerAlreadyAdded = False
MsgBox "ModifyListener aus allen Tabellen entfernt"
End Sub
Re: Listener will nicht so wie ich
Aloha
Ob der Unterschied sich in Deinem Fall auch so deutlich bemerkbar macht, kannst natürlich nur Du beurteilen.
Du musst übrigens keine regulären Ausdrücke verwenden - der SearchDescriptor bietet viele Möglichkeiten an (siehe API: Service SearchDescriptor).
Im Endeffekt kannst Du den SearchDescriptor haargenau so einsetzen wie die normale Suchfunktion der OOo-GUI.
"Step" gibt die Schrittweite an, um die nach jedem Schleifendurchlauf hochgezählt werden soll - gibt man dort nichts an, wird automatisch "Step 1" verwendet.
Das Ergänzen von "Next" um die Laufvariable dient nur der Leserlichkeit, bei mehreren verschachtelten Schleifen dann auch der Übersichtlichkeit.
Der Modified-Event wird ausgelöst, aber die aktuelle Selektion gibt nur den markierten Bereich her, nicht, in welcher Zelle genau die Änderung stattgefunden hat.
Bei der Frage kann ich Dir ehrlich gesagt nicht ganz folgen.Jason hat geschrieben:Eine Frage hab ich dahingehend noch: Wann kann ein Zellbereich noch nicht kopiert werden, außer wenn schon Inhalt in den Zellen ist und Zellen zusammengefügt sind? (...)
Ja, da gibt es gewaltige Unterschiede - logischerweise je mehr Datensätze es sind, desto größer der Unterschied. Das einzelne Ansprechen jeder Zelle ist bei OOo-Basic elendig langsam.Um die Eingabe des Anwenders in die Zelle mit den Daten aus meinem "Datenbereich" abzugleichen hast du einen regulären Ausdruck verwendet.(...)Gibt es bei größeren Datenmengen (ein paar hundert Datensätzen) gegenüber deiner Variante starke Performance-Unterschiede?
Ob der Unterschied sich in Deinem Fall auch so deutlich bemerkbar macht, kannst natürlich nur Du beurteilen.
Du musst übrigens keine regulären Ausdrücke verwenden - der SearchDescriptor bietet viele Möglichkeiten an (siehe API: Service SearchDescriptor).
Im Endeffekt kannst Du den SearchDescriptor haargenau so einsetzen wie die normale Suchfunktion der OOo-GUI.
Nein, da gibt es keinen Unterschied.Und zu meinem Code auch gleich noch: Gibt es einen Unterschied zwischen diesen vier Varianten(...)
"Step" gibt die Schrittweite an, um die nach jedem Schleifendurchlauf hochgezählt werden soll - gibt man dort nichts an, wird automatisch "Step 1" verwendet.
Das Ergänzen von "Next" um die Laufvariable dient nur der Leserlichkeit, bei mehreren verschachtelten Schleifen dann auch der Übersichtlichkeit.
Nun, highlighte mal mehrere Zellen (per gedrückter Maustaste) und tippe dann etwas ein, ohne vorher die Markierung aufzuheben.Letzte Frage: Gleich am Anfang deiner Funktion Autocomplete verwendest du(...)
Ist das notwendig? Sollte die Funktion nicht nur ausgeführt werden, wenn eine Zelle inhaltlich verändert wurde und somit als einzige markiert ist?
Der Modified-Event wird ausgelöst, aber die aktuelle Selektion gibt nur den markierten Bereich her, nicht, in welcher Zelle genau die Änderung stattgefunden hat.
Re: Listener will nicht so wie ich
Aloha
Aber prinzipiell kannst Du dafür doch einfach wieder die Hilfsvariable benutzen - wenn Du am Ende jeder Prozedur, die *potenziell* den Modified-Event auslösen könnte, bManuallyCalled präventiv wieder auf False stellst, ist es egal, ob nun tatsächlich etwas geschehen ist oder nicht.
Auf diese Weise kannst Du im Übrigen auch auf einen Integer als Hilfsvariable verzichten, wenn Du noch den Listener-Event so anpasst
Bei der Arbeit mit eigenen Listenern solltest Du um jeden Preis versuchen, jeden möglichen Fehler abzufangen, da es sonst z.B. vorkommen kann, dass die Listener ihre Referenzierung verlieren und sich somit nicht mehr deaktivieren lassen, weil sie zwar noch existieren, aber nicht mehr angesprochen werden können.
Ich persönlich habe rangecopy noch nie benutzt, daher kann ich Dir bei der Frage im Detail leider nicht weiterhelfen.Jason hat geschrieben:Meine erste Frage bezog sich darauf, dass rangecopy meinen Zellenbereich A nicht in den Zellenbereich B kopiert, wenn in B zwei oder mehrere Zellen miteinander verbunden sind (wohl gemerkt sind die Zellen genauso verbunden, wie sie das auch in A sind). Wann kopiert "rangecopy" den Zellenbereich A ebenfalls nicht über den Zellenbereich B?
Aber prinzipiell kannst Du dafür doch einfach wieder die Hilfsvariable benutzen - wenn Du am Ende jeder Prozedur, die *potenziell* den Modified-Event auslösen könnte, bManuallyCalled präventiv wieder auf False stellst, ist es egal, ob nun tatsächlich etwas geschehen ist oder nicht.
Code: Alles auswählen
Sub CopyMyRange
bManuallyCalled = True
.......(Kopier die Range oder was auch immer)
bManuallyCalled = False
End Sub
Code: Alles auswählen
If bManuallyCalled Then
REM ***Das brauchts dann nicht mehr*** bManuallyCalled = False
Exit Sub
End If
Bei mir (OOo 3.11) hat das beschriebene Vorgehen immer zu einem Fehler geführt, weil "sSearch = Cell.String" dann logischerweise nicht mehr funktionieren kann.Das kann ich durchaus machen, aber dann passiert einfach garnichts... ich überlege mir, ob ich motiviert genug bin deine Abfrage der Selektion wieder aufzunehmen, um etwaigen Fehlern aus dem Weg zu gehen
Bei der Arbeit mit eigenen Listenern solltest Du um jeden Preis versuchen, jeden möglichen Fehler abzufangen, da es sonst z.B. vorkommen kann, dass die Listener ihre Referenzierung verlieren und sich somit nicht mehr deaktivieren lassen, weil sie zwar noch existieren, aber nicht mehr angesprochen werden können.