Chiamare Macro contenute in altre cartelle xls - pagina vista: volte

Una recente domanda è il motivo di questo articolo, e visto che la letteratura in merito all'argomento di questo articolo, non è chiara, o quantomeno lacunosa, presento un'altra soluzione e alcuni chiarimenti. Premetto che forse la soluzione migliore è contenuta nel mio articolo "Funzioni Utente-Aggiunta .XLA" sul sito padre, dove i concetti espressi sono validi anche per macro da rendere comuni, e senza che altre cartelle siano aperte.

Il problema era: quale sintassi usare per lanciare una macro da una cartella diversa da quella in cui la macro risiede?

Intanto perchè la cosa funzioni, è necessario che entrambe le cartelle siano aperte: quella dalla quale chiameremo la macro, e quella che contiene la macro da lanciare.

La sintassi suggerita sia dalla guida in linea, sia dalla letteratura esistente, ci dice che abbiamo bisogno di dichiarare:

  • il nome non della cartella dove risiede la macro, ma il nome (versioni 97 e successive) del progettovb, che purtoppo, di default è per tutte le cartelle "VBAProject"; se non si diversificassero i nomi dei due VBAProject aperti in contemporanea (uno per ogni cartella), si genererebbe un errore perchè Excel non potrebbe identificare il VBAProject contenente la macro da lanciare trovandone due uguali; ma questo e di facile superamento: basta rinominare il nome del VBAProject, per esempio "VBAProjectdue". Per modificare il nome di un progetto vbp scegliere dal menu Strumenti/Proprietà di VBAProject e nella finestra che segue, nel campo "Nome progetto", digitare il nuovo nome, indi tornare in ambiente Excel e salvare.

  • poi il nome del modulo standard nel quale è contenuta la macro.

  • infine il nome della macro.

La sintassi prevede l'uso di parentesi quadre, come in questo esempio:

  • [VBAProjectdue.vbp].[Modulo1].NomeMacro

La guida in linea riporta, cercando l'argomento "Chiamata di routine con lo stesso nome", riporta, a conferma di quanto sopra esposto, queste testuali parole ed un esempio:

  • "Se a due routine differenti incluse in due progetti diversi (il nostro caso) viene assegnato lo stesso nome (che non è il nostro caso, ma il concetto è lo stesso), quando si effettua una chiamata alla routine è necessario specificare un nome di progetto. Nell'esempio seguente è illustrata la routine che richiama la routine Main nel modulo MyModule del progetto MyProject.vbp".

    Sub Main()
    [MyProject.vbp].[MyModule].Main
    End Sub

Rimane però il fatto che questo tipo di istruzione non funziona, genera un errore; il perchè non lo so, ma una nota, riportata a seguire dopo la descrizione sopra, cita:

  • Nota   Il nome di un progetto varia a seconda dell'applicazione. Ad esempio, in Microsoft Access un progetto è un database (.mdb); in Microsoft Excel, un progetto è una cartella di lavoro (.xls).

Questa precisazione fa sorgere quindi un dubbio: ma allora, devo usare il nome del progetto, o il nome della cartella di lavoro?

La risposta la troviamo in queste due soluzioni, che entrambe sfruttano il nome della cartella di lavoro. La sintassi cambia di molto rispetto a quelle viste sopra, e prevede: nomecartella ! nome macro, posti tra parentesi tonde e tra doppi apici, così:

  • ("NomeAltraCartella.xls!NomeMacro")

Potremo sfruttare due metodi per lanciare l'istruzione: il metodo Run o il metodo OnAction (cambia leggermente la sintassi):

esempio di istruzione inserita nell'evento Click di un CommandButton (ActiveX):

  • Private Sub CommandButton1_Click()
    Application.Run ("NomeAltraCartella.xls!NomeMacro")
    End Sub

esempio di istruzione inserita come macro in un modulo standard, ed attivata da un pulsante ottenuto dalla Forma "Rettangolo" presa da "Disegno":

  • ActiveSheet.Shapes("Rectangle 1").OnAction = "NomeAltraCartella.xls!Pippo"   'senza parentesi tonde

esempio di istruzione inserita in un evento di un foglio di lavoro, l'evento Change di un Worksheet; simula il lancio della macro esterna se il valore di una carta cella (la F9 ad esempio) conterrà un certo valore (15) :

  • Private Sub Worksheet_Change(ByVal Target As Range)
    If [F9].Value = 15 Then
    Application.Run ("NomeAltraCartella!Pippo")
    End If
    End Sub

Evidentemente, seguendo la sintassi suggerita nella guida, mancherò (o mancheremo) in qualche cosa, visto che non otteniamo il risultato sperato, ma i dilettanti come me troveranno in queste soluzioni una valida alternativa funzionante.

 

Buon lavoro.

prelevato sul sito www.ennius.altervista.org