LoginSignup
2
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-06-10

Round関数 - 数値の小数部分を丸める -Office Kitami
小数点以下を四捨五入する関数は?−0.5の加算+Int関数 - インストラクターのネタ帳
access 実践サンプル
AccessのRoundはJIS式丸めで四捨五入ではない。
負の数は処理できない。

つまり簡単に言うと
ユーザー定義関数を作らないと四捨五入できないよ
ということです。
もっと言うと
これを作らないとACCESSは使い物にならないよ
ということです。
しかしintがごちゃごちゃしてわかりません。なぜマイクロソフトは作らなかったのか。

バージョンを上げるならはよRoundを作れ

ということはほんとうにいっておきたい。
さて、簡単に作りましょう。
なのでVBAを動くようにしておくこと、EXCELがあることが前提だと可能です。というかこういう連携こそオフィスをまとめて買う真の意味があります。

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

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
日本語では事前バインディングといいます。
ではもう一つレイトバインディングをやります。こちらは参照設定をしないので、違うバージョンに移行しやすいです。しかし遅いです。大量に計算させると明らかに差が出ます。

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

こちらは
実行時バインディングとか書いてあります
2つともエラー処理を行い、数字ではないものが入ってきた場合は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 と組み合わせたものになり、意外とややこしく、ずいぶん時間がかかりました

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

参考:

事前バインディングと遅延バインディング(実行時バインディング)
[INFO] オートメーションにおける事前バインディングおよび実行時バインディングの使用
VBA references and early binding vs late binding - EXCEL MATTERS

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2