[[20260212162936]] 『シートの複製』(くわっす) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『シートの複製』(くわっす)

お尋ねします。
Sheet1のA列に名前のリストが入力されており、
そのリストのデータと同じ名前の個別シートがあるのですが、
リストに新規データが追加された場合に、シートを複製してリストの新規データと同じ名前のシート名で作成することは可能でしょうか?

ーーー
【Sheet1】
A列 B列 C列
地域名?@  ‥  ‥
地域名?A  ‥  ‥
地域名?B  ‥  ‥
地域名?C  ‥  ‥
地域名?D  ‥  ‥

ーーー
Dim Grpws As Worksheet
Dim GrpSheets As Variant

    GrpSheets = Array("地域名?@", "地域名?A", "地域名?B", "地域名?C", "地域名?D")

For Each Grpws In Worksheets

If Not IsError(Application.Match(Grpws.Name, GrpSheets, 0)) Then

 〜〜以下作業内容割愛〜〜

End If

ーーー
現状、リストの名前を直接Arrayでまとめているのですが、新規データが追加された場合に対応できないため、
1.シートの複製
2.シート名をリストの名前に変更
3.Arrayの中に含めて、作業を実行
できるようにしたいと考えています。

お力添えをいただければ幸いです。
不慣れなため、お伝えしている情報が不足しておりましたら申し訳ありません。
何かあれば追記しますので、どうぞよろしくお願いいたします。

< 使用 Excel:Microsoft365、使用 OS:Windows11 >


 こんな感じでどうですか。(動作確認済み)

 Sub test()
     Dim ws1     As Worksheet
     Dim ws      As Worksheet
     Dim wsName  As Variant

     Set ws1 = Worksheets("Sheet1")
     For Each wsName In ws1.Range("A1", ws1.Cells(Rows.Count, "A").End(xlUp)).Value
         Set ws = Nothing           'こちらに書くほうが自然かも
         On Error Resume Next
         Set ws = Worksheets(wsName)
         On Error GoTo 0
         If ws Is Nothing Then
             Worksheets("template").Copy Before:=Worksheets("template")
             Set ws = ActiveSheet
             ws.Name = wsName
         End If
         'このあと定例処理
         ws.Range("B1").Value = ws.Name  ' 架空例です
      Next
 End Sub

(xyz) 2026/02/12(木) 17:18:28


 ワークシートの存在をチェックする方法は、少なくともあと二つあります。ほかの方にお願いします。
(xyz) 2026/02/12(木) 17:20:15

 参考
 https://learn.microsoft.com/ja-jp/office/vba/api/excel.worksheet.change
 https://learn.microsoft.com/ja-jp/office/vba/api/excel.worksheet.calculate(even)

 >リストに新規データが追加された場合に、

 というのはイベント駆動にしたいということではないでしょうか。
 VBA全く知らないのでよくわからないのですが、
 プロシージャ名(オブジェクト名?)を特定のものにするとイベント駆動するみたいです。
(ちくわ) 2026/02/12(木) 18:28:19

 コードだけでなく、説明を追加しておきます。

 (1)
 最初に申し上げたいのは、
 ・Sheet1のA列に対象となるシート名があるにもかかわらず、
 ・VBAのコードのなかに別にArrayを(直接書き込んで)保持するというのは
 設計として適切ではないという点です。

 同じものをコードに書き込むのは、手作業になりますし、間違いも起きやいからです。
 理論的にはマクロでマクロを操作できますが、そもそもそんなことする必要がありません。
 Sheet1のA列のデータだけを、唯一のソースにして、それを直接読み込めばよいだけです。

 (2)
 次に、今のロジックは、
    ・各シートを順次見ていき、Sheet1にある対象シート名に該当すれば、なんらかの作業をするという方式。
 そうではなくて、   
    ・Sheet1にある対象シート名を順次見ていき、そのシートがあるかどうかを確認
    ・なければシートを追加
    ・その後、既定の作業を実施
 とすればいい。

 (3)シートの存在チェックについては、次の投稿に書きます。    

 (4)
 なお、Changeイベントプロシージャを使う案が出されていますが、
 質問者さんからの回答を待ちたいと思います。
 (そういう意図かもしれないし、そうでないかも知れません。こちらが答える話でもない)

 # 私見を書きますと、この場合はイベントプロシージャに余り賛成できません。
 #  (Changeイベントプロシージャに関してはここで何十回と回答してますけど)
 # こうした多くのシートにわたる作業を、簡単な操作で起動してしまうイベントプロシージャで実行することは、
 # かえって思わぬことに巻き込まれることがリスクとしてありえます。
 # 
 # イベントプロシージャで実行する内容が不明ですから、確定的なことは言えませんが。
 # "単にセルを変更したいだけで、そういう処理(極端な場合累積計算など)計算をする積りでは無かった"
 # などといったことは起きがちです。
 # マクロによる更新は、簡単に取り消しはできないので、修復が必要な場合は面倒なことになります。

 # また、イベントプロシージャは見た目以上に気を使う論点がいろいろあります。
 # (複数セルを同時に変更するケース(コピーペイスト等)への対応、消去動作への対応等々)
 # ステップを踏んで取り入れていくほうがよいと思います。 
 # 私は、提示されたマクロに機能追加する方向を推奨します。

 >何かあれば追記しますので、どうぞよろしく
 とのこと。言行一致でお願したい。
 回答者さんから確認のコメントがあるのですから。
(xyz) 2026/02/13(金) 15:58:58

 シートの存在チェックをFunctionプロシージャにしてしまったほうが分かり易かったですね。

 Sub test()
     Dim ws1     As Worksheet
     Dim ws      As Worksheet
     Dim wsName  As Variant

     Set ws1 = Worksheets("Sheet1")
     For Each wsName In ws1.Range("A1", ws1.Cells(Rows.Count, "A").End(xlUp)).Value
         If isExist(CStr(wsName)) Then       'ワークシートの存在チェック
             Set ws = Worksheets(wsName)
         Else
             Worksheets("template").Copy Before:=Worksheets("template")
             Set ws = ActiveSheet
             ws.Name = wsName
         End If
         '定例処理
         ws.Range("B1").Value = 100  ' 架空の例です
     Next
 End Sub

 Function isExist(s As String) As Boolean
         Dim ws As Worksheet
         On Error Resume Next
         Set ws = Worksheets(s)
         On Error GoTo 0
         If ws Is Nothing Then
             isExist = False
         Else
             isExist = True
         End If
 End Function

 =========================
 ついでに別の手法にも触れておきます。
 下記のように定義したうえで、isExistをisExist2またはisExist3に変更してみて下さい。

 'ワークシートの存在チェック2(既存シートを逐一走査する方法)
 Function isExist2(s As String) As Boolean
     Dim ws As Worksheet
     For Each ws In Worksheets
         If ws.Name = s Then
             isExist2 = True
             Exit For
         End If
     Next
 End Function

 'ワークシートの存在チェック3(ワークシート関数ISREFを援用する方法)
 Function isExist3(s As String) As Boolean
     isExist3 = Evaluate("ISREF('" & s & "'!A1)")
 End Function

(xyz) 2026/02/13(金) 16:01:08


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.