構造体のメンバについて質問です。
作成中の構造体は、メンバの数や階層などが深いのですが、
デバック実行を実施した時、アプリケーションエラーで
プログラムが終了してしまいます。
原因は、構造体の作りにあるのでしょうか?
また、上記事象を回避する案などがありましたら教えて下さい。
ちなみにVB5.0で作業を行っています。
制限値は調べてないのでなんなのですが・・
> メンバの数や階層などが深いのですが
とありますが、いったいどのくらいの数なんでしょう?
ここに公開できないような長さ?なのでしょうか?
ちらっとその定義されているコード部分だけでも
貼ってみられたらどうでしょう?
で、その構造体ってそもそも分けれないんですか?
例えば、多少格好悪いけど、
(まず似たような構造体名で2つ3つType作っておいて)
制御する添え字、インデックス値を同じにして
データ読み取り、書き込みするよう組めば、
むりむり分けれるのでは、と。
アプリケーションエラー、それじゃ回避できない??
たくみさん返答ありがとうございます。
定義されているコード部分を下記に載せます。
Type Torihikisakijoho
BytKoumoku(2) As Byte
StrKoumoku As String * 30
End Type
Type TorihikiSeigyojoho
BytKoumoku(2) As Byte
StrKoumoku As String * 61
End Type
Type HeaderBlock
BytKoumoku(2) As Byte
End Type
Type Tanmatujyoutaijoho
BytKoumoku(27) As Byte
End Type
Type TransactionSikibetu
BytKoumoku(19) As Byte
StrKoumoku As String * 5
End Type
Type Tanmatugyoumujoho
BytKoumoku1(4) As Byte
StrKoumoku1 As String * 5
BytKoumoku2(1) As Byte
StrKoumoku2 As String * 4
BytKoumoku3(1) As Byte
StrKoumoku3 As String * 3
BytKoumoku4(1) As Byte
StrKoumoku4 As String * 1
BytKoumoku5(1) As Byte
StrKoumoku5 As String * 11
BytKoumoku6(1) As Byte
StrKoumoku6 As String * 1
End Type
Type LogicalData
BytKoumoku(14) As Byte
StrKoumoku As String * 8 'マップ名称
End Type
Type IdCard
BytKoumoku(2) As Byte
StrKoumoku As String * 10
End Type
Type tagDATA0
Koumoku(7) As Byte
End Type
Type tagDATA1
Koumoku(7) As Byte
Data As String
End Type
Type tagDATA2
Koumoku(7) As Byte
Data As String * 1
End Type
Type tagDATA3
Koumoku(7) As Byte
Data As String * 2
End Type
Type tagDATA4
Koumoku(7) As Byte
Data As String * 3
End Type
Type tagDATA5
Koumoku(7) As Byte
Data As String * 6
End Type
Type tagDATA6
Koumoku(7) As Byte
Data As String * 7
End Type
Type Furikomi1
FI0020 As tagDATA5
FI0060 As tagDATA0
FI0070 As tagDATA1
FI0080 As tagDATA1
FI0090 As tagDATA2
FI0100 As tagDATA1
FI0110 As tagDATA1
FI0120 As tagDATA1
FI0130 As tagDATA0
FI0140 As tagDATA0
FI0190 As tagDATA3
FI0200 As tagDATA0
FI0220 As tagDATA0
FI0240 As tagDATA4
FI0250 As tagDATA2
FI0270 As tagDATA2
FI0290 As tagDATA2
FI0320 As tagDATA3
FI0330 As tagDATA6
End Type
Type strin04_01Rec
Koumoku1 As Torihikisakijoho
Koumoku2 As TorihikiSeigyojoho
Koumoku3 As HeaderBlock
Koumoku4 As Tanmatujyoutaijoho
Koumoku5 As TransactionSikibetu
Koumoku6 As Tanmatugyoumujoho
Koumoku7 As LogicalData
Koumoku8 As Furikomi1
Koumoku9 As IdCard
End Type
Global strin04_01 As strin04_01Rec
>(まず似たような構造体名で2つ3つType作っておいて)
>制御する添え字、インデックス値を同じにして
>データ読み取り、書き込みするよう組めば、
>むりむり分けれるのでは、と。
上記構造体の場合どういう形で構造体を分ければよいでしょうか?
申し訳ありませんが簡単に記述例など教えていただけましたら大変助かります。
ちなみに下記typeのFI0250〜FI0330をコメント化すると、
アプリケーションエラーは出ません。
Type Furikomi1
FI0020 As tagDATA5
FI0060 As tagDATA0
FI0070 As tagDATA1
FI0080 As tagDATA1
FI0090 As tagDATA2
FI0100 As tagDATA1
FI0110 As tagDATA1
FI0120 As tagDATA1
FI0130 As tagDATA0
FI0140 As tagDATA0
FI0190 As tagDATA3
FI0200 As tagDATA0
FI0220 As tagDATA0
FI0240 As tagDATA4
FI0250 As tagDATA2 'コメント化
FI0270 As tagDATA2 'コメント化
FI0290 As tagDATA2 'コメント化 → アプリケーションエラー
FI0320 As tagDATA3 'コメント化 は出ない。
FI0330 As tagDATA6 'コメント化
End Type
これって、COBOLの焼き直しとかですか?
・・ぜんぜんはずしてても、この際、発想の転換をしてみられては
どうなんでしょう?
でかいプロジェクトだったり、もうほとんどできあがってて今さら、
という段階なのかも知れませんね。
でもやっぱりVBなんだからもう少しMS$さんの役者たちを活用した方が
非常にすっきり、かつ便利で重宝すると思うのです。
例えば最初のType Torihikisakijohoとかですが、
わざわざTypeにしなくてもDBにテーブル作ってそっちに値を保持させ、
任意のフォーム起動時にレコードセットで取得させたり、
それと同じ考え方でINIファイルで管理したりレジストリで管理したり
すればいいんじゃないかと。
ちなみに私はINIもレジストリも日ごろよく使っていますが
それでトラブったことはほとんどないですよ。
あ、そういうことは普通にやってて、で内部の情報の管理(持たせ方)を
ただ構造体を登場させ出し入れしている、ということなのでしょうか?
もちろん普通ならばそれはそれでいいのでしょうが
今回のようにTypeの定義の多さや階層の深さが疑わしく思えるのなら
いっそそれらTypeをなるべく他の役者に変えてみられてはどうか、
という提案です。
でも、結局たらたらPublic変数とかいっぱい作ってそれらに
Type Torihikisakijohoとかの代替情報入れるのなら
わかりにくく、メンテしづらいし、あんまりメリット感じないよー
と言われるかも。
であれば、おすすめはレコードセット作った後に
GetRowsメソッドを実行し、配列に入れてしまいます。
構文:
array = recordset.GetRows( Rows, Start, Fields )
戻り値:
二次元の配列を返します。
詳しくはヘルプ見てみてください。
このサイト読まれている多くの方も意外と、というかぜんぜん
使っていないんじゃないでしょうか。
もちろん、絶対毎回使ったらいい、という性格のものじゃないですが
あとはその配列でスマートに、らくちんコーディングができるので
一度お試しあれ。
いつまでもいつまでも、いっぱいできたレコードセット殺せなくて
ひきずり回す、という必要もなくなるし。
たぶん、ペンネームさんの場合
Global strin04_01 As strin04_01Rec
とかは少なくともGetRowsの恩恵にあずかれるのではないでしょうか。
PS.
あと気になったのが、
Data As String * 1
Data As String * 2
とかです。
ものすごく変数がメモリ浪費するのを懸念しての策だと思ったのですが
ここは普通に、
Data As String
でやられてはどうでしょう?
実はそれでエラーでなくなったりとかありえませんか??
今、時間がなくなってきたのでその根拠までは
調べれないのでなんですが、なーんか関係あったような・・
単に見当違い、かもしれないのではずしてたらすみません。
・・もし知ってらっしゃる方おられましたら補足お願いします。
なんだか、私の言ってる焦点がぼやけて誤解されそうだったので
少し補足します。
Type strin04_01Rec
Koumoku1 As Torihikisakijoho
Koumoku2 As TorihikiSeigyojoho
・
・
Koumoku8 As Furikomi1
Koumoku9 As IdCard
End Type
Global strin04_01 As strin04_01Rec
のようにどんどん「たばねて」いく考えでなくても
ここはいいのではないでしょうか?ということです。
その観点から、情報「群」を「バラ」で持つことを
考え直したらいいのでは?ということです。
で、それで、Type Torihikisakijohoとかを
単体で、なおかつ「配列」で扱ってもいいのでは?
という提案をしたのですが。
逆になぜどうしても「たばねて」おきたいのかが??
それだったらRDB側で管理(これがさっき言ったレコードセットとか
その発展でGetRowsメソッドの話しの部分)をしたら
すっきりするんじゃないでしょうか、と。
なぜ、こういう「たばねる」必要があるのでしょう??
例えば、やっぱりCOBOLで言う多段階に(たいてい2〜3段に)
階層分けされたあの「ファイルレイアウト」とか「デザインシート」
が目に浮かんで来て、それをそのまんま(メンテしやすいよう)
たばねてコーディングしてみました、ということなのでは?
もし、それはずしてなければ「郷に入っては郷に従え」です。
せっかくのVBコーディングなのですから。
ちなみにオレの環境ではフツーにコンパイル通ったが…
[VB:6 WinXP(Home) Memory:512MB CPU:2.53GHz]
たくみさん色々ご教受ありがとうございました。
array = recordset.GetRows( Rows, Start, Fields )ですが、
ヘルプをみましたがいまいち使い方が分かりませんでした。
どこかよいサイトなどがありましたら教えていただきたくよろしくお願い致します。
GetRowsの前に普通にレコードセットは作ったのですよね?
今VB5の環境がないのでVB6での話しで書きます。
上の例で言うとarrayのところの変数を例えば
Dim RsArray As Variant
として宣言しておきます。
でもってあとは普通にレコードセット作ります。
Dim Rs As ADODB.Recordset
Set Rs = New ADODB.Recordset '毎回ここでNew初期化
'Rs作成
Rs.Open SQL, gCnSrc, adOpenStatic, adLockReadOnly, adCmdText
If RsSrc.EOF Then Exit Function
RsArray = RsSrc.GetRows() '既にRsArrayがあろうとなかろうと上書きさせる仕様
'いったんRsArrayに格納したのですみやかにRsをクローズしておく
RsSrc.Close: Set RsSrc = Nothing
すみません、今誤って途中で書きかけを送信してしまいました。
すぐ訂正したものを送ります。お待ちを。
さきほどの書きかけ誤送信分の訂正です。^^;
/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
GetRowsの前に普通にレコードセットは作ったのですよね?
今VB5の環境がないのでVB6での話しで書きます。
上の例で言うとarrayのところの変数を例えば
Dim RsArray As Variant
として宣言しておきます。
あと、ADO使うのだったら普通にADOコネクションをOpenしておきます。
DAOでは試してないのでなんなのですが、
とりあえずADOでの説明でご勘弁を。
・・でもってまずは普通にレコードセット作ります。
Dim Rs As ADODB.Recordset
Dim SQL As String
'(ここに取得したいSELECT文のSQL文を書きます)
SQL = "Select なんてらかんてら〜"
Set Rs = New ADODB.Recordset
'Rs作成
'※下記CnはADOコネクションの意味(オープンするコードは略)
Rs.Open SQL, Cn, adOpenStatic, adLockReadOnly, adCmdText
If Rs.EOF Then
'どうのこうののエラー処理
Exit Sub
End If
でここまでは普通のレコードセット作りの部分ですね。
で、次にこれをやるわけです。
RsArray = Rs.GetRows()
'いったんRsArrayに格納したのですみやかにRsをクローズしておく
Rs.Close: Set Rs = Nothing
で、それで、いったいどー使うのか?をお聞きになりたいのですよね?
RsArrayの説明:
1)RsArrayは発行されたSelect文に基づくRsを下記Rs.GetRows()でそっくり
配列にしたものです。
2)RsArrayの1次元目はSelect文で選択したフィールドデータが入るが
1番目のフィールドを0から数えます。
3)RsArrayの2次元目はSelect文で選択されたレコード数、つまりロー数を
意味します。
ということなのです。
だから、あ、もうレコードを意のままに操作できるのがみてとれますね。
わかりましたか?
えーーー、
でもどーやって動的にボトムのデータとかを(行数が変動するのにどうやって)
読むのか?質問が来そうですね。
それについてですが、そういうのはLBoundやUBoundを使えばOKなの。
例えば
UBound(RsArray, 2) + 1
とすればそれはレコード数を意味します。
これってまだASPで書いてる方なんかも恩恵ありです。
ASPとASPのルーチン間の連絡なんかに
むりむりPOSTでがんばんなくてもスマートだし、いろいろな局面で応用きくと
思いますよ。
今回の案件には無関係だったにしてもまずはお試しあれ。
ツイート | ![]() |