Excel。VBA。ROUND関数をExcel VBAでつかうと四捨五入の結果が変なんです。
<Excel VBA:ROUND>
四捨五入でお馴染みの、「ROUND関数」。
データをインポートした後に、ROUND関数をつかった計算式をつくるのもいいのですが、まとめて処理をしたほうが、楽だろうということで、Excel VBAでROUND関数をつかってプログラム文をつくると、普通のROUND関数と算出結果が異なるわけです。
次の表をつかって説明します。
C列は、A列÷B列で算出した結果です。
C2の数式は、
=A2/B2
としています。算出結果を四捨五入したのが、D列です。
D2の数式は、
=ROUND(C2,0)
第2引数を「0(ゼロ)」で設定したことにより、小数点第一位を四捨五入しています。
D列の算出結果は、なんら問題はないことがわかります。
E~G列は、Excel VBAでプログラム文を作ったものを実行していますが、E列のデータの一部に算出結果におかしな結果があります。
それでは、Excel VBAのプログラム文を見てみましょう。
Sub round関数()
Dim i As Long
Dim lastrow As Long
lastrow = Cells(Rows.Count, "a").End(xlUp).Row
For i = 2 To lastrow
Cells(i, "e").Value = Round(Cells(i, "c"), 0)
Cells(i, "f").Value = WorksheetFunction.Round(Cells(i, "c"), 0)
Cells(i, "g").Value = Int(Cells(i, "c") + 0.5)
Next
End Sub
簡単な説明ではありますが、変数宣言をしています。
Dim i As Long
Dim lastrow As Long
lastrow = Cells(Rows.Count, "a").End(xlUp).Row
「i」はこのあとのFor To Next文で使用します。
lastrowは、データの最終行の行番号を算出しています。
For To Next文でlastrowまで繰り返し実行するわけです。
For To Next文の中身を確認します。
Cells(i, "e").Value = Round(Cells(i, "c"), 0)
E列に算出しているのが、このプログラム文です。
Round(Cells(i, "c"), 0) と、Round関数を使用しています。
プログラム文自体おかしなところはありませんが、算出結果に、おかしな結果が出ているわけです。
実は、VBAのRound関数は、「四捨五入」するものではなくて、「数値を丸める」処理をする関数なのです。
4以下の場合は切り捨て、5以上の場合は切り上げという処理はしてくれないわけです。
偶数の場合、丸める値が、5だと、切り捨てをする「銀行での丸め処理」と同じで、AccessのRound関数と同じ動きをしています。
だから、通常のExcelと同じようにプログラム文をつくってしまうと、算出結果が、変わってしまうというわけです。
なので、Excel VBAで通常のExcelと同じ算出結果にしたい。
つまり通常のROUND関数と同じ算出結果にするには、次の2つの対応方法があります。
1つ目が、F列のWorksheetFunctionのROUND関数をつかいます。
WorksheetFunctionは、通常のExcel関数を用意しています。
今回のROUNDはWorksheetFunctionに用意されているので使用することができます。
WorksheetFunctionをつかったプログラム文が、
Cells(i, "f").Value = WorksheetFunction.Round(Cells(i, "c"), 0)
基本的に、WorksheetFunctionをつかうことで、問題は解決しますが、次のような方法もあります。
それが、2つ目の、
Cells(i, "g").Value = Int(Cells(i, "c") + 0.5)
これは、元の値に丸める「0.5」を加算した値を、整数化することで、ROUND関数を同じように算出することができます。
ただし、今回は、整数化した、四捨五入だったので、この数式で対応できますが、小数点第二位とか、色々かわると、加算値を考えないといけないので、WorksheetFunctionをつかうのがいいのかなと思います。
ということで、Excel VBAでROUND関数をつかうと、通常のROUND関数と算出結果が異なるので注意が必要です。