電子書籍の厳選無料作品が豊富!

お世話になってます。
アクセス2000のことで質問です。
簡単なことかも知れませんが、教えてください。

フォームにクエリで検索フォームを作成しました。
テキストボックスに記入して、コマンドボタンを押したら検索し、
帳票で表示されるようになってます。
元になったテーブルにはあいうえお順で名前が入っています。

以下困っている内容です。

1回目検索する
[佐々木]を検索。[佐々木]に含まれる情報が表示されます。

2回目検索する
[足立]を検索。表示されない。
サ行以前のものは検索できないようになっている。

3回目検索する
[田中]を検索。[田中]に含まれる情報が表示される。
ただし、4回目以後はタ行より先(チツテト~)しか表示されない。

というふうに、検索した言葉より前の言葉が表示されなくなってしまいます。

いったいどうしてこうなってしまうのでしょうか?
これはクエリの特徴なのでしょうか?
それとも解決する方法があるのでしょうか?

わかりづらい説明で大変申し訳ないのですが、ご回答いただけないでしょうか。
どうかよろしくお願いします。

A 回答 (3件)

フォームの構成/操作等イメージできていないので、的外れかもしれません。


(親フォームのレコードソースがどうなっているかわからないので)

サブフォームの表示部分だけで良いですか。
(サブフォームから入力する場合は、入力チェック等々組み込む必要があります)

※ 下記は今回の動き(ご質問内容)についてのものではありません。
  前のご質問をベースに記述したものになります。
  今回の動きの原因はわかりません。(後述の余談部分が影響?)


仮定条件)

コンボボックス「cbx1」で、テーブル「T01」を参照し顧客を選択、
日付の検索用テキストボックスが「txt1」になっていたとします。
(親側の表示状態がわからないので、検索に必要と思われるものに限定)
帳票フォームとして表示しているサブフォームのレコードソースは、
テーブル「T03」そのままのものとします。(抽出条件なし)
サブフォームコントロール名を「FSUB」と仮定します。
また、リンク親/子フィールドは設定しません。

指定された検索条件で、サブフォームに Filter を設定します。
実行ボタン「btn1」で設定し、クリアボタン「btn2」で解除します。

親フォームへ記述:一例)

Private Sub SetFilter(sS As String)
  With Me.FSUB.Form
    If (Len(sS) = 0) Then
      .FilterOn = False
      .Filter = ""
    Else
      .Filter = sS
      .FilterOn = True
    End If
  End With
End Sub

Private Sub btn1_Click()
  Dim sS As String
  Const sAndOr As String = " AND "

  sS = ""
  If (Not IsNull(Me.cbx1)) Then
    sS = sS & sAndOr & "顧客ID = " & Me.cbx1
  End If
  If (Not IsNull(Me.txt1)) Then
    sS = sS & sAndOr & "日付 = #" & Me.txt1 & "#"
  End If

  If (Len(sS) > 0) Then
    sS = "売上ID IN (SELECT 売上ID FROM T02 WHERE " _
        & Mid(sS, Len(sAndOr) + 1) & ")"
  End If
  Call SetFilter(sS)
End Sub

Private Sub btn2_Click()
  Me.cbx1 = Null
  Me.txt1 = Null
  Call SetFilter("")
End Sub


※ 条件はテーブル「T02」に対して作成します。
  その条件に合う「売上ID」で Filter を設定します。
  ( IN句 を使うのがミソ?)

※ 条件により1つだけを指定するのであれば、
    sS = "売上ID = " & Me.売上ID
  のように "=" にしてみたり・・・いろいろと変形できると思います。


※ 会社名の部分一致用にテキストボックス「txt2」を新設したとすると、
 (コンボボックスの設定を優先してみると)
 SetFilter 部分はそのまま流用し、「btn1」「btn2」部分を変更します。

Private Sub btn1_Click()
  Dim sS As String
  Const sAndOr As String = " AND "

  sS = ""
  If (Not IsNull(Me.cbx1)) Then
    Me.txt2 = Null
    sS = sS & sAndOr & "T02.顧客ID = " & Me.cbx1
  ElseIf (Not IsNull(Me.txt2)) Then
    sS = sS & sAndOr & "T01.会社名 Like '*" & Me.txt2 & "*'"
  End If
  If (Not IsNull(Me.txt1)) Then
    sS = sS & sAndOr & "T02.日付 = #" & Me.txt1 & "#"
  End If

  If (Len(sS) > 0) Then
    sS = "売上ID IN (SELECT 売上ID FROM T02 INNER JOIN T01 ON T02.顧客ID = T01.顧客ID WHERE " _
        & Mid(sS, Len(sAndOr) + 1) & ")"
  End If
  Call SetFilter(sS)
End Sub

Private Sub btn2_Click()
  Me.cbx1 = Null
  Me.txt1 = Null
  Me.txt2 = Null
  Call SetFilter("")
End Sub


※ Filter を使いたくない場合には、
  事前にサブフォームのレコードソースに指定するクエリに記述しておけば
  それなりに動くと思います。
  その場合は、必要に応じてサブフォームを Requery します。


余談)

LinkChildFields および LinkMasterFields プロパティについて、裏付けを取られたらと思います。

途中で設定を変えてもそこそこ動くようですが、ヘルプの中に気になる記述があります。

Access 2007 開発者用リファレンス > Access VBA リファレンス > SubForm オブジェクト > プロパティ
Access 開発者用リファレンス
SubForm."LinkChildFields/リンク子フィールド" プロパティ

の真ん中あたりに
-------------------
これらのプロパティは、デザイン ビュー (デザイン ビュー : データベース オブジェクト (テーブル、クエリ、フォーム、レポート、マクロ、およびデータ アクセス ページ) のデザインを表示するウィンドウ。デザイン ビューでは、新しいデータベース オブジェクトの作成と既存のデータベース オブジェクトの変更ができます。)、またはフォームやレポートの Open イベントの中で設定します。
-------------------

これに似た記述は、Access2000 のヘルプにもあります。
確認してみてください。

Open イベント以外での設定はできるし、エラーにもならない。
でも、このプロパティをいじったり、Filter も組み合わせたり・・・してみたり、
このような操作を繰り返していると動きがおかしくなってきたことがありました。

動的に変更するのではなく、固定して使われた方が良いような気がします。
    • good
    • 0
この回答へのお礼

お返事が大変遅くなってしまってすみません。
詳しい説明ありがとうございます。
30246kikuさんの説明に、従いやってみたのですがやはりできません…。
私のやり方が悪かったのだと思うのですが、検索ボタン(実行ボタン?)が反応しません。

やはり、最後のところでおっしゃってる通り、
結局アクセス2000の仕様なのだと思い、あっさり諦め、固定して使おうかと思います…。
わかりにくい状況の中、丁寧に説明してくださりありがとうございました。

お礼日時:2011/10/13 10:54

#2です



> やはり、最後のところでおっしゃってる通り、

ということは、今回のご質問でも
クエリだけではなくリンク親/子フィールドも動的に変更していたという事でしょうか
(前回のご質問を参考にされた記述があったので、もしかしてと・・・・)

> 結局アクセス2000の仕様なのだと思い、・・・・

Access2007 のヘルプにも記述があるので、2000 限定ではないように思います。
この記述を仕様とみるのか・・・・でも、仕様なんですかね
ただ、そこそこ動くんですよね・・・
でも、変な動きをする時があるので、固定しておいた方が良さそう・・・と思います。


> 私のやり方が悪かったのだと思うのですが、検索ボタン(実行ボタン?)が反応しません。

という事ですが、#2で記述していなかった前提があります。
(VBA読むとわかるかな・・・で忘れてました)

テーブル「T01」「T02」にある「顧客ID」は数値型、
テーブル「T02」にある「日付」は日付/時刻型、
テーブル「T02」「T03」にある「売上ID」も数値型

(でも、これが違えばエラーは出たような)


#2は、
・リンク親/子フィールドは何も設定しない(で、固定して使う)
・それにより、サブフォームからの入力は処理が増える
・サブフォーム(T03の帳票表示フォーム)の Filter 指定で IN 句を使う
 (時には "=" でも)

会社名の部分一致であれば、(例では「商事」)

SELECT 売上ID FROM T02 INNER JOIN T01 ON T02.顧客ID=T01.顧客ID WHERE T01.会社名 Like '*商事*'

とすると、会社名に "商事" が含まれる「T02」での 売上ID が求まるので
それを IN 句で指定した以下

"売上ID IN (・・・・前述の内容・・・・・・)"

の様に Filter 設定します。(#2の2つ目のパターン)
(IN の前にある「売上ID」は、サブフォームの「T03」でのものになります)
親フォームのレコードソースがテーブル「T02」をベースにしたものであったのなら、
サブフォームへの指定だけではなく、親の Filter へも共通に利用できると思います。

WEBを探すと、同じ様なテーブル/フォーム構成でのサンプルがあったように思います。


以下も参考程度で)

#2での動きを確認してみます(最低限の確認用です)

・新規 mdb を作成し、テーブル「T01」「T02」「T03」をインポートしておきます
・テーブル「T01」「T02」にある「顧客ID」は数値型、
 テーブル「T02」にある「日付」は日付/時刻型、
 テーブル「T02」「T03」にある「売上ID」も数値型を確認します
・テーブル「T03」を元にフォームウィザードで、表形式としてフォームを作成します
 フォーム名を「FSUB」とし、閉じておきます

・新規フォームをデザインで作成していきます
・コンボボックス「cbx1」を配置します
 値集合ソース:テーブル「T01」
 列数:2
 連結列:1
・テキストボックス「txt1」を配置し、書式を「日付(S)」
・テキストボックス「txt2」を配置します
・コマンドボタン、実行用「btn1」クリア用「btn2」を配置します

・作ってあったフォーム「FSUB」を上記配置した下側にドラッグ&ドロップします
・コマンドボタン「btn1」のプロパティで「クリック時」を「イベントプロシージャ」にし、
 右横の「・・・」をクリックします

Private Sub btn1_Click()

End Sub

の表示になるので、以下と置き換えます。

Private Sub SetFilter(sS As String)
  With Me.FSUB.Form
    If (Len(sS) = 0) Then
      .FilterOn = False
      .Filter = ""
    Else
      .Filter = sS
      .FilterOn = True
    End If
  End With
End Sub

Private Sub btn1_Click()
  Dim sS As String
  Const sAndOr As String = " AND "

  sS = ""
  If (Not IsNull(Me.cbx1)) Then
    Me.txt2 = Null
    sS = sS & sAndOr & "T02.顧客ID = " & Me.cbx1 ' ★
  ElseIf (Not IsNull(Me.txt2)) Then
    sS = sS & sAndOr & "T01.会社名 Like '*" & Me.txt2 & "*'"
  End If
  If (Not IsNull(Me.txt1)) Then
    sS = sS & sAndOr & "T02.日付 = #" & Me.txt1 & "#"
  End If

  If (Len(sS) > 0) Then
    sS = "売上ID IN (SELECT 売上ID FROM T02 INNER JOIN T01 ON T02.顧客ID = T01.顧客ID WHERE " _
        & Mid(sS, Len(sAndOr) + 1) & ")"
  End If
  Call SetFilter(sS)
End Sub

Private Sub btn2_Click()
  Me.cbx1 = Null
  Me.txt1 = Null
  Me.txt2 = Null
  Call SetFilter("")
End Sub


※ 「顧客ID」がテキスト型であったのなら、★部分は
    sS = sS & sAndOr & "T02.顧客ID = '" & Me.cbx1 & "'"
  のように ' ' で値を囲みます


一通り完成したので、フォームビューで動きを確かめてみます。

コンボボックスで選んで、実行「btn1」を押してみる、とか
テキストボックス「txt2」に 「商事」と入れて、実行を押してみる・・・とか

この確認では、親フォームのレコードソースは設定していませんでしたが、
テーブル「T02」をベースにしたものが指定され、
「売上ID」名のテキストボックスがあったとした場合(連結状態とした場合)、
サブフォームから入力するには、サブフォーム内の「挿入前処理」で

Private Sub Form_BeforeInsert(Cancel As Integer)
  If (IsNull(Me.Parent.売上ID)) Then
    Cancel = True
  Else
    Me.売上ID = Me.Parent.売上ID
  End If
End Sub

のように、
・親の「売上ID」が設定されていなかったら編集状態にしない
・テーブル「T03」登録に必要な「売上ID」を親から持ってくる
処理が最低限必要になると思います。
また、同一売上IDを登録できないようにするとか・・・・
(重複を許可する?とか・・・・)

※ リンク親/子フィールドに「売上ID」が設定されていた場合、
上記での親から「売上ID」を持ってくる処理は Access さんがやってくれてました。
リンク親/子フィールドを設定していないので、自分で処理する必要があります。
また、リンク親/子フィールドに「売上ID」が設定されていたら、
サブフォームへ複数の「売上ID」を表示することはできません。
(これに対して複数表示したい・・・が、前回ご質問の趣旨だったのかと思います)


なお、テーブル「T03」に日付がないもので確認していました。
(Filter を作成する時点でテーブル「T03」は使っていないので)

今回のご質問への回答になっていたでしょうか・・・・
前回のものについてばかりで・・・

失礼しました。

この回答への補足

お返事ありがとうございます。

このコメントを見て、最初から作り直そうと初期の状態を一応作動させたら正常に動きました…。
質問していたような現象にはならず、きちんと後方検索も行えました。

最初からと言っても、
http://oshiete.goo.ne.jp/qa/7043481.html
ここで作成したデータを元にコピーしたものです。

以前の検索が行えなかった段階から、いじったり何も変更した点はないのですが…。
なぜ正常?に動くようになったのか理解もできず、もやもやした状態です。
しかし、動くようになったものを動かなくすることもできないので、
こちらのコメントで教えていただいた方法は補完として使用させていただきます!
いつまた検索できなくなるかわからないので…笑

残念ながらこちらのコメントを私が理解するまで今しばらく時間がかかります。
ベストアンサーに選ばせていただきたいのですが、また質問がでるかもしれないので、
しばらくの間、この状態のままにさせておいてください。

大変申し訳ないのですが、よろしくお願いします。

補足日時:2011/10/14 15:53
    • good
    • 0

普通はそういう風にはならないと思います。


(クエリの表示で)SQL文を出していただけたら、何かわかるかも知れません。

誰かほかの人が作ったものなら、
レコードソースのデータが検索することによって書き換えられているかどうかご確認ください。
(わざとそういう仕組みにしてある可能性もなきにしもあらず)

あとは、ほかの端末で動きを試してみるとか、最適化・修復をやってみるとか、くらいしか思いつきません。

この回答への補足

そういう仕様ではないのですね。
先日こちらで質問して回答していただいたクエリを参考にし作成しました。

http://oshiete.goo.ne.jp/qa/7043481.html

これを見ただけでは私には何がその仕組みにしているのか
ということをわかりかねます。

すみませんが、ご回答いただけるようであれば、よろしくお願いします。

補足日時:2011/10/06 15:31
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!