Como declaro uma variável global no VBA?

132

Eu escrevi o seguinte código:

Function find_results_idle()

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

E recebo a mensagem de erro:

"atributo inválido na sub ou função"

Você sabe o que eu fiz de errado?

Tentei usar em Globalvez de Public, mas tive o mesmo problema.

Tentei declarar a função em si como `Pública, mas isso também não adiantou.

O que preciso fazer para criar a variável global?

Nimrod
fonte

Respostas:

177

Você precisa declarar as variáveis ​​fora da função:

Public iRaw As Integer
Public iColumn As Integer

Function find_results_idle()
    iRaw = 1
    iColumn = 1
SLaks
fonte
Quando tento declarar uma matriz como pública, ele diz: a matriz e os tipos de dados definidos pelo usuário não podem ser declarados como públicos.
Kapilddit 13/11/19
Acima do primeiro Function/ Sub, e não apenas do lado de fora: "As variáveis ​​no nível do módulo podem ser declaradas com uma instrução Dim ou Private na parte superior do módulo acima da primeira definição de procedimento." (do escopo de variáveis ​​no Visual Basic for Applications )
Nickolay
119

Esta é uma pergunta sobre o escopo .

Se você deseja que apenas as variáveis ​​durem a vida útil da função, use Dim(abreviação de Dimension ) dentro da função ou sub para declarar as variáveis:

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

Uma variável global (como SLaks apontou) é declarada fora da função usando a Publicpalavra - chave Essa variável estará disponível durante a vida útil do seu aplicativo em execução. No caso do Excel, isso significa que as variáveis ​​estarão disponíveis enquanto a pasta de trabalho em particular do Excel estiver aberta.

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.

Você também pode ter variáveis ​​acessíveis apenas dentro de um módulo (ou classe) específico, declarando-as com a Privatepalavra - chave.

Se você estiver criando um grande aplicativo e sentir necessidade de usar variáveis ​​globais, recomendo a criação de um módulo separado apenas para suas variáveis ​​globais. Isso deve ajudá-lo a acompanhá-los em um só lugar.

Ben McCormack
fonte
4
+1 Ainda útil 7 anos depois. Mas há alguma nuance adicional em relação a variáveis ​​de objeto versus variáveis ​​de dados? Encontrei um problema relacionado a variáveis ​​de objeto de escopo que geravam uma nova pergunta. Muito apreciado se você tiver tempo para dar uma olhada. stackoverflow.com/q/46058096/5457466
Egalth 5/17
2
Explicação sucinta da declaração de variáveis ​​no VBA.
PhillipOReilly
Eu tentei todas as outras sugestões sobre "escopo" e nenhuma funcionou. A única coisa que funcionou foi um novo módulo especificamente para vars globais e funciona!
Fandango68
18

A questão é realmente sobre o escopo, como o outro cara colocou.

Em resumo, considere este "módulo":

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). 

Você pode verificar esta referência do MSDN para obter mais informações sobre declaração de variáveis ​​e esta outra questão de estouro de pilha para saber mais sobre como as variáveis ​​ficam fora do escopo.

Duas outras coisas rápidas:

  1. Seja organizado ao usar variáveis ​​no nível da pasta de trabalho, para que seu código não fique confuso. Preferir funções (com tipos de dados adequados) ou passar argumentos ByRef .
  2. Se você deseja que uma variável preserve seu valor entre as chamadas, use a instrução Static .
FCastro
fonte
Tem certeza de que uma variável global pode ser usada em diferentes pastas de trabalho? Não funciona para mim
Seb
Bom ponto! Percebi que não adicionei uma referência para obter essas informações ... Também não as encontrei novamente. Melhor editar a resposta ...: / Oh, e obrigado Seb.
FCastro
14

Se essa função estiver em um módulo / classe, você pode simplesmente escrevê-los fora da função, como tem Global Scope. Escopo Global significa que a variável pode ser acessada por outra função no mesmo módulo / classe (se você usar dimcomo declaração, use publicse desejar que as variáveis ​​possam ser acessadas por todas as funções em todos os módulos):

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
Zai
fonte
1

Crie um número inteiro público na Declaração Geral.

Então, em sua função, você pode aumentar seu valor a cada vez. Veja o exemplo (função para salvar anexos de um email como 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
Dan Bidner
fonte
0

Uma boa maneira de criar variáveis ​​públicas / globais é tratar o formulário como um objeto de classe e declarar propriedades e usar Public Property Get [variable] para acessar a propriedade / método. Além disso, você pode precisar fazer referência ou passar uma referência ao módulo Formulário instanciado. Você receberá erros se chamar métodos para formulários / relatórios fechados.
Exemplo: passe Me.Form.Module.Parent para a sub / função que não está no formulário.

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

Portanto, no outro módulo, você seria capaz de acessar:

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

Se você usar a associação tardia como eu, sempre verifique valores e objetos nulos que são Nothing antes de tentar fazer qualquer processamento.

CPU E dupla
fonte
0

Também você pode usar -

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

Seu testado no office 2010

IshaniNet
fonte