セルに入力された数式・関数を、
VBAを使って別のセル範囲へコピーする方法を紹介します。
セル範囲に数式を入力するコード
D列に数式を入れましょう。
売上=価格×個数をやりたいので、「=B2*C2」が目的の数式ですね。
これをD2~D7セルに入力する場合は、以下のコードを実行します。
Range("D2:D7").Formula = "=B2*C2"
かなり簡単なコードで実行できますね。
「セル範囲.Formula = 数式」と入力した場合は、
セル範囲の第1セルにその数式を入力し、
その後他のセルへコピーしたときと同じように数式が入ります。
条件付き書式の数式をいじったことがある人は、
あれと同じような書き方というとわかりやすいでしょうか。
この「数式のコピー」について検索された方は、
- まずD2セルに数式を入れる
- D3~D7にその数式をコピーする
という手順をイメージされたかもしれません。
しかし、数式を一括入力するだけなら、
Range("D2:D7").Formula = "=B2*C2"
この1行で済むということになります。
簡単で便利な方法ですので覚えておきましょう。
あるセルの数式をコピーするコード
ただ数式を入力したい場合は、
- まずD2セルに数式を入れる
- D3~D7にその数式をコピーする
この手順は不要でした。
しかしD2セルの数式がシート上で既に入力されていて、
それをコピーしたいという場合もあると思います。
このD2セルに既に数式が入っている場合に、
それをD3~D7セルへコピーする方法がこちらになります。
' D2セルの数式をD3:D7セルにコピーする Range("D2:D7").Formula = Range("D2").Formula
この方法でD2セルの数式をD3~D7セルにコピーすることができます。
仕組みはとても単純で、セルの数式を取得するFormulaプロパティを使った、
Range("D2").Formula
このコードで「=B2*C2」を取得できます。
それを、
Range("D2:D7").Formula = Range("D2").Formula
これに代入してみると、
Range("D2:D7").Formula = "=B2*C2"
となって、目的の式になっていることがわかります。
!注意!コピーするセルもペースト範囲に含めること
この「数式をコピーするコード」には危険な罠があります。
手作業と明確に異なる点があったのですが、気づきましたでしょうか?
Range("D2:D7").Formula = Range("D2").Formula
↑よく見ると、
コピー先エリアがD2:D7と、コピー元であるD2セルが含まれていますね。
これがかなり重要なポイントです。
ただ「D2をD3~D7セルにコピー」というと、以下の式が思いつきます。
Range("D3:D7").Formula = Range("D2").Formula
D2をD3:D7へ、という素直な書き方です。
ですがこれをやると、
D3に「=B2*C2」が入力され1行ずつ関数がズレてしまうのです。
ここで冒頭の説明を思い出してください。
「セル範囲.Formula = 関数式」と入力した場合は、
セル範囲の第1セルにその関数を入力し、
その後他のセルへコピーしたときと同じように数式が入ります。
その仕様を意識してもう一度コードを見ましょう。
Range("D3:D7").Formula = Range("D2").Formula ' =B2*C2
よーくコードを見ると、素直に仕様通りに処理されただけなのがわかります。
手作業からくる錯覚で、このミスは気づきにくいですので注意してください。
数式のコピーを行う際は、「コピー元のセルをコピー先にも含める」必要があることを覚えておいてください。
なお、先ほどダメだった
Range("D3:D7").Formula = Range("D2").Formula
この書き方ですが、実は、
Range("D3:D7").FormulaR1C1 = Range("D2").FormulaR1C1
と、プロパティを「FormulaR1C1」に変えると成功します。
ただ、この方法はFormulaR1C1の正規の使い方ではなく、
裏技的な使い方なのでおすすめしません。
稀にこの解決策を取っているコードを見かけると思いますので、
コードを読むとき用に、心の片隅にでも置いておいてください。
おまけ:実はこの方法、超高速マクロの入り口です
この方法を探していた方は、
シートに入力する関数の作成も自動化したいとか、
関数の方が楽に書けるような処理をマクロでやりたいとか、
そういった需要と推測します。
が、この方法、簡単に書けるだけでなく、実は滅茶苦茶早いです。
For R = 2 To 7 Cells(R, 4) = Cells(R, 2) * Cells(R, 3) Next
こんな感じで普通にForを回すより速いのは当然なのですが、
' VLOOKUPをFormulaで Range("D2:D7").Formula = "=VLOOKUP(A2,くだものリスト!A:B,2,FALSE)" ' VlookupをWorksheetFunctionで For R = 2 To 7 Cells(R, 4) = WorksheetFunction.Vlookup(Cells(R, 1), wsくだものリスト.Columns("A:B"), 2, False) Next
↑このような、
「まったく同じ関数で戦う Formula VS WorksheetFunction」の戦いでも、
Formulaが圧勝します。
理由を説明しますと、
1番大きいのが、「セルひとつひとつに入力していないから」です。
よく「配列にすると早い」と言われますよね。
あれは「配列でメモリ上で処理するから早い」というのもありますが、
「処理後に配列ごと一気にセルに戻している」のが、早さの一番の理由です。
配列に限らず、
' 100回かけて1を代入 For R = 1 To 100 Cells(R, 1) = 1 Next ' 1回で1を代入 Range("A1:A100").Value = 1
↑のような単純な処理でも、後者が圧倒的に速いというのが、
配列を使った高速化のカラクリです。
今回のFormulaプロパティへの関数一括入力は、
すべてのセルに対して同時に入力されていますので、
配列でやったときに近い速度効果が得られるというわけですね。
この方法がチートなのは、
「配列などの高度な高速化に比べて、圧倒的にコーディング難易度が低い」ことです。
「わたしシート関数はわかりますが、VBAはそんなには…。」
くらいの人が、書けてしまいそうな難易度です。
そのうち検証記事を書くと思いますが、皆さんも使ってみてください。