Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


150 / 2272 ツリー ←次へ | 前へ→

【12834】サブフォームの抽出結果をメインフォームに表示させたい rinrin 15/5/26(火) 21:22 質問[未読]
【12835】Re:サブフォームの抽出結果をメインフォー... かるびの 15/5/28(木) 2:00 回答[未読]
【12836】Re:サブフォームの抽出結果をメインフォー... hatena 15/5/28(木) 15:08 回答[未読]
【12837】Re:サブフォームの抽出結果をメインフォー... かるびの 15/5/29(金) 0:07 発言[未読]
【12838】Re:サブフォームの抽出結果をメインフォー... rinrin 15/5/29(金) 23:18 お礼[未読]

【12834】サブフォームの抽出結果をメインフォーム...
質問  rinrin  - 15/5/26(火) 21:22 -

引用なし
パスワード
   Mainフォーム”R/3コード””小区分名称””中区分名称””大区分名称””内容””具体例””注意点”テキストボックスに、
サブフォーム SubGL勘定の抽出結果を表示させたいと思ってます。

ソースコードの書き方がわかりません。

ご指導よろしくお願いします

Option Compare Database
Option Explicit

Public Function SetFilter()
  Dim stCri As String
'配列変数を使用 配列番号はゼロから始まります。
  Dim MyCount(2) As Integer
  
'Private Sub ComboBoxInit()をCALLプロシージャで呼び出す。
  Call ComboBoxInit

'抽出条件を設定する
  With Me.ActiveControl
    stCri = .Name & " LIKE '" & .Value & "*'"
  End With
  
'上記のlike演算子の条件でフォームフィルターをかける
  Me.X0001GL勘定.Form.Filter = stCri
  Me.X0001GL勘定.Form.FilterOn = True
  
  
'レコード全件を代入する
  MyCount(0) = DCount("*", "X0001GL勘定")
  
'抽出件数を代入する
  MyCount(1) = DCount("*", "X0001GL勘定", Me.ActiveControl.Name & " LIKE '" & Me.ActiveControl.Value & "*'")

'抽出件数をラベルに表示させる
  If MyCount(1) = 0 Then
'レコードが無いときは"抽出データなし"と表示
    Me.L1.Caption = "抽出データなし"
  Else
'レコードがあるときは全レコード件数と抽出件数を表示させる
    Me.L1.Caption = "全レコード " & MyCount(0) & " 件中 " & MyCount(1) & " 件抽出しました"
  End If
  
  Call ラベル情報
End Function

Private Sub Cmd解除_Click()
  ComboBoxInit
  Me.X0001GL勘定.SetFocus
  Me.X0001GL勘定.Form.Filter = ""
  Me.X0001GL勘定.Form.FilterOn = False
End Sub

Private Sub txtGL勘定検索_AfterUpdate()
  Call CallPrivate4
End Sub

Private Sub CallPrivate4()
  Dim StrSQL As String
'サブフォームのレコードセットのSQL文を代入する
  Dim MyName As Variant
'アクティブコントロール名を歳入する変数
  Dim MyVariable As String
'フォーム上で取得した変数名
'DCount関数のレコード数を代入する変数
  
'アクティブなコントロール名を取得する
  MyName = Me.ActiveControl.Name
'初期化
  MyCount = 0
  
'SQL文の条件句の分岐条件をSELECT CASE文で対応して簡素化する
  Select Case MyName

    Case "txt単価契約品名検索"
      MyVariable = " WHERE 単価契約.品名 LIKE '*" & [Forms]![MAIN購買依頼]![txt単価契約品名検索] & "*' ;"
      
'txt品目検索に該当するレコード数をカウントする
    MyCount = DCount("品名", "単価契約", "品名 like '*" & [Forms]![MAIN購買依頼]![txt単価契約品名検索] & "*'")
    
    Case "Cmd解除"
      MyVariable = " ;"
      
'全レコード数をカウントする
    MyCount = DCount("品名", "単価契約")
  End Select
  
'サブフォームのレコードソースに代入するSQL文
  StrSQL = "SELECT * FROM 単価契約 " & MyVariable
  
'SQL文をサブフォームのレコードソースに代入する
  Me.Sub購買依頼.Form.RecordSource = StrSQL

'サブフォームを再表示させる処理
  Forms![MAIN購買依頼]![Sub購買依頼].Form.Requery
  Me.txt件数.Value = MyCount

End Sub

Private Sub ComboBoxInit()
'コンボボックスの初期化
  Dim Ctl As Control

   For Each Ctl In Me.Controls

      With Ctl
        
'以下のIf文の説明内容
'Or演算子よりAndの演算子が優先されるので
'Or演算子の計算を先にさせるため、括弧で括っておく。
'でないと、コンボboxで選択した項目が以下のif文でtrueとなり
'コンボboxをnull値を代入してしまうため。
        
'IF文の内容は以下の通り
'コンボboxもしくはテキストboxである時、←これが優先事項なので括弧で括る。
'尚且つアクティブなコントロール名と一緒でない
        
'演算子の優先順位により論理的に正しくても
'得られる結果が違ってくる場合がある
        
        '例
        ' 3 - 2 * 5 = 7
        '(3 - 2 )* 5 = 5
'数学的に説明すると掛算と足算、引算が混載する場合は掛算や割算が優先される
'割算、掛算が混載する場合は左側から計算される。 足算、引算はその後になります。
'これを四則演算の法則といい、VBAのOR,AND等にも当てはまりますので
'ANDとORの演算子が混在するときでORを先に計算するときは括弧で括る。
        
        If (.ControlType = acComboBox Or .ControlType = acTextBox) And _
          .Name <> Me.ActiveControl.Name Then
'コンボボックスをNULL(空)に設定(アクティブコントロール以外)
          .Value = Null
        End If
      End With
  Next Ctl
End Sub

Sub ラベル情報()
'  商品名lbl.Caption = 商品コードcmb.Column(1)
'  商品区分説明lbl.Caption = DLookup("[説明]", "商品区分T", "[区分コード]=" & 商品コードcmb.Column(2))
'  Me.lblR3番号.Caption = DLookup("[R/3コード]", "X0001GL勘定", "[R/3コード]=" & [MainGL勘定Pr]![SubGL勘定].Column(3))
  Me.txtR3番号.Value = DLookup("[R/3コード]", "X0001GL勘定", [Forms]![MainGL勘定Pr]![小区分名称])
End Sub


Private Sub Cmd最後_Click()
  Forms!MainGL勘定Pr.SetFocus
  Forms!MainGL勘定Pr!X0001GL勘定.SetFocus
  DoCmd.GoToRecord , , acLast
End Sub

Private Sub Cmd次_Click()
  Forms!MainGL勘定Pr.SetFocus
  Forms!MainGL勘定Pr!X0001GL勘定.SetFocus
  DoCmd.GoToRecord , , acNext
End Sub

Private Sub Cmd先頭_Click()
  Forms!MainGL勘定Pr.SetFocus
  Forms!MainGL勘定Pr!X0001GL勘定.SetFocus
  DoCmd.GoToRecord , , acFirst
End Sub

Private Sub Cmd前_Click()
  Forms!MainGL勘定Pr.SetFocus
  Forms!MainGL勘定Pr!X0001GL勘定.SetFocus
  DoCmd.GoToRecord , , acPrevious
End Sub

【12835】Re:サブフォームの抽出結果をメインフォ...
回答  かるびの  - 15/5/28(木) 2:00 -

引用なし
パスワード
    結構しっかりしたコードですね。
 メインフォームからサブフォームを参照することとか、
DCountやDLookupなどD系関数の第3引数の書き方などは、
しばしば間違えやすいのですが、しっかりできているところがあります。
 でも、いくつかおかしな点もありますね。


 第1に、あちこちでActiveControlプロパティが使われていますが、
「Me.ActiveControl」ではエラーになります。
 このコードは、ActiveControlプロパティをフォームオブジェクトに対して
適用しているわけですが、
ActiveControlプロパティは、Screenオブジェクトに対してしか使えません。
 したがって、この行でエラーです。


 また、ActiveControlとは、
その時点でアクティヴなウィンドウにおける、フォーカスがあるコントロール
という意味です。

 例えば、AフォームとBフォームが開かれており、
当初はAフォームのaテキストボックスにフォーカスがあったところ、
フォーカスをBフォームのbテキストボックスに移したとします。
 この場合のActiveControlはbテキストボックスです。 

 この状態で、Aフォームをアクティヴにすると、
aテキストボックスにフォーカスが移るわけですが、
だからといって、Bフォームがアクティヴな状況下において、
「AフォームのActiveControlはaテキストボックスだ」とは言えません。
 あくまでもActiveControlはbテキストボックスです。


 さらに、ActiveControlが何であるかということはかなり微妙です。
 例えば、aテキストボックスにフォーカスがある状態で、
抽出を実行するコマンドボタンをクリックしたとします。
 この場合、コマンドボタンをクリックすることにより
フォーカスは当該コマンドボタンに移ります。
 したがって、コマンドボタンのクリック時において、
ActiveControlは当該コマンドボタンとなります。
 コマンドボタンのクリックイベントにおいて、
ActiveControlはaコントロールであるという思い込みの下で
コードを書いていたりすると、コードは意図どおりに動いてくれません。


 加えて、デバッグに当たり、コードをステップ実行させると、
ActiveControlでエラーになります。
 これは、コードをステップ実行させているときは、
VBEのウィンドウがアクティヴウィンドウになっているためです。
 また、ステップ実行中にマウスカーソルをコード中のActiveControl
という文字の上に持って行っても、
ActiveControlの値は表示されず(ActiveControlプロパティの値はControl型であるため)、
どのコントロールがActiveControlなのかがすぐにはわかりません。
 なので、ActiveControlを使うと、デバッグがやりにくいです。


 その上、提示のコードにおいてはActiveControlプロパティを使うべき必然性が
ないように思います。
 微妙な取扱いが必要とされるActiveControlプロパティを使わなくても、
コードが書けると思います 


 第2に、SetFilter関数における
>  With Me.ActiveControl
>    stCri = .Name & " LIKE '" & .Value & "*'"
>  End With
です。
 ここではFilterプロパティに設定する条件式を作っているわけですが、
Filterプロパティに設定する条件式の基本形は、「フィールド名 = 値」です。
 上記のコードだと、「コントロール名 = 値」という形になってしまうので、
エラーになる可能性があります。
 
 もっとも、フォームをウィザードで作ると、フィールド名とコントロール名が同じ名前になりますから、そうなっていれば、エラーにはなりません。
 ただ、フィールド名とコントロール名が同じ名前だと、取り違えやすいので、
通常は、フィールド名とコントロール名は別の名前にします。


 第3に、
>    MyCount(1) = DCount("*", "X0001GL勘定", Me.ActiveControl.Name & " LIKE '" & Me.ActiveControl.Value & "*'")
です。
 これはだめですね。
 まず、DCount関数の第2引数には、テーブル名又はクエリ名を指定します。
 「X0001GL勘定」は、サブフォーム・コントロール名ですから、この行でエラーです。

 ほかにも、D系関数の第2引数にサブフォーム・コントロール名を指定したものがありましたが、
同様にエラーとなります。

 次に、第3引数ですが、第3引数の基本形は「フィールド名 = 値」です。
上記コードだと「コントロール名 = 値」という形になってしまうので、エラーになる可能性があります。


 第4に、ラベル情報サブプロシージャの
>  Me.txtR3番号.Value = DLookup("[R/3コード]", "X0001GL勘定", [Forms]![MainGL勘定Pr]![小区分名称])
です。
 まず、第2引数にサブフォーム・コントロール名を指定していることについては
既に指摘したとおりです。

 次に、第1引数です。
 フィールド名には、記号は使えません。例外は、アンダーバー(_)だけです。
 だから、フィールド名に「/」を使っていること自体でエラーになります。
 使ってはいけない文字をオブジェクト名に使った場合のエラーは、
エラーメッセージを見ても、エラーの原因を推測できず、原因探求に苦労します。

 さらに、第3引数ですが、条件式になっていませんね。


 第5に、これはコードの問題ではないのですが、
フォーム構成がよくわかりません。
 メインフォームが少なくとも2つ、
サブフォームコントロールが少なくとも2つ出てくるようですが、
それらがどういう機能を持つものなのかピンときません。
 また、提示されたコードがどのフォームに書かれているのかもわかりません。

【12836】Re:サブフォームの抽出結果をメインフォ...
回答  hatena  - 15/5/28(木) 15:08 -

引用なし
パスワード
   かるびの さん、こんにちは。hatenaです。
つっこみご容赦。

>  第1に、あちこちでActiveControlプロパティが使われていますが、
> 「Me.ActiveControl」ではエラーになります。

エラーにはなりません。
Formオブジェクトも、ActiveControlプロパティを持っています。

例えば、
フォーム1 の コントロール1 にフォーカスがあるとき、

Screen.ActiveControl.Name は、コントロール1
Forms!フォーム1.ActiveControl.Name も コントロール1
になります。

ここで、フォーム2 をアクティブにして、そこのコントロール2をアクティブにしたとします。

Screen.ActiveControl.Name は、コントロール2
Forms!フォーム2.ActiveControl.Name も コントロール2
になります。
さらに、
Forms!フォーム1.ActiveControl.Name は コントロール1 となり、エラーになりません。

つまり、フォームがアクティブではなくても、フォーム自体は自分のどのコントロールがアクティブなのか記憶しているということです。ですので、また、自分自身にフォーカスが戻ってきた時、前にアクティブだったコントロールがそのままアクティブになっているわけです。

デバッグに当たり、コードをステップ実行させるときも、
Screen.ActiveControl はエラーになりますが、
Me.ActiveControl はエラーにならずそのフォームのアクティブなコントロールを参照できます。


今回の、SetFilter 関数がどこのどのイベントで呼び出されるのか不明ですが、
更新後処理などで、自分自身を参照したいときなどに使えば問題無いです。
私自身も、コードを複数のコントロールで共通化したい場合によく使います。


さて、本題の rinrinさんの質問に関して、
かるびのさんも指摘していますが、
フォームの構成と目的がはっきりしません。

メインフォームの名前は?
メインフォームは連結なのか非連結なのか?

このコードはどこに記述してあるのですか。

あと、SetFilter は提示のコードでは使われてませんが、どこで使用しているのですか。

また、サブフォームの抽出結果をメインフォームに表示ということですが、
抽出結果が複数の場合は、どのレコードを表示するのですか。

そもそも、どのような目的でフォームを作成しているのですが、その概要も説明してください。

【12837】Re:サブフォームの抽出結果をメインフォ...
発言  かるびの  - 15/5/29(金) 0:07 -

引用なし
パスワード
    hatenaさん、御指摘ありがとうございます。

>Formオブジェクトも、ActiveControlプロパティを持っています。

 え、そうだったんですか。
 以前、ActiveControlプロパティをフォームオブジェクトに適用しようとしたら、
エラーが続出したので、ヘルプを熟読し、
ActiveControlプロパティの対象オブジェクトは意外にもScreenオブジェクトなんだ
と思ったことが印象に残っていたので、あのようにレスしてしまいました。

 今、ヘルプを見て、ActiveControlプロパティの対象オブジェクトに
フォームとレポートもあることを確認しました。

 知識の幅が1つ広がりました。御指摘ありがとうございました。

【12838】Re:サブフォームの抽出結果をメインフォ...
お礼  rinrin  - 15/5/29(金) 23:18 -

引用なし
パスワード
   すっごいスキルのある方お二人から丁寧なご指導心より感謝します。
ありがとうございます

あたし自身のスキルが解釈についていけず、このように遅くなってしまったこと 心よりお詫び申し上げます


Q フォームの構成と目的がはっきりしません。
A メインフォームの中にサブフォームを設定した、閲覧 及び 検索フォームを構築しようと思っています

Q メインフォームの名前は?
A MainGL勘定Pr です

Q メインフォームは連結なのか非連結なのか?
A 非連結で考えています

このコードはどこに記述してあるのですか。

Q あと、SetFilter は提示のコードでは使われてませんが、どこで使用しているのですか。
A 更新後処理に =SetFilter() と設定してます

以前 hatenaさんにこのやり方を教わりました。。。^^

また、サブフォームの抽出結果をメインフォームに表示ということですが、
Q  抽出結果が複数の場合は、どのレコードを表示するのですか。
A サブフォームに一覧を表示し、メインフォームに”先頭””前””次””最後”の移動ボタンを設置するつもりです。

ご指導よろしくお願いします。。。
☆かるびのさん 親切 丁寧なご指導ありがとうございます。。。
 少しでも早く 趣旨を理解できるように頑張る所存です。今後ともよろしくお願いいたします

 hatenaさん 適正なアドバイス 本当にありがとうございます

※今回で当該案件はCloseさせていただき、あたしの勝手なお願いごとではありますが、hatenaさんのブログに 
 あたしが考えているAccessプログラムを掲載させていただき、そちらでご指導願えませんでしょうか

 よろしくお願いいたします

150 / 2272 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
1078188
(SS)C-BOARD v3.8 is Free