Pagina 1 di 1

Emulare CallByName del Vba con esempio Applicativo

MessaggioInviato: sabato 12 ottobre 2019, 17:39
da unlucky83
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:

Re: Emulare CallByName del Vba con esempio Applicativo

MessaggioInviato: sabato 12 ottobre 2019, 22:18
da charlie
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!

Re: Emulare CallByName del Vba con esempio Applicativo

MessaggioInviato: sabato 12 ottobre 2019, 22:25
da unlucky83
Hai letto fino alla fine il messaggio, complimenti a te @charlie