VBAの比較処理においてバグ?

このQ&Aのポイント
  • VBAの比較処理にバグがあるのかどうか疑問です。
  • 163.05 < 163.07 の比較でTrueを返してしまう問題があります。
  • 163.04 < (163.05 - 0.01) の条件がTrueになる不正な挙動が発生しています。
回答を見る
  • ベストアンサー

VBAの比較処理においてバグ?

環境はVistaBusiness、Excel2003です。 以下のような比較処理をして条件を満たせばTrueを返す関数を作成しましたが 偶然このパラメータ(関数上は引数としてデータ取得)が入ってきた場合に Trueを返すようになってしまいました。 論理的に考えれば当然Falseになるのかと思うのですが なぜかTrueが返ってきます。 If 163.05 < 163.07 Then If 163.04 < (163.05 - 0.01) Then Chk = True Exit Function End If End If Chk = False 但しこの数字を下記のように変更すると意図するとおり Falseが返ってきます If 163.06 < 163.07 Then If 163.05 < (163.06 - 0.01) Then Chk = True Exit Function End If End If Chk = False これはバグなのでしょうか? お分かりになる方がいれば回答お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • kmetu
  • ベストアンサー率41% (562/1346)
回答No.1

If CCur(163.04) < (CCur(163.05) - CCur(0.01)) Then にしてみてください。バグというより丸め誤差です。

tyeggs
質問者

お礼

ありがとうございます。 久々のプログラミングで、すっかり丸め誤差忘れてました。 助かりました、早急な回答ありがとうございます。

関連するQ&A

  • Accessでのvbaについての質問

    Accessでのvbaを使用したプログラムについてお聞きしたいです。前にも似たようなことを質問していましたが、まだうまくいってません。マスタメンテナンス画面を作成しているのですがテキストボックスの入力チェック が上手くいきません。テキストボックス はコードという名前をつけています。 以下のコードでコーディングしています。 未入力チェック関数 Public Function EmptyCheck(Koumoku As Variant) As Boolean '引数で渡された項目が入力されているかチェック If Koumoku = ""Then EmptyCheck = True Else EmptyCheck = False End If End Function 桁数チェック関数 Public Function NumberCheck(Koumoku As Variant, Number As Integer) As Boolean If Len(Koumoku) <>Number Then NumberCheck = True Else NumberCheck = False End If End Function 半角英数字チェック関数 Public Function ZokuseiCheck(Koumoku As Variant) As Boolean If IsNumeric(Koumoku) = False And Not Koumoku Like "[a-z]*"And Len(Koumoku) <>6 Then ZokuseiCheck = True Else ZokuseiCheck = False End If End Function コード処理 Private Sub コード_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = 13 Then ' If EmptyCheck(コード) = True Then MsgBox "コードを入力してください。" コード.SetFocus KeyCode = 0 Exit Sub ElseIf NumberCheck(コード, 6) = True Then MsgBox "コードの桁数が不正です。" コード.SetFocus KeyCode = 0 Exit Sub ElseIf ZokuseiCheck(コード) = True Then MsgBox "コードの属性が不正です。" コード.SetFocus KeyCode = 0 Exit Sub Else コード.Locked = True End If End If 上手くいかない点は以下の通りです。 1、テキストボックス(コード)の未入力チェックが上手く行きません。テキストボックスが空白の時も""になったりNullになったり変わるのでIf Koumoku = ""ThenにしてしまうとNullになった時処理されずそのまま次のテキストボックスにカーソルが移ってしまう時があります。なんでNullになったり""になったりで変わるのかも謎です。あと空白の時、Koumoku=""で一致しているにも関わらず、Falseで返されてしまい、未入力処理がされません。IsNullを使ってNull値判定してもKoumoku=Nullで一致してるのにFalseで返されました。 2、桁数チェックも上手く行きません。コード処理の方で桁数チェック関数に6という数字を渡して6桁入力としているのですが6桁でもエラーになってしまう時があります。LEN関数でどのように文字数を測っているのかも よくわからないです。 3.これは単純に半角英数字の判定の仕方が間違っているんだと思いますが、やり方がよく分からず、上手く判定できません。 4.これは入力チェックに当てはまるのですがEnterキーを押した時に処理するようにコードを書いていましたが変な結果が出ます。最初にテキストボックスでEnterキーを押して未入力の時に、「コードを入力してください。」とメッセージが出るのはいいのですがその後入力してもまた同じメッセージが出てきます。ほかのテキストボックスをクリックしてカーソルを移さないと同じメッセージが出続けます。桁数や半角英数字チェックの時も同じです。他のカーソルをクリックしないと次の項目のチェックにいかず、同じエラーメッセージが出続けます。何とかほかのカーソルに移さずに修正したら正しく処理が通るようにできないでしょうか。 5、最後に何も問題なかったらテキストボックスにロックかけるよう処理をしているのですが「コントロールの変更を保存していないときはコントロールをロックできません」というエラーメッセージが出てくる時があります。意味が分からず調べても出てこなかったので意味のわかる方何が悪くてエラーになっているのか教えて下さい。 調べてもデバッグしても原因が分からないものばかりです。 長文になってしまいましたがわかる方よろしくお願いします。

  • 正規表現-数字

    VB6で開発しています。 ひとつのテキストボックスがあり(MAXLENGTHが4)、 半角数字or小数点しか入力できないように制御しています。 下記正規表現確認関数で、 00.0~99.9の値のみ認証したいのですが、 (チェック前に Format( XX , '00.0')に変換してます) ○ 3 ○ 3.3 ○ 33 ○ 33.3 × 3.33 × .333 × 333 △ 3.00 → 3.0に変換させる パターンマッチング (\d{1,2}.\d|\d{1,2})ですと 本来×の333がOKとなってしまいます。 正規表現が間違っているのでしょうか? アドバイスお願いします。 関数はこちら Public Function RegExpCheck(ByVal ChkString As String, _ ByVal RegPattern As String) As Boolean '(一部省略) '引数:ChkString 正規表現確認対象文字 ' RegPattern パターン '戻り値:True マッチしている ' :False マッチしていない、あるいは文字・パターンが空白 '(一部省略) Dim reg As New RegExp RegExpCheck = False On Error GoTo RegErr '引数空白チェック・・・空白の場合はFalseを返す '対象文字列 If Trim$(ChkString) = vbNullString Then Exit Function End If 'パターン If Trim$(RegPattern) = vbNullString Then Exit Function End If reg.Pattern = RegPattern If reg.Test(CStr(ChkString)) = True Then RegExpCheck = True End If Exit Function RegErr:

  • 関数から関数を呼び出したときのリターン処理について

    宜しくお願いいたします。 ユーザー定義関数からユーザ定義関数を呼び出す必要があり 以下の様にしてみたところ function chk($value) {    if ($value>0) {       return TRUE;    }    return FALSE; } function test(){    $a = 0;    $b = -1;    $c = 2;    $txt = '';    if (chk($a)) {       $txt .= 'aはhoge<br>';    }    if (chk($b)) {       $txt .= 'dはhoge<br>';    }    if (chk($c)) {       $txt .= 'cはhoge<br>';    }    return $txt; } 最初の chk($a) で処理が終わってしまいます。 この場合 chk() の return が test() をも止めてしまっているのでしょうか? return で調べて見ると 呼び出し元のスクリプトに戻る というような解説だったので test() に戻って処理の続きをしてくれる と思ったのですがうまくいきません。 これを return $txt; まで処理させるにはどのようにしたらよいでしょうか? できれば chk() をTRUE、FALSEの判定に使いたいと思います。 何卒ご教授のほどよろしくおねがいします。

    • ベストアンサー
    • PHP
  • Like演算子で、[と]を文字として扱い比較したい

    今、フォルダ内のファイルリストを作成するVBA(Excel2003)を作っています。そこで、ファイル(絶対パス:フルパス)に「含まれていい文字」と「含まれない文字」(キーワード)を指定できる機能を作っています。 以前、VB6で類似の機能を作った時は、すんなり行ったのですが、VBAではうまくいきません。正規表現が使えるに越したことはないのですが、「 [ や ] を文字として認識するだけでもいいです。」 リストを作るフォルダには、  [20].txt  テキスト[a]txt  メモ[10] - コピー.txt などのテストファイルとその他ファイルが存在します。 キーワードを指定しないときには、うまく行きます。 指定すると、たとえば [10].txt というファイルがヒットしないように、NGワードを [10] を指定すると、[20].txtまでヒットしません。[a]では全てがヒットしません。 また、OKワードに[10]を指定すると[10]と[20]がヒットします。 ===== NGワードを比較している部分 ==== 引数:in_str が NGワード(スペースで区切って複数指定可能) 引数:target_Str がフルパス Public Function keywords_NG(in_Str As String, target_Str As String) As Boolean   If in_Str = "" Then     keywords_NG = True     Exit Function   End If      Dim wordArray() As String   Erase wordArray()   wordArray() = Split(in_Str, Space(1))     Dim tempFLG As Boolean   tempFLG = True      Dim wordIDX As Long   For wordIDX = 0 To UBound(wordArray) Step 1     If wordArray(wordIDX) <> "" And target_Str <> "" Then       If target_Str Like "*" & wordArray(wordIDX) & "*" = True Then         tempFLG = False       End If     End If   Next   If tempFLG = True Then     keywords_NG = True   Else     keywords_NG = False   End If End Function ===== OKワードを比較している部分 ==== 引数:in_Str が OKワード(スペースで区切って複数指定可能) 引数:target_Str がフルパス Public Function keywords_OK(in_Str As String, target_Str As String) As Boolean   If in_Str = "" Then     keywords_OK = True     Exit Function   End If   Dim wordArray() As String   Erase wordArray()   wordArray() = Split(in_Str, Space(1))      Dim tempFLG As Boolean   tempFLG = False      Dim wordIDX As Long   For wordIDX = 0 To UBound(wordArray) Step 1     If wordArray(wordIDX) <> "" And target_Str <> "" Then       If target_Str Like "*" & wordArray(wordIDX) & "*" = True Then         tempFLG = True       End If     End If   Next      If tempFLG = True Then     keywords_OK = True   Else     keywords_OK = False   End If    End Function ===== [や]を区切り文字ではなくする関数 ==== Public Function keywords_escape_sequence(keywordStr As String) As String      If keywordStr = "" Then     keywords_escape_sequence = ""     Exit Function   End If      Dim myIDX As Currency   Dim str_X As String      str_X = ""        For myIDX = 1 To Len(keywordStr) Step 1     If Mid(keywordStr, myIDX, 1) = "[" Then       str_X = str_X & "[[]"     ElseIf Mid(keywordStr, myIDX, 1) = "]" Then       str_X = str_X & "[]]"     Else       str_X = str_X & Mid(keywordStr, myIDX, 1)     End If   Next      keywords_escape_sequence = str_X End Function =====================================================     If keywords_OK(keywords_OK_Str, フルパス)) = True And _       keywords_NG(keywords_NG_Str, フルパス)) = True Then         'ファイルリスト作成     end if ===================================================== 正規表現を使うためには…というページを見つけ参照設定に以下の項目にチェックを入れてみましたが、結果は変わらす □Microsoft VBScript Regular Expressions 5.5 ===== RegExp と CreateObject ==== 参照設定をできれば変更したくない場合は、RegExp と CreateObject を使えば良いとあるページに書いてありましたが、参照設定でもできなかったので、これだけは試してません。 ヒントだけでもお教えください。

  • この場合エクセルVBAでどう書けばいいでしょうか?

    あるシートのH列で、H21からH46のあいだで"False"がある行を非表示にしたいのです。 下記の冗長なマクロでもそうなりますが、For Nextというのを使うともっと簡潔に記述できると思うのですが、初心者のためよくわかりません。ご教示ください。 また、下記の式はシートが保護されていると働きませんが、保護したシートでも動く方法があればそれもあわせて教えていただけると幸いです。 エクセルは95です。 Sub 空白行非表示() G% = Sheets("見積書").Range("H48").Value With Sheets("見積書") Rows("19:47").RowHeight = G% If Range("H21") = False Then Rows("21").EntireRow.Hidden = True End If If Range("H22") = False Then Rows("22").EntireRow.Hidden = True End If If Range("H23") = False Then Rows("23").EntireRow.Hidden = True End If If Range("H24") = False Then Rows("24").EntireRow.Hidden = True End If 途中、繰り返しのため省略 If Range("H42") = False Then Rows("42").EntireRow.Hidden = True End If If Range("H43") = False Then Rows("43").EntireRow.Hidden = True End If If Range("H44") = False Then Rows("44").EntireRow.Hidden = True End If If Range("H45") = False Then Rows("45").EntireRow.Hidden = True End If If Range("H46") = False Then Rows("46").EntireRow.Hidden = True End If End With End Sub

  • エクセルVBAについて質問です。

    エクセルVBAについて質問です。 ユーザーフォームのテキストボックスに数字以外を入力するとエラーメッセージが出るように関数を作ったのですが、 Private Function AA(objtextbox As MSForms.TextBox) As Boolean Dim A As String AA = False A = Trim(objtextbox.Text) If objtextbox.Text <> "" Then If IsNumeric(A) = False Then MsgBox "数値 Error", vbCritical With objtextbox .SetFocus .SelStart = 0 .SelLength = Len(.Value) End With AA = True End If End If End Function Private Sub textbox1_exit(ByVal cancel As MSForms.ReturnBoolean) cancel = AA(TextBox1) End Sub テキストボックス200近くある場合、1つ1つに Private Sub textbox1_exit(ByVal cancel As MSForms.ReturnBoolean) cancel = AA(TextBox1) End Sub と作っていかなくてはいけないのでしょうか? プロシージャ名に変数使おうとしたら上手くできませんでした。 どなたか助けてください。

  • クラスモジュールの処理

    VB6.0で開発しています。 以下のようにクラスモジュールを作ったのですが フォームでコマンドボタンを押したら 処理されるようにしたいのですが どうすればいいかわかりません。 教えてください。 Class CExcel Public App Public WshShell Public ErrDescription Private WorkBook Public CurBook Private Sub Class_Initialize() Call InitSetting() End Sub Private Sub Class_Terminate() Call Quit() End Sub Public Default Function InitSetting() if IsEmpty( App ) then Set App = CreateObject("Excel.Application") end if if IsEmpty( WshShell ) then Set WshShell = CreateObject("WScript.Shell") end if App.DisplayAlerts = False Set CurBook = Nothing end function Public Function Quit() If not IsEmpty( App ) Then For Each Workbook In App.Workbooks WorkBook.Saved = True Next App.Quit Set App = Nothing App = Empty Set CurBook = Nothing End If End Function Public Property Let Visible( bFlg ) App.Visible = bFlg End Property Public Property Get Visible Visible = App.Visible End Property Public Function Open( strPath ) on error resume next Set Open = App.Workbooks.Open(strPath) if Err.Number <> 0 then Set Open = Nothing ErrDescription = Err.Description Exit Function end if on error goto 0 Set CurBook = Open ' アクティブなウィンドウを最大化 App.ActiveWindow.WindowState = xlMaximized End Function Public Function Create( strPath ) Dim nBooks App.Workbooks.Add nBooks = App.Workbooks.Count Set Create = App.Workbooks( nBooks ) Set CurBook = Create CurBook.Activate App.ActiveWindow.WindowState = xlMaximized if strPath <> "" then on error resume next CurBook.SaveAs( strPath ) if Err.Number <> 0 then MsgBox( Err.Description ) Exit Function end if on error goto 0 end if End Function Public Function Close( MyBook ) if IsObject( MyBook ) then MyBook.Saved = True MyBook.Close Set MyBook = Nothing MyBook = Empty else if CurBook is Nothing then else CurBook.Saved = True CurBook.Close Set CurBook = Nothing end if end if End Function Function Save( MyBook ) if IsObject( MyBook ) then MyBook.Save else CurBook.Save end if End Function Function SaveAs( MyBook, strPath ) if IsObject( MyBook ) then MyBook.SaveAs strPath else CurBook.SaveAs strPath end if End Function Function Load( strPath ) if not IsEmpty( App ) then MsgBox( "Excel をロードする前に、Quitを実行して下さい   " ) Exit Function end if Call WshShell.Run( _ "RunDLL32.EXE shell32.dll,ShellExec_RunDLL " & _ strPath _ ) End Function End Class

  • VBAの処理が止まる原因と対策を知りたい

    現在以下のとおりのVBAを動かしいますが、途中でフリーズしてしまうため、 原因が特定できずに困っています。 その原因と対策もしくは、原因を突き止める方法をご教授いただければと思います。 ・サーバ上にあるブックを4つ開く(BookA、BookB、BookC、BookD) ・BookAに記載している文字列を配列に入れる ・BookB上にて、前述の文字列を検索し、そのアドレスを取得(後述の関数B) ・BookB上にて、前述のアドレスから別の文字列を取得(後述の関数A) となります。なお「Application.ScreenUpdatingの停止」と「Application.Calculationを手動」は実施しましたが、改善しませんでした。 以下環境、状況、VBAの記述になります。 環境 OS:Windows7 64bit CPU:i3 メモリ:8GB EXCEL:2010 状況 ・関数Aから関数Bを呼んだ後にフリーズしている模様です(関数Bを呼ぶところまでは、確認できますが、その後フリーズをするため、関数Aに戻っているかは不明です)。 ・フリーズ時のEXCEL.EXEのCPU使用率は25%で固定です。 関数A Function Test1(WS1 As Worksheet, Str1() As String, Str2() As String) Dim i As Integer Dim Row As Integer, Co As Integer Dim Temp_Range As Range Dim Temp_Str As String For i = 1 To UBound(Str2) ReDim Preserve Str1(i) Temp_Str = Test2(WS1, Str2(i - 1)) If Temp_Str <> "ない" And Temp_Str <> "重複" Then Set Temp_Range = WS1.Range(Temp_Str) If Temp_Range.MergeCells Then Co = Temp_Range.Column + Temp_Range.MergeArea.Count - 1 Else Co = Temp_Range.Column End If   Row = Temp_Range.Row Str1(i - 1) = WS1.Cells(Row, Co).Offset(0, 1).Value End If Next i End Function 関数B Function Test2(WS1 As Worksheet, Str1 As String) As String Dim temp As Range Dim a, b As Boolean Dim r As String Dim i, j As Integer Set temp = WS1.UsedRange For i = 1 To temp.Rows(temp.Rows.Count).Row For j = 1 To temp.Columns(temp.Columns.Count).Column If Replace(WS1.Cells(i, j).Value, vbLf, "") = Replace(Str1, vbLf, "") Then If a = False Then r = WS1.Cells(i, j).Address a = True Else r = "重複" b = True Exit For End If End If Next If b = True Then Exit For Next If r = "" Then r = "ない" Test2 = r End Function

  • access vbaで引数によって、関数を変えたい

    引数名の関数を実行したいのですが、どうすればいいでしょうか? 【やりたいイメージ】 Function 関数選択(関数) 関数選択 = 関数() ← 引数の関数が"z"の場合、"Function z()"を呼びたい End Function -------------------- 呼び出す関数 -------------------- Function a() a = "a" End Function ~ Function z() z = "z" End Function -------------------------- "Function 関数選択(関数)"の中で、ifやswich すればできると思うのですが、ずらずら書くのもうっとおしいのでスマートにしたいと思っています。 call がいいと思ったのですが、戻り値がかえせません。 何かいい方法はないでしょうか? よろしくお願いします。

  • VBAでの疑問

    以下のようなコードを見ました。 Private Sub Workbook_BeforeClose(Cancel As Boolean) With ThisWorkbook Application.DisplayAlerts = False If .Name <> .FullName Then SaveAs Else Me.Saved = True End If Application.DisplayAlerts = True End With End Sub これは何のためのコードでしょうか? If .Name <> .FullName Then って、パスなしのBOOK名とパス付BOOK名が同じじゃないのは当然で、同じになるのは新規に作成したばかりで保存する前のファイルくらいしか思いつきません。これでは必ず上書きされてしまうと思いますが、どういう意図が考えられるのかお分かりの方教えていただけないでしょうか?

専門家に質問してみよう