セルの操作(セルのコピー)
マクロ記録の落とし穴
マクロによるセルのコピーは、ビギナーとベテランで最も差が出るコードのひとつです。たとえば、セルA1をセルC2にコピーするコードを考えてみましょう。この操作をマクロ記録すると、次のようなコードが生成されます。
Sub Macro1()
Range("A1").Select
Selection.Copy
Range("C2").Select
ActiveSheet.Paste
End Sub
なるほど、確かに間違っていませんが、決して美しいコードではありません。このコードを参考にして、Sheet1のセルA1をSheet2のセルC2にコピーするコードを作ってみましょう。おそらく次のようになると思います。
Sub Sample1()
Worksheets("Sheet1").Select
Range("A1").Select
Selection.Copy
Worksheets("Sheet2").Select
Range("C2").Select
ActiveSheet.Paste
Worksheets("Sheet1").Select
End Sub
Selectの多用は速度的に不利ですし、画面が切り替わるのもわずらわしいです。そもそも、セルをコピーするのに「コピー元を選択」→「選択セルをコピー」→「コピー先を選択」→「選択シートに貼り付け」という手順がナンセンスです。マクロ記録は操作を忠実にコード化しますから、決して最適化されたコードを生成しないという良い例ですね。
マクロ記録で得られたコードを見て、「そうか、セルのコピーはCopyを使うのか」とわかったら、すぐに
ヘルプで確認 しなければいけません。Copyは何オブジェクトのメソッドだろう?Copyに引数はないのだろうか?など、マクロ記録のコードからはわからないからです。こうした好奇心を持つことが、VBAマスターへも第一歩なのです。ちなみにヘルプは日本語で書かれています。「わかりにくい」と嘆くより「わかろう」と努力してください。さて、ヘルプでCopyメソッドを調べると、次のような構文が書かれています。
expression.Copy(Destination)
expression 必ず指定します。対象となるRangeオブジェクトを返すオブジェクト式を指定します。
Destination 省略可能です。バリアント型(Variant)の値を使用します。コピー先のセル範囲を指定します。
この引数を省略すると、クリップボードへコピーされます。
ヘルプを読むコツは「すべてを理解しようと思わない」ことです。書いてあるうちの
意味の分かるところだけ読んで 、意味の分からない部分は飛ばし読みしてください。たとえば上記の「
バリアント型(Variant)の値を使用します 」は、おそらく多くの方が正確に理解できないであろう記述です。書いてあることは正しいのですが、これを理解するには、ほかのさまざまな知識が必要です。なので、分からなければ、そこは読み飛ばします。引数Destinationは「省略可能」で「コピー先を指定」できるのか・・・と理解すればいいです。意味が分からなかったところは、今後VBAを学習していけば、自然と理解できるようになります。
さて、ヘルプに書かれている内容に戻りましょう。expressionは、要するにコピー元です。Selection.Copyとか、Range("A1").Copyのように書けという意味です。それより気になるのは引数Destinationです。解説によると、
コピー先のセルを指定します と書かれています。Copyメソッドは、コピー元をクリップボードにコピーするだけでなく、同時にコピー先を指定することもできるのです。
マクロ記録で生成されたコードでは、Copyメソッドの引数Destinationが省略されていますので、解説の通りコピー元はクリップボードへコピーされます。そこで次のコードとして、貼り付けのPasteメソッドが必要になってくるのです。
とはいえ、マクロ記録を責めてはいけません。マクロ記録は、行われた操作を忠実にコード化しただけなのですから。
では、ベテランはどう書くかというと、Copyメソッドの引数Destinationにコピー先を指定して、次のようにスッキリしたコードを使います。
Sub Sample2()
Range("A1").Copy Range("C2")
End Sub
もし、Sheet1のセルA1からSheet2のセルC2にコピーする場合も、
Sub Sample3()
Worksheets("Sheet1").Range("A1").Copy Worksheets("Sheet2").Range("C2")
End Sub
これで終わりです。
コードが少ないので高速ですし、修正が容易ですし、ミスが減りますし、可読性が高いですし、良いことばかりです。
なお、Copyメソッドの引数を指定するとき、
Range("A1").Copy Range("C2")
と
Range("A1").Copy
Destination:= Range("C2")
の違いについては、下記ページで解説していますのでご覧ください。
もっと簡単にコピーする
Copyメソッドは、セル全体をコピーします。セル内のデータだけでなく、セルに設定されている書式も含めてセル全体です。ところが、セルをコピーするとき「データだけでいいんだけど・・・」というときもあるでしょう。そんなときは、律儀にCopyメソッドを使わず、次のようにする手もあります。
Sub Sample4()
Range("C2") = Range("A1")
End Sub
書式は引き継がれませんが、セルのデータはコピーできます。これで十分なケースも多いはずです。いわゆる
値貼り付け ですね。実務では、セルの値だけをコピーしたい場合が少なくありません。そんなとき「値だけコピーするんだから・・・そうか!
形式を選択して貼り付け の"値"を使えばいいのか。うん、手作業でもそうするしな。よし、マクロ記録してみよう。え〜と、なになに・・・PasteSpecial・・・なんか、ゴチャゴチャして・・・ま、いっか。マクロ記録されたんだから正しいんだろう。これをそのまま使っちゃえ」
などと考えて、ずらずらとPasteSpecialを繰り返している人が、実に多いです。ほら、これを読んでいるあなた。あなたですよ(笑)。こうした方は、次の重要な2つのことを、正しく認識していなかったのでしょうね。
セルの値はValueプロパティで表される
マクロ記録で、マクロを作ろうとしてはいけない
もし、この方法で、複数セルの値だけをコピーするときは、次のように
Valueプロパティを省略せずに指定 してください。複数セルの値を操作するとき、Valueプロパティは省略できません。
Sub Sample5()
Range("C1:D5").Value = Range("A1:B5").Value
End Sub
もちろん、コピー元と貼り付け先は、
同じ大きさのセル範囲 でなければなりません。
← 表示形式の設定 | セル範囲の取得 →