Access VBA質問箱 IV

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

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


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

【12669】一つの条件で複数検索 kok 14/12/17(水) 14:37 質問[未読]
【12670】Re:一つの条件で複数検索 かるびの 14/12/17(水) 23:19 回答[未読]
【12671】Re:一つの条件で複数検索 kok 14/12/19(金) 11:49 質問[未読]
【12672】Re:一つの条件で複数検索 かるびの 14/12/20(土) 0:10 回答[未読]
【12674】Re:一つの条件で複数検索 kok 14/12/20(土) 10:20 発言[未読]
【12675】Re:一つの条件で複数検索 かるびの 14/12/21(日) 1:25 回答[未読]
【12677】Re:一つの条件で複数検索 kok 14/12/24(水) 9:52 発言[未読]
【12678】Re:一つの条件で複数検索 かるびの 14/12/25(木) 0:09 回答[未読]
【12679】Re:一つの条件で複数検索 kok 14/12/25(木) 15:54 発言[未読]
【12680】Re:一つの条件で複数検索 かるびの 14/12/26(金) 0:41 回答[未読]
【12684】Re:一つの条件で複数検索 kok 15/1/15(木) 10:00 お礼[未読]

【12669】一つの条件で複数検索
質問  kok  - 14/12/17(水) 14:37 -

引用なし
パスワード
   詳細の中にコード1、コード2、コード3とういうデータが入っているテキストボックスがあります。

ヘッダー部に検索用の検索コードというテキストボックスを作成し、そこにコードを入れ、コード1、コード2、コード3のいずれか完全一致するものをボタンを押すと抽出する仕組みを作りたいと考えています。

例として、

顧客名     コード1  コード2  コード3
A社      11     12       (ブランク)
B社      12     14     15
C社      13     14     15

というデータがあり、検索コードに12を入れボタンを押すと、

顧客名     コード1  コード2  コード3
A社      11     12       (ブランク)
B社      12     14      15

と、C社が抽出されないようなVBAがありましたら教えていただけないでしょうか。

よろしくお願いします。

【12670】Re:一つの条件で複数検索
回答  かるびの  - 14/12/17(水) 23:19 -

引用なし
パスワード
    フォームのレコードソースは何ですか。
 レコードソースにはどんなフィールドがありますか。
 それらフィールドのデータ型は何ですか。
 コード1、コード2、コード3はテキストボックスだと思いますが、
それぞれのコントロールソースは何ですか。

 フォームの状況だけを説明されても、そちらの状況がさっぱりわかりません。
テーブルの状況も説明してもらわないと。

【12671】Re:一つの条件で複数検索
質問  kok  - 14/12/19(金) 11:49 -

引用なし
パスワード
   ▼かるびの さん:

すみません。補足させていただきます。

> フォームのレコードソースは何ですか。

「Q顧客名1」です。


> レコードソースにはどんなフィールドがありますか。
> それらフィールドのデータ型は何ですか。
> コード1、コード2、コード3はテキストボックスだと思いますが、
>それぞれのコントロールソースは何ですか。

フォームヘッダーに、非連結のテキストボックスの「顧客番号入力」、「顧客名入力」、「コード入力」

ボタンの「検索ボタン」。
検索ボタンには下記のVBAを組んでいます。


Private Sub 検索ボタン_Click()
  If Forms!F顧客一覧!顧客番号入力 <> "" Then
  DoCmd.ApplyFilter "", "[Q顧客名1]![顧客番号] = [Forms]![F顧客一覧]![顧客番号入力]"
  ElseIf Forms!F顧客一覧!顧客名入力 <> "" Then
  DoCmd.ApplyFilter "", "[Q顧客名1]![顧客名] like '*" & [Forms]![F顧客一覧]![顧客名入力] & "*'"
  End If
End Sub


実際この検索ボタンの中にコード入力の検索も組み込みたいと考えています。


詳細には、フィールド名、コントロールソース共同名のテキストボックス、「顧客番号」、「コード1」、「コード2」、「コード3」があり、
「顧客番号」、「顧客名」がテキスト型
「コード1」、「コード2」、「コード3」が数値型です。


この説明で大丈夫でしょうか?
お手数掛けすみません。

【12672】Re:一つの条件で複数検索
回答  かるびの  - 14/12/20(土) 0:10 -

引用なし
パスワード
    いろいろな掲示板でいろいろな人の質問を見ていて思うんですが、
フォームとテーブルが全く別個のものであるというのを意識している人が
少ないんですよね。
 よく見かけるのが、フィールドとテキストボックスを混同しているものです。
「フォームに××フィールドを配置する」など言ってみたり、
「△△テキストボックスのデータ型は日付型だ」などという表現を
よく見かけますが、いずれも間違いです。
 フィールドはテーブル又はクエリの要素であり、
フォームにフィールドという概念が入り込む余地はありません。
 またテキストボックスにデータ型はありません。
 上記の例について正確な言い回しをすれば、
「フォームに、××フィールドをコントロールソースとするテキストボックス配置する」
「△△テキストボックスのコントロールソースたる▲▲フィールドのデータ型は日付型だ」
となります。
 確かに、ウィザードでフォームを作ると、
テキストボックス名はフィールド名と同じになるので、両者を混同することはやむを得ない
とは思いますが、テキストボックス イコール フィールドだと思っていると、
どこかで行き詰まると思います。
 なので、少々厳しめにレコードソースやらコントロールソースやらを聞いてみた次第です。

 少し脱線しますが、テーブル(クエリ)とフォーム、
あるいはフィールドとテキストボックスの関係ですが、
テーブル(クエリ)とフォームを結び付けるのが「レコードソース」プロパティです。
レコードソースにテーブルを指定してやることで、
当該テーブルのデータをフォームで表示できるようになります。
 フィールドとテキストボックスを結び付けるのが「コントロールソース」プロパティです。
レコードソースたるテーブル(クエリ)のフィールドをコントロールソースに指定してやることで、
テキストボックスに当該フィールドの値を表示できるようになります。


 さて、本題です。
>> レコードソースにはどんなフィールドがありますか。
 これの答えがないですね。
 質問の仕方を変えると、Q顧客名1にはどんなフィールドがありますかということです。

>> コード1、コード2、コード3はテキストボックスだと思いますが、
>>それぞれのコントロールソースは何ですか。
 これについても、答えがないですね。
 それぞれのテキストボックスについて、
プロパティシートの「データ」タブの「コントロールソース」には、何が設定されていますか
ということです。


 今回のレスは、ここで終わりにしてもいいんですが、折角コードを示してくれたので、
もう少し先まで進めたいと思います。

>  DoCmd.ApplyFilter "", "[Q顧客名1]![顧客番号] = [Forms]![F顧客一覧]![顧客番号入力]"
 ApplyFilterって使ったことがないのでわからないのですが、
ApplyFilterは、例えば、クエリをデータシートビューで開いているときに、
メニューからレコード、フィルタと選択して(ちなみに当方はアクセス2003です)
行う動作をマクロで行うものだと思います。
 この場合、データシートビューの表示上だけでレコードを絞り込んでいるに過ぎず、
クエリ自体では何らの絞り込みもされていません。
 だから、ApplyFilterを使っても、フォームでのレコードの絞り込みはできないと思います。

 フォームでレコードの絞り込みを行うには、通常、
フォームの Filter プロパティと FilterOn プロパティを使います。

 Filter プロパティでは、条件式を文字列として指定する必要があります。
条件式の基本形は、「フィールド名 = 値」です。
 フィールドが数値型の場合は、値は何も囲いません。例えば、「数量 = 123」です。
 フィールドがテキスト型の場合は、ダブルコーテーションで囲います。
例えば、「都道府県 = "青森県"」です。
VBAのコード中では、文字列であることを示すダブルコーテーションと区別するために
シングルコーテーションで値を囲います。
例えば、「strWhere = "市町村 = '長野市'"」です。
 フィールドが日付時刻型の場合は、シャープで囲います。
例えば、「受注日 = #2014/12/19#」です。
 条件式を2つ以上指定したい場合は、条件式を AND 又は OR でつなげた文字列にします。
例えば「数量 = 234 AND 都道府県 = "岩手県"」です。

【12674】Re:一つの条件で複数検索
発言  kok  - 14/12/20(土) 10:20 -

引用なし
パスワード
   ▼かるびの さん:


>>> レコードソースにはどんなフィールドがありますか。
> これの答えがないですね。
> 質問の仕方を変えると、Q顧客名1にはどんなフィールドがありますかということです。

フォームで使用する部分のみ書いてみましたが、足りなかったみたいですね。
ごちゃごちゃして見づらいかもしれませんが、Q顧客名1の中身を下記で纏めました。

フィールド名 ― テーブル名 ― フィールド名に関連するデータ型

顧客番号 ― T顧客名 ― テキスト型
顧客名 ― T顧客名 ― テキスト型
部署名 ― T顧客名 ― テキスト型
役職名 ― T顧客名 ― テキスト型
氏名 ― T顧客名 ― テキスト型
敬称 ― T顧客名 ― テキスト型
〒1 ― T顧客名 ― テキスト型
〒2 ― T顧客名 ― テキスト型
住所1 ― T顧客名 ― テキスト型
住所2 ― T顧客名 ― テキスト型
TEL ― T顧客名 ― テキスト型
FAX ― T顧客名 ― テキスト型
フリガナ ― T顧客名 ― テキスト型
コード1 ― T顧客名 ― 数値型
事業所等 ― T事業所コード1 ― テキスト型
コード2 ― T顧客名 ― 数値型
事業所等 ― T事業所コード2 ― テキスト型
コード3 ― T顧客名 ― 数値型
事業所等 ― T事業所コード3 ― テキスト型


>>> コード1、コード2、コード3はテキストボックスだと思いますが、
>>>それぞれのコントロールソースは何ですか。
> これについても、答えがないですね。
> それぞれのテキストボックスについて、
>プロパティシートの「データ」タブの「コントロールソース」には、何が設定されていますか
>ということです。

前回フィール名、コントロールソース共同名のテキストボックスと書いたのですが、先程と同じように下記に纏めました。

テキストボックス名 ― コントロールソース ― 関連するデータ型

コード1 ― コード1 ― 数値型
コード2 ― コード2 ― 数値型
コード2 ― コード2 ― 数値型


質問箇所だけ回答してみました。
これで大丈夫でしょうか?

【12675】Re:一つの条件で複数検索
回答  かるびの  - 14/12/21(日) 1:25 -

引用なし
パスワード
   >フォームで使用する部分のみ書いてみましたが、足りなかったみたいですね。
 「コード1〜3」の各テキストボックスの名前は書いてありましたが、
それらのフィールド名が書いてなかったので、お尋ねしたんです。


>>>>>顧客名     コード1  コード2  コード3
>>>>>A社      11     12       (ブランク)
>>>>>B社      12     14     15
>>>>>C社      13     14     15
>>>>>
>>>>>というデータがあり、検索コードに12を入れボタンを押すと、
>>>>>
>>>>>顧客名     コード1  コード2  コード3
>>>>>A社      11     12       (ブランク)
>>>>>B社      12     14      15
>>>>>
>>>>>と、C社が抽出されないようなVBAがありましたら教えていただけないでしょうか。

 前回(12672)でも触れましたが、
フォームの Filter プロパティと FilterOn プロパティを使います。

 上例で言えば、
   「コード1」フィールドが12であるか、
   又は「コード2」フィールドが12であるか、
   又は「コード3」フィールドが12である
レコードを抽出することになります。
 これを条件式に表すと
   コード1 = 12 OR コード2 = 12 OR コード3 = 12
となります。
 この文字列を Filter プロパティに代入します。


 上記の条件式の「12」という値ですが、「検索コード」テキストボックスの値を使うわけですよね。
 なので、「検索コード」テキストボックスを使って、
上記条件式のような文字列を生成する必要があります。   

 「検索コード」テキストボックスに15という値が入力されているとし、
strWhereがString型の変数だとすると、
   strWhere = "コード1 = " & Nz(検索コード.Value,0)
というコードを実行すると、strWhereに「コード1 = 15」という文字列が格納されます。
 「Nz(検索コード.Value,0)」の部分をダブルコーテーションで囲われたものの外に出す
という点がポイントです。

 strWhere の後に文字列をつなげたければ、上記のコードに続けて
   strWhere = strWhere & " AND "
というコードを実行すれば、strWhere には「コード1 = 15 AND 」という文字列が格納されます。


 それから、半角スペースも重要な意味を持っています。
半角スペースを省いてしまったり、
半角スペースを入れるべきところに全角スペースを入れたりすると、
エラーになります。


 Filter プロパティに値を設定したら、FilterOn プロパティに True を設定しないと、
フィルタは効きません。


 以下は蛇足です。
 「T顧客名」の作り方が間違っているように思います。
 というのは、「コード1」「コード2」「コード3」というフィールド名だからです。

 エクセルの場合、ワークシートにおける列の項目名として「氏名1」「氏名2」「氏名3」
というようにすることが少なくありません。
 しかし、データベースの場合、そのようなフィールド名を付けた場合、テーブル設計として
誤っていることが少なくありません。
 ことに、「氏名2」の値と「氏名3」の値とが入れ替わっても、大した違いはない
というのであれば、テーブル設計は確実に誤りです。

 この場合、コード1〜3の各フィールドをT顧客名から外し、
新たに「Tコード」というテーブルを作ります。
フィールドは、
  コードID 長整数型又はオートナンバー (主キー)
  顧客番号 テキスト型
  コード番 数値型  (「コード2」の2を格納する。このフィールドはなくてもよい)
  コード 数値型
となると思います。
 T顧客とは、顧客番号で結合させます。

 なぜこういうテーブル構成にするのかというと、OR検索は、AND検索に比べて遅いからです。
 コード1〜3を一つのフィールドにしてしまえば、OR検索をしなくて済むので、
迅速な処理ができるようになります。
 つまり、処理方法や計算方法に合わせてテーブルを作るわけです。
 なお、ここがアクセスとエクセルの違いの一つです。
 エクセルでは、まず表を作り、表に合わせて処理方法や計算方法を考えるのに対し、
アクセスでは、処理方法や計算方法に合わせてテーブルを作ります。


 それから、T事業所コード1〜3の各テーブルですが、格納されているデータが3テーブルとも
同じなのではないですか。
 もしそうであれば、T事業所コード2及び3の各テーブルは不要だと思います。
というより、T事業所コード2及び3みたいなテーブルは作ってはいけません。
同じデータを複数のところに格納することは、データベースでは御法度です(一事実一箇所の原則)。

 では、どう対応するかですが、
 クエリのデザインビューで、マウスを右クリックをし、「テーブルの表示」を選択します。
「テーブルの表示」フォームから「T事業所コード1」を2回追加します。
 そうすると、デザインビューに「T事業所コード1」「T事業所コード1_1」「T事業所コード1_2」
というテーブルが表示されるはずです。
 あとは、これらを使ってクエリを作ります。

 「T事業所コード1_1」「T事業所コード1_2」の実体は、「T事業所コード1」です。
一つのテーブルを、名前を変えて使い回すわけです。

 とはいえ、コード1〜3を一つのフィールドにしてしまえば、T事業所コード1〜3の問題は
出てこないことになるんですけどね。

【12677】Re:一つの条件で複数検索
発言  kok  - 14/12/24(水) 9:52 -

引用なし
パスワード
   ▼かるびの さん:

回答ありがとうございます。

下記のように書いていただいたのですが、実際どう組み込んでいったらよいかわからない状態です。

> 「検索コード」テキストボックスに15という値が入力されているとし、
>strWhereがString型の変数だとすると、
>   strWhere = "コード1 = " & Nz(検索コード.Value,0)
>というコードを実行すると、strWhereに「コード1 = 15」という文字列が格納されます。
> 「Nz(検索コード.Value,0)」の部分をダブルコーテーションで囲われたものの外に出す
>という点がポイントです。
>
> strWhere の後に文字列をつなげたければ、上記のコードに続けて
>   strWhere = strWhere & " AND "
>というコードを実行すれば、strWhere には「コード1 = 15 AND 」という文字列が格納されます。

自分の勉強不足だという事はわかっていますので、理解するまでは時間がかかりそうなので保留させて下さい。


> クエリのデザインビューで、マウスを右クリックをし、「テーブルの表示」を選択します。
>「テーブルの表示」フォームから「T事業所コード1」を2回追加します。
> そうすると、デザインビューに「T事業所コード1」「T事業所コード1_1」「T事業所コード1_2」
>というテーブルが表示されるはずです。
> あとは、これらを使ってクエリを作ります。
>
> 「T事業所コード1_1」「T事業所コード1_2」の実体は、「T事業所コード1」です。
>一つのテーブルを、名前を変えて使い回すわけです。
>
> とはいえ、コード1〜3を一つのフィールドにしてしまえば、T事業所コード1〜3の問題は
>出てこないことになるんですけどね。
     
上記は以前やってみたのですが、クエリ表示をしたら何も出てこなかったんです。
何かやり方を間違えたのかもしれませんので、後日チャレンジしてみます。

【12678】Re:一つの条件で複数検索
回答  かるびの  - 14/12/25(木) 0:09 -

引用なし
パスワード
   >> 「検索コード」テキストボックスに15という値が入力されているとし、
>>strWhereがString型の変数だとすると、
>>   strWhere = "コード1 = " & Nz(検索コード.Value,0)
>>というコードを実行すると、strWhereに「コード1 = 15」という文字列が格納されます。
>> 「Nz(検索コード.Value,0)」の部分をダブルコーテーションで囲われたものの外に出す
>>という点がポイントです。
>>
>> strWhere の後に文字列をつなげたければ、上記のコードに続けて
>>   strWhere = strWhere & " AND "
>>というコードを実行すれば、strWhere には「コード1 = 15 AND 」という文字列が格納されます。

 文字で書くとごちゃごちゃしますが、実際に試してみるのが一番だと思います。


 まずテスト用のフォーム(Fテスト)を作り、ここにテキストボックス(txtテスト)を
配置します。
 Fテストのレコードソースを指定する必要はありません。
 txtテストのコントロールソースも指定しません。

 そして、Fテストを開き、txtテストに「28」と入力します。

 次に、VBEのウィンドウからメニューにおいて、表示→イミディエイト ウィンドウを選択して、
イミディエイトウィンドウを表示させます。
 イミディエイトウィンドウに
   ? "txtテストの値は" & Forms("Fテスト")!txtテスト.Value & "です。"
と入力し、エンターキーを押してみてください。
 イミディエイトウィンドウの次の行に、この式の結果が表示されます。

 次にtxtテストの値を変えて、再び、
   ? "txtテストの値は" & Forms("Fテスト")!txtテスト.Value & "です。" 
と入力し、エンターキーを押してみてください。


 こんなところで、イメージをつかめないですかね。

【12679】Re:一つの条件で複数検索
発言  kok  - 14/12/25(木) 15:54 -

引用なし
パスワード
   ▼かるびの さん:

回答ありがとうございます。

>   ? "txtテストの値は" & Forms("Fテスト")!txtテスト.Value & "です。"
イミディエイトウィンドウで結果は出ました。

しかし、これを
>   strWhere = "コード1 = " & Nz(検索コード.Value,0)
この式にどう変換し組み込むのか?

そして、Filterプロパティを使ったことがないので、
Me.Filter = strWhere = "コード1 = " & Nz(検索コード.Value,0)
この式でいいのか?さらに、
>   strWhere = strWhere & " AND "
strWhereが2つ出てきて、さらにAND
イメージよりも完全に混乱しました。

親切に教えていただいているのですが、前回の回答から何を質問したらいいのかわからなくなってしまいました。

申し訳ないですが、完全に自分の中で迷宮に入ってしまいました。

【12680】Re:一つの条件で複数検索
回答  かるびの  - 14/12/26(金) 0:41 -

引用なし
パスワード
   >Me.Filter = strWhere = "コード1 = " & Nz(検索コード.Value,0)
>この式でいいのか?
 この式ではだめですね。

 Filter プロパティには、条件式たる文字列、例えば、「数量 = 80」というような文字列を
設定します。
 例えば、
   Me.Filter = "数量 = 80"
のようにします。
 しかし、本件では、「検索コード」テキストボックスの値を使うため、
条件式はその都度違うものとなります。
 そのため、その都度、条件式たる文字列を生成する必要があります。
 ただ、正しい条件式を作れているかどうかは、コードを見ているだけではわかりません。
 とりわけエラーになった場合には、Filter プロパティに実際に渡された文字列を
確認したいところです。
 その確認を容易にするため、条件式たる文字列は、通常、変数に格納します。

 その確認の仕方ですが、
条件式を strWhere という String 型変数に格納するとします。
 この変数への格納を行った次の行に、
   Debug.Print strWhere
というコードを入れます。
 このコードをが実行されると、 strWhere 変数に格納されている文字列が
イミディエイトウィンドウに表示されます。
 その表示を見て、正しい条件式を作れているかどうかをチェックします。


>>   strWhere = strWhere & " AND "
>strWhereが2つ出てきて、さらにAND
>イメージよりも完全に混乱しました。
 strWhereが2つ出てくるというこのパターンですが、VBAではよく使います。
 このコードの意味は、strWhereに格納された文字列の後に「 AND 」という文字列を
くっつけるというこです。
 strWhereに「あいう」という文字列が格納されているとしたら、
上記コードを実行後は、strWhereに格納されている文字列は「あいう AND 」と変わります。

【12684】Re:一つの条件で複数検索
お礼  kok  - 15/1/15(木) 10:00 -

引用なし
パスワード
   ▼かるびの さん:

正月休みに一度頭をリセットしました。
前回私の書いた式ではダメということなので、一番初めから間違っていることだとわかりました。


自分なりになぜわからないのか纏めてまみした。

まず、Filterプロパティを自分は理解していないこと。
調べたら、Me.Filter ="対象フィールド名 = 抽出条件" ということになるのがわかりましたが、前回も書いた strWhere という変数がいきなり出てきて混乱を招いています。

変数ですから宣言をし、変数に格納する式を作り、Filterプロパティに変数を組み合わせるという工程でいかなければならないですね。

そもそも、最初の質問にテーブルやフォームの構成を書きましたが、検索するにはこんな複雑にしないといけないレベルなのでしょうか?


そして最近では、Filterプロパティのレクチャーのみで自分の質問とかけ離れてしまったような感じがします。


まず、自分が変数を使わないFilterプロパティを勉強してから教えていただいたものを理解していく順序じゃないと、いくら説明されてもわからないと思いますので、この質問はここで締め切らせて下さい。
長々とお付き合いしていただきありがとうございました。

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