マクロによるセルのコピーは、ビギナーとベテランで最も差が出るコードのひとつです。たとえば、セル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プロパティは省略できません。
Sub Sample5() Range("C1:D5").Value = Range("A1:B5").Value End Sub
もちろん、コピー元と貼り付け先は、同じ大きさのセル範囲でなければなりません。