¿Cómo declaro una variable global en VBA?

Escribí el siguiente código:

Function find_results_idle() Public iRaw As Integer Public iColumn As Integer iRaw = 1 iColumn = 1 

Y recibo el mensaje de error:

“atributo inválido en Sub o Función”

¿Sabes lo que hice mal?

Traté de usar Global lugar de Public , pero tuve el mismo problema.

Intenté declarar la función en sí misma como `Pública, pero tampoco sirvió de nada.

¿Qué debo hacer para crear la variable global?

Necesita declarar las variables fuera de la función:

 Public iRaw As Integer Public iColumn As Integer Function find_results_idle() iRaw = 1 iColumn = 1 

Esta es una pregunta sobre el scope .

Si solo quiere que las variables duren la vida útil de la función, use Dim (abreviatura de Dimensión ) dentro de la función o sub para declarar las 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 

Una variable global (como señaló SLaks) se declara fuera de la función utilizando la palabra clave Public . Esta variable estará disponible durante la vida de su aplicación en ejecución. En el caso de Excel, esto significa que las variables estarán disponibles siempre que ese libro de Excel en particular esté abierto.

 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. 

También puede tener variables que solo son accesibles dentro de un módulo (o clase) en particular al declararlas con la palabra clave Private .

Si está creando una gran aplicación y siente la necesidad de usar variables globales, le recomendaría crear un módulo separado solo para sus variables globales. Esto debería ayudarlo a hacer un seguimiento de ellos en un solo lugar.

Para usar variables globales, inserte un nuevo módulo desde la interfaz de usuario del proyecto VBA y declare las variables usando Global

 Global iRaw As Integer Global iColumn As Integer 

Si esta función está en un módulo / clase, puede simplemente escribirlos fuera de la función, por lo que tiene Global Scope . Alcance global significa que se puede acceder a la variable mediante otra función en el mismo módulo / clase (si usa dim como statement, use public si desea que todas las funciones accedan a las variables en todos los 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 

La pregunta es realmente sobre el scope, como dijo el otro tipo.

En resumen, 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). 

Puede consultar esta referencia de MSDN para obtener más información sobre statement de variables y esta otra Pregunta de desbordamiento de stack para obtener más información sobre cómo las variables quedan fuera del scope.

Otras dos cosas rápidas:

  1. Organícese cuando use variables de nivel de libro, para que su código no se vuelva confuso. Preferir funciones (con tipos de datos adecuados) o pasar argumentos ByRef .
  2. Si desea que una variable preserve su valor entre llamadas, puede usar la instrucción Estática .

Crea un entero público en la Declaración General.

Luego, en su función puede boost su valor cada vez. Ver ejemplo (función para guardar adjuntos de un correo electrónico 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 

Una buena forma de crear variables públicas / globales es tratar el formulario como un objeto de clase y declarar propiedades y usar la propiedad pública Obtener [variable] para acceder a la propiedad / método. También es posible que necesite hacer referencia o pasar una referencia al módulo de formulario instanciado. Recibirá errores si llama a métodos a formularios / informes que están cerrados.
Ejemplo: pasar Me.Form.Module.Parent en sub / función no dentro de la forma.

 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 

Entonces, en el otro módulo, podrías acceder a:

 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 usa la vinculación tardía, como siempre, compruebo si hay valores nulos y objetos que no son nada antes de intentar hacer ningún procesamiento.