Pannello di Controllo Moderatore ]

Emulare CallByName del Vba con esempio Applicativo

Emulare CallByName del Vba con esempio Applicativo

Messaggioda unlucky83 » sabato 12 ottobre 2019, 17:39

In Vba esiste una funzione chiamata CallByName che consente di richiamare una subroutine o una function dandogli come parametro una stringa che corrisponde al nome della macro.
Il Vb di Aoo e Lo non implementano questa funzione. Sul forum francese ho trovato le macro che emulano CallByName del vba (vedi qui). Ho preso quelle macro e le ho modificate per ciò che mi interessava.

Il Disagio: Quando sviluppo un file calc con molte macro complesse e vari pulsanti di lancio, durante la fase dello sviluppo riorganizzo spesso le varie macro suddividendole nei moduli e non contento rinomino spesso le macro e i moduli :knock:.
Dopo aver fatto queste modifiche una buona parte dei pulsanti non trova più (giustamente) la macro da lanciare dato che gli ho biato il percorso. A questo punto o modifico gli eventi dei pulsanti oppure devo ripristinare i vecchi nomi e le posizioni delle macro in questione. :shock:
Obiettivo: Voglio rendere l'associazione Pulsante/macro più flessibile, ovvero mi piacerebbe poter cambiare/rinominare il modulo in cui è inserita la macro ogni qual volta mi va senza dover essere poi costretto a cambiare l'evento del pulsante. Inoltre, se volessi rinominare la macro, vorrei evitare di modificare gli eventi del pulsante (si aprono varie finestre di dialogo e bisogna selezionare la macro dopo aver selezionato prima il modulo, dopo aver selezionato prima la libreria)...vorrei intervenire facendo una modifica altrettanto efficace ma più rapida.
Soluzione trovata: Mi sto trovando bene nell'assegnare a tutti i pulsanti la stessa macro dal nome banale "Pulsanti", nel classico modulo "Module1". Quando sviluppo macro complesse, in cui anche il nome della sub mi aiuta a dare un ordine mentale, mantenere fissi i nomi "Pulsanti" e "Module1" non mi da alcun problema, detta in altri termini questi nomi sono perfetti così come sono e non mi viene in mente di cambiarli.
Codice: Seleziona tutto   Espandi visualeStringi visuale
Sub Pulsanti(oEv)
   SubOrFunc= oEv.source.model.label
   call CallByName(SubOrFunc,array())
End Sub

I vari pulsanti eseguiranno quindi tutti la sub "Pulsanti", ma grazie alla macro CallByName riesco ad ottenere comportamenti differenti semplicemente usando come label del pulsante il nome della macro che avrei associato direttamente. Potrei anche usare, invece del label, il name del pulsante.
Ora posso cambiare la posizione delle macro tra i moduli senza alcun problema, basta che non sposti la sub Pulsanti.
Se decido di rinominare le macro, devo solo impostare nel label il nuovo nome della macro.
Se devo inserire 100 pulsanti, una volta inserito il primo e impostata l'associazione con sub "Pulsanti", posso copiare il pulsante e incollarlo 99 volte. Successivamente mi basta solo cambiare i vari label e ecco che tutti i pulsanti sono sistemati.

Codice: Seleziona tutto   Espandi visualeStringi visuale
sub CallByName(sFonction as string ,aParams as variant)
    dim oDS as object       'objet dispatch helper utilisé pour le call de la sub
    dim sURL as string      'string qui contient l'URL de la fonction a appeler

    on error goto CallByName_error
       'initilisation objet dispatchhelper
       oDS = createUnoService("com.sun.star.frame.DispatchHelper")
       'initialisation de l'URL du script Basic a appeler : Standard,CallByName."+sFonction+"?language=Basic&location=document
       'le script est dans la bibliothèque Standard du document contenant les macro
       'le script a appeler est dans le module CallByName
       'le nom du script basic a appeller est dans la variable sFonction
       sURL = "vnd.sun.star.script:Standard."+getModule(sFonction)+"."+sFonction+"?language=Basic&location=document"
       'appel du script
       oDS.executeDispatch(ThisComponent.CurrentController.frame,sURL,"",0,aParams())
       exit sub
    CallByName_error:
      on error resume Next
       msgbox "erreur dans la procédure CallByName"
       on error goto 0
end sub

"CallByName" così impostato, cerca all'interno della libreria Standard del documento, il nome della macro tra i vari moduli sfruttando un'altra funzione chiamata "getModule"
Codice: Seleziona tutto   Espandi visualeStringi visuale
function getModule(sFunction as string) as string
    CONST LibraryName = "Standard"

    dim oLib as object      'objet libarie Standard
    dim aModules()         'tableau de tous les modules de la librairie Standard
    dim iC as Integer      'indice de boucle
    dim sModule   'le module à analyser (texte basic)

    on error goto getModule_error

       oLib = BasicLibraries.getByName( LibraryName )   'initialise l'objet librarie
       getModule = ""
       aModules = oLib.getElementNames()         'initialise le tableau qui contient tous les modules
       for iC = 0 to ubound(aModules)            'pour chacun des modules
          sModule = oLib.getByName(aModules(iC))   'charge le contenu texte du module dans la variable Smodule
           if instr(sModule,"Sub " & sFunction) > 0 Then
              getModule = aModules(iC)
              exit Function
           Elseif instr(sModule,"function " & sFunction) >0 Then
              getModule = aModules(iC)
              exit function
           end if
       next iC
       exit function
    getModule_error:
       on error resume next
       msgbox "erreur dans la procédure getModule"
       on error goto 0
end function

Delle macro trovate nel forum francese, ho modificato la funzione "getmodule" in cui ho scelto di usare la funzione "Instr" per stabilire se il modulo presenta o no la macro cercata.

Criticità All'interno dei vari moduli non devono essere presenti tra i commenti "sub nomemacro" o "function nomemacro" altrimenti viene individuato il modulo sbagliato. Inoltre tra sub e il nomemacro deve esserci uno e un solo spazio, stessa cosa se si tratta di una function

Conclusioni: Forse altri utenti troveranno utile queste macro per i miei stessi motivi o trovarle utili per risolvere un problema di compatibilità con il vba qualora fosse impiegata proprio la funzione CallByName o forse ci sarà qualcuno che le troverà semplicemente interessanti o di spunto per fare tutt'altro.
Di certo ci sarà chi sbadiglierà :lol:
Allegati
PulsantiSvincolatiDaModuli.ods
esempio applicativo
(11.63 KiB) Scaricato 8 volte
LibO5.1.6.2-Ubuntu 16.04.2 32-bit
-
Se risolvi:
1. Condividi la soluzione qui con noi
2. Metti [Risolto] al titolo del primo messaggio
Avatar utente
unlucky83
Volontario
Volontario
 
Messaggi: 2088
Iscritto il: lunedì 7 gennaio 2013, 1:23
Località: Latina

Re: Emulare CallByName del Vba con esempio Applicativo

Messaggioda charlie » sabato 12 ottobre 2019, 22:18

unlucky83 ha scritto:Di certo ci sarà chi sbadiglierà

........
Ma un asin bigio, rosicchiando un cardo
Rosso e turchino, non si scomodò:
Tutto quel chiasso ei non degnò d’un guardo
E a brucar serio e lento seguitò.

G. Carducci: Rime nuove/Libro V/Davanti San Guido

Cercheremo di non essere così.
Intanto complimenti!
charlie
macOS 10.12 Sierra: Open Office 4.1.7 - LibreOffice 6.2.8.2
http://www.charlieopenoffice.altervista.org
Avatar utente
charlie
Site Admin
Site Admin
 
Messaggi: 6160
Iscritto il: mercoledì 19 dicembre 2012, 10:50

Re: Emulare CallByName del Vba con esempio Applicativo

Messaggioda unlucky83 » sabato 12 ottobre 2019, 22:25

Hai letto fino alla fine il messaggio, complimenti a te @charlie
LibO5.1.6.2-Ubuntu 16.04.2 32-bit
-
Se risolvi:
1. Condividi la soluzione qui con noi
2. Metti [Risolto] al titolo del primo messaggio
Avatar utente
unlucky83
Volontario
Volontario
 
Messaggi: 2088
Iscritto il: lunedì 7 gennaio 2013, 1:23
Località: Latina


Torna a Macro

Chi c’è in linea

Visitano il forum: Nessuno e 0 ospiti