VBA中公共变量的替代方案

时间:2014-05-28 17:16:34

标签: excel vba excel-vba

我有几个模块引用的公共变量。我知道如果你调试或点击停止变量被清除。我一直把这些变量写到电子表格中,所以如果它们被清除,我会把它们弄清楚,但这很麻烦。我宁愿让它全部存储它代码。是否有任何替代永远不会被清除的公共变量?

5 个答案:

答案 0 :(得分:10)

以下是CustomDocumentProperties的一个示例,我最近开始使用它来存储一些元信息(比处理CustomXMLParts更容易)。

以下示例仅存储字符串数据,但您也可以使用日期,数字和是/否(可以使用某些标记作为布尔值)。字符串数据限制为255个字符。

   Sub Test()
   '## Assign a CDP
   SetCustomProperty "myProperty", "some value I want to store"

   End Sub

您可以在Backstage中查看CPD信息|属性|高级属性|自定义:

enter image description here

如果您End运行时,您可以从CDP恢复值,您可以通过以下方式查询属性值:

myVar = ActiveWorkbook.CustomDocumentProperties("myProperty").Value

您可以使用这些功能在CustomDocumentProperties集合中设置属性:

Sub SetCustomProperty(property$, val$)
    Dim cdp As Variant
    Dim hasProperty As Boolean
    If HasCustomProperty(property) Then
        ActiveWorkbook.CustomDocumentProperties(property).Value = val
    Else
        ActiveWorkbook.CustomDocumentProperties.Add property, False, msoPropertyTypeString, val

    End If
End Sub
Private Function HasCustomProperty(property$) As Boolean
Dim cdp As Variant
Dim boo As Boolean
For Each cdp In ActiveWorkbook.CustomDocumentProperties
    If cdp.name = property Then
        boo = True
        Exit For
    End If
Next
HasCustomProperty = boo
End Function

答案 1 :(得分:7)

一个简单的解决方案是将变量存储在注册表中,并根据需要进行读/写。这具有在多个Excel会话中保留值的额外好处(甚至在计算机重新启动或崩溃之后 - 假设您的注册表幸存下来了!)。

编辑:有关详细信息,请参阅John Walkenbach's book

编辑:请参阅Ioannis的以下评论作为重要考虑因素。


Boilerplate警告: Here be dragons,在您的危险中使用Windows注册表等等。


尽管有上述警告,但请注意,Windows计算机上几乎每个程序都使用注册表执行某些操作,这样做本身并不危险。只需确保您的代码仅更改/删除由Excel应用程序创建的注册表项


使用Windows Scripting的示例程序(我没有写这些;来自quick search):

从注册处阅读:

'reads the value for the registry key i_RegKey
'if the key cannot be found, the return value is ""
Function RegKeyRead(i_RegKey As String) As String
Dim myWS As Object

  On Error Resume Next
  'access Windows scripting
  Set myWS = CreateObject("WScript.Shell")
  'read key from registry
  RegKeyRead = myWS.RegRead(i_RegKey)
End Function

检查注册表项是否存在:

'returns True if the registry key i_RegKey was found
'and False if not
Function RegKeyExists(i_RegKey As String) As Boolean
Dim myWS As Object

  On Error GoTo ErrorHandler
  'access Windows scripting
  Set myWS = CreateObject("WScript.Shell")
  'try to read the registry key
  myWS.RegRead i_RegKey
  'key was found
  RegKeyExists = True
  Exit Function

ErrorHandler:
  'key was not found
  RegKeyExists = False
End Function

保存注册表项:

'sets the registry key i_RegKey to the
'value i_Value with type i_Type
'if i_Type is omitted, the value will be saved as string
'if i_RegKey wasn't found, a new registry key will be created
Sub RegKeySave(i_RegKey As String, _
               i_Value As String, _
      Optional i_Type As String = "REG_SZ")
Dim myWS As Object

  'access Windows scripting
  Set myWS = CreateObject("WScript.Shell")
  'write registry key
  myWS.RegWrite i_RegKey, i_Value, i_Type

End Sub

从注册表中删除密钥:

'deletes i_RegKey from the registry
'returns True if the deletion was successful,
'and False if not (the key couldn't be found)
Function RegKeyDelete(i_RegKey As String) As Boolean
Dim myWS As Object

  On Error GoTo ErrorHandler
  'access Windows scripting
  Set myWS = CreateObject("WScript.Shell")
  'delete registry key
  myWS.RegDelete i_RegKey
  'deletion was successful
  RegKeyDelete = True
  Exit Function

ErrorHandler:
  'deletion wasn't successful
  RegKeyDelete = False
End Function

答案 2 :(得分:2)

如果仍有引用在代码中进一步指向它们,则公共变量不会在调试(中断)模式下从内存中删除。事实上,在某些情况下,如果您将鼠标移到变量上,它会告诉您休息时的值。

如果你想要保持变量,我会使用你当前使用的相同方法(在excel工作表上写下来)或数据库。

如果你确实写下这些变量,我建议你不要直接修改变量,而是使用适合你模型的setter和getter。例如,如果将它们写到工作表,则可以使用以下命令:

public sub setVariable(v as String)
     worksheets("Sheet1").Range("A1").value = v
end sub

public function getVariable() as String
    getVariable = worksheets("Sheet1").range("A1").value
End Function

答案 3 :(得分:1)

根据用例,这是另一种可能比我的第一个答案(使用注册表)更可取的解决方案。

您可以将值存储在"Very Hidden" worksheet中。这具有以下优点:

  1. 防止变量被意外销毁(对用户完全不可见)
  2. 允许工作簿的多个副本拥有自己的变量版本,而不是从注册表访问相同值的所有实例
  3. 防止工作簿的多个实例同时尝试编辑注册表项
  4. 允许工作簿在多台计算机上使用,通过电子邮件发送等后维护这些值

答案 4 :(得分:1)

TempVars Collection是公共变量的绝佳替代品。 它不会在会话之间持续存在,但持续整个A会话。

您需要添加对 Microsoft Access 14.0对象库的引用。 TempVars仅在2007年开始提供。