Buttons in mehreren Calc-Sheets generieren

Programmierung unter AOO/LO (StarBasic, Python, Java, ...)

Moderator: Moderatoren

Kalinka
*
Beiträge: 15
Registriert: Mi, 22.03.2006 11:05
Wohnort: Hamburg

Buttons in mehreren Calc-Sheets generieren

Beitrag von Kalinka »

Hallo,

ich schreibe gerade ein Programm, das mir meine DB abfragt und die Ergebnisse in eine Tabelle (auf mehreren Blättern) schreibt.
Um Detailinfo abrufen zu können, will ich vor jeder Datenzeile einen Button generieren, über den ich eine SQl-Abfrage generiere.
Da ich erst seit kurzem mit OO-Basic arbeite, geht mir das ganze noch nicht so flüssig von der Hand.
Also, ich habe Danny's Basic Library in meine Haupt-Library kopiert, da sie ungemein nützliche Funktionen enthält (u.a. zur Erzeugung von Buttons in Formularen).
Mein Test-Code sieht folgendermaßen aus:

Code: Alles auswählen

Sub Test
	oDoc = ThisComponent
	oDocCtrl = GetDocumentController( oDoc )
	oListener = CreateUnoListener( "btnPress_", "com.sun.star.awt.XActionListener" )
	for p = 0 to 2
		oSheet = oDoc.getSheets().getByIndex(p)
		oDocCtrl.setActiveSheet(oSheet)
		for i = 0 to 1
			sText = "Button " & i & " on Page " & p & " was pressed"
			sButton = "btn_" & p & "_" & Format(i,"00")
			oControlModel = FormCreateControl_Button( 900, 455 * i, 1200, 430, "Details", sButton, "MyForm_" & p , p, oDoc, sText )
			oControl = oDocCtrl.getControl( oControlModel )
			oControl.addActionListener( oListener )
		Next
	Next
End Sub

Sub btnPress_actionPerformed( tActionEvent As com.sun.star.awt.ActionEvent )
	Print tActionEvent.Source.Model.Tag
End Sub

Sub btnPress_disposing( tActionEvent As com.sun.star.awt.ActionEvent )
	Print "Disposing of the Listener " & tActionEvent.Source.Model.Tag
End Sub
Diese Routine erzeugt auf den 3 Standardtabellenblättern jeweils 2 Buttons, die alle denselben ActionEvent aufrufen. Ich habe Dannys FormCreateControl_Button() Routine um eine Eintragungsmöglichkeit für Zusatztext im jeweiligen Button ergänzt (sText), da man dort wunderbar z.B. SQL statements o.ä. ablegen könnte und dann nur einen Event-Handler für alle Button bräuchte.
Aber zurück zum Thema. Ich habe herausgefunden, daß oDocCtrl.getControl( oControlModel ) nur dann funktioniert, wenn ich vorher dem betreffenden sheet den Focus gebe, es also nach vorne hole. Ansonsten greift die getControl()-Routine ins Leere und gibt eine <com.sun.star.container.NoSuchElementExeption> aus. Sobald ich aber mittels setActiveSheet() einem anderen Sheet den Focus gebe, wird immer die disposing-Routine für alle Buttons der letzten Seite getriggert und die Buttons sind funktionslos. Ich habe leider keine Ahnung warum das passiert und wie ich das verhindern kann.
Wer kennt sich da aus ?

Danke, Rado
Kalinka
*
Beiträge: 15
Registriert: Mi, 22.03.2006 11:05
Wohnort: Hamburg

Beitrag von Kalinka »

Hallo,

jetzt habe ich es endlich hinbekommen :lol:
Als ich mich durch die SDK-Doku gewühlt habe, habe ich einige interessante Hinweise gefunden. Falls es jemanden interessiert, fasse ich es hier kurz zusammen:
Statt globale Event-Listener zu schreiben und diese an Controls zu hängen (was ressourcenhungrig ist), wird dort empfohlen, mittels der registerScriptEvent()-Methode des Formularobjektes Events zu erzeugen. Hier mein Beispielprogramm:

Code: Alles auswählen

REM *****  BASIC  *****
REM Programm zur Erzeugung von Buttons in einem Calc-Sheet (auch über mehrere Tabellen)
REM Damit es funktioniert, muß Danny's Basic Library (http://www.oooforum.org/forum/viewtopic.phtml?p=73054)
REM -> hier die Module DocDraw, UtilAPI & UtilForm
REM geladen sein.

Dim oDoc as Object
Dim oControlModel as Object
Dim sText as String
Dim sButton as String
Dim i as Integer, p as Integer

Sub doThis
	Test
End Sub

Sub Test
	toggleDesign	' Sheet in Design-Modus setzen, sehr wichtig, denn ansonsten funktionieren die Events nicht
	Dim oEvent as new com.sun.star.script.ScriptEventDescriptor
	oEvent.ListenerType = "com.sun.star.awt.XActionListener"	' hier können natürlich auch alle anderen X___Listener stehen
	oEvent.EventMethod = "actionPerformed"
	oEvent.ScriptType = "StarBasic"
	oEvent.ScriptCode = "document:Standard.Module1.btnPress"	' falls das Makro im aktuellen Dokument steht, document:, 
	' falls es unter Meine Makros & Dialog steht, application:, dahinter stehen der Libraryname, der Modulname, sowie der Funktionsname
	oDoc = ThisComponent
	for p = 0 to 2	' Anzahl der Sheets, die Buttons bekommen sollen
		for i = 0 to 5	' Anzahl der Buttons, die erzeugt werden sollen
			sButton = "btn_" & p & "_" & Format(i,"00")	' eindeutiger Name eines Buttons
			sText = "es wurde Button " & i & " auf Seite " & p  & " gedrückt."	
			' in sText könnten z.B. verschieden SQL-Befehle oder Variablenwerte abgelegt werden
			oControlModel = FormCreateControl_Button( 900, 900+(455 * i), 1200, 430, "Details", sButton, "MyForm_" & p , p, oDoc, sText )
			' Parameter: (in Twips) Abstand links, Abstand von oben, Breite des Buttons, Höhe des Buttons,
			' Beschriftung, Name, Name des Formulars, Sheet-Nr., oDoc, sText)
			oControlModel.Parent.registerScriptEvent( i, oEvent )
		Next
	Next
	toggleDesign	' Sheet wieder in den Live-Modus setzen
End Sub

Sub btnPress( tActionEvent As com.sun.star.awt.ActionEvent )
	Print tActionEvent.Source.Model.Tag
End Sub


Sub toggleDesign
	' toggle the document (view) to live/design mode
    Dim oURL as new com.sun.star.util.URL
	Dim oDispatcher as Object
	Dim oEmptyArgs() as new com.sun.star.beans.PropertyValue
	oDoc = ThisComponent
    oURL.Complete = ".uno:SwitchControlDesignMode"
    createUnoService( "com.sun.star.util.URLTransformer" ).parseStrict( oURL )
    oDispatcher = GetDocumentController( oDoc ).queryDispatch( oURL, "", 63 )
    oDispatcher.dispatch( oURL, oEmptyArgs() )
End Sub


REM modifizierte Version von Danny's FormCreateControl_Button (UtilForm)
REM übergebener Text kann im Zusatzinfofeld abgelegt werden
Function FormCreateControl_Button( _
            ByVal x As Long, ByVal y As Long,_
            ByVal width As Long, ByVal height As Long,_
            ByVal cControlCaption As String,_
            ByVal cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc, _
            Optional sTag As String ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   ' übergibt dem ButtonControl einen String. Praktisch, falls die gleich Event-Routine des Buttons von verschiedenen Buttons aufgerufen
   ' wird. Der Source.model.Tag des EventListener entsprechend dem Tag des Button-Controlmodels
   If IsMissing( sTag ) Then
      sTag = ""
   EndIf

   oControlShape = FormCreateControlShape( "com.sun.star.form.component.CommandButton",_
            cControlName, cFormName, nPage, oDoc )
   oControlModel = oControlShape.getControl()
   
   oControlShape.Position = MakePoint( x, y )
   oControlShape.Size = MakeSize( width, height )
   
   oControlModel.Label = cControlCaption
   oControlModel.Tag = sTag
   FormCreateControl_Button = oControlModel
End Function
Ich hoffe, es hilft irgendjemandem weiter,

Rado
Antworten