スポンサーサイト 


上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--/--/--

Category: スポンサー広告

TB: --  /  CM: --

top △

検索用途コンボの4階層連携 


複数のコンボボックスを連携させる。
つまり、基本となるコンボで選ばれた内容によって、次、次のコンボの表示を変更する。

過去記事「帳票 + 3つのコンボ変則連携 + α」で入力とか・・・
また、単なる3つの連携では、http://oshiete.goo.ne.jp/qa/7990927.html で回答してました。

今回のものは、4つのコンボが連携しつつ絞込み表示するものになります。
コンボボックスを4つを連動させてデータを絞り込み表示さ… に回答したそのものなんですけど・・・

まず、テーブル構成のイメージを初めに・・・

kEnt198.jpg

単純/簡単に考えると上記イメージになるのですが、実際のところわかりません。
今回のサンプルは、回答時に作っていたものが主になります。(ほとんど変更なし)
フォームとしては、以下の様な感じで・・・

kEnt198_1.jpg  kEnt198_2.jpg
 
回答した内容は以下

仕様・環境がわからないので、勝手に決めます。

コンボボックス名を「cbx1」「cbx2」「cbx3」「cbx4」
コンボボックスの操作は、必ず「cbx1」→「cbx2」→・・・

以下「an」はオートナンバ、「anX」(Xは数字)は長整数

「cbx1」用のテーブル「T50A」
・フィールド:an(主キー), F1
値集合ソース: SELECT an, F1 FROM T50A;
連結列: 1
列数: 2
列幅: 0cm;2cm (F1だけ表示する様に)

「cbx2」用のテーブル「T50B」
・フィールド:an(主キー), an1, F1
値集合ソース: SELECT an, an1, F1 FROM T50B WHERE an1=[cbx1];
連結列: 1
列数: 3
列幅: 0cm;0cm;2cm (F1だけ表示する様に)

「cbx3」用のテーブル「T50C」
・フィールド:an(主キー), an2, F1
値集合ソース: SELECT an, an2, F1 FROM T50C WHERE an2=[cbx2];
連結列: 1
列数: 3
列幅: 0cm;0cm;2cm (F1だけ表示する様に)

「cbx4」用のテーブル「T50D」
・フィールド:an(主キー), an3, F1
値集合ソース: SELECT an, an3, F1 FROM T50D WHERE an3=[cbx3];
連結列: 1
列数: 3
列幅: 0cm;0cm;2cm (F1だけ表示する様に)

フォームの参照するテーブル「T50」
フィールド:an(主キー), an1, an2, an3, an4, F1 FROM T50;

コンボボックスを選択することで、フォームにフィルタをかける。
(各コンボボックスで選ばれる都度)

フォームに記述したのは以下
Option Compare Database
Option Explicit

Dim vCtl As Variant

Private Sub Form_Load()
  Dim i As Long

  vCtl = Array("cbx1", "cbx2", "cbx3", "cbx4")
  For i = 0 To UBound(vCtl)
    With Me(vCtl(i))
      .ValidationRule = "Is Not Null"
      .OnEnter = "=EnterCheck()"
      .AfterUpdate = "=UpdateCheck()"
    End With
  Next
End Sub

Private Function EnterCheck()
  Dim i As Long, j As Long

  For i = 0 To UBound(vCtl)
    If (Me.ActiveControl Is Me(vCtl(i))) Then
      For j = 0 To i - 1
        If (IsNull(Me(vCtl(j)))) Then
          Me(vCtl(j)).SetFocus
          Exit Function
        End If
      Next
      Exit For
    End If
  Next
  With Me.ActiveControl
    .Requery
    .Dropdown
  End With
End Function

Private Function UpdateCheck()
  Dim i As Long, j As Long

  For i = 0 To UBound(vCtl)
    If (Me.ActiveControl Is Me(vCtl(i))) Then
      For j = i + 1 To UBound(vCtl)
        Me(vCtl(j)) = Null
      Next
      Call SetFilter
      If (i <> UBound(vCtl)) Then Me(vCtl(i + 1)).SetFocus
      Exit For
    End If
  Next
End Function

Private Sub SetFilter()
  Dim sFilter As String
  Dim i As Long

  sFilter = ""
  For i = 0 To UBound(vCtl)
    If (IsNull(Me(vCtl(i)))) Then Exit For
    sFilter = sFilter & " AND an" & i + 1 & " = " & Me(vCtl(i))
  Next
  Me.Filter = Mid(sFilter, 6)
  Me.FilterOn = Len(Me.Filter) > 0
End Sub

回答時の文字数制限もあり、動きを説明できていないので補足しておくと
( goo での回答と、ほとんど変わりないのですが: Filter 処理が増えた程度)

4つのコンボボックスの「フォーカス取得時」「更新後処理」は共通で処理させます。

・「フォーカス取得時」
Private Function EnterCheck()
  Dim i As Long, j As Long

  For i = 0 To UBound(vCtl)
    If (Me.ActiveControl Is Me(vCtl(i))) Then
      For j = 0 To i - 1
        If (IsNull(Me(vCtl(j)))) Then
          Me(vCtl(j)).SetFocus
          Exit Function
        End If
      Next
      Exit For
    End If
  Next
  With Me.ActiveControl
    .Requery
    .Dropdown
  End With
End Function

 私は誰?・・・ ActiveControl であるコンボボックスを特定します。
 特定出来たら、自分より前で選ばれているはずのコンボ状態を確認します。
 選ばれていなかったら、そこにフォーカスを移動して・・・終わり。
 選ばれていたら、自分を再クエリして、リスト一覧を表示

・「更新後処理」
Private Function UpdateCheck()
  Dim i As Long, j As Long

  For i = 0 To UBound(vCtl)
    If (Me.ActiveControl Is Me(vCtl(i))) Then
      For j = i + 1 To UBound(vCtl)
        Me(vCtl(j)) = Null
      Next
      Call SetFilter
      If (i <> UBound(vCtl)) Then Me(vCtl(i + 1)).SetFocus
      Exit For
    End If
  Next
End Function

 私は誰?・・・ ActiveControl であるコンボボックスを特定します。
 特定出来たら、自分より後のコンボ値を Null にして選ばれていない状態に。
 そして、Filter 設定して、自分より後ろにコンボがあるのなら、そこにフォーカスを・・・

この動きを確認できるのが、フォーム「F_T50」になります。
チョコチョコ操作していると、気に入らない点が1つ。
コンボボックスで絞り込み検索を始めてしまうと、Filter 解除できなくなってしまう・・・・
これは、コンボボックスの入力規則に
      .ValidationRule = "Is Not Null"
と、未入力状態をエラーとするように設定していたから・・・・

フォーム「F_T50」を「F_T51」としてコピー後、上記入力規則部分をコメント化
この変更だけで、Filter 解除できるようになるのか・・・・ じゃないんですよね。
もう1箇所・・・
「更新後処理」で、自分の後ろにコンボがあったらフォーカス移動していた部分
      If (i <> UBound(vCtl)) Then Me(vCtl(i + 1)).SetFocus

選択していたものを削除した後で動くと、後ろにフォーカスを移動するのは良いけど
後ろのコンボの「フォーカス取得時」で、前のコンボが未選択なのでフォーカスを元に戻そうとします。
なので、後ろのコンボにフォーカスを移動できないエラーとなります。
そこで、上記部分を以下に変更します。
      If (i <> UBound(vCtl) And _
        (Not IsNull(Me(vCtl(i))))) Then Me(vCtl(i + 1)).SetFocus
後ろがいて、自分が選ばれていたら・・・・後ろにフォーカス移動

サンプルファイルでは、このフォーム「F_T50」「F_T51」をいじってみる事が出来ます。

今回は、検索用途での連携について記述してみましたが、実際には入力時にも連携が必須と思います。
サンプルでは入力時の連携はしていないので、ゴチャゴチャなデータが作れます。
帳票フォームで連携しつつ入力・・・・ 動作の基本は「重ねる」になると思います。
見せる用途のコンボ/入力用途のコンボを重ねて・・・・云々
この辺グチャグチャやっていたのが「予定表」とか・・・
(この記事・・・コンボ以外の処理がメインで多いし、コンボの表示状態変更方法は今回のと違うけど)

また、今回イメージしたテーブル構成・・・ かなり稀だと思います。

kEnt198.jpg

例えば、親を参照する 「anX」(Xは数字)・・・・ こんな綺麗に連番になっているはずはない???
「★★ID」とか「▲▲CD」とか・・・ 色々なフィールド名になっていたりするんじゃないでしょうか・・・
サンプルファイルにはありませんが、いろいろなフィールド名に対応する記述例として
Dim vCtl As Variant

Private Sub Form_Load()
  Dim i As Long

  vCtl = Array( _
        Array("cbx1", "an1 = ", ""), _
        Array("cbx2", "an2 = ", ""), _
        Array("cbx3", "an3 = ", ""), _
        Array("cbx4", "an4 = ", "") _
      )

  For i = 0 To UBound(vCtl)
    With Me(vCtl(i)(0))
      .OnEnter = "=EnterCheck()"
      .AfterUpdate = "=UpdateCheck()"
    End With
  Next
End Sub

Private Function EnterCheck()
  Dim i As Long, j As Long

  For i = 0 To UBound(vCtl)
    If (Me.ActiveControl Is Me(vCtl(i)(0))) Then
      For j = 0 To i - 1
        If (IsNull(Me(vCtl(j)(0)))) Then
          Me(vCtl(j)(0)).SetFocus
          Exit Function
        End If
      Next
      Exit For
    End If
  Next
  With Me.ActiveControl
    .Requery
    .Dropdown
  End With
End Function

Private Function UpdateCheck()
  Dim i As Long, j As Long

  For i = 0 To UBound(vCtl)
    If (Me.ActiveControl Is Me(vCtl(i)(0))) Then
      For j = i + 1 To UBound(vCtl)
        Me(vCtl(j)(0)) = Null
      Next
      Call SetFilter
      If (i <> UBound(vCtl) And _
        (Not IsNull(Me(vCtl(i)(0))))) Then Me(vCtl(i + 1)(0)).SetFocus
      Exit For
    End If
  Next
End Function

Private Sub SetFilter()
  Dim sFilter As String
  Dim i As Long

  sFilter = ""
  For i = 0 To UBound(vCtl)
    If (IsNull(Me(vCtl(i)(0)))) Then Exit For
    sFilter = sFilter & " AND " & vCtl(i)(1) & Me(vCtl(i)(0)) & vCtl(i)(2)
  Next
  Me.Filter = Mid(sFilter, 6)
  Me.FilterOn = Len(Me.Filter) > 0
End Sub

 
連携するコンボボックス名を教えつつ、どのフィールドに対してどうする・・・・
想定処理によっては、情報を Tag に設定しておく等ありますが、今回は配列で定義・・・
  vCtl = Array( _
        Array("cbx1", "an1 = ", ""), _
        Array("cbx2", "an2 = ", ""), _
        Array("cbx3", "an3 = ", ""), _
        Array("cbx4", "an4 = ", "") _
      )
部分になるのですが、
「cbx1」では、Filter 条件を作る時の左には「an1 = 」を使って、右には「」
    sFilter = sFilter & " AND " & vCtl(i)(1) & Me(vCtl(i)(0)) & vCtl(i)(2)

この定義をしておけば、例えば
文字列だったら Array("cbx1", "★★ = '", "'")
部分一致・・・ これはあるのかな???
部分一致でも  Array("cbx1", "★★ Like '", "*'") とか Array("cbx1", "★★ Like '*", "*'") とかとか
この定義部分を変更するだけで、いろいろと対応できるかと・・・・
ただ、コンボの値集合ソースも一緒に書き換えておく必要がありますけど・・・・
定義内容をもう少し変更して、動的に値集合ソースを書き換える様にするとか・・・
まぁ、それも大した変更量じゃないですね・・・・

う~~ん。 でもでも、
綺麗な階層になっているのであれば、Filter 条件は選択されている最後のものだけで良さそう・・・

まっ、この方法であれば、4つ連携だけでなく、5・6・・・連携も容易と思います。
ただ今回は、最上位のコンボから設定を順序良く・・・・としていたので楽でしたが、
途中からのコンボ選択を可能にすると、上位が設定されていなかった場合等など処理が増えますね・・・

想定していたテーブルは、単純/簡単に考えただけのものなので、例えば

kEnt198_N.jpg

の様なものだったら、また考え直さないと・・・・


サンプルは以下
 バージョン 20002003 (2002)2007
 ファイル kEnt198_2000.zipkEnt198_2003.zipkEnt198_2007.zip
 サイズ 27,30028,34231,753
※ ファイルは zip 形式
※ 2007 以外は、2007 保存時に変換 & 各バージョンで動作確認 & 最適化

関連記事

2014/07/06

Category: サンプルかな

TB: --  /  CM: 6

top △

この記事に対するコメント

コンボボックスを用いてデータ抽出および表示について 

お忙しいところご助力、本当に有難うございます。ご回答のところでいくつか質問があります。

・フィールド:an(主キー), F1

というところのF1ですが、一項目だけでなく以下のように複数存在するのですが・・・。

コード(機材番号),枝番(機材番号),分類(機材名称),仕様(機材名称),重量(kg),単位(損料),損料区分(損料),滅失価格(円)(損料),保有数H226運用計画表,図面情報,摘要

これらを記述するということでしょうか。

それから、下記の記述についてですが。これは、検索フォームのコンボボックスのプロパティに記述するということでよろしいでしょうか。
                ↓
値集合ソース: SELECT an, F1 FROM T50A;
連結列: 1
列数: 2
列幅: 0cm;2cm (F1だけ表示する様に)

必死に頑張りますのでよろしくお願いいたします。

ii-hide #- | URL | 2014/07/07 13:11 * edit *

Re: コンボボックスを用いてデータ抽出および表示について 

http://hatena-access.progoo.com/bbs/hatena-access_tree_pr_2961.html

にサンプルファイルを添付して回答しておきました。

kiku #1a/xiM.Q | URL | 2014/07/07 22:10 * edit *

ご助力有難うございます。もう少しで完成すると思うのですが、行き詰まっています。

コンボボックス選択すると下記メッセージが表示されてしまいます。

” イベントプロパティに指定した式 更新後処理でエラーが発生しました:抽出条件でデータ型一致しませえ。”「

考えられる原因をし教えてください

ii-hide #- | URL | 2014/07/11 10:56 * edit *

Re: タイトルなし

> 下記メッセージが表示されてしまいます

どの様な記述・設定にして、どの様な操作をした時に発生したものでしょうか?
ご自身で記述した文章を、環境が全くわからない事を自ら想定・設定して読み直した時、
理解できるものとなっているか確認されてみてはどうでしょうか。

急遽、新記事「検索用途コンボの4階層連携 その2」にまとめましたが、
そのサンプルでわかりますか?

kiku #oNfrJm22 | URL | 2014/07/12 07:45 * edit *

解決いたしました。

長い期間、お付き合い頂きありがとうございました。私が購入いたしました2冊の参考書よりも、本当にわかりやすく勉強になりました。
お礼の返事が遅れたこと、申し訳ありません。体調を崩し1日、休んでしまいました。
ご協力いただいたことを、糧にこれからもっと勉強したいと思います。

ii-hide #- | URL | 2014/07/17 09:19 * edit *

Re: 解決いたしました。

解決されたようで何よりですが、後始末はしっかりやってください

Re: コンボボックスを用いてデータ抽出および表示について 
http://hatena-access.progoo.com/bbs/hatena-access_tree_pr_2961.html

できれば、どうやって解決されたか・・・を添えてもらえればと

kiku #Nq.ElOvo | URL | 2014/07/17 13:02 * edit *

top △

コメントの投稿

Secret

top △


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。