[[20210611120508]] 『オブジェクト変数 と Array について』(しのみや) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『オブジェクト変数 と Array について』(しのみや)

 教えてください。

 今まで、
 新規ワークブックに2枚のシートをコピーする場合、
 SubTESTのようにシート名を固定にして使っていました。

 Sub TEST()
    Sheets(Array("A", "B")).Copy
 End Sub

 オブジェクト変数に入れて、SubTEST2にしました。
 Sub TEST2()
    Dim wsA As Worksheet
    Dim wsB As Worksheet
    Set wsA = Sheets("A")
    Set wsB = Sheets("B")

   ’ハテナ   
 End Sub

 Arrayの部分をどうしたらよいかわからずにいます。

 wsA.copy
 wsB.copy
 とすると、新規ワークブックにwsAとwsBが別々にコピーされてしまいます。
 どのようにするのでしょうか。

< 使用 Excel:Excel2010、使用 OS:Windows10 >


 wsA.name など。
(オーソドックス) 2021/06/11(金) 12:21

 オーソドックスさん ありがとうございます。

 wsA.Nameですと、
 Sheets(Array(wsA.Name, wsB.Name)).Copy
 こんな感じを思いつくのですが仰っていることと合ってますでしょうか…

 上記で必要な結果は得られるのですが、
 Sheets(wsA.Name).Copyの場合は、wsA.copyとすっきり書けるのに…と…

 https://www.excel.studio-kazu.jp/kw/20210526152051.html
 ここで教えて頂いておりまして、今オブジェクトを勉強中でして、
 今まで自分が作っていたコードにいろいろ疑問が出ている状況にいます…

(しのみや) 2021/06/11(金) 12:41


>Sheets(Array(wsA.Name, wsB.Name)).Copy

はい。
(オーソドックス) 2021/06/11(金) 12:43


 >Sheets(wsA.Name).Copyの場合は、wsA.copyとすっきり書けるのに…と…

どうなったらすっきりかわかりませんが、そういう仕様です。

マクロの記録をしてみたら、そうなるから、そういうもんだと納得してますが。。。。

あぁ、
複数シートだからそういう場合はオブジェクトの型が

 Sheets

になりますね。

Sub test()

    Dim shts As Sheets

    Set shts = Worksheets(Array("Sheet1", "Sheet2"))

    shts.Copy
End Sub
(まっつわん) 2021/06/11(金) 13:15

型が分らん時はとりあえずvariant型の変数に代入してみると、
ローカルウィンドウでどんな型が入ったか確認することができます。

臨機応変に行きましょう^^
(まっつわん) 2021/06/11(金) 13:18


ちょっと質問の趣旨と違いますが・・・

個人の見解です。
文字列での指定が重複している場合、可能な限り、定数や変数に代入して
1度だけ記述し、定数や変数を使う。

理由はバグ防止と可読性です。
バグ防止として
質問者さんの場合を仮定すると、何らかの理由でシート名が変更になった場合、
各モジュールに文字列でシート名を記載していると、全て修正しなければいけなく、
変更漏れが起こりうることが考えられます。
場合によってはコンパイルチェックも実行してもエラーが出ず、結果が望んでいるものとは
違うことに。

モジュールの頭にOption Explicitとしていると思いますので、
定数、変数の記述ミスがあればVBEが教えてくれます。
インテリセンスも働きますし、記述も楽かな、と。

可読性に関しては、定数にしてしまえば不変ですので、中身をいちいち考えなくていいですよね。
変数であれば、中身を気にしながら読んでいきますので。

(tkit) 2021/06/11(金) 13:20


サンプルです

    Option Explicit
    Private Const SHT_A_NAME As String = "A"
    Private Const SHT_B_NAME As String = "B"
    Sub Sample()
        Dim wsA As Worksheet
        Dim wsB As Worksheet
        Set wsA = Worksheets(SHT_A_NAME)
        Set wsB = Worksheets(SHT_B_NAME)
    End Sub

ルールに則って記述すればいいと思いますよ。
無ければご自身のまたはチームで作ってみては。
(tkit) 2021/06/11(金) 14:01


 私が覚えたてなのでいろいろ必要のない疑問に
 ぶつかってしまっていることもあるかと思いますが…
 Arrayの場合、.nameで名前指定することが、
 どんなけ名前好きなの症候群になってるような気がしてしまったのです… -_-

 まっつわんさん ありがとうございます。
 Arrayにした配列をsheetsのオブジェクトにして扱うのですね。
 variant型に入れて型を確認する方法もありがとうございます。

 tkitさん ありがとうございます。
 おかげさまで少しは理解はできてきましたので…
 オブジェクトに入れる方が扱いやすいことはわかります。

 わかるのですが、それで…どうしたら?というところで頭が固まるので、
 サンプルも助かります。

 ほかにVBAを触ってる方がおらず全くルールもない環境でして…
 自分ルールを作るにしても知識がなさすぎて、
 試行錯誤中です…
(しのみや) 2021/06/11(金) 14:32

 オーソドックスさん 
 教えてくださりありがとうございます。
 *頭がいっぱいで書き込み遅れましたすみません。
(しのみや) 2021/06/11(金) 14:54

Selectする例です。
参考になれば。

Option Explicit

Sub test2()

    Dim v As Variant
    Dim flg As Boolean
    Dim ws As Worksheet

    flg = True
    v = Split("Sheet1,Sheet2", ",")

    For Each ws In Worksheets
        If IsError(Application.Match(ws.Name, v, 1)) = False Then
            ws.Select flg
            If flg = True Then flg = Not flg
        End If
    Next

    ActiveWindow.SelectedSheets.Copy
End Sub

動作確認してません。
(まっつわん) 2021/06/11(金) 18:06


 > どんだけ名前好きなの症候群になってるような気がしてしまったのです… -_-

 今回のケースでは、名前(配列)で指定しないとワークしないんですよ。

 マイクロソフトの仕様がお粗末とも言えますが、仕様に逆らうことはできません。
 マイクロソフトに言わせれば、そんなに手厚く配慮しなければならないメソッドですかねぇ・・ってことじゃないですか?

(半平太) 2021/06/11(金) 18:20


 見直していたら書き込み頂いていることに気が付きました
 遅くなりすみません…
 まっつわんさん 半平太さん ありがとうございます
(しのみや) 2021/06/29(火) 12:15

ArrayというのはVB6時代ものなので
オブジェクトを扱えないのです。
「新しい酒は新しい革に入れよ」
なんて言葉を思い出す。
(γ) 2021/06/29(火) 12:45

編集がかぶりましたがそのまま。

久々に見かけたので、ふと思ったことなど
まっつわんさんのコメントは、研究してみたのでしょうか?

>Arrayの部分をどうしたらよいかわからずにいます。
Arrayが配列を意味しているということが判っていればですが↓のようにしてもよいことに気づくとおもいます

    Sub 実験()
        Dim 文字列 As String
        文字列 = "A,B"

        ThisWorkbook.Worksheets(Split(文字列, ",")).Copy
    End Sub

こうなれば、「文字列」はそのまま"文字列"として扱っているだけなので、好きな形にできますよね?
さらに、上記はSplit関数で"配列"に加工しているわけですから

    Sub 実験2()
        Dim 文字列 As String
        Dim 配列 As Variant
        文字列 = "A,B"
        配列 = Split(文字列, ",")

        ThisWorkbook.Worksheets(配列).Copy
        MsgBox Join(配列, "・") & "シートをコピーしました"
    End Sub

のようなことも可能です。

よって、「Arrayの部分」だけに注目するのではなく、その意味するところにも注目するとよいのではないかとおもいました。

(もこな2) 2021/06/29(火) 12:51


 既に指摘いただいているとおりですが、遅ればせながら少しコメントします。

 "○○症候群"(○○は省略)と書いたのは、すでにそうしたオブジェクト変数があるにもかかわらず、
 名前を使ってオブジェクトを再指定するようなことを指した積もりでした。

 オブジェクトそのものを作成する段階で、名前を使うことは結構あると思います。
 こうした場合に準拠すべきは、VBAのヘルプです。これが原典ですから。

 <<Sheetsオブジェクト>>のヘルプから引用。
 | 指定されたブックまたは作業中のブックにあるすべてのシートのコレクションです。
 | 複数のシートを指定するには、Sheets(array) プロパティを使用します。
 | 次の使用例は、"Sheet4" と "Sheet5" というシートをブックの先頭に移動します。
 | Sheets(Array("Sheet4", "Sheet5")).Move before:=Sheets(1) 
 この場合は、Sheets(Array("Sheet4", "Sheet5"))のような形で指定せざるを得ないのです。

 単にオブジェクトのコレクションを作っても、Sheetsオブジェクトとはならないので、
 私の指摘はミスリーディングの懸念がありました。
 Arrayは値や文字列(や配列など)を納める容れ物であって、
 オブジェクトを対象にできないこと、が言いたいことでした。

 何事もそうですが、オブジェクトにどんなコンストラクターが装備されているかは
 原典に戻るのが基本です。
(γ) 2021/06/30(水) 06:14

 問題の所在が不明瞭に感じるのですが、

 これは成立します。
  ↓
 Sub TestArray()
     Dim a As Worksheet
     Dim b As Worksheet
     Dim c

     Set a = Sheets(1)
     Set b = Sheets(2)

     c = Array(a, b)         '0ベースの配列

     Debug.Print c(1).Name   'Sheet2が表示される
 End Sub

 これは成立しない。
  ↓
 Sub SheetsCopy()
     Dim a As Worksheet
     Dim b As Worksheet
     Dim c

     Set a = Sheets(1)
     Set b = Sheets(2)

     c = Array(a, b)            '0ベースの配列

     Sheets(Array(a, b)).Copy   '型不一致エラー
     Sheets(c).Copy             '型不一致エラー
 End Sub

 何故かと言えば、Microsoftがその構文で成立するように作ってないからです。

 不成立にする必然性がある訳ではありません。
 Microsoftがその気になれば成立させることは出来るんです。
 でもそう作り込まなかった。それだけです。悩んでもしょうがないです。

 それが「仕様」と言うものです。仕様に従うしかないです。

(半平太) 2021/06/30(水) 09:45


 あれ、私はだいぶ勘違いしていたようですね。失礼しました。
 私のArrayに関する記述はなかったことにしてください。
(γ) 2021/06/30(水) 10:02

 Arrayは配列なので Split関数で指定する方法について、
 お教えくださり感謝しております。

 今現在、オブジェクト変数と、固定のシート名を指定したりしています。
 Sheets(Array(wsAAA.Name, "結果")).copy
 この1行で必要な動作は得られているので、これでよいかなぁ…とは思っておりますが、
 だいぶ不恰好な気もしています。
 かといってこの1行のためにややこしく書くのもうーんと思っています。

 たくさんの情報下さりありがとうございます、頭に入れておきたいと思います。

(しのみや) 2021/07/01(木) 11:05


コメント返信:

[ 一覧(最新更新順) ]


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