2012-10-09 11 views
7

詳細を述べると、ワークブックに2つの名前付き範囲があるとします。両方の名前付き範囲は同じ名前(「myName」と言う)がありますが、1つはSheet1にスコープされ、もう1つはブックにスコープされます。名前が重複しているときにExcelワークブックで名前付き範囲を文字列で取得

名前付き範囲の名前(文字列)を指定すると、ブックレベルの名前付き範囲を取得したいと考えています。

ネイティブコール:wb.Names.Item("myName")を使用すると、名前付き範囲のシートスコープが返されます。

代わりに私が:wb.Names.Item("Sheet1!myName")を実行すると、明らかにシートスコープの名前範囲が返されます。私はこれを使用してシート固有のものを指定できますが、ワークブックは指定できないことがわかりました。

とにかく私はワークブックスコープ1を指定できますか?

現在、すべての名前のリストに対して反復処理を行い、.Nameプロパティを比較してブックのスコープ名前付き範囲を取得しています。これは、.Nameプロパティが "Sheet1!"シートスコープの名前付き範囲に追加します。しかしこれは非常にコストがかかり、私はそれを避けたい。

+2

私はどのように使用していますか?範囲。範囲オブジェクトを名前文字列に設定しようとすると、 'set rng1 = Range(" myName ")'は* sheet1がアクティブな場合にローカルシート名から範囲を返します*そうでなければブック名から範囲を返します。私はこれが一番きれいな回避策だと思います。つまり、アクティブシートが、ブック名をワークブックスコープとして使用する前にローカル名をホストしているシートと異なることをテストします。理にかなっている? :) – brettdj

+0

でも、parent.nameとブック名を比較できますが、名前をループしてそのコレクションを抽出する必要があります。 – nutsch

+0

re:@ 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")の形式で渡すことで、すでに行うことができるシートレベル1を返します。 私はあなたのコードの中で私が興味があることに気づいた。文字列を比較する前に長さを比較すると、パフォーマンスが大幅に向上しますか? – Shark

+0

グローバル名とアクティブなワークシート名を渡して、グローバルなローカル名が重複しているかどうかを検出します。重複がある場合は、ワークシートを変更して、重複を含まないワークシートを見つけるまで(または新しいシートを一時的に追加するまで)再度試行し、名前にアクセスするとグローバルになるようにします。文字列の長さを取得するのはVBAでは非常に高速ですが、文字列を比較するのは遅いです。これがC#でどの程度適用されるかはわかりません。 –

+0

ああ、今は意味をなさない。あなたのアプローチ(C#に翻訳されている)が私が思いついた別のアイデアよりも速いかどうかを見なければなりません。私は解決策を別の答えとして掲示します。パフォーマンステストで勝者が決まります! – Shark

関連する問題