分享

[VBA]名称的秘密:Excel中隐藏着的名称空间

 墨小烟木作 2010-08-09
作者:fanjy
关于Excel的隐藏名称空间
这个被隐藏的名称空间是一个属于当前Excel实例的内存区域,该区域加载项DLLs(“XLLS”)能存储临时的名称。使用这个区域,即使没有可利用的宏工作表可用,XLLs也能定义名称。
隐藏着的名称操作基于XLM函数SET.NAME、GET.NAME和EVALUATE,而且当在XLM宏工作表中使用时,SET.NAME定义一个标准的工作表级名称,同时,当它在XLL中被调用时,创建一个应用程序级名称并且存储在一个被隐藏的区域中。
定义在被隐西藏域的名称有一些特殊的功能,这使得它们与标准工作簿名称有很大的不同。这些功能将在后面描述。
与隐藏着的名称相关的可用C API命令如下:
Excel4(xlfSetName,&xResult,2,&xName,&xValue),定义包含xValue的名称xlName。
Excel4(xlfGetName,&xResult,1,&xName),获取xlName的定义(例如”=1”)并将它存储在xResult中。
Excel4(xlfEvaluate,&xResult,1,&xName),获取xlName的内容(例如:1)并将它存储在xResult中。
Excel4(xlfSetName,&xResult,1,&xName),删除xName(忽略第二个参数)。
在VBA中访问被隐藏的名称空间
(1) 创建一个隐藏的名称
下面的语句创建一个包含字符串“OK”的名为Test的隐藏名称:
Application.ExecuteExcel4Macro "SET.NAME(""Test"",""OK"")"
(2) 获取一个隐藏名称所代表的内容
为了获取名称Test所代表的内容,使用下面的代码:
TestVal = Application.ExecuteExcel4Macro("Test")
注意,只使用名称本身作为ExecuteExcel4Macro的参数。
(3) 删除一个隐藏的名称
为了删除名称Test,使用下面的语句:
Application.ExecuteExcel4Macro "SET.NAME(""Test"")"
注意,忽略了SET.NAME中的第二个参数。
被隐藏的名称空间的特征
在被隐藏的名称空间中所定义的名称的主要特征是:它们不属于任何工作簿,而属于应用程序本身,这意味着:
(1)在Excel中的任何地方可以直接访问这些名称。无论在哪个工作簿中创建了这种名称,在任何工作簿中的任何VBA模块、工作表或宏工作表(和任何DLL加载项)中直接都能直接读取和修改它们。
(2) 它们的“生存时间”与当前Excel会话一致
如果在工作簿Wbk1.xls中的某个VBA模块中创建了一个名称,然后关闭了这个工作簿,那么该名称仍然存储在被隐藏的命名空间中。如果接着打开另一个工作簿Wbk2.xls,那么这个工作簿的VBA过程仍能获取和修改刚才在Wbk1.xls中所创建的名称。在没有被任何VBA加载项所限制的情况下,在被隐藏的名称空间中所定义的名称能作为永久的“公共变量”访问。
对于这些属于应用程序的隐藏的名称,关闭所有工作簿和加载项不会销毁它们。通过对SET.NAME(没有第二个参数)明确的调用或者退出并重启Excel,才能销毁它们。在这种情况下,这些名称能作为一种Excel的环境变量来使用。
(3) 它们是“完全隐藏着的”
当一个受保护的加载项使用这个隐藏的名称空间时,新的名称不能被任何其它的VBA模块读取,也不能被用户读取,除非他们知道名称空间的身份证书。没有方法去“列出”被定义在隐藏命名空间中的名称。
这些名称无须与标准的隐藏名称(即将工作簿或工作表名称的.Visible属性设置为False)相混淆。标准的工作簿级的名称决不会真正的被隐藏,因为它们能通过使用Application.Names集合的任何VBA过程来获取和修改,如下面的代码所示:
Dim CName As Name
  For Each CName In Workbooks("Wbks1.xls").Names
    If CName.Hidden Then
        MsgBox CName.Name & " deleted"
        CName.Delete
    End If
  Next CName
上面的代码在工作簿Wbks1.xls所有隐藏的名称中循环并删除它们,但是这些代码不能发现存储在被隐藏的命名空间中的名称,因为这些名称不属于Application.Names集合,因此,它们被保护以反对任何恶意的访问或修改。
示例
下面的代码演示了在受保护的VBA加载项中隐藏着的命名空间的可能的用途。
它限制用户在相同的Excel会话中执行加载项主过程超过3次。允许剩余执行次数的计数器没有存储在模块级的变量中,也没有存储在依赖加载项的名称中,而是存储在隐藏的命名空间里。通过排除了传统方法的下列缺点,隐藏的命名空间阻止了用户能够中止保护。
(1) 像所有变量一样,存储在VBA中的计数器变量能在VBE中手动清除。
(2) 同样的方式,任何外部过程通过在加载项的Names集合中循环,都可以读取、修改和可能删除加载项中所有隐藏的或未隐藏的工作簿名称。
但是,隐藏的命名空间避免了这些危险。它也比使用基于环境字符串的实例、临时文件或注册进入等方法更简单,而且隐藏的命名空间是永久的,用户能关闭和重新打开该工作簿而无须重新设置这个计数器。
在这个代码中,函数SetHName、GetHName和DelHName可以创建、获取和删除隐藏的名称,而不需要直接使用冗长的Application.ExecuteExcel4Macro方法。
代码清单如下:
Sub Main()
  Application.EnableCancelKey = xlDisabled
  Dim Count
  Count = GetHName("TswbkCount")
  If IsError(Count) Then
    SetHName "TswbkCount", 3
  ElseIf Count = 1 Then
    MsgBox "Macro disabled. You must restart Excel.", vbInformation
  Else
    SetHName "TswbkCount", Count - 1
  End If
End Sub
Sub SetHName(Name As String, Value)
  Application.ExecuteExcel4Macro _
    "SET.NAME(""" & Name & """," & Value & ")"
End Sub
Function GetHName(Name As String)
  GetHName = Application.ExecuteExcel4Macro(Name)
End Function
Sub DelHName(Name As String)
  Application.ExecuteExcel4Macro "SET.NAME(""" & Name & """)"
End Sub
注:本文翻译整理自Chip Pearson的文章《Hidden Name Space In Excel》,略作修改。并提供示例文档 Wbks1.xls。UploadFiles/2006-12/121312334.rar

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多