2012-10-09 10 views
7

Per elaborare, diciamo che ho due intervalli nominati nella mia cartella di lavoro. Entrambi gli intervalli denominati hanno lo stesso nome (diciamo "myName"), ma uno è limitato a Sheet1 e l'altro è ambito alla cartella di lavoro.Ottieni un intervallo denominato per stringa nella cartella di lavoro di Excel quando il nome è duplicato

Dato un nome (stringa) dell'intervallo denominato, desidero accedere all'intervallo denominato livello di cartella di lavoro.

Se utilizzo la chiamata nativa: wb.Names.Item("myName"), restituisce l'intervallo denominato ambito.

Se invece lo faccio: wb.Names.Item("Sheet1!myName"), restituisce ovviamente l'intervallo del nome dell'ambito del foglio. Ho scoperto che posso usarlo per specificare quelli specifici per il foglio, ma non per quello di una cartella di lavoro.

Esiste comunque la possibilità di specificare la cartella di lavoro con scope?

La mia soluzione alternativa sta attualmente eseguendo l'iterazione nell'elenco di tutti i nomi e il confronto della proprietà .Name per acquisire l'ambito denominato Intervallo di lavoro. Funziona perché la proprietà .Name aggiunge un "Foglio1!" all'intervallo denominato ambito. Questo è comunque molto costoso da fare, e voglio evitarlo.

+2

Non è chiaro al 100% per me come si sta utilizzando il gamma. Se si sta tentando di impostare un oggetto range su una stringa nome allora 'Set rng1 = Range (" myName ")' restituirà l'intervallo dal nome del foglio locale se * sheet1 è attivo * altrimenti restituirà l'intervallo dal nome della cartella di lavoro . Penso che questa sia la soluzione più pulita, ovvero test che il foglio attivo sia diverso dal foglio che ospita il nome locale prima di cercare di usare il nome come ambito della cartella di lavoro. Ha senso? :) – brettdj

+0

è anche possibile confrontare il parent.name con il nome della cartella di lavoro, ma è comunque necessario scorrere i nomi per estrarre tale raccolta. – nutsch

+0

re: @ commento di brettdj. a seconda di cosa stai cercando di ottenere, il più semplice potrebbe essere semplicemente aggiungere un foglio temporaneo all'inizio della tua macro, da eliminare alla fine del tuo codice. – nutsch

risposta

1

Quando noi (JKP e io) scrivevamo Name Manager abbiamo aggiunto in modo specifico un filtro e un messaggio di avviso per nomi globali/locali duplicati perché questo comportamento del modello di oggetto Excel che hai menzionato porta a errori difficili da rilevare.

Quindi la mia raccomandazione è di non usare mai nomi globali/locali duplicati.

Utilizziamo il codice per rilevare se un nome è duplicato globale/locale con il genitore del nome locale attivo e quindi passare i fogli se necessario. Il codice VBA ottimizzato che usiamo per trovare la versione locale di un nome globale è questo: la sua ragionevolmente veloce a meno che non si dispone di diverse decine di migliaia di nomi -

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

Non sono sicuro che questo risponda alla mia domanda. Forse sto fraintendendo, ma ho bisogno di ottenere la versione globale del nome. Questo restituisce il livello del foglio uno, che posso già fare passandolo nel formato di wb.Names.Item ("Sheet1! MyName"). Ho notato una cosa nel tuo codice di cui sono curioso. Confrontare la lunghezza prima di confrontare le stringhe comporta un guadagno in termini di prestazioni? – Shark

+0

Viene utilizzato per rilevare se esiste un nome locale globale duplicato passando il nome globale e il nome del foglio di lavoro attivo. Se è presente un duplicato, è necessario modificare il foglio di lavoro e riprovare finché non si trova un foglio di lavoro che non contiene un duplicato (o aggiungere temporaneamente un nuovo foglio) in modo che quando si accede al nome si ottenga quello globale. Ottenere la lunghezza di una stringa è molto veloce in VBA ma il confronto delle stringhe è lento: non so fino a che punto questo si applica in C#. –

+0

Ah, ha senso ora. Dovrò vedere se il tuo approccio (tradotto in C#) è più veloce di un'altra idea che ho ideato. Presenterò la soluzione come un'altra risposta. Quindi il test delle prestazioni determinerà il vincitore! – Shark

Problemi correlati