Name Managerを使用して名前付き範囲を作成すると、Workbookまたは[worksheet name]
スコープを指定するオプションが与えられます。ただし、スコープを変更する場合は、ドロップダウンがグレー表示されます。 Name Managerまたは、できればVBAに、既存の名前付き範囲のスコープを変更する方法はありますか?
例えば:
testName
は、スコープWorkbookで'sheet1'!A1:B2
を参照します。それをどのように変更しますかtestName
は 'sheet1'スコープの'sheet1'!A1:B2
を参照しますか?自分とJan Karel Pieterseが開発した無料のName Managerアドインを http://www.decisionmodels.com/downloads.htm からダウンロードできます。これにより、Excel 2007 Name Managerが処理できない多くの名前操作が可能になります。名前の範囲の変更を含む。
VBAの場合:
Sub TestName()
Application.Calculation = xlManual
Names("TestName").Delete
Range("Sheet1!$A$1:$B$2").Name = "Sheet1!TestName"
Application.Calculation = xlAutomatic
End Sub
私は解決策を見つけました!名前付き変数を使用してシートをコピーするだけです。次に、元のシートを削除します。コピーされたシートには、同じ名前の変数がありますが、ローカルスコープ(scope =コピーされたシート)があります。
ただし、ローカル変数からグローバル変数に変更する方法がわかりません。
互いに逆になり、アクティブシート上の範囲を参照するすべての名前付き範囲のスコープ(ワークシートからワークブックへ、または逆へ)を切り替えるこれらの2つのサブを確認します。
Option Explicit
'---------------------------------------------------------------------------------------
' Procedure : RescopeNamedRangesToWorkbook
' Author : JS20'07'11
' Date : 11/18/2013
' Purpose : Rescopes the parent of worksheet scoped named ranges to the active workbook
' for each named range with a scope equal to the active sheet in the active workbook.
'---------------------------------------------------------------------------------------
Public Sub RescopeNamedRangesToWorkbook()
Dim wb As Workbook
Dim ws As Worksheet
Dim objName As Name
Dim sWsName As String
Dim sWbName As String
Dim sRefersTo As String
Dim sObjName As String
Set wb = ActiveWorkbook
Set ws = ActiveSheet
sWsName = ws.Name
sWbName = wb.Name
'Loop through names in worksheet.
For Each objName In ws.Names
'Check name is visble.
If objName.Visible = True Then
'Check name refers to a range on the active sheet.
If InStr(1, objName.RefersTo, sWsName, vbTextCompare) Then
sRefersTo = objName.RefersTo
sObjName = objName.Name
'Check name is scoped to the worksheet.
If objName.Parent.Name <> sWbName Then
'Delete the current name scoped to worksheet replacing with workbook scoped name.
sObjName = Mid(sObjName, InStr(1, sObjName, "!") + 1, Len(sObjName))
objName.Delete
wb.Names.Add Name:=sObjName, RefersTo:=sRefersTo
End If
End If
End If
Next objName
End Sub
'---------------------------------------------------------------------------------------
' Procedure : RescopeNamedRangesToWorksheet
' Author : JS20'07'11
' Date : 11/18/2013
' Purpose : Rescopes each workbook scoped named range to the specific worksheet to
' which the range refers for each named range that refers to the active worksheet.
'---------------------------------------------------------------------------------------
Public Sub RescopeNamedRangesToWorksheet()
Dim wb As Workbook
Dim ws As Worksheet
Dim objName As Name
Dim sWsName As String
Dim sWbName As String
Dim sRefersTo As String
Dim sObjName As String
Set wb = ActiveWorkbook
Set ws = ActiveSheet
sWsName = ws.Name
sWbName = wb.Name
'Loop through names in worksheet.
For Each objName In wb.Names
'Check name is visble.
If objName.Visible = True Then
'Check name refers to a range on the active sheet.
If InStr(1, objName.RefersTo, sWsName, vbTextCompare) Then
sRefersTo = objName.RefersTo
sObjName = objName.Name
'Check name is scoped to the workbook.
If objName.Parent.Name = sWbName Then
'Delete the current name scoped to workbook replacing with worksheet scoped name.
objName.Delete
ws.Names.Add Name:=sObjName, RefersTo:=sRefersTo
End If
End If
End If
Next objName
End Sub
最初から新しい名前を作成し、古い名前を削除します。
別の方法は、2007以降のExcelファイルを「ハッキング」することです。ただし、これを行う場合は注意し、元のバックアップを保持することをお勧めします。
最初に、Excelスプレッドシートを.xlsxまたは.xlsmファイル(バイナリではない)として保存します。ファイルの名前を.Zipに変更してから、解凍します。 Zip構造のxlフォルダーに移動し、ワードパッドまたは同様のテキストエディターでworkbook.xmlを開きます。名前付き範囲は、definedNameタグにあります。ローカルスコープはlocalSheetId = "x"によって定義されます(シートIDは、スプレッドシートを開いた状態でExcelでAlt-F11を押すと、VBAウィンドウに移動して、プロジェクトペインを見ることができます)。非表示の範囲はhidden = "1"で定義されるため、たとえば、hidden = "1"を削除して再表示するだけです。
ここで、フォルダー構造の整合性を維持するように注意してフォルダー構造を再圧縮し、名前を.xlsxまたは.xlsmに戻します。
多数の定義済み範囲の範囲を変更したり、非表示/非表示を解除する必要がある場合、これはおそらく最良の解決策ではありませんが、1つまたは2つの小さな調整を行う場合はうまく機能します。
すべてのワークシート名をグローバル名に昇格させる方法は次のとおりです。 YMMV
For Each wsh In ActiveWorkbook.Worksheets
For Each n In wsh.Names
' Get unqualified range name
Dim s As String
s = Split(n.Name, "!")(UBound(Split(n.Name, "!")))
' Add to "Workbook" scope
n.RefersToRange.Name = s
' Remove from "Worksheet" scope
Call n.Delete
Next n
Next wsh
私にとっては、Name Managerと同じ範囲に対して新しい名前タグを作成すると、スコープを変更するオプションが提供されます;)ワークブックはデフォルトとして提供され、利用可能なシートのいずれかに変更されました。
これにはさらに改良が必要ですが、既存のローカル名を削除せずに、すべての単純な参照で機能します。
Type GlobalNamesToLocalNames_Type
Name As String
Sheet As String
Ref As String
End Type
Sub GlobalNamesToLocalNames(Optional Void As Variant)
Dim List() As GlobalNamesToLocalNames_Type
Dim Count As Long
Dim Name As Name
Dim Dat() As String
Dim X As Long
' count the size
For Each Name In ActiveWorkbook.Names
Count = Count + 1
Next
ReDim List(Count - 1)
Count = 0
' Collecect all name data
For Each Name In ActiveWorkbook.Names
With List(Count)
' Pick up only the name
If InStr(Name.Name, "!") > 0 Then
Dat = Split(Name.Name, "!")
.Name = Dat(1)
Else
.Name = Name.Name
End If
' pick up the sheet and refer
Dat = Split(Name.RefersTo, "!")
.Sheet = Mid(Dat(0), 2)
.Ref = Dat(1)
' make local sheet name
.Name = .Sheet & "!" & .Name
End With
Count = Count + 1
Next
' Delete all names
For Each Name In ActiveWorkbook.Names
Name.Delete
Next
'rebuild all the names
For X = 0 To Count - 1
With List(X)
If Left(.Ref, 1) <> "#" Then
ActiveWorkbook.Names.Add Name:=.Name, RefersToLocal:="=" & .Sheet & "!" & .Ref
End If
End With
Next
End Sub
JS20'07'11のコードは本当にシンプルで直接的です。私がお伝えしたいのは、条件に感嘆符を付けることです。
InStr(1, objName.RefersTo, sWsName+"!", vbTextCompare)
これにより、誤ったシートにNamedRangeを追加できなくなります。例:NamedRangeがPlan11という名前のシートを参照しており、Plan1感嘆符を使用しない場合、範囲を追加するときにコードが混乱する可能性があります。
[〜#〜] update [〜#〜]
修正:シートの名前を評価する正規表現を使用するのが最善です。使用できる簡単な関数は次のとおりです( http://blog.malcolmp.com/2010/regular-expressions-Excel-add-in で調整、Microsoft VBScript Regular Expressions 5.5を有効化):
Function xMatch(pattern As String, searchText As String, Optional matchIndex As Integer = 1, Optional ignoreCase As Boolean = True) As String
On Error Resume Next
Dim RegEx As New RegExp
RegEx.Global = True
RegEx.MultiLine = True
RegEx.pattern = pattern
RegEx.ignoreCase = ignoreCase
Dim matches As MatchCollection
Set matches = RegEx.Execute(searchText)
Dim i As Integer
i = 1
For Each Match In matches
If i = matchIndex Then
xMatch = Match.Value
End If
i = i + 1
Next
End Function
そのため、次のようなものを使用できます。
xMatch("'?" +sWsName + "'?" + "!", objName.RefersTo, 1) <> ""
の代わりに
InStr(1, objName.RefersTo, sWsName+"!", vbTextCompare)
これは、Plan1および 'Plan1'(範囲が複数のセルを参照する場合)のバリエーションをカバーします
ヒント:シート名に単一引用符( ')、:)を使用しないでください。
JS20'07'11の以前のMakroにコードの追加行を追加して、シートの名前付き範囲の名前がブックの名前付き範囲の名前になっていないことを確認しました。これらの行がないと、既に定義されているワークブックスクープされた名前付き範囲は削除され、置き換えられます。
Public Sub RescopeNamedRangesToWorkbookV2()
Dim wb As Workbook
Dim ws As Worksheet
Dim objNameWs As Name
Dim objNameWb As Name
Dim sWsName As String
Dim sWbName As String
Dim sRefersTo As String
Dim sObjName As String
Set wb = ActiveWorkbook
Set ws = ActiveSheet
sWsName = ws.Name
sWbName = wb.Name
'Loop through names in worksheet.
For Each objNameWs In ws.Names
'Check name is visble.
If objNameWs.Visible = True Then
'Check name refers to a range on the active sheet.
If InStr(1, objNameWs.RefersTo, sWsName, vbTextCompare) Then
sRefersTo = objNameWs.RefersTo
sObjName = objNameWs.Name
'Check name is scoped to the worksheet.
If objNameWs.Parent.Name <> sWbName Then
'Delete the current name scoped to worksheet replacing with workbook scoped name.
sObjName = Mid(sObjName, InStr(1, sObjName, "!") + 1, Len(sObjName))
'Check to see if there already is a Named Range with the same Name with the full workbook scope.
For Each objNameWb In wb.Names
If sObjName = objNameWb.Name Then
MsgBox "There is already a Named range with ""Workbook scope"" named """ + sObjName + """. Change either Named Range names or delete one before running this Macro."
Exit Sub
End If
Next objNameWb
objNameWs.Delete
wb.Names.Add Name:=sObjName, RefersTo:=sRefersTo
End If
End If
End If
Next objNameWs
End Sub
これらの回答は、Workbook
スコープで名前付き範囲を定義しようとする際に、同様の問題を解決するのに役立ちました。 「あーは!」私にとっては、Names Collectionを使用することです(これは、whole Workbookに関連しています!これは、多くの人にとって明らかなことですが、私の研究では明確に述べられていなかったので、他の人にも同様の質問を共有します。
' Local / Worksheet only scope
Worksheets("Sheet2").Names.Add Name:="a_test_rng1", RefersTo:=Range("A1:A4")
' Global / Workbook scope
ThisWorkbook.Names.Add Name:="a_test_rng2", RefersTo:=Range("B1:b4")
Sheet2がアクティブなときに名前のリストを見ると、両方の範囲がありますが、他のシートに切り替えられ、"a_test_rng1"
は存在しません。
これで、適切と思われるスコープで名前付き範囲をコード内で喜んで生成できます。ネームマネージャーやプラグインをいじる必要はありません。
それ以外にも、Excel Mac 2011のネームマネージャーは混乱していますが、名前の範囲のリストを表示しているときに、名前の横にシートが表示されている場合、何を見ているかを伝える列ラベルはありません、その名前の範囲はワークシート/ローカルです。添付のスクリーンショットをご覧ください。
この記事 への完全な功績は、ピースをまとめることです。