Access の連続フォームのコンボ ボックスのカスタム行ソース

StackOverflow https://stackoverflow.com/questions/86278

  •  01-07-2019
  •  | 
  •  

質問

調べてみたところ、これは MS Access の制限のようです。そのため、このパズルに対して他の人がどのような創造的な解決策を見つけたのか気になります。

連続フォームがあり、フィールドをその行に固有のオプションのコンボ ボックスにしたい場合、Access は機能しません。コンボ ボックスの行ソースはフォームの先頭で 1 回だけクエリされるため、フォームの残りの部分には間違ったオプションが表示されます。

もちろん、私たち全員が試みる次のステップは、onCurrent イベントを使用してコンボ ボックスを再クエリすることです。これにより、実際にはオプションが指定された行に制限されます。ただし、この時点で、Access がおかしくなり、再クエリが発生します。 全て その結果、現在のレコードの行ソースに対して有効なオプションが選択されているかどうかに応じて、他の行のオプションが消えたり再表示されたりすることがよくあります。

私が見つけた唯一の解決策は、利用可能なすべてのオプションを常にリストすることです。創造的な答えはありますか?

編集 また、コンボ ボックスの理由は、クエリをルックアップ テーブルとして使用するためであり、人間が判読できるバージョンが表示される一方で、実際の値は非表示にして保存する必要があることに注意してください。コンボボックス行ソース内の複数の列。したがって、制限をリストに変更しても役に立ちません。現在の行ソース クエリに含まれていない ID には、人間が判読できる一致する部分がないからです。

この特定のケースでは、連続形式は非常に意味があるので、それが間違った解決策であるとは言わないでください。創造的な答えを求めています。

役に立ちましたか?

解決

私もアクセスは嫌いですが、配られたカードでプレイしなければなりません。この例のように、一般的に発生するような何らかの複雑な問題に遭遇するまでは、Access では連続フォームは素晴らしいものになります。

この状況に直面した場合に私がとるべき行動は次のとおりです (以前にも同様の回避策を実装しました)。

UNBOUND コンボボックスをフォーム上に配置します。次に、編集するフィールドに BOUND テキストボックスを配置します。

コンボボックスが textBox の後ろに隠れていることを確認します (非表示ではなく、単に隠れているだけです)。

OnCurrent イベントで、listBox に必要なデータを入力します。さあ、それも「リストに制限」してください。

textBox の OnEnter または OnClick イベントで、コンボボックスにフォーカスを与えます。これにより、コンボボックスが最前面に表示されます。フォーカスがコンボボックスから離れると、コンボボックス自体が再び非表示になります。

コンボボックスの AfterUpdate イベントで、テキストボックスの値をコンボボックスの値と同じに設定します。

状況によっては、他にも詳細を検討する必要があるかもしれませんが、それほど複雑になることなく、多かれ少なかれ目的を達成できるはずです。

他のヒント

連続形式を使用します。絶対に。実際、連続フォーム上に構築された優れた直感的なユーザー インターフェイスを備えたアプリケーション全体を構築できます。トーストは聞かないでください!

利用可能なすべてのオプションをリストするという解決策は正しいものです。実際、これ以外にクリーンな解決策はありません。しかし、Access がおかしくなるというのは間違いです。連続フォームでは、各行を詳細セクションのインスタンスとして見ることができます。コンボボックスは、詳細セクションのすべてのインスタンスに共通のプロパティです。このプロパティはすべてのインスタンスに対して更新できますが、特定の 1 つのインスタンスに対して設定することはできません。このため、Access ではすべてのレコードのコンボボックスに同じデータを表示しなければなりません。

このコンボボックスでレコード固有の値のみを受け入れる必要がある場合は、beforeUpdate イベントを使用して制御プロシージャを追加してください。新しい値を受け入れられない場合は、データ更新をキャンセルして、フィールド内の以前の値に戻すことができます。

リンクされたデータ (コントロールに保存されているデータ) が非表示になっている場合、limitToList プロパティを 'No' に設定することはできません。これは論理的です:リンクされたフィールド (表示されていない) が空のままの場合、マシンはどのようにして新しいデータ行の入力を受け入れることができるでしょうか?

コンボ ボックスの値を編集不可のテキスト フィールドにして、ポップアップ/モーダル ウィンドウを起動してその値を編集することもできます。ただし、それを行う場合、いずれかのウィンドウでレコード全体を編集する傾向があるかもしれません。

Access の連続フォームが非難されるべきだとは全く思いませんが、データの編集に関しては絶対に避けるべきだと思います。これらはリストに最適で、単なるリストボックスよりも大幅に多くの書式設定機能を提供します (もちろん、複数選択はできませんが、操作もはるかに簡単です)。

編集用のレコードへのナビゲーションに連続フォームを使用する場合は、編集用の詳細データを表示するサブフォームを使用し、サブフォームの PK 値をリンク フィールドに使用します。これは、連続フォームの背後にあるテーブルの PK にリンクされたヘッダーまたはフッターに詳細サブフォームを配置する連続フォームを使用して実行できます。

または、連続フォームを使用して親フォームに子データを表示している場合は、次のように、連続サブフォーム内の PK への参照を使用して詳細サブフォームをリンクできます。

[MySubForm].[Form]!MyID

これがリンク マスター プロパティになり、MyID がリンクの子プロパティになります。

私たちのアプリケーションでもこれによく遭遇します。私たちが発見した良い解決策は次のとおりです。コンボボックス内のすべての行を表示するだけです。次に、ユーザーが特定の行のコンポボックスに入るとすぐに、(その行のフィルターを使用して) 行ソースを調整します。コンボボックスがフォーカスを失った場合は、すべてを表示するように行ソースを再設定できます。

私にはギリガンよりも簡単な方法があります。大変な作業のように思えますが、実際はそうではありません。私のソリューションでは、連続フォームをサブフォーム データシートとして持つ必要があります。私のサブフォームには、「機器」と「製造元」というフィールドと呼ばれる 2 つのルックアップ コンボボックスがあります。どちらも単に長整数キーをデータ ソース内に保持するだけです。メーカーは、機器で選択したものによってフィルタリングする必要があります。Maker.RowSource をフィルターするのは、Manufacturing_GotFocus イベントの場合のみです。

プライベート サブ メーカー_GotFocus()

If Nz(Me.Equipment, 0) > 0 Then
    Me.Manufacturer.RowSource = GetMfrSQL()  '- gets filtered query based on Equipment
Else
    Me.Manufacturer.RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"
End If

エンドサブ

Maker_LostFocus で、Manufacturing.RowSource もすべての製造元にリセットします。これを行う必要があるのは、最初にサブフォームをクリックしたときに、実際にはフィールドを更新していないにもかかわらず、製造元を含むすべてのコントロールに対して GotFocus イベントが発生するためです。

プライベート サブ メーカー_LostFocus()

Me.Manufacturer.RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"

エンドサブ

メーカーの Enter イベントでは、機器が選択されているかどうかを確認する必要があります。選択されていない場合は、機器にフォーカスが設定されています。

プライベート サブ メーカー_Enter()

If Nz(Me.EquipmentID, 0) = 0 Then
    '-- Must select Equipment first, before selecting Manufacturer
    Me.Equipment.SetFocus
End If

エンドサブ

Form_Current イベントの製造元コンボボックスを再クエリする必要もあります (つまり、Me.Manufacturing.Requery)、このサブフォームの Cycle プロパティを "Current Record" に設定する必要があります。

とても簡単そうに見えますが、まだ作業は完了していません。また、ユーザーが [製造元] コンボボックスに移動しても選択を行わずに親フォームのどこかをクリックした場合に備えて、親フォームの SubForm_Exit イベントで、製造元.RowSource をすべての製造元にリセットする必要があります。コードサンプル (親フォーム内):

Private Sub sFrmEquip_Exit(整数としてキャンセル)

Me.sFrmEquip.Controls("Manufacturer").RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"

エンドサブ

この中にまだきれいではない部分が 1 つあります。[製造元] をクリックし、データシート グリッドに複数の行がある場合、現在の行の製造元を変更している間、他の行の [製造元] フィールドは空白になります (コンボボックスの下のデータはそのままです)。このフィールドの外に移動すると、他の製造元フィールドのテキストが再び表示されます。

これはうまくいくようです。CBOsfrmTouchpoint8 は、ドロップダウンの四角形のみに短縮されたコンボボックスです。CBOsfrmTouchpoint14 は、残りのスペースを構成するテキストボックスです。絶対とは絶対言うな:

  Private Sub CBOsfrmTouchpoint8_Enter()  

  If Me.CBOsfrmTouchpoint8.Tag = "Yes" Then  
  CBOsfrmTouchpoint14.SetFocus  
  Me.CBOsfrmTouchpoint8.Tag = "No"  
  Exit Sub  
  End If  

  Me.CBOsfrmTouchpoint8.Tag = "No"  
  Me.CBOsfrmTouchpoint8.RowSource = "XXX"  
  Me.CBOsfrmTouchpoint8.Requery  
  Me.CBOsfrmTouchpoint8.SetFocus  
  End Sub 

  Private Sub CBOsfrmTouchpoint8_GotFocus()  
  Me.CBOsfrmTouchpoint14.Width = 0  
  Me.CBOsfrmTouchpoint8.Width = 3420  
  Me.CBOsfrmTouchpoint8.Left = 8580  
  Me.CBOsfrmTouchpoint8.Dropdown  
  End Sub

  Private Sub CBOsfrmTouchpoint8_LostFocus()  
  Me.CBOsfrmTouchpoint8.RowSource = "XXX"  
  Me.CBOsfrmTouchpoint8.Requery  
  End Sub 

  Private Sub CBOsfrmTouchpoint8_Exit(Cancel As Integer)  
  Me.CBOsfrmTouchpoint14.Width = 3180  
  Me.CBOsfrmTouchpoint8.Width = 240  
  Me.CBOsfrmTouchpoint8.Left = 11760  
  Me.CBOsfrmTouchpoint8.Tag = "Yes"  
  End Sub

「リストに限定」オプションをオフにして、更新前に検証を行って、ユーザーが入力した可能性のある内容が、提示したリスト内の内容と一致することを確認したらどうなるでしょうか?

より良い...

コンボ ボックスのコントロール ソースを、コンボ ボックスの値が保存されるクエリの列に設定します。

私にとって、最も簡単な方法は、すべてのバインドされたフィールドと、はい/いいえフィールドである追加フィールドを含む一時テーブルを作成することだと思います。

次に、このテーブルを連続 for のデータ ソースとして使用します。onLoad を使用して、一時テーブルに必要なデータを入力できます。

その後、選択肢をループするのは簡単だと思います。一時テーブルからはい/いいえフィールドを読み取るための小さなループだけです。

これがお役に立てば幸いです

使用 OnEnter イベントを使用してコンボ ボックスに値を設定します。固定値は使用しないでください。 rowsource.

私も同様のことをしたばかりです。私の解決策は、クエリにバインドされた固定行ソースを使用することでした。クエリの WHERE 句はフォームのコントロールを参照します。つまり、 Client=Forms!frmMain!ClientTextBox. 。これだけで、コンボ ボックスに最初の行のデータが入力されます。そこで重要なのは、「」を設定することです。On Enter' コンボボックスで単純に再クエリを実行するイベント。 ComboBox1.Requery, これにより、そのコンボ ボックスのみが再クエリされ、そのレコード行に関連するデータのみがドラッグされます。

それがあなたにもうまくいくことを願っています!

免責事項:私はアクセスを心から嫌います。

連続フォームは使用しないでください。彼らは、あなたが達成したいことを実現するための頼れる存在です。連続フォームとは、異なるデータで同じフォームが何度も繰り返されることです。同じフォームを複数回開くことができないため、これはすでに Access の通常の操作モードの難題です。表示されている動作は、Access の「設計どおり」です。これらの ComboBox コントロールはそれぞれ、実際には同じコントロールです。他のものに影響を与えずに 1 つに影響を与えることはできません。

基本的に、ここで行ったことは、Access がプロジェクトに適さなくなった領域に遭遇したことになります (ただし、すでに大量の作業が必要なため、無視することはできません)。

ここで最も可能性の高い行動は、本当にうまく偽装することです。データに対してクエリを実行し、結果に基づいてプログラムでフォーム要素を作成します。Access のデータ処理機能のかなりの部分を自分で複製することになるため、これはかなりの作業量です。

編集への返信:
しかし、このままでは連続形式では目的を達成できません。連続形式には実際にできることに実際の制限があるため、私が独自の連続形式を偽造することを提案したのはこのためです。特定の実装に固執しすぎて、機能しなくなったときにそれを手放すことができないようにしないでください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top