DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Functionの値保持について

環境/言語:[WinXP Pro,VB6.0]
分類:[VB6以前]

はじめて投稿させていただきます。

旧環境で作成したモジュールの新環境への移行作業を行っています。
【旧環境】 OS :WindowsNT 4.0 言語:VB4.0 Access:Access 95
TDBG:TrueDBGrid Pro 4.0 DAO :3.51
【新環境】 OS :WindowsXP Pro 言語:VB6.0 Access:Access 2003
TDBG:TrueDBGrid Pro 6.0 DAO :3.6

新環境において、コンパイルエラー等は起こっていないのですが
現在、以下のような問題が発生しています。
問題1:AccessのデータをTDBGに値を渡すFunctionがあるのですが、
    Function内部での値の受け渡しはできているようですが、
    Functionを抜けると値が消えてしまいます。
問題2:Function内でFormのテキストボックス(DataSource:MDBファイル)に
    文字列の値を格納しても
Functionを抜けるとテキストボックスの値が消えてしまいます。

以上2点について、どなたか解決策をご存知でしたら
お教えいただけると幸いです。
よろしくお願いします。
2004/08/05(Thu) 10:56:41 編集(投稿者)

■No5351に返信(アバ茶さんの記事)
> はじめて投稿させていただきます。
>
> 旧環境で作成したモジュールの新環境への移行作業を行っています。
> 【旧環境】 OS :WindowsNT 4.0 言語:VB4.0 Access:Access 95
> TDBG:TrueDBGrid Pro 4.0 DAO :3.51
> 【新環境】 OS :WindowsXP Pro 言語:VB6.0 Access:Access 2003
> TDBG:TrueDBGrid Pro 6.0 DAO :3.6
>
> 新環境において、コンパイルエラー等は起こっていないのですが
> 現在、以下のような問題が発生しています。
> 問題1:AccessのデータをTDBGに値を渡すFunctionがあるのですが、
>     Function内部での値の受け渡しはできているようですが、
>     Functionを抜けると値が消えてしまいます。
> 問題2:Function内でFormのテキストボックス(DataSource:MDBファイル)に
>     文字列の値を格納しても
> Functionを抜けるとテキストボックスの値が消えてしまいます。
>
> 以上2点について、どなたか解決策をご存知でしたら
> お教えいただけると幸いです。
> よろしくお願いします。

質問を質問で返すようで悪いのですが、
貴方の仰る、「Function」というのは値を返す自作関数という解釈でよろしいでしょうか?

普通に考えて、勝手に消えるなんてことはありません。(COBOLやRPGなら別ですがw)
意図はしないが、消す制御をしてしまっているか、(ありえないですが)
関数内で渡しているモノが実体でない可能性も・・・。(画面で確認できてないようですから)

ということは、渡し方(ByVal? ByRef?)が気になります。
その関数への渡し方はどのようにやってますか?

# というより、ソースを貼り付けてもらった方が早そうです。
■No5352に返信(java.lang.Nullpoさんの記事)
> 2004/08/05(Thu) 10:56:41 編集(投稿者)
>
> 質問を質問で返すようで悪いのですが、
> 貴方の仰る、「Function」というのは値を返す自作関数という解釈でよろしいでしょうか?
>
>
> # というより、ソースを貼り付けてもらった方が早そうです。

ご指摘ありがとうございました。
以下に環境とソースの一部を載せてみました。

○問題点1の環境、問題点
grdJUSYO(TDBG)の列のプロパティ
Columns(00)【都道府県】
Columns(01)【市区郡】
Columns(02)【都道府県カナ・非表示】
Columns(03)【市区郡カナ・非表示】
Columns(04)【都道府県コード・非表示】
Columns(05)【市区郡コード・非表示】
DataSource 【daoJUSYO】

daoJUSYOのプロパティ
RecordSource【JUSYO.mdb(Access2003)のテーブル】
Connect 【Access 2000;】

#### 問題と思われるソース ####

Public Function SetJusyoKen() as Integer
Dim dbMy As Database
Dim rsMy As Recordset
Dim strSQL As String

With grdJUSYO
Set dbMy = Workspaces(0).OpenDatabase("マスタ.mdb")
strSQL = 〜略 #指定した県のコード、カナを抽出するSQLを作成
Set rsMy = dbMy.OpenRecordset(strSQL, dbOpenSnapshot, dbForwardOnly + dbReadOnly)
If rsMy.EOF Then
.Columns(02).Value = ""
.Columns(04).Value = ""
Else
.Columns(02).Value = rsMy![都道府県カナ]
.Columns(04).Value = rsMy![都道府県コード]
End If
rsMy.Close
dbMy.Close
End With
mproSetJusyoKen = True
Exit Function
End Function

大まかな流れとしては
@Form起動時にサーバと接続してJUSYO.mdbに都道府県のデータを格納
ATDBGの都道府県の列をクリックして都道府県を選択
B都道府県を選択した状態で市区郡の列をクリック
3-1. TDBGのAfterColUpdateイベント発生
3-2. SetJusyoKenをCALL
3-3. rsMy.Closeを実行した際にgrdJUSYOのデータが消える
(それ以前のステップでは.Columnsにはそれぞれ値が入っています)
といった流れとなってます。
こちらの問題点は表題と現象が異なってますね。。。
不正確な説明で申し訳ありませんでした。


○問題点2の環境、問題点
txtNendo(テキストボックス)のプロパティ
DataSource【daoKihon】
MaxLength【4】

daoKihon(DAO)のプロパティ
RecordSource 【Kihon.mdb(Access 2003)のテーブル([tw基本])】
Connect 【Access 2000;】

#### 問題と思われるソース ####
Private Sub Form_Load()

Screen.MousePointer = vbHourglass
mstrNendo = Year(Now()) #mstrNendoはString * 4のform内のPrivate変数

Call DataClear
Unload TitleForm
Me.Show

Exit Sub
End Sub

Private Sub DataClear()

strSQL = "delete from [tw基本]"
gdbPS.Execute strSQL #gdbPSはDatabaseのPublic変数
daoKIHON.Refresh

txtNendo.Text = mstrNendo
Exit Sub
End Sub

大まかな流れとしては
@タイトルフォームからForm_Loadを実行
AForm_LoadでmstrNendoに年度データを格納
BDataClearをCall
CDataClearにて、DataSourceのクリアの後txtNendo.txtに
mstrNendoの値を格納してDataClearを抜ける
DタイトルフォームのUnload、Me.showの実行
EExit SubでForm_Loadを抜ける際にtxtNendo.txtの値が""に変更される

といった流れとなってます。ご不明な点があればお知らせください。
こんにちわ、アバ茶さん。

まず簡単に解決しそうな、2つ目の問題点の方。

> EExit SubでForm_Loadを抜ける際にtxtNendo.txtの値が""に変更される

これは、つまり…

> txtNendo.Text = mstrNendo

[↑]この時点で、mstrNendoが空文字になっているということですね?
モジュールスコープ変数のようなので、どこかで変わってしまってる可能性があります。
デバッガと変数ウォッチで見れば概ね、どの関数で置き換わってるかわかるはずです。
こちらは、追って頂くしかなさそうです。


1つ目の問題についてですが、私の頭では仕様がイマイチ理解できないんですが…

まず、SetJusyoKen()関数についてですが、Functionの割に値を返してなさそうですね。
(関数名 = ReturnValueがない)
しかし、関数名が「Get」ではなく「Set」であることと、内容を見る限りでは、Sub関数(void関数)のようですね。
# まあ、それは直接関係ないので良いですが…。

処理としては、

(1) 列をクリックするとAfterColUpdateが発生して、その中でSetJusyoKen()関数をCall。
(2) SetJusyoKen()内で、SQL文を使って抽出をかける。
(3) ヒットしなければブランク表示。
  ヒットすれば、都道府県カナなどを2番目と4番目のカラムに表示。

(3)の時点、またはそれ以前では、
 grdJUSYO.Columns(2).Value には、何かしろの都道府県カナが入ってる。
 grdJUSYO.Columns(4).Value には、何かしろの都道府県コードが入ってる。
っていうことですよね?

(4) rsMy.Closeでデータが消える。

rsMy.Close()実行時に、変数ウォッチで見えていたデータまで消滅する…ということですよね?
rsMyはレコードセット・・・ローカル変数なので、grdJUSYOと連結している可能性はない。
なのに、Close()メソッドを実行するとgrdJUSYOで設定したカラム値が、消える…。ヘンな話ですね。

こんな感じでできないですか? (ローカル変数はプロシージャを抜けると、消滅するので私はCloseしません)

Public Sub SetJusyoKen()
  Dim dbMy As Database
  Dim rsMy As Recordset
  Dim strSql As String

  With grdJusyo
    Set dbMy = Workspaces(0).OpenDatabase("マスタ.mdb")
    strSql = GetSql()
    Set rsMy = dbMy.OpenRecordset(strSQL, dbOpenSnapshot, dbForwardOnly + dbReadOnly)

    If rsMy.EOF Then
      .Columns(2).Value = ""
      .Columns(4).Value = ""
    Else
      .Columns(2).Value = rsMy.Fields("都道府県カナ").Value
      .Columns(4).Value = rsMy.Fields("都道府県コード").Value
    End If
  End With

  mproSetJusyoKen = True
End Sub
■No5360に返信(java.lang.Nullpoさんの記事)
こんにちわ、java.lang.Nullpoさん。
何度も回答を頂きまして、ありがとうございます。

>
>>EExit SubでForm_Loadを抜ける際にtxtNendo.txtの値が""に変更される
>
> これは、つまり…
>
>>txtNendo.Text = mstrNendo
>
> [↑]この時点で、mstrNendoが空文字になっているということですね?
> モジュールスコープ変数のようなので、どこかで変わってしまってる可能性があります。
> デバッガと変数ウォッチで見れば概ね、どの関数で置き換わってるかわかるはずです。
> こちらは、追って頂くしかなさそうです。

ウォッチ式で値を追った結果

txtNendo.text = mstrNendo

の段階では双方に正しい値が格納されていましたし、
Form上からもテキストボックスの値が確認されましたが、
Form_Loadを抜けた瞬間に、txtNendo.textの値が""に変わっていました。
説明不足で申し訳ありません。

> rsMy.Close()実行時に、変数ウォッチで見えていたデータまで消滅する…ということですよね?
> rsMyはレコードセット・・・ローカル変数なので、grdJUSYOと連結している可能性はない。
> なのに、Close()メソッドを実行するとgrdJUSYOで設定したカラム値が、消える…。ヘンな話ですね。
>
> こんな感じでできないですか? (ローカル変数はプロシージャを抜けると、消滅するので私はCloseしません)
>

Closeを省略しても、変数を抜ける際にGridの値は破棄されてしまいました。。。
が、rsMy,dbMyをForm全体で使えるPrivateとして宣言してみたところ
値の消滅が起こりませんでしたので、現状のエラーは回避できました。
同様に問題2の問題もmstrNendoをPublicとして宣言したところ
現状のエラーは回避できました。
とりあえずは、この方針で改修を進めたいと思います。
度重なるご指導、本当にありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板