许多子程序的变量:代码清理

Variables for many subroutines: code clean up

我已经思考并搜索了好几个小时的解决方案,但无法找到我的基本问题的答案(显然对我来说很难):

所以我有很多子程序:

Sub OUTPUT()

Call CompañiasCubiertas
Call RangosDatos
Call EERR
Call Balance
Call Flujo
Call Indicadores
Call FormatoEERR
Call FormatoBalance
Call FormatoFlujo
Call FormatoIndicadores

End Sub

在每个子程序中,我都有许多重复的变量和工作簿声明:

Dim y As Workbook
Dim x As Workbook

Dim rangoi As Integer
Dim rangof As Integer
Dim compañia As String
Dim oipf As Integer
Dim ogpf As Integer 
Dim ogp As Integer 
Dim Fechai As Long
Dim Fechaf As Long
Dim Fechaper1 As Long
Dim Fechaper2 As Long


Set y = Application.ActiveWorkbook
Set x = Application.Workbooks.Open("G:\Estudios\Biblioteca\Mercado Accionario Chileno\BBDD Oficial.xlsm")

compañia = y.Sheets("Información Financiera").Range("A3")

'Definir rangos para buscar los datos

Fechai = y.Sheets("Información Financiera").Range("C4").Value
Fechaf = y.Sheets("Información Financiera").Range("D4").Value
Fechaper1 = y.Sheets("Información Financiera").Range("C8").Value
Fechaper2 = y.Sheets("Información Financiera").Range("D8").Value
rangoi = Application.Match(Fechai, y.Sheets("Información Financiera").Range("E2:E300"), 0) + 1
rangof = Application.Match(Fechaf, y.Sheets("Información Financiera").Range("E2:E300"), 0) + 1

那么,我怎样才能避免在所有子程序中声明所有这些变量和工作簿。 我一直在尝试我在几乎每个网站上读到的内容:

Public rangoi As Integer
Public rangof As Integer

等等....但是如果我在OUTPUT()内部创建这些变量,它会抛出一个错误,并且在外部启动宏时不会读取它。

我在这里遗漏了一些基本的东西。

我对制作变量特别感兴趣...

Dim compañia As String
 compañia = y.Sheets("Información Financiera").Range("A3")

...对所有子例程都很有用,因为我想对变量 compañia 进行循环(将其重置为字符串数组)并将 for 放入 OUTPUT 子程序为:

 Sub OUTPUT()
    For i=1 To UBound(compañia)

Call subs1 ' subs1(compañia) , meaning the value of compañia changes the value of subroutines
Call subs2 ' subs2(compañia)
Call subs3 ' subs3(compañia)

Next i
End Sub

必须在子例程外创建一个public变量,这就是当您试图在子例程内声明它时会出错的原因。当您声明一个 public 变量时,它对所有子例程都是可见的 - 它将在您启动 运行 您的宏时创建。它在子例程之外声明的事实并不意味着声明不会发生。

请注意,您还可以使用 "Dim"(而不是 Public)在子例程外声明变量,但此类变量仅对同一模块内的子例程可见。 Public 变量将对所有模块中的所有例程可见。

要考虑的另一种方法是将您广泛需要的变量作为参数传递。例如在您的主例程中声明它们,然后将它们传递给需要它们的子例程。这通常比有很多 public 个变量更可取,但这两种方法都有其用途。

编辑:为响应 Jules 的评论而添加。 Jules 提出了一个非常好的观点——相信工作表代码块中的 "Public" 变量并不是真正的 public,而是仅对该工作表中的所有例程可见。但是,模块中的 public 声明实际上是 Public.

作为替代方案,您可以在模块中声明一个 public 自定义类型,并且只使用一行在本地声明。此解决方案比使用全局变量更安全。

Module1.bas

Public Type CustomType
    y As Workbook
    x As Workbook
    compania as String '<-- I don't have accent on my machine.
    rangoi As Integer
    rangof As Integer
    oipf As Integer
    ogpf As Integer
    ogp As Integer
    Fechai As Long
    Fechaf As Long
    Fechaper1 As Long
    Fechaper2 As Long
End Type

Module2.bas

Public Sub Sub1()
   dim lCustom as CustomType

   set lCustom.x = ActiveWorkBook '<-- just a sample
   lCustom.loipf = 1
End Sub

Module3.bas

Public Sub Sub2()
   dim lCustom as CustomType

   set lCustom.x = ActiveWorkBook '<-- just a sample
   lCustom.loipf = 1
End Sub

我必须得到代码 运行,幸运的是我想出了一个解决方案。可能我确实做了不该做的事,或者不推荐的事,但我又没有时间思考更好的解决方案。我只是在学习不同类型的变量(Public、私有变量、模块内部或外部变量等),并试图理解它们。感谢您的建议,但这些代码对我来说有点太高级了。

Public compañia2() As String
Public compañia As String 

Sub OUTPUT()
Application.ScreenUpdating = False 'To avoid screen flickering
Application.DisplayAlerts = False 'Mensajes de alertas desactivado

CompañiasCubiertas
RangosDatos

For i = 1 To UBound(compañia2)
compañia = compañia2(i)
EERR
Balance
Flujo
Indicadores
FormatoEERR
FormatoBalance
FormatoFlujo
FormatoIndicadores

Next i

Application.DisplayAlerts = True
Application.ScreenUpdating = True 'To avoid screen flickering
End Sub

Sub CompañiasCubiertas()

'Other code for declaration of variables and other stuff

ReDim compañia2(x.Sheets.Count - 3 + 1) ' Define lenght of the array

For i = 1 To x.Sheets.Count - 2
compañia2(i) = y.Sheets("CompañiasCubiertas").Range("A" & i + 2).Value ' Fill array
Next i

End Sub