Wir sind auf Ihre Unterstützung angewiesen!
💚 BITTE helfen Sie uns HEUTE mit einer SPENDE 💚
Helfen Sie das LibreOffice Forum zu erhalten!

❤️ DANKE >><< DANKE ❤️

> KEINE WERBUNG FÜR REGISTRIERTE BENUTZER!<
Ihre Spende wird für die Deckung der laufenden Kosten sowie den Erhalt und Ausbau 🌱 des LibreOffice Forums verwendet.
🤗 Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet. 🤗

Via Macro erstellten Button via Macro löschen

Alles zur Programmierung im LibreOffice.
Antworten
gneiss
Beiträge: 5
Registriert: Mi 24. Aug 2022, 22:47

Via Macro erstellten Button via Macro löschen

Beitrag von gneiss » Mi 24. Aug 2022, 22:49

Wie im Betreff angedeutet erzeuge ich via Macro einen oder mehrere Buttons in einem SpreadSheet.
Wenn der User darauf klickt, soll ein bestimmter "Update" im Sheet ausgeführt werden und der Button anschließend wieder "verschwinden"
Der Button ist an die Sub 'BtnFunc' gebunden.
Die Zeile "form.removeByName( model.Name )" löscht aber offenbar nur den Event (danach reagiert der Button nicht mehr auf klick's.
Die "Darstellung" verbleibt im Sheet...
Daher gehe ich davon aus das ich irgendwie auch die beiden anderen Objekte (btn & shap) löschen muss.
Nur habe ich bisher dazu nichts gefunden.
Wo (in welchem Container) sind die ?

Ich habe den Objekten extra eindeutige Namen gegeben (cell.AbsoluteName & "_BTN" & shape.Name = cell.AbsoluteName & "_SHAPE").
Als model.Name zeigt mit Xray "..._BTN" an, ".._SHAE" finde ich jedoch nicht.
Wie komme ich an die ?

Code: Alles auswählen

Public Sub PlaceBtnOnCell( action As String, form As Object, cell As Object, btnTxt As String, Optional backColor As Long, Optional tag As String )  
  Dim btn As Object: btn = ThisComponent.createInstance( "com.sun.star.form.component.CommandButton" )
  Dim shape As Object: shape = ThisComponent.createInstance( "com.sun.star.drawing.ControlShape" )
  Dim script As Object: script = new com.sun.star.script.ScriptEventDescriptor
  
  Dim sheet As Object: sheet = cell.Spreadsheet

  btn.Name = cell.AbsoluteName & "_BTN"
  btn.Label = btnTxt
  btn.FocusOnClick = False
  If IsMissing( tag ) Then tag = cell.AbsoluteName & "_TAG"
  btn.Tag = tag

  shape.Name = cell.AbsoluteName & "_SHAPE"
  shape.Control = btn
  sheet.Drawpage.add( shape )
  shape.Anchor = cell
  shape.Size = GetSizeOfCellRange( cell )
  shape.Position = cell.Position
  shape.SizeProtect = True
  shape.MoveProtect = True
  If IsMissing( backColor ) Then backColor = cell.CellBackColor
  shape.ControlBackground = backColor
  shape.CharColor = cell.CharColor
  shape.CharFontName = cell.CharFontName
  shape.CharHeight = cell.CharHeight
  shape.CharWeight = cell.CharWeight

  script.ListenerType	= "com.sun.star.awt.XActionListener"
  script.EventMethod	= "actionPerformed"
  script.ScriptType		= "StarBasic"
  script.ScriptCode		= action
  
  form.registerScriptEvent( form.count - 1, script )
End Sub

Code: Alles auswählen

Sub BtnFunc( event As Variant )
  RemoveButton( event.Source.Model )
End Sub

Sub RemoveButton( model As Object )
  'Xray model

  Dim form As Object: form = model.Parent
  ' removes: form.registerScriptEvent( form.count - 1, script )
  'Done in PlaceBtnOnCell
  'form.removeByName( model.Name )	

  ' How to:
  ' get/remove shape ?
  ' get/remove btn ?
End Sub

gogo
Beiträge: 1072
Registriert: Sa 5. Feb 2011, 19:07

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gogo » Do 25. Aug 2022, 08:25

evtl. über die Drawpage:

Code: Alles auswählen

...
oEvent.Source.Model.Parent.Parent.Parent.Drawpage.remove( xShape as object )
...
... besser wahrscheinlich von ThisComponent aus...
g
2008 LucidL./MaverickM./WinXP LibreOffice 3.3.2 > 02/13 LinuxMint13/Xubuntu > 09/13 Debian Wheezy+LO3.5.4.2 > 01/15 Debian Jessie KDE+LO4.3.3.2/Mint17 openbox auf USB+LO4.2.8.2 > 03/16 ArchLin & LO5.1+ff > 02/18 Kubuntu

gneiss
Beiträge: 5
Registriert: Mi 24. Aug 2022, 22:47

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gneiss » Do 25. Aug 2022, 12:22

evtl. über die Drawpage:
Genau das mache ich doch schon (denke ich).

Code: Alles auswählen

RemoveButton( model As Object )
...
form.removeByName( model.Name )
Nur das in meinem Fall "form" einer Form innerhalb der DrawPage entspricht.
Drawpage.remove( xShape as object )
würde (nach meinem Verständnis) doch eine Form löschen.
Außerdem weiß ich nicht wie ich an "xshape" kommen soll.
Xray zeigt mir keinerlei Property/Method an welche mir die Shapes einer Drawpage (oder innerhalb der dort enthaltenen Forms) zurückgibt.

gneiss
Beiträge: 5
Registriert: Mi 24. Aug 2022, 22:47

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gneiss » Do 25. Aug 2022, 17:24

OK, ich habe jetzt ein Beispiel gefunden das das so macht. Das man dazu aber wieder "alles" durchsuchen muss um das "xShape" zu finden finde ich sehr umständlich. Ich hätte gedacht das ich (ausgehen von btn) das zugehörige shape ermitteln kann...
OOO ist leider teilweise recht kompliziert :-(

Hier der Link der mir weiter geholfen hat: https://ask.libreoffice.org/t/manipulat ... et/55072/2

gogo
Beiträge: 1072
Registriert: Sa 5. Feb 2011, 19:07

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gogo » Do 25. Aug 2022, 18:34

Ich dachte, da wärst Du klüger als ich ;) - ich hab's nämlich auch nicht gefunden, aber da Du das shape in die Drawpage gesetzt hast und ich das mit der "Public Sub PlaceBtnOnCell" alleine nicht nachstellen kann, hätte es sein können, dass Du da erfolgreicher bist.

Buttons werden, soweit ich weiß, immer innerhalb eines Form-Objektes gesetzt. Wenn Du den _Formular_-Navigator (Icon auf der Symbolleiste "Formular-Entwurf") ansiehst, siehst Du: Formulare/Formular/Schaltflächexyz

Wenn du den normalen Navigator (F5) ansiehst, siehst Du in Calc unter Zeichnungsobjekte nichts, in einem Writer-Dokument steht da "Form1" ... da dürfte LO nicht ganz konsistent laufen.

Evtl. kannst Du auch den Hammer .dispose() auf das Form-Objekt anwenden, der sollte auch zugehörige Listener killen.

Code: Alles auswählen

sub delbut(oEvent)
oEvent.source.model.parent.parent.parent.Drawpages.getbyindex(0).forms.getbyindex(0).dispose()
end sub
Aber Hämmer soll man immer mit Vorsicht benutzen!

edit ... war schon erledigt ...
g
2008 LucidL./MaverickM./WinXP LibreOffice 3.3.2 > 02/13 LinuxMint13/Xubuntu > 09/13 Debian Wheezy+LO3.5.4.2 > 01/15 Debian Jessie KDE+LO4.3.3.2/Mint17 openbox auf USB+LO4.2.8.2 > 03/16 ArchLin & LO5.1+ff > 02/18 Kubuntu

gogo
Beiträge: 1072
Registriert: Sa 5. Feb 2011, 19:07

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gogo » Do 25. Aug 2022, 22:11

Da der Button nur zur Laufzeit existiert, kannst Du das Shape als Global deklarieren. Dann kannst Du nachher wieder drauf zugreifen

Code: Alles auswählen

...
Global GL_shape As Object: GL_shape = ThisComponent.createInstance( "com.sun.star.drawing.ControlShape" )
...
g
2008 LucidL./MaverickM./WinXP LibreOffice 3.3.2 > 02/13 LinuxMint13/Xubuntu > 09/13 Debian Wheezy+LO3.5.4.2 > 01/15 Debian Jessie KDE+LO4.3.3.2/Mint17 openbox auf USB+LO4.2.8.2 > 03/16 ArchLin & LO5.1+ff > 02/18 Kubuntu

gneiss
Beiträge: 5
Registriert: Mi 24. Aug 2022, 22:47

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gneiss » Fr 26. Aug 2022, 12:46

Hallo gogo,

> Buttons werden immer...
So sieht das (in der GUI) auch in Calc aus.
Wenn man (via Symbolleiste Form-Design) in den "Design-Mode" wechselt und "Form-Navigator" anwählt, sieht man "Forms/Formulare", dort sind dann die erzeugten Formulare mit Namen aufgeführt und darunter die erzeugten "Controls".

Deshalb hatte ich ja auch angenommen das das so funktioniert...

Wie ich jetzt aber erfahren habe ist das shape (ControlShape) jedoch direkt unter der DrawPage angeordnet.

> Da der Button nur zur Laufzeit existiert...
Da bin ich mir jetzt nicht sicher (muss ich mal testen).
Bei mir läuft ja zunächst ein Makro welches die Button erzeugt.
Der Event (Button clicked) wird ja erst nach Ablauf des 1. Makros ausgelöst. Das kann ja auch erst nach neuladen des Dokumentes geschehen, dann ist die Variable definitiv nicht mehr gesetzt.

Ich bin parallel auch in englisch sprachigen Foren unterwegs, mal sehen was dabei rauskommt...

gogo
Beiträge: 1072
Registriert: Sa 5. Feb 2011, 19:07

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gogo » Sa 27. Aug 2022, 09:46

Poste doch bitte die crossref-links!

ad Globale Objekte:
So lange Du den LO-Prozess laufen hast (soffice.bin ...), ist eine Variable, die unter "Meine Makros"/Standard/Modulxyz als

Code: Alles auswählen

REM  *****  BASIC  *****
Global GlobalXYZ
...
definiert ist persistent. D.h. egal was Du machst, Du kannst immer auf sie zugreifen. Ein Objekt wird zwar in der globalen Variable persistent gespeichert, und man kann es noch z.B. mit XRay abfragen, aber beim Schließen des Dokuments werden die dem Objekt zugehörigen Objekte (Parent ...) geschlossen und beim Reopen des Dokumentes ist das Objekt in der Globalen Variable nicht mehr ident. (d.h. nach dem Reopen funktioniert das Löschen über die globalen Variablen NICHT mehr)

Ein Objekt in einer Liste, die .getbyname() nicht unterstützt zu suchen, geht in der Regel mit .createEnumeration():

Code: Alles auswählen

...
oEnum = myDrawpage.createEnumeration()

Do While oEnum.hasMoreElements()
	actual_Object= oEnum.nextElement()
	if actual_Object.supportsService("com.sun.star.drawing.ControlShape")
		' Shape found!!!
		xray(actual_Object)
	end if
Loop
...
Wenn Du beim Erstellen des Buttons das zugehörige Shape mit einem eindeutigen Namen versiehst, kannst Du nach dem Reopen des Dokuments mit .createEnumeration() nach allen Shapes suchen, die Du löschen willst, und "Drawpage.remove( Shape)" entfernt die Buttons dann.
Schau Dir die angehängten Dateien an. In Set_Globals.odt wird die Drawpage und das erste Shape in 2 globalen Variablen gespeichert, vom 2. Dokument aus (Show_Globals.ods) kannst Du Dir die Variablen ansehen, auch wenn das erste Dokument wieder geschlossen wurde, und so lange das erste Dok offen ist kannst du vom 2. Dok aus den Button entfernen...
Nicht vergessen, die Variablen unter "Meine Makros"/Standard/Modul1 definieren!

Code: Alles auswählen

REM  *****  BASIC  *****
Global Global_Drawpage
Global Global_Shape
...
Dateianhänge
GlobaleObjekte.zip
(18.33 KiB) 65-mal heruntergeladen
g
2008 LucidL./MaverickM./WinXP LibreOffice 3.3.2 > 02/13 LinuxMint13/Xubuntu > 09/13 Debian Wheezy+LO3.5.4.2 > 01/15 Debian Jessie KDE+LO4.3.3.2/Mint17 openbox auf USB+LO4.2.8.2 > 03/16 ArchLin & LO5.1+ff > 02/18 Kubuntu

F3K Total
Beiträge: 2416
Registriert: So 10. Apr 2011, 10:10

CROSSPOSTING:Via Macro erstellten Button via Macro löschen

Beitrag von F3K Total » So 28. Aug 2022, 08:48

Crossposting ohne Referenz ist unhöflich!
Windows 10: AOO, LO Linux Mint: AOO, LO

gneiss
Beiträge: 5
Registriert: Mi 24. Aug 2022, 22:47

Re: Via Macro erstellten Button via Macro löschen

Beitrag von gneiss » Mo 29. Aug 2022, 19:22

@F3K Total
> Crossposting...
Sorry,
Ich bin/war ich der Meinung das Crossposting nur innerhalb eines Forums gilt. Das ich auch woanders Anfrage ist IMHO normal. Wenn man hier eine Referenz will, OK; werde ich beim nächsten Mal drauf achten.
Dann muss ich hier aber auch noch einen Link zu einer Englischen Seite angeben:
https://ask.libreoffice.org/t/calc-dele ... acro/81066

@gogo
> Globale Objekte...
Klar, so kann man es machen, Allerdings befinden sich alle meine Makros "im Dokument". Ansonsten stehen die ja nur auf einem PC zur Verfügung, bzw. müssten immer "rüber kopiert" werden.
Deshalb ist das (für mich) keine wirkliche Lösung.

@All
Insgesamt funktioniert das ganze jetzt schon recht gut.
Ich habe nur noch ein offenes Problem.
Ich habe zwei Formulare im Sheet angelegt.
Eines das "fixe" Steuerelemente enthält und ein zweites das die "generierten" enthält.
So kann ich über einen Button (start) die Berechnung starten. Die erzeugt dann die Buttons die der User klickt nachdem er die berechneten Aktionen ausgeführt hat. Dann wird das Dokument "upgedatet" und der Button verschwindet.
Meine Idee war, das das "Start" Makro das 2. Form komplett löscht, dann dort die (neuen) Buttons einfügt..
Irgendwie hatte ich aber bisher immer ein Problem:
- Entweder wurde das ctrlModel (manchmal) im falschen Form angelegt (wenn ich nur drawPage.add genutzt habe)
- führe ich (vorher) form.insertByIndex aus wurde der Event wurde nicht (richtig) gesetzt.

Nach längeren Trial & Error hab ich jetzt eine Lösung gefunden:
Im Code sind die Problem-Fälle markiert.
Zum einen fügt "form.insertByIndex( idx, btnModel )" das btnModel leider nicht da ein wo man es angibt. (Bei mir halt 0)
Den Index braucht man aber für "form.registerScriptEvent( idx, script )"
Daher ermittle ich den Index jetzt über eine eigene Funktion. So klappt beides..

Code: Alles auswählen

Public Sub PlaceBtnOnCell( ByVal action As String, ByVal form As Object, ByVal cell As Object, ByVal btnTxt As String, Optional ByVal backColor As Variant, Optional ByVal tag As Variant )  
  Dim btnModel As Object:	btnModel	= ThisComponent.createInstance( "com.sun.star.form.component.CommandButton" )
  Dim ctrlShape As Object:	ctrlShape	= ThisComponent.createInstance( "com.sun.star.drawing.ControlShape" )
  Dim script As Object:		script		= new com.sun.star.script.ScriptEventDescriptor
  
  Dim drawPage As Object:	drawPage	= cell.Spreadsheet.Drawpage

  If IsMissing( tag ) Then tag = cell.AbsoluteName

  With btnModel
    .Name					= cell.AbsoluteName
    .Label					= btnTxt				' cell.Value
    .FocusOnClick			= False
    '....
  End With

  With ctrlShape
    .Name					= cell.AbsoluteName
    .Control				= btnModel
    .Anchor					= cell
    .Size					= GetSizeOfCellRange( cell )
    .Position				= cell.Position
    .SizeProtect			= True
    .MoveProtect			= True
    If Not IsMissing( backColor ) Then
      .ControlBackground		= backColor
    End If
    .CharColor				= cell.CharColor
    .CharFontName			= cell.CharFontName
    .CharHeight				= cell.CharHeight
    .CharWeight				= cell.CharWeight
    '...
  End With

  form.insertByIndex( 0, btnModel )	' It's not placed at Index 0 !! It's places at form.count - 1 ? So it act's like 'AddCtrlShapeToForm'
  drawPage.add( ctrlShape )
  Dim idx As Integer: idx = GetFormIndexOfModel( btnModel )
  
  With script
    .ListenerType			= "com.sun.star.awt.XActionListener"
    .EventMethod			= "actionPerformed"
    .ScriptType				= "StarBasic"
    '.ScriptCode				= action
    .ScriptCode				= action
  End With
  
  form.registerScriptEvent( idx, script )
End Sub

Public Function GetFormIndexOfModel( model As Object ) As Integer
  GetFormIndexOfModel = -1
  On Local Error Goto Fail
  Dim form As Object: form = model.Parent	' form is the container for the model
  Dim idx As Integer
  For idx = 0 To form.Count - 1
    If EqualUnoObjects( model, form( idx ) ) Then Exit For
  Next idx
  GetFormIndexOfModel = idx
 Fail:
End Function

An alle, die das LibreOffice-Forum nutzen:


Bitte beteiligen Sie sich mit 7 Euro pro Monat und helfen uns bei unserem Budget für das Jahr 2024.
Einfach per Kreditkarte oder PayPal.
Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet.

❤️ Vielen lieben Dank für Ihre Unterstützung ❤️

Antworten