2010年1月23日
さて、2桁ができたので、同じように考えて3桁にも挑戦。
同じように考えていたのだが、こちらは分岐が多そうなので、ちょっと違うプログラムにしてみた。
まず、何が違うかというと、後ろに追加する可能性のある文字列がやや多い。
2つのゼロを追加しないといけない「00」「.00」の他、1つのゼロで事足りる「0」「.0」という可能性もある。
では、どんな場合に起こるのか、という事なのだが、これもじ〜っと数字を見ながら考えていた。
そして、分かったのが、とりあえず、2桁と同じように末尾がゼロになるかどうかを評価した後で、
もう1つ上の位まで調べて、そこもゼロになるかどうか評価すれば楽そうだという事。
人間の頭で考えている時は一瞬なのに、何故こんなにも難しくなるんだ?
方針が決まったら場合分け。末尾が0になるのは、2桁の時と同じで、
四捨五入する位ともう1つ上の位が00〜04、95〜99の時。
さらに、末尾が00となるのは、000〜004、995〜999の時。
どうやら、この2段構えでいけばいいらしいのだ。
つまり、2桁を調べて末尾がゼロになるかを調べ、
その上で、さらに3桁を調べてゼロが2つ付くかを調べれば漏れが無さそう。
それにしたって、これらを一気に全部If文で入れ子にすると大変なことになりそうなので、
Booleanの変数を導入することに。その名もaddZeroとaddZeroZero。
我ながらセンスの無さに惚れ惚れしてしまう。
そして、3桁を調べないといけないので、3桁を取り出した時の受け皿としてlastThreeDigitも宣言しておく。
勿論、2桁も調べるのでlastTwoDigitも健在。
これら2つの変数への代入は2桁のところと同じ発想で移植してくる。つまり、
lastTwoDigit = Right(Int(Abs(myCellValue) * 10 ^ (3 - Int(Log(Abs(myCellValue)) / Log(10)))), 2)
lastThreeDigit = Right(Int(Abs(myCellValue) * 10 ^ (3 - Int(Log(Abs(myCellValue)) / Log(10)))), 3)
となる。
四捨五入する位置が4桁目なので、Intの前の数字が2から3になっているのと、
2桁と3桁を抜き出すのでRightの最後に出てくる抜き出す文字数が2と3になっているくらいの違い。
あとはこれらを上手く組み合わせて、組み込んでいけばいい。
あとはパターンをどう分けるか・・・だけである。
このパターンについては言葉で書くよりも、表に書いた方が早い。
今回はaddZeroがTrueかFalseかで最初の分岐を行っているが、
丸めた後の絶対値で最初の分岐を行ってもいいかもしれない。
また、絶対値の後にaddZeroZeroを評価しているが、これもよく分からない。
何となくプログラムを書いていて、この順番が頭の整理をしながら書き易かったというだけです。
処理としてどの順番が一番早いのかは・・・よく分からない。
addZero | 丸めた後の絶対値 | 丸める前の絶対値 | addZeroZero | 付け加える文字列 |
---|---|---|---|---|
True | 100以上 | 99.5以上 | True/False | なし |
10以上100未満 | 9.95以上99.5未満 | True/False | 0 | |
1以上10未満 | 0.995以上9.95未満 | True | .00 | |
False | 0 | |||
1未満 | 0.995未満 | True | 00 | |
False | 0 | |||
False | なし |
ここまで分かれば、後はこれを実際のIf文などに書き起こしていくだけである。
今回はElseIfとNotという演算子も使っているが、大したものではないので、ヘルプの検索でもして頂きたい。
さぁ、これで3桁も出来上がったので、長くなるが3桁のスクリプトを全部載せておく。
ここまで書いてきた事を見れば、きっと理解できる筈・・・(希望)。
Sub significantFigure3() Call significantCancel '重複防止の為、一度呼び出す '変数の定義 Dim myRange As Range Dim myCellFormula As String '式として変換する為の変数 Dim myCellValue As Variant 'variantで数字と文字列の判定 Dim startFrom As Variant 'variantで1文字目を取得 Dim lastTwoDigit As Integer '残る桁とその1つ下の桁の判定 Dim lastThreeDigit As Integer '残る桁2つとその下の桁の判定 Dim isMinus As Boolean '負の数の判別用 Dim isNotZero As Boolean '0でないことの確認 Dim stringAddition As Boolean '文字列を追加する必要性の有無 Dim addZero As Boolean '丸めた後の数の末尾が0 Dim addZeroZero As Boolean '丸めた後の数の末尾が00 Set myRange = Application.Selection For Each c In myRange.Cells '個々のセルを抽出 myCellFormula = c.Formula myCellValue = c.Value isNotZero = True addZero = False addZeroZero = False If Len(myCellFormula) > 0 Then '空白セルをエスケープ If IsNumeric(myCellValue) Then '文字列セルをエスケープ '値が正か負か0かを判定。 'isMinusのBooleanに値を代入 Select Case myCellValue Case Is < 0 isMinus = True Case Is > 0 isMinus = False Case Is = 0 isNotZero = False End Select If isNotZero Then 'セルの先頭文字を取得して式か数かを判定。 '式なら=を除去 startFrom = Left(myCellFormula, 1) If startFrom = "=" Then myCellFormula = Mid(myCellFormula, 2) End If 'ここで丸めを実行 c.Formula = "=ROUND(ABS(" & myCellFormula & "),2-INT(LOG10(ABS(" & myCellFormula & "))))" '負の数の場合、マイナスを復活させる。 If isMinus Then c.Formula = c.Formula & "*(-1)" End If '末尾の0、.0、.00の処理 lastTwoDigit = Right(Int(Abs(myCellValue) * 10 ^ (3 - Int(Log(Abs(myCellValue)) / Log(10)))), 2) '2桁の取り出し lastThreeDigit = Right(Int(Abs(myCellValue) * 10 ^ (3 - Int(Log(Abs(myCellValue)) / Log(10)))), 3) '3桁の取り出し If lastTwoDigit >= 95 Or lastTwoDigit <= 4 Then If lastThreeDigit >= 995 Or lastThreeDigit <= 4 Then addZeroZero = True End If addZero = True End If If addZero Then 'そもそもの必要性の判断 If Abs(myCellValue) < 99.5 And Abs(myCellValue) >= 9.95 Then '10の位までの数。「.0」を追加 c.Formula = c.Formula & "&"".0""" c.HorizontalAlignment = xlRight ElseIf Abs(myCellValue) < 9.95 And Abs(myCellValue) >= 0.995 Then '1の位までの数。 If Not addZeroZero Then c.Formula = c.Formula & "&""0""" c.HorizontalAlignment = xlRight Else c.Formula = c.Formula & "&"".00""" c.HorizontalAlignment = xlRight End If ElseIf myCellValue < 0.995 Then '1より小 If Not addZeroZero Then c.Formula = c.Formula & "&""0""" c.HorizontalAlignment = xlRight Else c.Formula = c.Formula & "&""00""" c.HorizontalAlignment = xlRight End If End If End If End If End If End If Next End Sub |
これで有効数字を3桁のプログラムも完成した事になる。
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14]