2012-10-09 5 views
7

Aby opracować, załóżmy, że mam dwa nazwane zakresy w moim skoroszycie. Oba nazwane zakresy mają tę samą nazwę (powiedzmy "myName"), ale jedna z nich ma zasięg do arkusza1, a druga ma zasięg do skoroszytu.Uzyskaj nazwany zakres według ciągu w skoroszycie programu Excel, gdy nazwa jest powielana

Biorąc pod uwagę nazwę (ciąg) nazwanego zakresu, chcę pobrać poziom nazwany Skrócone skoroszytu.

Jeśli korzystam z połączenia natywnego: wb.Names.Item("myName"), funkcja zwraca zakres nazwany w arkuszu.

Jeśli zamiast tego robię: wb.Names.Item("Sheet1!myName"), to oczywiście zwraca zakres nazw zakresów arkusza. Zauważyłem, że mogę użyć tego do określenia specyficznych dla arkusza, ale nie do skoroszytu.

Czy mimo to mogę określić, że skoroszyt ma jeden zakres?

Moje obejście polega na iteracji na liście wszystkich nazw i porównaniu właściwości .Name w celu pobrania zakresu nazwanego zakresu skoroszytu. Działa to, ponieważ właściwość .Name dołącza "Arkusz1!" do arkusza o nazwie Zasięg. Jest to jednak bardzo kosztowne i chcę tego uniknąć.

+2

To nie jest 100% dla mnie jasne, w jaki sposób są za pomocą zasięg. Jeśli próbujesz ustawić obiekt zakresu na ciąg znaków, wówczas 'Set rng1 = Range (" myName ")' zwróci zakres z lokalnej nazwy arkusza, jeśli * sheet1 jest aktywny * w przeciwnym wypadku zwróci zakres od nazwy ze skoroszytu . Myślę, że jest to najczystsze rozwiązanie - tzn. Sprawdź, czy aktywny arkusz różni się od arkusza zawierającego nazwę lokalną, zanim zacznie używać tej nazwy jako zakresu skoroszytu. Ma sens? :) – brettdj

+0

można również porównać parent.name ze nazwą skoroszytu, ale nadal trzeba pętli przez nazwy, aby wyodrębnić tę kolekcję. – nutsch

+0

re: @ brettdj's comment. w zależności od tego, co próbujesz osiągnąć, najłatwiej jest po prostu dodać arkusz tymczasowy na początku makra, który ma zostać usunięty na końcu kodu. – nutsch

Odpowiedz

1

Kiedy my (JKP i ja) pisaliśmy Name Manager, specjalnie dodaliśmy filtr i komunikat ostrzegawczy dla Duplikatów nazw globalnych/lokalnych, ponieważ wspomniane zachowanie modelu obiektowego Excel prowadzi do trudnych do wykrycia błędów.

Dlatego moją rekomendacją jest nigdy nie używać duplikatów globalnych/lokalnych nazw.

Używamy kodu, aby wykryć, czy nazwa jest zduplikowana globalnie/lokalnie, gdy nadrzędna nazwa lokalna jest aktywna, a następnie w razie potrzeby zmienić arkusze. Zoptymalizowany kod VBA używamy, aby znaleźć lokalną wersję nazwy globalnej to: jego dość szybko, chyba że masz kilkadziesiąt tysięcy nazwisk -

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

Nie jestem pewien, czy to odpowiada na moje pytanie. Może źle to rozumiem, ale muszę uzyskać globalną wersję nazwy. Zwraca to arkusz pierwszego poziomu, który już mogę zrobić, przekazując go w formacie wb.Names.Item ("Sheet1! MyName"). Zauważyłem jedną rzecz w kodzie, którą jestem ciekawy. Czy porównywanie długości przed porównaniem łańcuchów powoduje znaczny wzrost wydajności? – Shark

+0

Używamy tego do wykrycia, czy istnieje zduplikowana nazwa globalna lokalna, przekazując nazwę globalną i nazwę aktywnego arkusza roboczego. Jeśli istnieje duplikat, musisz zmienić arkusz roboczy i spróbować ponownie, aż znajdziesz arkusz roboczy, który nie zawiera duplikatu (lub tymczasowo dodaje nowy arkusz), aby wtedy, gdy uzyskasz dostęp do nazwy, otrzymasz wersję globalną. Uzyskanie długości ciągu znaków jest bardzo szybkie w VBA, ale porównywanie napisów jest powolne: nie wiem do jakiego stopnia ma to zastosowanie w języku C#. –

+0

Ahh, teraz ma sens. Będę musiał sprawdzić, czy twoje podejście (przetłumaczone na C#) jest szybsze niż inny pomysł, który wymyśliłem. Postawię rozwiązanie jako kolejną odpowiedź. Następnie testowanie wydajności określi zwycięzcę! – Shark

Powiązane problemy