工作簿之间重复的命名范围会导致我的自定义函数混淆

时间:2009-08-05 15:17:49

标签: excel vba excel-vba

我对Excel中命名范围的范围有点困惑。我有两个版本的excel工作簿。有时,用户需要将旧版本工作簿中的数据复制到较新版本中。在大多数单元格计算中使用了一些自定义VBA函数。这些功能中的每一个都在工作表上查找大约4到12个命名范围。这似乎运行良好...但是,我最近发现,当文件的两个版本打开时,对所有命名范围的VBA引用仅返回打开的第一个文件的值(所以如果更新版本的表单首先打开,然后旧版本的行为就像它的一些数据来自新版本!)。只要两个文件保持打开状态,第二个文件中的命名范围似乎被第二个文件忽略,至少在VBA代码中。如果我关闭首先打开的工作簿,第二个将正确计算。

我找到了部分修复:而不是这样做:

Blah = Range("valueXYZ").Value

我这样做:

Blah = ThisWorkbook.Names("namedCellXYZ").RefersToRange.Value

这很好用,但仅适用于较新版本的工作簿。我无法更新旧版本工作簿中的VBA代码。这意味着如果客户在新版本打开后打开旧版本(因此两者都是打开的,但旧的版本是第二次打开的),旧版本将从较新版本获取值和命名范围 - 和因此报告错误的数字和范围。这是不好的。我需要一个好方法来防止旧表从新表中访问命名范围,但我只能修改新表。我唯一能想到的是重命名所有命名范围并在新版本中更新大量VBA代码 - 这些代码容易出错并听起来像是过度工作。

有什么建议吗?例如,是否可以在第二个文件打开时向用户显示警告?或者是否可以使用VBA来限制命名范围的范围?还有其他想法吗?

2 个答案:

答案 0 :(得分:1)

您可以尝试在“ThisWorkbook”代码窗口中处理WorkbookOpen Event。打开新版本的工作簿时,您可以遍历所有打开的工作簿,并查看列表中是否有任何旧版本。如果是,请警告用户旧版电子表格中的值可能不正确,因为正在从较新版本读取数据。

答案 1 :(得分:0)

[编辑]

此子将告诉您在任何打开的工作簿中是否有重复的命名范围。正如DanThMan所说,您可以在ThisWorkbook对象模块中引用它:

Sub CheckRangeDups()
    Dim wb As Workbook
    Dim nm As Name
    Dim count As Integer, i As Integer
    Dim arrNm() As String
    Dim dup As Boolean
    Dim rngChk As Range

    ReDim arrNm(0)
    'cycle through workbooks'
    For Each wb In Workbooks
        'cycle through names in workbook'
        For Each nm In wb.Names
            'check if name refers to a range'
            On Error Resume Next
            Set rngChk = Nothing
            Set rngChk = nm.RefersToRange
            On Error GoTo 0
            If Not rngChk Is Nothing Then
                dup = False
                'check if name in array of names'
                For i = 0 To UBound(arrNm)
                    If nm.Name = arrNm(i) Then
                        MsgBox "Named range " & nm.Name & " duplicated."
                        dup = True
                        Exit For
                    End If
                Next i
                'if not then add it'
                If Not dup Then
                    arrNm(count) = nm.Name
                    count = count + 1
                    ReDim Preserve arrNm(count)
                End If
            End If
        Next nm
    Next wb
End Sub

[/编辑]

如果我理解你的话,完全符合你对范围的引用将解决你的问题。示例:打开两个名为file1和file2的文件,在两个文件中的工作表1“arange”上命名单元格A1。在file1中键入“file1”进入单元格,在file2上键入“file2”进入单元格。现在运行:

Sub whichRange()
    Dim f1 As Workbook, f2 As Workbook
    Set f1 = Workbooks("file1.xls")
    Set f2 = Workbooks("file2.xls")
    Dim s1 As Worksheet, s2 As Worksheet
    Set s1 = f1.Worksheets(1)
    Set s2 = f2.Worksheets(1)

    Dim r1 As Range, r2 As Range
    Set r1 = s1.Range("arange")
    Set r2 = s2.Range("arange")

    Debug.Print "WB: "; f1.Name; " cell: "; r1.Name; " contents: "; r1
    Debug.Print "WB: "; f2.Name; " cell: "; r2.Name; " contents: "; r2
End Sub

完全限定允许Excel知道您所指的是哪个。