Excelロールバック

今朝から、ある特定のExcelファイル開くとエラーになり、「可能な限り回復しますか?」と聞かれるので、回復をお願いしてみましたが、VBAがゴッソリ消えていました。

ファイルが壊れたのかと思いましたが、私のPC以外では問題なく開けることが発覚。PCを再起動したりしましたが、回復せず。

いろいろ調べたり、試行錯誤したら、どうも先週のExcelのアップデートが怪しい気がしてきました。

とりあえず、Excelのロールバック手順を下記を参考にして実施したところ、開けるようになりました!

Officeのロールバック初めてやりましたが、作業は簡単でした。

ただ、バージョンがどれがどれだかよくわかりません。よくわからないので、3月のバージョンに戻したら、動いたからOKとするかって感じです。

Excelの更新を手動に変更したので、早いうちに良くなって、また自動に戻したいのですが、バグじゃないのかな?ずっとこのままなのはつらいです。

大きなニュースの陰で・・・

今週は、ブラックホールの輪郭撮影に成功したってニュースがありました。子供のころは、「ホール」なんだから穴があいているのかと思っていました。アリジゴクのイメージです。

とてつもなく重いのは知っていましたが、大きさも馬鹿でかいですね。数字が大きすぎてよく分かりません。

「ブラックホールの影」は直径がおよそ1000億キロメートルと太陽系がすっぽりと入る大きさでブラックホールの質量は太陽のおよそ65億倍に達する超巨大なものだとわかったということです。

NHK NEWS WEB「 世界初 ブラックホールの輪郭撮影に成功 」より引用

非常にスケールの大きいニュースに注目が集まる陰で、私はround関数に驚かされていました。四捨五入すると思っていた関数です。ネットで調べると結構出てきますが、MS ExcelのVBAで使用するround関数は普通の四捨五入とは違う結果になることがあります。

こんなプログラムを用意して、

Private Sub CommandButton0_Click()
    MsgBox "Round(2.49,0)=" & Round(2.49, 0)
End Sub

Private Sub CommandButton1_Click()
    MsgBox "Round(2.5,0)=" & Round(2.5, 0)
End Sub

Private Sub CommandButton2_Click()
    MsgBox "Round(2.51,0)=" & Round(2.51, 0)
End Sub

それぞれ実行すると、

これは正しい
ん?
これも正しい

2.5は四捨五入したら3じゃないの?

正式名称はよく分かりませんが、これはこれで正しい?動きのようです。ただ、MS Excelの数式のround関数は私の思っている通りの四捨五入をします。

2.5にRound関数を使うとVBAとは違って3になります。

B列の数字に対して、C列でround関数の結果を表示しています。この場合は2.5は3になります。ちゃんと決まっているのであれば、どちらの処理でもいいですが、揃えて欲しいなあとは思います。きっと開発者の方が一所懸命に考えられた結果だと思いますので、何か意図があるのでしょう。

そして私がなんでこんなことをやっているのかというと、「弊社の生産管理システム(仮称)のデータを使って、納品書・請求書を出力するようにしよう!」化に取り組んでいるためです。消費税で四捨五入が必要なんです。実際に月次の集計処理をさせるのは、MariaDBなのですが、「SQLも四捨五入ってroundだっけな?」って軽い気持ちでネットで検索したら、ハマりました・・・。

というわけで、Excelのことは置いておいて、実際に四捨五入するのはMariaDBなので、MariaDBを調べてみます。

Description
Rounds the argument X to D decimal places. The rounding algorithm depends on the data type of X. D defaults to 0 if not specified. D can be negative to cause D digits left of the decimal point of the value X to become zero.

MariaDB公式サイトより引用

「ラウンドアルゴリズム ハ、データ ケイシキ ニ イゾンシマス」しか書いていません。これでは、ちょっと心配なので、MySQLの方も調べてみると、

ROUND() uses the following rules depending on the type of the first argument:

・For exact-value numbers, ROUND() uses the “round half away from zero” or “round toward nearest” rule: A value with a fractional part of .5 or greater is rounded up to the next integer if positive or down to the next integer if negative. (In other words, it is rounded away from zero.) A value with a fractional part less than .5 is rounded down to the next integer if positive or up to the next integer if negative.

・For approximate-value numbers, the result depends on the C library. On many systems, this means that ROUND() uses the “round to nearest even” rule: A value with a fractional part exactly halfway between two integers is rounded to the nearest even integer.

MySQL公式サイトより引用

詳しく書いてありました。「セイカクナ スウジナラ シシャゴニュウ ニ ナルヨ。キンジチ ノ バアイ、ショウスウブブン ガ ドマンナカ ナラ グウスウ ニ マルメラレルヨ(合ってるかな?)」

とりあえず、近似値使わなければ、私の欲する四捨五入になりそうです。

・・・でもこれはMySQLの話ですね。・・・弊社はMariaDBです。

・・・まあ、たぶん大丈夫じゃないかと。実際round関数使ってみるとMySQLに書かれている通りに動きましたし。

MariaDB [XXXXXXXXXX]> select round(2.49,0), round(2.50,0), round(2.51,0);
+---------------+---------------+---------------+
| round(2.49,0) | round(2.50,0) | round(2.51,0) |
+---------------+---------------+---------------+
|             2 |             3 |             3 |
+---------------+---------------+---------------+
1 row in set (0.00 sec)

MariaDB [XXXXXXXXXX]> select round(249E-2,0), round(250E-2,0), round(251E-2,0)
;
+-----------------+-----------------+-----------------+
| round(249E-2,0) | round(250E-2,0) | round(251E-2,0) |
+-----------------+-----------------+-----------------+
|               2 |               2 |               3 |
+-----------------+-----------------+-----------------+
1 row in set (0.00 sec)

深追いはやめて、とりあえず、システム作り切っちゃうことを優先します。消費税10%になれば、弊社の場合、小数点以下なんてほぼ無くなるし(言い訳)。