ワークシートをコピーしたときに取得するnewシートのワークシートオブジェクトを取得する簡単/短い方法はありますか?
ActiveWorkbook.Sheets("Sheet1").Copy after:=someSheet
.Copyメソッドがワークシートオブジェクトの代わりにブール値を返すことがわかりました。そうでなければ、私はできたでしょう:
set newSheet = ActiveWorkbook.Sheets("Sheet1").Copy after:=someSheet
そのため、オブジェクトを取得するために約25行のコードを記述しました。コピー前にすべてのシートをリストし、後にすべてのシートをリストし、2番目のリストのみにあるシートを特定します。
よりエレガントで短いソリューションを探しています。
Dim sht
With ActiveWorkbook
.Sheets("Sheet1").Copy After:= .Sheets("Sheet2")
Set sht = .Sheets(.Sheets("Sheet2").Index + 1)
End With
私はこの問題をついに釘付けにしたと信じています-それもまた私を狂わせてきました! Addメソッドと同じように、MSがコピーにシートオブジェクトを返させたら、それは本当に素晴らしいことでした...
問題は、VBAが新しくコピーされたシートを割り当てるインデックスは実際には決定されていないことです...他の人が指摘しているように、非表示のシートに大きく依存します。実際、Sheets(n)という表現は実際には「n番目に表示されるシート」として解釈されると思います。したがって、すべてのシートの可視プロパティをテストするループを作成しない限り、ユーザーがシートの可視プロパティを混乱させることができないようにワークブックが保護されていない限り、コードでこれを使用すると危険が伴います。あまりにもハード...
このジレンマに対する私の解決策は次のとおりです。
これが私のコードです-今は防弾のようです...
Dim sh as worksheet
Dim last_is_visible as boolean
With ActiveWorkbook
last_is_visible = .Sheets(.Sheets.Count).Visible
.Sheets(Sheets.Count).Visible = True
.Sheets("Template").Copy After:=.Sheets(Sheets.Count)
Set sh=.Sheets(Sheets.Count)
if not last_is_visible then .Sheets(Sheets.Count-1).Visible = False
sh.Move After:=.Sheets("OtherSheet")
End With
私の場合、私はこのようなものを持っていました(Hは隠されたシートを示します)
1 ... 2 ... 3(H)... 4(H)... 5(H)... 6 ... 7 ... 8(H)... 9(H)
.Copy After:=。Sheets(2)は、実際には次のVISIBLEシートの前に新しいシートを作成します。つまり、それは新しいインデックス6になります。予想通り、インデックス3ではありません。
お役に立てば幸いです;-)
私が使用したもう1つの解決策は、インデックスを知っている場所にシートをコピーすることです。そこで、必要なものを簡単に参照でき、その後、好きな場所に自由に移動できます。
このようなもの:
Worksheets("Sheet1").Copy before:=Worksheets(1)
set newSheet = Worksheets(1)
newSheet.move After:=someSheet
更新:
Dim ThisSheet As Worksheet
Dim NewSheet As Worksheet
Set ThisSheet = ActiveWorkbook.Sheets("Sheet1")
ThisSheet.Copy
Set NewSheet = Application.ActiveSheet
この投稿は1年以上前のものだと思いますが、私はここに来て、シートのコピーに関する同じ問題と、非表示のシートによって引き起こされる予期しない結果の答えを探しました。上記のどれも、主にワークブックの構造が原因で、私が欲しかったものに実際には適していません。本質的に、非常に多数のシートがあり、表示されるのはユーザーが特定の機能を選択することによって駆動されます。さらに、表示されるシートの順序は私にとって重要でしたので、それらを台無しにしたくありませんでした。したがって、私の最終的な解決策は、コピーしたシートをExcelのデフォルトの命名規則に依存し、新しいシートの名前を明示的に変更することでした。以下のコードサンプル(余談ですが、私のワークブックには42枚のシートがあり、7枚だけが永続的に表示されています。after:=Sheets(Sheets.count)
は、現在表示されているシートに応じて、コピーしたシートを42枚のシートの中央に配置します。
Select Case DCSType
Case "Radiology"
'Copy the appropriate Template to a new sheet at the end
TemplateRAD.Copy after:=Sheets(Sheets.count)
wsToCopyName = TemplateRAD.Name & " (2)"
'rename it as "Template"
Sheets(wsToCopyName).Name = "Template"
'Copy the appropriate val_Request to a new sheet at the end
valRequestRad.Copy after:=Sheets(Sheets.count)
'rename it as "val_Request"
wsToCopyName = valRequestRad.Name & " (2)"
Sheets(wsToCopyName).Name = "val_Request"
Case "Pathology"
'Copy the appropriate Template to a new sheet at the end
TemplatePath.Copy after:=Sheets(Sheets.count)
wsToCopyName = TemplatePath.Name & " (2)"
'rename it as "Template"
Sheets(wsToCopyName).Name = "Template"
'Copy the appropriate val_Request to a new sheet at the end
valRequestPath.Copy after:=Sheets(Sheets.count)
wsToCopyName = valRequestPath.Name & " (2)"
'rename it as "val_Request"
Sheets(wsToCopyName).Name = "val_Request"
End Select
とにかく、誰かに役立つので念のため投稿しました
Daniel Labelleからの提案で更新:
非表示の可能性のあるシートを処理するには、ソースシートを表示してコピーし、ActiveSheet
メソッドを使用して新しいシートへの参照を返し、表示設定をリセットします。
Dim newSheet As Worksheet
With ActiveWorkbook.Worksheets("Sheet1")
.Visible = xlSheetVisible
.Copy after:=someSheet
Set newSheet = ActiveSheet
.Visible = xlSheetHidden ' or xlSheetVeryHidden
End With
これは@TimWilliamsへの応答としてのコメントでなければなりませんが、これは私の最初の投稿なのでコメントできません。
これは、非表示のシートに関連して@RBarryYoungが言及した問題の例です。最後のシートの後にコピーを配置しようとすると、最後のシートが非表示になるという問題があります。最後のシートが非表示の場合、常に最高のインデックスが保持されるようなので、次のようなものが必要です
Dim sht As Worksheet
With ActiveWorkbook
.Sheets("Sheet1").Copy After:=.Sheets(.Sheets.Count)
Set sht = .Sheets(.Sheets.Count - 1)
End With
非表示の最初のシートの前にコピーしようとしたときの同様の状況。
非表示のワークシートが原因で、新しいワークシートのインデックスがソースワークシートのいずれかの側で非順次になるのは正しいことです。以前にコピーしている場合は、レイチェルの答えが機能することがわかりました。ただし、後でコピーする場合は、調整する必要があります。
モデルが表示されてコピーされると、ソースをコピーする前でも後でも、新しいワークシートオブジェクトはActiveSheetになります。
プリファレンスとして、次のものを置き換えることができます。
Set newSheet = .Previous
セット付きnewSheet = Application.ActiveSheet
。
これがあなたの一部に役立つことを願っています。
すでにここで述べたように、シートを左端(インデックス= 1)にコピーして貼り付け、変数に割り当ててから、好きな場所に移動します。
Function CopyWorksheet(SourceWorksheet As Worksheet, AfterDestinationWorksheet As Worksheet) As Worksheet
Dim DestinationWorkbook As Workbook
Set DestinationWorkbook = AfterDestinationWorksheet.Parent
Dim FirstSheetVisibility As XlSheetVisibility
FirstSheetVisibility = DestinationWorkbook.Sheets(1).Visible
DestinationWorkbook.Sheets(1).Visible = xlSheetVisible
SourceWorksheet.Copy Before:=DestinationWorkbook.Sheets(1)
DestinationWorkbook.Sheets(2).Visible = FirstSheetVisibility
Dim NewWorksheet As Worksheet
Set NewWorksheet = DestinationWorkbook.Sheets(1)
NewWorksheet.Move After:=AfterDestinationWorksheet
Set CopyWorksheet = NewWorksheet
End Function
古い投稿ですが、シートを再表示したり、名前にサフィックスを追加したりすることについては確信がありませんでした。
これは私のアプローチです:
Sub DuplicateSheet()
Dim position As Integer
Dim wbNewSheet As Worksheet
position = GetFirstVisiblePostion
ThisWorkbook.Worksheets("Original").Copy Before:=ThisWorkbook.Sheets(position)
Set wbNewSheet = ThisWorkbook.Sheets(position)
Debug.Print "Duplicated name:" & wbNewSheet.Name, "Duplicated position:" & wbNewSheet.Index
End Sub
Function GetFirstVisiblePostion() As Integer
Dim wbSheet As Worksheet
Dim position As Integer
For Each wbSheet In ThisWorkbook.Sheets
If wbSheet.Visible = xlSheetVisible Then
position = wbSheet.Index
Exit For
End If
Next
GetFirstVisiblePostion = position
End Function
Trevor Normanの方法 に基づいて、シートをコピーして新しいシートへの参照を返す関数を開発しました。
コード:
Function CopySheet(ByRef sourceSheet As Worksheet, Optional ByRef destinationWorkbook As Workbook) As Worksheet
Dim newSheet As Worksheet, lastSheet As Worksheet
Dim lastIsVisible As Boolean
If destinationWorkbook Is Nothing Then Set destinationWorkbook = sourceSheet.Parent
With destinationWorkbook
Set lastSheet = .Worksheets(.Worksheets.Count)
End With
lastIsVisible = lastSheet.Visible
lastSheet.Visible = True
sourceSheet.Copy After:=lastSheet
Set newSheet = lastSheet.Next
If Not lastIsVisible Then lastSheet.Visible = False
Set CopySheet = newSheet
End Function
これにより、コピー先のブックの最後に常にコピーされたシートが挿入されます。
この後、移動、名前変更などを行うことができます。
使用法:
Sub Sample()
Dim newSheet As Worksheet
Set newSheet = CopySheet(ThisWorkbook.Worksheets("Template"))
Debug.Print newSheet.Name
newSheet.Name = "Sample" ' rename new sheet
newSheet.Move Before:=ThisWorkbook.Worksheets(1) ' move to beginning
Debug.Print newSheet.Name
End Sub
または、動作/インターフェースを組み込みのCopyメソッドに似せる場合(つまり、前/後)、次のように使用できます。
Function CopySheet2(ByRef sourceSheet As Worksheet, Optional ByRef beforeSheet As Worksheet, Optional ByRef afterSheet As Worksheet) As Worksheet
Dim destinationWorkbook As Workbook
Dim newSheet As Worksheet, lastSheet As Worksheet
Dim lastIsVisible As Boolean
If Not beforeSheet Is Nothing Then
Set destinationWorkbook = beforeSheet.Parent
ElseIf Not afterSheet Is Nothing Then
Set destinationWorkbook = afterSheet.Parent
Else
Set destinationWorkbook = sourceSheet.Parent
End If
With destinationWorkbook
Set lastSheet = .Worksheets(.Worksheets.Count)
End With
lastIsVisible = lastSheet.Visible
lastSheet.Visible = True
sourceSheet.Copy After:=lastSheet
Set newSheet = lastSheet.Next
If Not lastIsVisible Then lastSheet.Visible = False
If Not beforeSheet Is Nothing Then
newSheet.Move Before:=beforeSheet
ElseIf Not afterSheet Is Nothing Then
newSheet.Move After:=afterSheet
Else
newSheet.Move After:=sourceSheet
End If
Set CopySheet2 = newSheet
End Function
複数のプロジェクトで再利用できるように、sheet.Copyメソッドの信頼できる汎用「ラッパー」関数を何年も作成しようとしています。
ここでいくつかのアプローチを試しましたが、すべてのシナリオで信頼できるソリューションであるのはマークムーアの答えだけでした。つまり、「テンプレート(2)」の名前を使用して新しいシートを識別します。
私の場合、「ActiveSheetメソッド」を使用したソリューションは役に立たなかった。インスタンスによっては、ターゲットブックが非アクティブまたは非表示のワークブックにある場合があった。
同様に、私のワークブックのいくつかは、さまざまな場所で非表示のシートと目に見えるシートが混在しています。最初、途中、最後。したがって、Before:オプションとAfter:オプションを使用したソリューションも、表示シートと非表示シートの順序、およびソースシートも非表示になっている場合の追加の要因によっては信頼できないことがわかりました。
したがって、何度か書き直した後、次のラッパー関数が作成されました。
'***************************************************************************
'This is a wrapper for the worksheet.Copy method.
'
'Used to create a copy of the specified sheet, optionally set it's name, and return the new
' sheets object to the calling function.
'
'This routine is needed to predictably identify the new sheet that is added. This is because
' having Hidden sheets in a Workbook can produce unexpected results in the order of the sheets,
' eg when adding a hidden sheet after the last sheet, the new sheet doesn't always end up
' being the last sheet in the Worksheets collection.
'***************************************************************************
Function wsCopy(wsSource As Worksheet, wsAfter As Worksheet, Optional ByVal sNewSheetName As String) As Worksheet
Dim Ws As Worksheet
wsSource.Copy After:=wsAfter
Set Ws = wsAfter.Parent.Sheets(wsSource.Name & " (2)")
'set ws Name if one supplied
If sNewSheetName <> "" Then
Ws.Name = sNewSheetName
End If
Set wsCopy = Ws
End Function
注:最大のシート名が31であるため、ソースシートの名前が27文字を超える場合、このソリューションでも問題が発生しますが、通常、これは私の管理下にあります。