Comment déclarer une variable globale dans VBA?


132

J'ai écrit le code suivant:

Function find_results_idle()

    Public iRaw As Integer
    Public iColumn As Integer
    iRaw = 1
    iColumn = 1

Et je reçois le message d'erreur:

"attribut invalide dans le sous-système ou la fonction"

Savez-vous ce que j'ai fait de mal?

J'ai essayé d'utiliser à la Globalplace de Public, mais j'ai eu le même problème.

J'ai essayé de déclarer la fonction elle-même comme `Public, mais cela n'a pas non plus fait de bien.

Que dois-je faire pour créer la variable globale?

Réponses:


177

Vous devez déclarer les variables en dehors de la fonction:

Public iRaw As Integer
Public iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1

Lorsque j'essaie de déclarer un tableau comme public, cela dit: les types de données de tableau et définis par l'utilisateur ne peuvent pas être déclarés comme publics.
kapilddit

Au - dessus du premier Function/ Sub, pas seulement à l'extérieur: "Les variables au niveau du module peuvent être déclarées avec une instruction Dim ou Private en haut du module au-dessus de la première définition de procédure." (à partir de la portée des variables dans Visual Basic pour Applications )
Nickolay

119

C'est une question de portée .

Si vous souhaitez que les variables ne durent que la durée de vie de la fonction, utilisez Dim(abréviation de Dimension ) à l'intérieur de la fonction ou du sous pour déclarer les variables:

Function AddSomeNumbers() As Integer
    Dim intA As Integer
    Dim intB As Integer
    intA = 2
    intB = 3
    AddSomeNumbers = intA + intB
End Function
'intA and intB are no longer available since the function ended

Une variable globale (comme SLaks l'a souligné) est déclarée en dehors de la fonction à l'aide du Publicmot - clé. Cette variable sera disponible pendant la durée de vie de votre application en cours d'exécution. Dans le cas d'Excel, cela signifie que les variables seront disponibles tant que ce classeur Excel particulier est ouvert.

Public intA As Integer
Private intB As Integer

Function AddSomeNumbers() As Integer
    intA = 2
    intB = 3
    AddSomeNumbers = intA + intB
End Function
'intA and intB are still both available.  However, because intA is public,  '
'it can also be referenced from code in other modules. Because intB is private,'
'it will be hidden from other modules.

Vous pouvez également avoir des variables qui ne sont accessibles que dans un module (ou une classe) particulier en les déclarant avec le Privatemot - clé.

Si vous créez une grande application et ressentez le besoin d'utiliser des variables globales, je vous recommande de créer un module séparé uniquement pour vos variables globales. Cela devrait vous aider à les garder en un seul endroit.


4
+1 Toujours utile 7 ans plus tard. Mais y a-t-il une nuance supplémentaire concernant les variables d'objet par rapport aux variables de données? J'ai rencontré un problème lié à la portée des variables d'objet qui a suscité une nouvelle question. Très apprécié si vous aviez le temps de jeter un coup d'œil. stackoverflow.com/q/46058096/5457466
Egalth

2
Explication succincte de la déclaration des variables dans VBA.
PhillipOReilly

J'ai essayé toutes les autres suggestions sur la "portée" et aucune n'a fonctionné. La seule chose qui a fonctionné était un nouveau module spécifiquement pour les variables globales et cela fonctionne!
Fandango68 du


18

La question porte vraiment sur la portée, comme l’a dit l’autre gars.

En bref, considérez ce "module":

Public Var1 As variant     'Var1 can be used in all
                           'modules, class modules and userforms of 
                           'thisworkbook and will preserve any values
                           'assigned to it until either the workbook
                           'is closed or the project is reset.

Dim Var2 As Variant        'Var2 and Var3 can be used anywhere on the
Private Var3 As Variant    ''current module and will preserve any values
                           ''they're assigned until either the workbook
                           ''is closed or the project is reset.

Sub MySub()                'Var4 can only be used within the procedure MySub
    Dim Var4 as Variant    ''and will only store values until the procedure 
End Sub                    ''ends.

Sub MyOtherSub()           'You can even declare another Var4 within a
    Dim Var4 as Variant    ''different procedure without generating an
End Sub                    ''error (only possible confusion). 

Vous pouvez consulter cette référence MSDN pour en savoir plus sur la déclaration de variable et cette autre question de débordement de pile pour en savoir plus sur la façon dont les variables sortent de la portée.

Deux autres choses rapides:

  1. Soyez organisé lorsque vous utilisez des variables de niveau de classeur, afin que votre code ne soit pas déroutant. Préférez les fonctions (avec les types de données appropriés) ou en passant des arguments ByRef .
  2. Si vous souhaitez qu'une variable conserve sa valeur entre les appels, vous pouvez utiliser l' instruction Static .

Êtes-vous sûr qu'une variable globale peut être utilisée dans différents classeurs? Ça ne marche pas pour moi
Seb

Bon point! J'ai remarqué que je n'ai pas ajouté de référence pour savoir où j'ai obtenu cette information ... Je ne l'ai pas non plus retrouvée. Mieux vaut éditer la réponse ...: / Oh, et merci Seb.
FCastro

14

Si cette fonction est dans un module / classe, vous pouvez simplement les écrire en dehors de la fonction, donc c'est le cas Global Scope. Global Scope signifie que la variable est accessible par une autre fonction dans le même module / classe (si vous utilisez dimcomme déclaration de déclaration, utilisez publicsi vous voulez que les variables soient accessibles par toutes les fonctions de tous les modules):

Dim iRaw As Integer
Dim iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1
End Function

Function this_can_access_global()
    iRaw = 2
    iColumn = 2
End Function

1

Créez un entier public dans la déclaration générale.

Ensuite, dans votre fonction, vous pouvez augmenter sa valeur à chaque fois. Voir l'exemple (fonction pour enregistrer les pièces jointes d'un e-mail au format CSV).

Public Numerator As Integer

Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
Dim FileName As String

saveFolder = "c:\temp\"

     For Each objAtt In itm.Attachments
            FileName = objAtt.DisplayName & "_" & Numerator & "_" & Format(Now, "yyyy-mm-dd H-mm-ss") & ".CSV"
                      objAtt.SaveAsFile saveFolder & "\" & FileName
                      Numerator = Numerator + 1

          Set objAtt = Nothing
     Next
End Sub

0

Un bon moyen de créer des variables publiques / globales est de traiter le formulaire comme un objet de classe et de déclarer les propriétés et d'utiliser Public Property Get [variable] pour accéder à la propriété / méthode. Vous devrez peut-être également référencer ou transmettre une référence au module Formulaire instancié. Vous obtiendrez des erreurs si vous appelez des méthodes à des formulaires / états fermés.
Exemple: passez Me.Form.Module.Parent dans la sous / fonction pas dans le formulaire.

Option Compare Database 
Option Explicit
''***********************************''
' Name: Date: Created Date Author: Name 
' Current Version: 1.0
' Called by: 
''***********************************''
' Notes: Explain Who what when why... 
' This code Example requires properties to be filled in 
''***********************************''
' Global Variables
Public GlobalData As Variant
''***********************************''
' Private Variables
Private ObjectReference As Object
Private ExampleVariable As Variant
Private ExampleData As Variant
''***********************************''
' Public properties
Public Property Get ObjectVariable() As Object
   Set ObjectVariable = ObjectReference
End Property 
Public Property Get Variable1() As Variant 
  'Recommend using variants to avoid data errors
  Variable1 = ExampleVariable
End property
''***********************************''
' Public Functions that return values
Public Function DataReturn (Input As Variant) As Variant
   DataReturn = ExampleData + Input
End Function 
''***********************************''
' Public Sub Routines
Public Sub GlobalMethod() 
   'call local Functions/Subs outside of form
   Me.Form.Refresh
End Sub
''***********************************''
' Private Functions/Subs used not visible outside 
''***********************************''
End Code

Ainsi, dans l'autre module, vous pourrez accéder:

Public Sub Method1(objForm as Object)
   'read/write data value
   objForm.GlobalData
   'Get object reference (need to add Public Property Set to change reference object)
   objForm.ObjectVariable
   'read only (needs Public property Let to change value)
   objForm.Variable1
   'Gets result of function with input
   objForm.DataReturn([Input])
   'runs sub/function from outside of normal scope
   objForm.GlobalMethod
End Sub

Si vous utilisez la liaison tardive comme je le fais, vérifiez toujours les valeurs Null et les objets qui ne sont rien avant de tenter d'effectuer un traitement.


0

Vous pouvez également utiliser -

Private Const SrlNumber As Integer = 910

Private Sub Workbook_Open()
    If SrlNumber > 900 Then
        MsgBox "This serial number is valid"
    Else
        MsgBox "This serial number is not valid"
    End If
End Sub

Son testé sur Office 2010

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.