[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『オブジェクト変数 と 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
はい。
(オーソドックス) 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
臨機応変に行きましょう^^
(まっつわん) 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
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の部分をどうしたらよいかわからずにいます。
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.