Accessを始めるまえに簡単にパパッと作る関数xlRnd（おまけ付き）

[Round関数　- 数値の小数部分を丸める -Office Kitami](http://www.office-kitami.com/lesson/afunction/round.html)
[小数点以下を四捨五入する関数は？−0.5の加算＋Int関数 - インストラクターのネタ帳](http://www.relief.jp/itnote/archives/002655.php)
[access 実践サンプル](accessとround関数と四捨五入)
AccessのRoundはJIS式丸めで四捨五入ではない。
負の数は処理できない。

つまり簡単に言うと
**ユーザー定義関数を作らないと四捨五入できないよ**
ということです。
もっと言うと
**これを作らないとACCESSは使い物にならないよ**
ということです。
しかしintがごちゃごちゃしてわかりません。なぜマイクロソフトは作らなかったのか。
##バージョンを上げるならはよRoundを作れ
ということはほんとうにいっておきたい。
さて、簡単に作りましょう。
なのでVBAを動くようにしておくこと、EXCELがあることが前提だと可能です。というかこういう連携こそオフィスをまとめて買う真の意味があります。

ACCESSを起動
ALT+F11でvisualBasiceditorを起動
ALT+T Alt+R で参照設定でMicrosoft Excelを参照設定する
という前提で

```visualbasic:xlRnd
Function xlRnd(varLong As Long)
'For Access VBA ; You need Reference Setting Microsoft Excel XX.X Object Library
Dim xlApp As New Excel.Application: xlApp.Visible = False 'Change From Dim xlApp As Excel.Application
On Error GoTo Err
xlRnd = xlApp.WorksheetFunction.Round(varLong,1)
Set xlApp = Nothing 'Add
Exit Function
Err:
xlRnd = 0
If Not xlApp Is Nothing Then xlApp.Quit: Set xlApp = Nothing 'Add
End Function
```

これをクエリに入れるときにビルダを起動し
xlRnd([テーブル名]![フィールド名])
で計算できます。（式をビルドするときはクエリではなくテーブルからフィールド名をもってくること）
この参照設定は
英語では
Reference Setting
Early Binding
日本語では事前バインディングといいます。
ではもう一つレイトバインディングをやります。こちらは参照設定をしないので、違うバージョンに移行しやすいです。しかし遅いです。大量に計算させると明らかに差が出ます。

 ```vbnet:xlRndLate
Function xlRndLate(varLong As Long)
Dim xlApp: Set xlApp = CreateObject("Excel.Application")
On Error GoTo Err
xlRnd = xlApp.WorksheetFunction.Round(varLong,1)
Set xlApp = Nothing
Exit Function
Err:
xlRnd = 0
If Not xlApp Is Nothing Then Set xlApp = Nothing
End Function
```

こちらは
実行時バインディングとか書いてあります
２つともエラー処理を行い、数字ではないものが入ってきた場合は0が返ります。
###おまけ Set Nothingのテクニック
If not Is nothing
はVBAではあまり使わないのですが、Set で変数を設定して放棄する場合、途中でなくなっている場合、あるいは設定できない場合があります。On errorで抜けているとわからなくなるんですね。
　なのでこの
If Not 変数 Is Nothing Then Set 変数 =Nothing
とするとエラーがなく変数を放棄できます。
さらに言うと
Dim 変数:Set 変数 =
If Not 変数 Is Nothing Then Set 変数 =Nothing
は
For Next
If End IF
Do Loop
と同じように最初に書いて間にコードを書くようにしています。
Dim 変数:Set 変数 =
Dim 変数:Set 変数a =

If Not 変数a Is Nothing Then Set 変数a =Nothing
If Not 変数 Is Nothing Then Set 変数 =Nothing
こんな感じで外側から包み込むようにすると間違いが少ないです。

　これはAccessの学習を始める前に、まずVBAを知っておく必要があることを意味しています。できないことはないんだけど面倒なんだもん。
　ただ、簡単だけにいくら事前バインディングで早いと言ってもAccess本体で処理をするよりはやっぱり遅いです。あとユーザ定義関数だとSQLがPowerShellとかで処理できないみたい。
#Excelを使わない場合
Excelを使わないWorksheetfunction.Roundは Log10 と組み合わせたものになり、意外とややこしく、ずいぶん時間がかかりました

```vb
Static Function Log10(X) As Double
Log10 = Log(X) / Log(10#)
End Function

Function xlRnd2(X, intflo As Integer)
Dim xDegit As Integer
' IsNumeric Check
If X * 0 <> 0 Then GoTo ERR_Hndl
On Error GoTo ERR_Hndl
If intflo < 0 Then
  If CInt(Log10(Abs(X))) + 1 <= Abs(intflo) Then
    xlRnd2 = X 'Error Return X value
    Exit Function
  Else
    xlRnd2 = Int((Abs(X) * 10 ^ (intflo)) + 0.5) / (10 ^ intflo) * Sgn(X)
    Exit Function
  End If
Else
  xlRnd2 = Int((Abs(X) * 10 ^ (intflo)) + 0.5) / (10 ^ intflo) * Sgn(X)
  Exit Function
End If
Exit Function
ERR_Hndl:
xlRnd2 = 0
End Function
```
詳しい解説はこちらで https://qiita.com/Q11Q/items/ad8e3139b02f495db181

#参考：
[事前バインディングと遅延バインディング（実行時バインディング)](http://excel-ubara.com/excelvba4/EXCEL227.html)
[[INFO] オートメーションにおける事前バインディングおよび実行時バインディングの使用 ](https://support.microsoft.com/ja-jp/kb/245115)
[VBA references and early binding vs late binding - EXCEL MATTERS]
(http://excelmatters.com/2013/09/23/vba-references-and-early-binding-vs-late-binding/)