和風スパゲティのレシピ

日本語でコーディングするExcelVBA

6本目:セルに計算式

Excel&VBA解説サイト「エクセルの神髄」様出題の問題集、
VBA100本ノック」に対する私の回答と解説のページです。

100本ノックの出題リストはこちらから
excel-ubara.com

出題:セルに計算式

#VBA100本ノック 6本目
画像のようにA1から始まる表があります。
D列にB列×C列の計算式を入れてください。
ただし商品コードに"-"の枝番が付いている場合は計算式を入れずそのままにしてください。
例.D2にはA2×B2の計算式を入れる。D4:D5には計算式を入れない。

データサンプル

◇ 出題ページはこちら

ソースコード

定義モジュール

Option Explicit

' データ
Public Const R1stデータ = 2
Public Const C1stデータ = 1
Public Enum CNoデータ
    商品コード = C1stデータ
    単価
    点数
    金額
End Enum
Public Const CLastデータ = CNoデータ.金額
Public Const FormulaR1C1_金額 = "=RC[-2]*RC[-1]"

メインモジュール

Option Explicit

' 100本ノック006:セルに計算式
Sub ハイフンなし商品のみに金額計算式を入力する()
    With WSデータ
    
        Dim R As Long
        For R = R1stデータ To Get最終行(WSデータ)
            
            If InStr(.Cells(R, CNoデータ.商品コード), "-") = 0 Then
            
                .Cells(R, CNoデータ.金額).FormulaR1C1 = FormulaR1C1_金額
                
            End If
            
        Next
    
    End With
End Sub

汎用関数モジュール

Option Explicit

' 最終行の取得
' 参考:https://www.limecode.jp/entry/library/get-lastrow-lastcolumn
Function Get最終行(指定オブジェクト As Variant, Optional ByVal C As Long = -1) As Long

    ' 渡されたオブジェクトからセル範囲を取得
    Dim 対象セル範囲 As Range
    Select Case TypeName(指定オブジェクト)
    Case "Range"
        If 指定オブジェクト.Cells.CountLarge = 1 Then ' 単独セルにはCurrentRegionを取る
            Set 対象セル範囲 = 指定オブジェクト.CurrentRegion
        Else
            Set 対象セル範囲 = 指定オブジェクト
        End If
    Case "Worksheet"
        Set 対象セル範囲 = 指定オブジェクト.UsedRange
    Case "AutoFilter", "ListObject"
        Set 対象セル範囲 = 指定オブジェクト.Range
    Case Else
        Err.Raise 1000, , "対象外のオブジェクト「" & TypeName(指定オブジェクト) & "」が指定されました。"
    End Select

    ' エリアの最終行を取得
    Get最終行 = 対象セル範囲.Rows.Count + 対象セル範囲.Row - 1

    ' 列が指定されていればその列の入力最終行を取得
    If C <> -1 Then
        Do While 対象セル範囲.Worksheet.Cells(Get最終行, C) = ""
            Get最終行 = Get最終行 - 1
            If Get最終行 < 対象セル範囲.Row Then
                Get最終行 = 0
                Exit Function
            End If
        Loop
    End If

End Function

解説

計算式を入力する問題でした。

計算式を入力するにはFormulaプロパティが簡単ですが、
今回は飛び飛びのエリアに入力する必要があります。


その場合、Formulaですとなかなか面倒なコードになってしまいますが、
FormulaR1C1を使うことで相対位置を使った式にすることが出来ます。

"=RC[-2]*RC[-1]" ' ← 2つ左のセル × 1つ左のセル

 
この書き方ができることは覚えておきましょう。


ちなみにこの式を定数化する方法ですが、

  • 2や-1をEnumから計算することはおすすめしません。


定義モジュールに数式を文字列定数として宣言しておき、
改修時にはEnumと一緒にここを修正すれば問題ないですからね。

このあたり、メンテナンス性を重視しすぎてコーディングコストがかさんでしまわないよう気を付けましょう。