【VBA】四捨五入・切り上げ・切り捨てを正しく行う方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク

この記事でできること

  • VBAで四捨五入・切り上げ・切り捨てを正しく使い分けられる
  • VBA Round関数の「銀行家の丸め」問題を回避できる
  • 請求書の税込金額を端数処理方法を選んで一括計算できる

対象: Excel 2016以降 / Microsoft 365、Windows 10/11


完成イメージ(Before / After)

Before(手作業):

  1. 税抜金額にExcelの数式で消費税を計算
  2. 端数が出たら手動で四捨五入・切り上げ・切り捨て
  3. 100件あると計算ミスや処理漏れが起きる
  4. VBAのRound関数を使ったら「2.5」が「2」になって混乱

After(マクロ実行):

  1. 「売上一覧」シートに税抜金額を入力
  2. マクロを実行する
  3. 端数処理方法を選ぶ(1:四捨五入, 2:切り上げ, 3:切り捨て)
  4. 税込金額が全件一括で計算される
  5. 100件が数秒で完了。計算ミスゼロ

売上一覧シート(処理前):

A B C D
1 商品名 税抜金額 消費税 税込金額
2 商品A 1980
3 商品B 2550
4 商品C 3333

売上一覧シート(処理後 — 四捨五入の場合):

A B C D
1 商品名 税抜金額 消費税 税込金額
2 商品A 1980 198 2178
3 商品B 2550 255 2805
4 商品C 3333 333 3666

請求書のマクロを作ったとき、消費税の計算で Round(2.5, 0) と書いたら結果が「2」になった。Excelのワークシートで =ROUND(2.5, 0) と入力すると「3」になるのに、VBAだと結果が違う。バグかと思って1時間調べた。

原因はVBAのRound関数が「銀行家の丸め」という特殊なルールを使っていること。.5のときに最も近い偶数に丸めるため、2.5は2に、3.5は4になる。一般的な四捨五入とは違う。

WorksheetFunction.Round に切り替えてからは、Excelの関数と同じ結果になるので安心して金額計算ができるようになった。請求書の消費税で1円ズレる問題が完全になくなった。

VBAのRound関数の罠は、知らないと絶対にハマる。請求書の金額で1円ズレたら信用問題になる。同じ落とし穴に落ちる人を減らしたい。請求書を自動作成する方法と組み合わせれば、金額計算から請求書の作成まで一気通貫で自動化できる。

VBA Round の「銀行家の丸め」を知らないと、金額計算で確実にハマる。


事前準備

シート構成を用意する

実務版コードでは以下の構成を使う。最小版はシート構成不要(イミディエイトウィンドウで結果を確認する)。

「売上一覧」シート — 税抜金額を入力する場所

内容
A列 商品名 商品A
B列 税抜金額 1980
C列 消費税 (マクロで計算)
D列 税込金額 (マクロで計算)
  • 1行目はヘッダー。データは2行目から入力する
  • B列が空の行が最終行として判定される

バックアップを取る

金額の計算結果をセルに書き込む処理のため、実行前にファイルのコピーを取っておくこと。テスト用のダミーデータで動作確認してから本番データで実行することを強く推奨する。

Excelをマクロ有効ブック(.xlsm)で保存する

拡張子が .xlsx のままだとマクロは保存できない。

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. コード内の書き換えポイント(★マーク)を自分の環境に合わせて変更する
  3. Alt + F8 → マクロ名を選んで「実行」

コード(最小版)– 端数処理の動作を確認する

まず各関数の動作を確認する。イミディエイトウィンドウ(Ctrl + Gで表示)に結果が出力される。


Sub 端数処理の動作確認()
    Dim val As Double
    val = 2.5

    ' ★ VBA Round(銀行家の丸め=偶数丸め)
    Debug.Print "--- VBA Round(銀行家の丸め) ---"
    Debug.Print "Round(2.5, 0) = " & Round(2.5, 0)       ' → 2
    Debug.Print "Round(3.5, 0) = " & Round(3.5, 0)       ' → 4
    Debug.Print "Round(2.15, 1) = " & Round(2.15, 1)     ' → 2.2

    ' ★ WorksheetFunction.Round(算術丸め=一般的な四捨五入)
    Debug.Print "--- WorksheetFunction.Round(算術丸め) ---"
    Debug.Print "WF.Round(2.5, 0) = " & WorksheetFunction.Round(2.5, 0)   ' → 3
    Debug.Print "WF.Round(3.5, 0) = " & WorksheetFunction.Round(3.5, 0)   ' → 4
    Debug.Print "WF.Round(2.15, 1) = " & WorksheetFunction.Round(2.15, 1) ' → 2.2

    ' ★ WorksheetFunction.RoundUp(切り上げ)
    Debug.Print "--- WorksheetFunction.RoundUp(切り上げ) ---"
    Debug.Print "WF.RoundUp(2.31, 1) = " & WorksheetFunction.RoundUp(2.31, 1)   ' → 2.4(小数第1位に切り上げ)
    Debug.Print "WF.RoundUp(2.31, 0) = " & WorksheetFunction.RoundUp(2.31, 0)   ' → 3(整数に切り上げ)

    ' ★ WorksheetFunction.RoundDown(切り捨て)
    Debug.Print "--- WorksheetFunction.RoundDown(切り捨て) ---"
    Debug.Print "WF.RoundDown(2.39, 1) = " & WorksheetFunction.RoundDown(2.39, 1) ' → 2.3(小数第1位に切り捨て)
    Debug.Print "WF.RoundDown(2.39, 0) = " & WorksheetFunction.RoundDown(2.39, 0) ' → 2(整数に切り捨て)

    ' ★ Int / Fix の違い(負の数で差が出る)
    Debug.Print "--- Int / Fix の違い ---"
    Debug.Print "Int(2.9) = " & Int(2.9)     ' → 2
    Debug.Print "Int(-2.9) = " & Int(-2.9)   ' → -3(負の無限大方向)
    Debug.Print "Fix(2.9) = " & Fix(2.9)     ' → 2
    Debug.Print "Fix(-2.9) = " & Fix(-2.9)   ' → -2(ゼロ方向)

    MsgBox "イミディエイトウィンドウ(Ctrl+G)に結果を出力しました。"
End Sub

実行結果(イミディエイトウィンドウ)


--- VBA Round(銀行家の丸め) ---
Round(2.5, 0) = 2
Round(3.5, 0) = 4
Round(2.15, 1) = 2.2
--- WorksheetFunction.Round(算術丸め) ---
WF.Round(2.5, 0) = 3
WF.Round(3.5, 0) = 4
WF.Round(2.15, 1) = 2.2
--- WorksheetFunction.RoundUp(切り上げ) ---
WF.RoundUp(2.31, 1) = 2.4
WF.RoundUp(2.31, 0) = 3
--- WorksheetFunction.RoundDown(切り捨て) ---
WF.RoundDown(2.39, 1) = 2.3
WF.RoundDown(2.39, 0) = 2
--- Int / Fix の違い ---
Int(2.9) = 2
Int(-2.9) = -3
Fix(2.9) = 2
Fix(-2.9) = -2

Round(2.5, 0)2 になっている点に注目。これがVBA Round関数の「銀行家の丸め」。一般的な四捨五入をしたい場合は WorksheetFunction.Round を使う。

動作確認

  1. マクロを実行する
  2. 「イミディエイトウィンドウに結果を出力しました」のメッセージが出る
  3. Ctrl + G でイミディエイトウィンドウを表示して結果を確認する

最小版で各関数の動作が確認できたら、次の実務版に進む。


コード(実務版)– 請求書の税込金額を端数処理で一括計算

自分はこの方法で毎月の請求書の消費税計算を処理している。端数の1円ズレがなくなって安心して請求書を送れるようになった。

売上一覧の税抜金額に対して、消費税(10%)を計算し、端数処理方法を選んで一括適用する。請求書作成の全体の流れはExcelで請求書を自動作成する方法を参照。


Sub 税込金額を一括計算()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim taxRate As Double
    Dim taxAmount As Double
    Dim roundMethod As String
    Dim cnt As Long

    ' ★ シート名を指定
    Set ws = Worksheets("売上一覧")

    ' ★ 税率を指定(10% = 0.1)
    taxRate = 0.1

    ' ★ 最終行を取得(B列=税抜金額で判定)
    lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

    If lastRow < 2 Then
        MsgBox "データがありません。", vbExclamation
        Exit Sub
    End If

    ' 端数処理方法を選択
    roundMethod = InputBox( _
        "端数処理方法を番号で入力してください。" & vbCrLf & vbCrLf & _
        "1: 四捨五入" & vbCrLf & _
        "2: 切り上げ" & vbCrLf & _
        "3: 切り捨て", _
        "端数処理の選択", "1")

    If roundMethod = "" Then
        Exit Sub  ' キャンセル時
    End If

    If roundMethod <> "1" And roundMethod <> "2" And roundMethod <> "3" Then
        MsgBox "1, 2, 3 のいずれかを入力してください。", vbExclamation
        Exit Sub
    End If

    ' 確認ダイアログ
    Dim methodName As String
    Select Case roundMethod
        Case "1": methodName = "四捨五入"
        Case "2": methodName = "切り上げ"
        Case "3": methodName = "切り捨て"
    End Select

    If MsgBox((lastRow - 1) & " 件の税込金額を計算します。" & vbCrLf & _
              "端数処理: " & methodName & vbCrLf & _
              "税率: " & Format(taxRate * 100, "0") & "%" & vbCrLf & vbCrLf & _
              "実行しますか?", vbYesNo + vbQuestion) = vbNo Then
        Exit Sub
    End If

    On Error GoTo ErrHandler
    Application.ScreenUpdating = False

    For i = 2 To lastRow
        ' 税抜金額が数値でない場合はスキップ
        If Not IsNumeric(ws.Cells(i, 2).Value) Then GoTo NextRow
        If ws.Cells(i, 2).Value = "" Then GoTo NextRow

        ' 消費税を計算(端数処理を適用)
        Select Case roundMethod
            Case "1"  ' 四捨五入(算術丸め)
                taxAmount = WorksheetFunction.Round(ws.Cells(i, 2).Value * taxRate, 0)
            Case "2"  ' 切り上げ
                taxAmount = WorksheetFunction.RoundUp(ws.Cells(i, 2).Value * taxRate, 0)
            Case "3"  ' 切り捨て
                taxAmount = WorksheetFunction.RoundDown(ws.Cells(i, 2).Value * taxRate, 0)
        End Select

        ' ★ C列に消費税、D列に税込金額を書き込む
        ws.Cells(i, 3).Value = taxAmount
        ws.Cells(i, 4).Value = ws.Cells(i, 2).Value + taxAmount

        cnt = cnt + 1
NextRow:
    Next i

    ' 金額列の表示形式を設定
    ws.Range("B2:D" & lastRow).NumberFormat = "#,##0"

    Application.ScreenUpdating = True

    MsgBox cnt & " 件の税込金額を計算しました。" & vbCrLf & _
           "端数処理: " & methodName, vbInformation
    Exit Sub

ErrHandler:
    Application.ScreenUpdating = True
    MsgBox "エラーが発生しました。" & vbCrLf & _
           "行番号: " & i & vbCrLf & _
           Err.Description, vbCritical
End Sub

書き換えポイント

# 書き換え箇所 初期値 説明
1 Worksheets("売上一覧") 売上一覧 データのシート名
2 taxRate = 0.1 0.1 消費税率(10%)。軽減税率なら0.08
3 ws.Cells(i, 2) 列2(B列) 税抜金額の列番号
4 ws.Cells(i, 3) 列3(C列) 消費税の出力先列
5 ws.Cells(i, 4) 列4(D列) 税込金額の出力先列

実務版で追加した機能

機能 説明 参考記事
端数処理の選択 InputBoxで四捨五入/切り上げ/切り捨てを選択
確認ダイアログ 件数+端数処理方法+税率を表示してYes/No確認
数値チェック IsNumericで非数値セルをスキップ エラー処理の方法
表示形式の自動設定 NumberFormatで金額列にカンマ区切りを設定 書式を一括変更する方法
高速化 ScreenUpdating = Falseで画面更新を停止
エラー復帰 On Error GoTo ErrHandlerでScreenUpdating復帰 エラー処理の方法

各関数の違いと使い分け

比較表(入力値ごとの結果)

入力値 VBA Round WF.Round WF.RoundUp WF.RoundDown Int Fix
2.5 2 3 3 2 2 2
3.5 4 4 4 3 3 3
2.4 2 2 3 2 2 2
2.6 3 3 3 2 2 2
-2.5 -2 -3 -3 -2 -3 -2
-2.3 -2 -2 -3 -2 -3 -2

※ 第2引数はすべて 0(整数に丸め)。WF = WorksheetFunction

使い分けの結論

やりたいこと 使う関数
一般的な四捨五入(算術丸め) WorksheetFunction.Round(値, 桁数)
切り上げ WorksheetFunction.RoundUp(値, 桁数)
切り捨て WorksheetFunction.RoundDown(値, 桁数)
正の数の整数切り捨て(高速) Int(値)
負の数も含む整数切り捨て(ゼロ方向) Fix(値)
表示上だけ丸めたい Format(値, "書式")

重要: VBAの Round 関数は銀行家の丸め(偶数丸め)のため、一般的な四捨五入には使わない。金額計算には WorksheetFunction.Round を使う。

第2引数(桁数)の意味

第2引数 意味 例(値: 1234.567)
2 小数第2位に丸め 1234.57
1 小数第1位に丸め 1234.6
0 整数に丸め 1235
-1 十の位に丸め 1230
-2 百の位に丸め 1200

Format関数の注意点

表示形式の変換には日付や数値の表示形式をFormatで自由に変換する方法が便利だが、Format関数は表示用の文字列を返すだけで、元の値は変わらない。


Dim val As Double
val = 1234.567

' Format関数: 表示は丸まるが、値は変わらない
Debug.Print Format(val, "#,##0.0")  ' → "1,234.6"(文字列)
Debug.Print val                       ' → 1234.567(値はそのまま)

' WorksheetFunction.Round: 値そのものが丸まる
val = WorksheetFunction.Round(val, 1)
Debug.Print val                       ' → 1234.6(値が変わる)

計算に使う場合はWorksheetFunction.Roundで値を丸めてから使うこと。Format関数で丸めた「つもり」になると、合計金額がズレる原因になる。


よくある落とし穴5選

# 症状 原因 対策
1 Round(2.5, 0)2 になる VBAのRound関数は「銀行家の丸め(偶数丸め)」を採用。.5のとき偶数側に丸める WorksheetFunction.Round(2.5, 0) を使えば 3 になる(算術丸め)
2 Format関数で丸めたが合計が合わない Format(val, "#,##0") は文字列を返すだけで値は変わらない。後続の計算で元の値が使われる 計算には WorksheetFunction.Round で値を丸めてからセルに書き込む
3 Int(-2.3)-3 になる Int関数は「負の無限大方向」に丸める。-2.3 → -3。ゼロ方向に切り捨てたいなら Fix(-2.3)-2 負の数がある場合は Fix または WorksheetFunction.RoundDown を使う
4 小数第2位で丸めたいのに結果がおかしい 第2引数の桁数を間違えている。0=整数、1=小数第1位、2=小数第2位。-1=十の位 第2引数の一覧表を確認してから設定する
5 Round(2.15, 1)2.1 になる 浮動小数点の内部表現で 2.15 が 2.14999… として格納される WorksheetFunction.Round(2.15, 1) を使う。または通貨型(Currency)で変数を宣言する

Format関数で “#,##0” にしたら見た目は四捨五入されたが、実際の値は元のまま。表示と値が違うことに気づかず、後続の計算で合計が合わなくなったことがある。端数処理は「見た目」ではなく「値」を変えるのが鉄則。


FAQ

Q1. VBAのRound関数とExcelのROUND関数は同じ動作?

違う。VBAのRound関数は「銀行家の丸め(偶数丸め)」、ExcelのROUND関数は「算術丸め(一般的な四捨五入)」。VBAでExcelと同じ四捨五入をするには WorksheetFunction.Round を使う。


' VBA Round(銀行家の丸め)
Debug.Print Round(2.5, 0)                    ' → 2

' WorksheetFunction.Round(算術丸め = ExcelのROUNDと同じ)
Debug.Print WorksheetFunction.Round(2.5, 0)  ' → 3

Q2. 消費税の計算で切り捨てにしたい場合は?

WorksheetFunction.RoundDown を使う。正の数のみなら Int でも同じ結果。


Dim tax As Long
' 切り捨て(小数点以下を切り捨て)
tax = WorksheetFunction.RoundDown(1980 * 0.1, 0)  ' → 198

' 正の数なら Int でも同じ
tax = Int(1980 * 0.1)  ' → 198

Q3. 十の位で四捨五入したい(1234 → 1230)場合は?

第2引数に -1 を指定する。引数の「向き」に注意。正の数が小数側、負の数が整数側を指す。


Debug.Print WorksheetFunction.Round(1234, -1)   ' → 1230
Debug.Print WorksheetFunction.Round(1256, -1)   ' → 1260
Debug.Print WorksheetFunction.Round(1234, -2)   ' → 1200

Q4. 通貨型(Currency)を使えば浮動小数点の問題は起きない?

Currency型は小数第4位まで正確に扱える固定小数点型。金額計算にはDouble型よりCurrency型が安全。ただし小数第5位以下は切り捨てられる。


Dim price As Currency
price = 2.15
Debug.Print Round(price, 1)  ' → 2.2(Currency型なら正確)

Q5. 既に入力済みの金額を一括で端数処理したい

実務版コードの構成を応用する。対象範囲をループして WorksheetFunction.Round で値を上書きする。実行前にバックアップを取ること


Sub 金額を一括四捨五入()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    For i = 2 To lastRow
        If IsNumeric(ws.Cells(i, 1).Value) Then
            ws.Cells(i, 1).Value = WorksheetFunction.Round(ws.Cells(i, 1).Value, 0)
        End If
    Next i

    MsgBox "完了しました。"
End Sub

まとめ

この記事では、VBAで四捨五入・切り上げ・切り捨てを正しく使い分ける方法を解説した。

  • 最小版: 各関数の動作をイミディエイトウィンドウで確認
  • 実務版: 請求書の税込金額を端数処理方法を選んで一括計算

最も重要なポイントは VBAのRound関数は一般的な四捨五入ではない こと。金額計算には WorksheetFunction.Round を使う。

テスト用のダミーデータで動作確認してから、本番データで実行すること。

関連記事


次にやりたくなること

コメント

タイトルとURLをコピーしました