tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトル「式が複雑すぎます」の対処について
記事No16248
投稿日: 2016/07/07(Thu) 16:53
投稿者たまご
お世話になります。よろしくお願いします。

VB6.0でプログラムを作成中なのですが、「式が複雑すぎます」というエラーが出るようになってしまいました。

エラー箇所は、

        If i = 0 Then
            sDay = CStr(startdate)
        Else
            sDay = DateAdd("d", 1, sDay)
        End If

というところで、「sDay = DateAdd("d", 1, sDay)」にきたときにエラーが起こりました。

また、エラーの起こり方も少しおかしいのですが、
エラーが起きる行で止め、「Format(DateAdd("d", 1, sDay), GCSS_YYYYMMDD)」
にカーソルを近づけてみると、1回目は「式が複雑すぎます」と出るのに、
一度カーソルを遠ざけてもう一度近づけるときちんと日付が表示されます。

ちなみに、「式が複雑すぎます」と表示されているタイミングでもsDayの中身はきちんと日付が出ています。

どういうことなのか判らずに困っています。

「式が複雑すぎます」というエラーだと、ネットの対処法では式を分割するということのようなのですが、
正直長さが感じられないため、どのようにすればよいかがよくわかりません。

対処法を教えていただけませんでしょうか。よろしくお願いいたします。

[ツリー表示へ]
タイトルRe: 「式が複雑すぎます」の対処について
記事No16249
投稿日: 2016/07/07(Thu) 18:57
投稿者魔界の仮面弁士
> VB6.0でプログラムを作成中なのですが、「式が複雑すぎます」というエラーが出るようになってしまいました。
Access や Excel の Visual Basic 6.0 (VBA) でしょうか。
それとも単体開発ツールとしての Visual Basic 6.0 でしょうか。

前者だとしたら、参照設定情報の破損によって引き起こされることがあります。
この場合、参照設定を可能な限り外してからファイルを開きなおし、
管理者モードで起動してから参照設定をやり直すことで解決することがあります。

後者だとしたら、デバッグ実行では無く、コンパイル動作でも同じ結果になるか
確認してみてください。

あとは、Service Pack やセキュリティパッチの類が最新になっているかを確認するとか。



> 「sDay = DateAdd("d", 1, sDay)」にきたときにエラーが起こりました。

他の環境で再現性があるかどうか、調査してみたいので、
変数 sDay のデータ型と、エラー発生直前の sDay の値を教えてください。

 Open "C:\TEMP\TEST.BIN" For Binary As #257
 Put #257, , sDay
 Close #257

[ツリー表示へ]
タイトルRe^2: 「式が複雑すぎます」の対処について
記事No16250
投稿日: 2016/07/07(Thu) 20:37
投稿者魔界の仮面弁士
> > 「sDay = DateAdd("d", 1, sDay)」にきたときにエラーが起こりました。
>
> 他の環境で再現性があるかどうか、調査してみたいので、
> 変数 sDay のデータ型と、エラー発生直前の sDay の値を教えてください。

試しに、sDay として特殊値を渡してみましたが、『式が複雑すぎます』な現象は確認できませんでした。

DateAdd("d", 1, zero)
DateAdd("d", 1, epsilon)
→ 1899/12/31

DateAdd("d", 1, min_oledate)
→ 100/01/02

DateAdd("d", 1, max_double)
DateAdd("d", 1, min_double)
→ [Error 13: 型が一致しません。]

DateAdd("d", 1, max_oledate)
DateAdd("d", 1, max_oledate2)
DateAdd("d", 1, not_a_number)
DateAdd("d", 1, negative_infinity)
DateAdd("d", 1, positive_infinity)
→ [Error 5: プロシージャの呼び出し、または引数が不正です。]



--- 特殊値の生成コード ---

Option Explicit

Private Type B8
    Bin(7) As Byte
End Type

Private Type DBL
    value As Double
End Type

Private Function GetDouble(ParamArray b() As Variant) As Double
    Dim src As B8, dst As DBL
    Dim i As Integer, u As Integer
    
    u = UBound(b)
    For i = 0 To IIf(u > 7, 7, u)
        src.Bin(i) = b(i)
    Next
    LSet dst = src
    On Error Resume Next
    GetDouble = dst.value
End Function


Private Sub Command1_Click()
    Dim zero As Double
    zero = GetDouble(0, 0, 0, 0, 0, 0, 0, 0, 0)
    Debug.Print zero                '「 0」
    
    Dim epsilon As Double           '0より大きい最小の値
    epsilon = GetDouble(1, 0, 0, 0, 0, 0, 0, 0, 0)
    Debug.Print epsilon             '「 4.94065645841247E-324」
    
    Dim min_double As Double        'Double型の最小値
    min_double = GetDouble(&HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HEF, &HFF)
    Debug.Print min_double          '「-1.79769313486232E+308」
    
    Dim max_double As Double        'Double型の最大値
    max_double = GetDouble(&HFF, &HFF, &HFF, &HFF, &HFF, &HFF, &HEF, &H7F)
    Debug.Print max_double           '「 1.79769313486232E+308」
    
    Dim min_oledate As Double       'Date型の最小値
    min_oledate = GetDouble(0, 0, 0, 0, &H34, &H10, &H24, &HC1)
    Debug.Print min_oledate         '「-657434」0100/01/01 00:00:00.0000000
    
    Dim max_oledate As Double       'Date型の最大値
    max_oledate = GetDouble(&HE9, &H9E, &HFF, &HFF, &H40, &H92, &H46, &H41)
    Debug.Print max_oledate         '「 2958465.99998843」9999/12/31 23:59:59.0000000
    
    Dim max_oledate2 As Double      'Date型の本当の最大値
    max_oledate2 = GetDouble(&HFE, &HFF, &HFF, &HFF, &H40, &H92, &H46, &H41)
    Debug.Print max_oledate2        '「 2958466」※実際には958466より小さい最大の値
    
    Dim not_a_number As Double      '非数値
    not_a_number = GetDouble(0, 0, 0, 0, 0, 0, &HF8, &HFF)
    Debug.Print not_a_number        '「-1.#IND」indeterminate value

    Dim negative_infinity As Double '負の無限大
    negative_infinity = GetDouble(1, 0, 0, 0, 0, 0, &HF0, &HFF)
    Debug.Print negative_infinity   '「-1.#QNAN」negative quiet Not-a-Number
    
    Dim positive_infinity As Double '正の無限大
    positive_infinity = GetDouble(1, 0, 0, 0, 0, 0, &HF0, &H7F)
    Debug.Print positive_infinity   '「 1.#QNAN」positive quiet Not-a-Number
End Sub

[ツリー表示へ]
タイトルRe^3: 「式が複雑すぎます」の対処について
記事No16251
投稿日: 2016/07/07(Thu) 22:08
投稿者たまご
お世話になります。

ご返信ありがとうございます。

私が使っているのはVisual Basic 6.0です。
検証までしていただき、ありがとうございます。

あまり頻発するような事例ではないのですね。

ご質問に関してですが、
コンパイル後に試してみると、どういうわけかそのままエラーにならず進みます。
また、もう少し詳しくソースを書きますと、


Public Function GetPercentage(ByVal alDayEnd As Long, _
                              ByVal adteStart As Date) As Integer
On Error GoTo ERR_HANDLER_RTE

    GetPercentage = GCI_RET_ERR

Dim sDay        As String

    '日付ごとの合計点の取得
    For i = 0 To alDayEnd - 1

        ' 日付
        If i = 0 Then
            sDay = CStr(adteStart)
        Else
            sDay = DateAdd("d", 1, sDay)
            sDay = Format(sDay, GCSS_YYYYMMDD)
        End If

・・・という流れになるのですが、Forの一回目のループではsDay = CStr(adteStart)に正しく日にちが入ります。
日にちは必ず月初めの1日が入り、それから1日ずつ足していく流れになります。


上の関数の呼び出しのときは、

If GCI_RET_SUS <> GetPercentage(uJoken.iDayEnd, _
                                uJoken.dteStt) Then
GoTo END_HANDLER_NML
End If

です。

1度目のループのときに    For i = 0 To alDayEnd - 1で止めてみましたが、
alDayEnd  = 7、adteStart  = 2016/07/01 でした。

2度目のループ(エラーが起きるとき)は、sDayの時点で「式が複雑すぎます」になります。
これも一度カーソルを話して近づけると正しく2016/07/01になります。

ただ、この関数の中でsDayに値を入れているのがこの部分のみになります。

VBのソースの書き方というよりも、VB自体というか、パソコン自体の問題にも思えてきました。

sDayがどの時点で複雑になるか、確認してみます。

[ツリー表示へ]
タイトルRe^4: 「式が複雑すぎます」の対処について
記事No16252
投稿日: 2016/07/08(Fri) 10:44
投稿者魔界の仮面弁士
> sDayがどの時点で複雑になるか、確認してみます。

型が曖昧で、かつ、複数の意味に使い回されているように見えます。


> Dim sDay        As String
> sDay = CStr(adteStart)

まず、日付型をわざわざ 文字列型にしているようですが、
DateAdd の第三引数および戻り値の型は、本来は String 型ではなく
日付型、より正確には「内部処理形式 Date の Variant 型」であるため、
String にしてから DataAdd させるのは得策とは言えません。

基準日たる adteStart は Date 型なので、変数を As Date にして、
型を揃えておいた方が良いと思います。日付計算時には
文字列型を介在させる必要が無さそうなので、今回は
CStr / CDate / CVDate 等の出番も無さそうですね。


> sDay = DateAdd("d", 1, sDay)
> sDay = Format(sDay, GCSS_YYYYMMDD)
この二行は、上の sDay と 下の sDay とで、変数の意味が変わってしまっています。

一つの変数を使い回して複数の用途を持たせるのは、バグの温床になりますので
 Dim dDay As Date, sDay As String
 dDay = DateAdd("d", 1, dDay)         '日付型としての演算
 sDay = Format(dDay, GCSS_YYYYMMDD)   'その日付値の文字列表記
などのように、意図に応じて変数を分けておく事をお奨めします。


> それから1日ずつ足していく流れになります。
コード全体を見たわけではありませんが、その流れであれば
そもそも If 文も不要で、下記の処理だけで済みそうです。


Dim dDay As Date, sDay As String
For i = 0 To alDayEnd - 1
  dDay = DateAdd("d", i, adteStart)   '基準日adteStartの i 日後の日付
  sDay = Format(dDay, GCSS_YYYYMMDD)  '上記日付の文字列表現
  '
  '
  '
Next

[ツリー表示へ]