2012-10-09 20 views
7

詳細說明一下,假設我在工作簿中有兩個命名範圍。兩個命名範圍具有相同的名稱(比如說「myName」),但其中一個範圍爲Sheet1,另一個範圍爲工作簿。重複名稱時,通過Excel工作簿中的字符串獲取命名範圍

給定命名範圍的名稱(字符串),我想抓取工作簿級命名範圍。

如果我使用本地調用:wb.Names.Item("myName"),它將返回工作表範圍命名範圍。

如果我這樣做:wb.Names.Item("Sheet1!myName"),這顯然返回工作表範圍的名稱範圍。我發現我可以使用它來指定特定表格,但不是工作簿。

有無論如何我可以指定我想工作簿作用域?

我的解決方法是遍歷所有名稱的列表,並比較.Name屬性以獲取工作簿作用域命名範圍。這是因爲.Name屬性附加了「Sheet1!」到工作表範圍的命名範圍。然而,這樣做非常昂貴,我想避免它。

+2

這是不是100%清楚地知道你是如何使用範圍。如果你想設置一個範圍對象爲一個名字串然後'Set rng1 = Range(「myName」)'將返回本地表名的範圍,如果* sheet1是活動的*否則它將返回工作簿名稱的範圍。我認爲這是最乾淨的解決方法 - 即在查看使用名稱作爲工作簿範圍之前,測試活動工作表與承載本地名稱的工作表不同。合理? :) – brettdj

+0

您還可以將parent.name與工作簿名稱進行比較,但您仍然需要遍歷名稱以提取該集合。 – nutsch

+0

回覆:@ brettdj的評論。取決於你要實現的目標,最簡單的方法可能是在宏的開始處添加一個臨時表單,在代碼結束時刪除它。 – nutsch

回答

1

當我們(JKP和我自己)在編寫Name Manager時,我們特別爲重複的全局/本地名稱添加了過濾器和警告消息,因爲您提到的這種Excel對象模型行爲導致很難檢測到錯誤。

所以我的建議是永遠不要使用重複的全球/本地名稱。

我們使用代碼來檢測名稱是否與本地名稱的父級活動的全局/本地重複,然後在必要時切換表單。我們用它來尋找全局名稱的本地版本優化VBA代碼是這樣的:它的相當快的,除非你有成千上萬的數十名 -

Function FindNameLocal(oSheet As Worksheet, sName As String) As Name 
     Dim oName As Name 
     Dim strLocalName As String 
     Dim strLocalNameNoQuote 
     Dim strName As String 
     Set FindNameLocal = Nothing 
     If Len(sName) > 0 And Not oSheet Is Nothing And oSheet.Names.Count > 0 Then 
      On Error Resume Next 
      strLocalName = "'" & oSheet.Name & "'!" & sName 
      strLocalNameNoQuote = oSheet.Name & "!" & sName 
      Set FindNameLocal = oSheet.Names(strLocalName) 
      If Err <> 0 Or (FindNameLocal.NameLocal <> strLocalName And FindNameLocal.NameLocal <> strLocalNameNoQuote) Then 
       On Error GoTo 0 
       Set FindNameLocal = Nothing 
       For Each oName In oSheet.Names 
        strName = oName.Name 
        If Len(strLocalName) = Len(strName) Or Len(strLocalNameNoQuote) = Len(strName) Then 
         If strName = strLocalName Or strName = strLocalNameNoQuote Then 
          Set FindNameLocal = oName 
          GoTo GoExit 
         End If 
        End If 
       Next 
      End If 
     End If 
GoExit: 
    End Function 
+0

我不確定這是否回答我的問題。也許我在誤讀它,但我需要獲得全球版的名稱。這將返回工作表級別,我可以通過以wb.Names.Item(「Sheet1!myName」)的格式傳遞它來完成工作。 我注意到你的代碼中有一件事我很好奇。在比較字符串之前比較長度是否會導致很多性能增益? – Shark

+0

我們通過傳遞全局名稱和活動工作表名稱來檢測是否存在重複的全局本地名稱。如果有重複,則需要更改工作表並重試,直到找到不包含重複的工作表(或暫時添加新工作表),以便在訪問該名稱時您將獲得全局工作表。在VBA中獲取字符串的長度非常快,但比較字符串很慢:不知道這在C#中適用的程度。 –

+0

啊,現在有道理。我將不得不看看你的方法(轉換爲C#)是否比我提出的另一個想法更快。我將張貼解決方案作爲另一個答案。然後性能測試將決定勝利者! – Shark

相關問題