Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Excel 2019)
2つのファイルでユーザー定義関数の結果が異なる
投稿日時: 23/02/03 10:48:37
投稿者: FHH

 Excelファイル「A.xlsm」 ユーザー定義関数「eval」 文字列の計算式を計算
 Excelファイル「B.xlsm」 ユーザー定義関数「calc」 文字列の計算式を計算
 
「A.xlsm」には、文字列の計算式を計算するユーザー定義関数「eval」が入力されていました。
「B.xlsm」には、当方で使用していた同様のユーザー定義関数「calc」を使用していましたが
式を統一するため「B.xlsm」のユーザー定義関数を「eval」へ変更することになりました。
 
 
「A.xlsm」からユーザー定義関数「eval」を記述している標準モジュールをエクスポートし、
「B.xlsm」に標準モジュールをインポートしました。
「B.xlsm」で試しに簡単な文字列を入力したところ、「#VALUE!」と表示されました。
  セル  入力値   結果
  A1  2×2
  B1  =eval(A1)  #VALUE!
  C1  =calc(A1)  4
 
同様に「A.xlsm」へ「B.xlsm」からユーザー定義関数「calc」の標準モジュールをインポート
した場合は計算結果が表示されます。
 セル  入力値   結果
  A1  2×2
  B1  =eval(A1)  4
  C1  =calc(A1)  4
 
この場合、エクセルファイル「B.xlsm」でユーザー定義関数「eval」の結果が「#VALUE!」となるのは
どのような原因が考えられるのでしょうか。
 
 

回答
投稿日時: 23/02/03 11:42:36
投稿者: Suzu

#VALUE! なのであれば、関数は呼び出せているが、
演算最中に、問題が発生しているのではないでしょうか?
 
とりあえず、シングルステップで コードを実行し、
希望通りの演算が進んでいるか確認しましょう。

投稿日時: 23/02/03 11:55:43
投稿者: FHH

とりあえず、途中経過の報告です。
 
ユーザー定義関数「eval」は、他の人が作成したコードのため
記述内容や動作結果がよくわかりませんでした。
 
とりあえず、2つ目の引数を削除するか、2つ目の引数に「Optinal」を
追記することで正しく計算されるようになりました。
 
///////////////////////////////////////////////////////////////////////////////////////////
ユーザー定義関数「eval」
///////////////////////////////////////////////////////////////////////////////////////////
 Function eval(cl, n%)
    Dim e$, eq$, i%, ro%, co%, c$
 
    eval = ""
    e = cl.Text
    If Len(e$) < 1 Then Exit Function
    eq = ""
    For i = 1 To Len(e$)
        c = Mid$(e, i, 1)
        Select Case c
            Case "+": c = "+"
            Case "−": c = "-"
            Case "×": c = "*"
            Case "÷": c = "/"
            Case "π": c = "pi()"
            Case "√": c = "sqrt"
            Case "Σ": c = "sum"
            Case "(": c = "("
            Case ")": c = ")"
            Case "{": c = "("
            Case "}": c = ")"
            Case "{": c = "("
            Case "}": c = ")"
            Case "m": c = ""
            Case "k": c = ""
            Case "g": c = ""
        End Select
        If LenB(StrConv(c, vbFromUnicode)) = 2 Then
            c = ""
        End If
        eq = eq & c
    Next i
    eval = Application.WorksheetFunction.Round(Evaluate(eq$), n%)
 End Function
///////////////////////////////////////////////////////////////////////////////////////////
 
ユーザー定義関数「eval」には引数が2つ必要ですが、コード内では2つ目の引数について
なんら処理はされていません。
 
とりあえず、Excelファイル「B.xlsm」側で、標準モジュールで「eval」の2つ目の引数を
削除したところ計算されるようになりました。
 
すると、Excelファイル「A.xlsm」側でユーザー定義関数「eval」の計算結果が「#VALUE!」と
表示されるようになりました。
 
ユーザー定義関数「eval」の2つ目の引数に「Optional」を付けて省略可能にすると
正しく計算されるようになりました。
 
///////////////////////////////////////////////////////////////////////////////////////////
 
作業結果から、質問の内容を以下にまとめました。
後学のためにご教示頂けないでしょうか。
 
Q1 今までExcelファイル「A.xlsm」側ではユーザー定義関数「eval」に対して
  2つ目の引数を入力しなくてもエラーになりませんでした。
  
  引数を省略可能にするには「Optional」を記述する必要があると思いますが、
  なぜ「A.xlsm」ではエラーにならず、「B.xlsm」ではエラーになるのでしょうか。
 
 
 
Q2 「B.xlsm」の標準モジュールで2つ目の引数を削除すると「A.xlsm」側で
  ユーザー定義関数「eval」がエラーにかわるのはなぜでしょうか。
 
  「A.xlsm」の標準モジュールでは2つ目の引数はそのままなのでエラーに
  あるのが正しいのですが、今までエラーにならなかったのに突然エラーに
  なる理由が分かりません。
 
 
Q3 ユーザー定義関数「eval」は他人が作成したので記述ルールや仕様が
  よく分かりません。
 
  引数「n%」や変数「e$」、「eq$」、「i%」、「ro%」、「co%」、「c$」など、
  「%」や「$」は何を意味しているのでしょうか。
 
 
Q4 Q3に関係しますが、変数の宣言時に「$」を付けるのに、コード内では
  省略できるのはなぜでしょうか。
  

投稿日時: 23/02/03 12:01:11
投稿者: FHH

Suzu さんの引用:
#VALUE! なのであれば、関数は呼び出せているが、
演算最中に、問題が発生しているのではないでしょうか?
 
とりあえず、シングルステップで コードを実行し、
希望通りの演算が進んでいるか確認しましょう。

 
すず様、ご返信頂きありがとうございます。
 
投稿が前後しましたが、ユーザー定義関数の内容と途中経過をUPいたしました。
 
私の理解が乏しいため、先ほどまでシングルステップでのコード実行が行えませんでした。
「Optiona」を記述したためか、今はステップ実行できるようになりました。
 
もとのコードでステップ実行できなかった理由が分かりません。

回答
投稿日時: 23/02/03 12:32:03
投稿者: simple

横入失礼します。
Q1,2
   不明ですね。詮索しても余り利益はない気はします。(どなたかから回答があればよいけど)
   要するに、定義と同じ個数の引数を指定してください。
   両用にするには、ご指摘のOptionalを使用してください。
 
Q3 「型宣言文字」というものです。
   例えば、Integerのヘルプを見て下さい。
   Integer の型宣言文字はパーセント (%) 記号です。
   と書かれています。
   ちなみに、$ は String です。
 
Q4 変数使用時にはつけない仕様かと思います。
   ただし、2.5# などと 数値に対しては Double指定などをつけることがあります。
   これは数値の型指定をしていると理解ください。
 
余談ですが、質問掲示板の回答では余り使うことがありません(説明が必要になるので)が、
個人的には、入力負荷軽減になるので結構使います。

回答
投稿日時: 23/02/03 12:50:46
投稿者: simple

変数使用時にはつけない仕様かと思います、は
変数使用時にはつけないことが多いと思います、に訂正します。
 
余談ですが、
MID$,LEFT$,RIGHT$などの関数は、$をつけないものに比べて早かったんですかね、
昔はそういう話がありましたが、最近は余り見ませんね。

投稿日時: 23/02/03 12:59:19
投稿者: FHH

simple様、ご返信ありがとうございます。
 
 A1,2 モーグに投稿する前にも検索しましたが何も得るものがありませんでした。
    「今までは、たまたまOKだった。」と考えるようにします。
 
 A3,4 「型宣言文字」は知りませんでした。有用な情報をありがとうございます。
 
 
ご回答いただきました、Suzu様、simple様、誠にありがとうございました。
これで「解決済み」とさせていただきます。