アクセス2007でフォームフィルターをレポートにも使う方法

このQ&Aのポイント
  • アクセス2007のフォームフィルターを使って、特定のデータを表示する方法について解説します。
  • フォームAとフォームBの関連付けについて説明し、フォームBでフィルターをかけた後にフォームAで該当データを表示する方法について詳しく説明します。
  • しかし、フォームAを元にレポートCを表示する際には、フィルターが長くなるとエラーが発生することがあります。そのため、フォームの検索条件をレポートに反映する方法についても考える必要があります。
回答を見る
  • ベストアンサー

アクセス2007 フォームフィルターをレポートにも

アクセス2007 フォームフィルターをレポートにも フォームA---「家」データ        「家ID」 佐藤さん、斎藤さん、住所、電話等 フォームB---「家族内」データ        各家の家族構成 お父さんの誕生日、お母さんの誕生日などなど「家ID」有り フォームBでフィルターをかけ、「家ID」を元にフォームAで該当するデータを表示させています。 ----------------------------------------------------   Set rs = Forms.フォームB.RecordsetClone   Do Until rs.EOF     フィルタ = フィルタ & "," & rs!家ID rs.MoveNext Loop rs.Close   フィルタ = "家ID IN (" & Mid$(フィルタ, 2) & ")"   DoCmd.OpenForm "フォームA", WhereCondition:=フィルタ, ---------------------------------------------------- ※フィルタは255文字を超える場合有り このフォームAを元に レポートC(はがき宛先)で DoCmd.OpenReport "レポートC", acViewPreview, WhereCondition:=フィルタ(または、forms.フォームA.Filter) とすると「フィルターが長い」とエラーになります。 OpenFormでのWhereCondition:=は長くても受け付けますが、OpenReportの方は受付ないみたいです。 リレーションの知識不足のまま、進めてきたシッペ返しが今きているのですが、 こんな場合どうしたらフォームの検索条件をレポートに反映できるでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • DexMachina
  • ベストアンサー率73% (1287/1744)
回答No.6

フォームやレポートのレコードソースには、テーブルやクエリの他に SQL文を直接指定してやることもできます。 一例: http://okwave.jp/qa/q5784557.html ですので、フォームAのフィルタをDoCmd.OpenReportのWhere Conditionに指定する代わりに、レポートのレコードソースを 切り替えてしまうのが、現状からの大幅な改修は行わずに 目的の結果を得られる解決策ではないかと思います。 (No.5のお礼欄の対応をされた後では、ちょっと遅かったかも  しれませんが(汗):  但し、『フォームAのクローンをつくって「選択」をTrue』という  操作で、もしもテーブルは元のフォームAと同じままだとすると、   ・クローンではなくフォームAそのもので処理してもいいか、   ・フォームだけでなくテーブルも別に用意しないとまずいか、  のような気がします(汗)) 以下、上記内容での改修案になります: 【現状】 DoCmd.OpenReport "レポートC", acViewPreview, WhereCondition:=フィルタ 【改修】 'フィルタは使用せずにレポートを開く DoCmd.OpenReport "レポートC", acViewPreview 'レポートのレコードソースを差し替え '(元のレコードソースが「クエリZ」だった場合) Reports!レポートC.RecordSource = "Select * From クエリZ Where " & フィルタ & ";" 上記の例は、元のコードが「フォームAで現在フィルタが 適用されているか」を判定していないので、それを踏襲 した形としました。 通常は、フィルタを解除(フォームのFilterOnプロパティを Falseに設定、或いはツールバー等で「フィルタの解除」 を指定)しても、フォームのFilterプロパティには、直前の 条件が記録されたままになりますので、フォームAの フィルタを解除した状態で、上記コードでレポートを開くと、 レポート側はフォームAと異なる結果を表示してしまいます。 これを避けるためには、フィルタ解除時に「Filter=""」の 代入を行うか、上記のコードを以下のようにして下さい: 【再改修】 Dim strRs As String   '変数を宣言 DoCmd.OpenReport "レポートC", acViewPreview 'フォームAのフィルタ適用状況に応じてレコードソースを選択 Select Case Forms!フォームA.FilterOn   Case True  'フォームAでフィルタ適用済     strRs = "Select * From クエリZ Where " & フィルタ & ";"   Case Else  'フォームAでフィルタ解除済     strRs = "クエリZ" End Select '選択したレコードソースに差し替え Reports!レポートC.RecordSource = strRs ・・・以上です。

situmonnsya
質問者

お礼

お礼が大変遅くなり申し訳ありません。 「レコードソースの差し替え」了解しました。 一度チャレンジしたのですが、コードの書き方がわからず挫折してました。 クローンを使うのはスピードが全然違う為でした。 フォームでループさせるとスクロールもしてしまいます。 クローンだと一瞬で終わりますので。 ほぼ完成に近づいている状態で、レコードソースの差し替えについては今後勉強して使わせて頂きます。 ご回答、ありがとうございました。

その他の回答 (5)

  • NOBNNN
  • ベストアンサー率50% (93/186)
回答No.5

#1 です。 一部、私の側でのミスがりましたので訂正いたします。 Access の使用では SQL の長さは 64,000文字、また vBA で記述できる文字列型については 文字列型 (String)   文字列には、可変長文字列と固定長文字列の 2 種類があります。   可変長文字列には、約 2GB (2^31) までの文字を格納することができます。   固定長文字列には、1 ~ 約 2GB (2^31) の文字を格納することができます。 となっています。 255文字としたのは デバッグウインドウで見るとそのように見えるので、勘違いしていました。 詳細は http://www.accessclub.jp/bbs2/0040/beginter12916.html いずれにせよ 長いSQL文は間違いの元になります。 できるだけ短くなるように工夫しましょう。 SQLの勉強については Google で「SQL入門」でさがせばたくさんあります。 できるだけ VBAでループ処理などは行わずSQLで解決できるように心がけてください。 できない場合はアクションクエリで 別テーブルを作成し、そのデータを入力データにすれば かなり効率的にできます。 これで 解決でしたら ベストアンサーボタン クローズしてください。 以上

situmonnsya
質問者

お礼

長らくSQLを必要としない「ファイルメーカー」を使っていたので、勉強しなおし中です。 ほぼ完成、というところでレポートでひっかかってしまいました。 クエリは全部がデザインで組んでおり、いま更きつい所があります。 そこで、 テーブルAに「選択」フィールドを追加 フォームA、レポートCに「選択」を追加 レポートCを作る時 一旦全レコードの「選択」をfalseにUPDATE 抽出表示されたフォームAのクローンをつくって「選択」をTrue レポートCを開く時、Filterに「選択」=True、 データベースをまじめにやってる方には、ひっくり返るような回りくどさでしょうが、目的は達成しました。 ご親切なご回答、ありがとうございました。

  • NOBNNN
  • ベストアンサー率50% (93/186)
回答No.4

#3 のつづき  もし、CreateQueryDef を使わないで行う場合は フォームBから抽出条件のみ フォームAにパラメータとして  渡してあげてください。 グローバル変数(モジュール内で定義) でできます。    例:    モジュールを作成(Module1)         Type T_抽出条件 お父さんの誕生日 As String お母さんの誕生日 As String 子供さん1の誕生日 As String 子供さん2の誕生日 As String 子供さん3の誕生日 As String End Type Public FM_A抽出パラメータ As T_抽出条件 フォームBからパラメータを設定   例:    Privte Sub BB() With FM_A抽出パラメータ .お父さんの誕生日 = "1961/08/10" .お母さんの誕生日 = "1964/05/10" .子供さん1の誕生日 = "1990/05/10" .子供さん2の誕生日 = "1993/02/15" .子供さん3の誕生日 = "1996/09/24" End With End Sub フォームAでパラメータを受け取り クエリをレコードソースに指定。   例:   Privte Sub aa()     DIM Str_Where as string         With FM_A抽出パラメータ       Str_Where = Str_Where & " お父さんの誕生日 = '" & .お父さんの誕生日 & "' AND " & VBCRLF & _       Str_Where = Str_Where & " お母さんの誕生日 = '" & .お母さんの誕生日 & "' AND " & VBCRLF & _     Str_Where = Str_Where & " 子供さん1の誕生日 = '" & .子供さん1の誕生日 & "' AND " & VBCRLF & _     Str_Where = Str_Where & " 子供さん2の誕生日 = '" & .子供さん2の誕生日 & "' AND " & VBCRLF& _     Str_Where = Str_Where & " 子供さん3の誕生日 = '" & .子供さん3の誕生日         End with         me.Recordsource = "SELECT TBL_A.* FROM クエリA基本 AS TBL_A " & VBCRLF & _      "Inner JOIN クエリB基本 AS TBL_B " & VBCRLF & _          "On TBL_A.家ID = TBL_B.家ID " & VBCRLF & _      " WHERE " & Str_Where & " " & VBCRLF & _          " Order BY TBL_A.家ID"       End Sub

situmonnsya
質問者

お礼

ご丁寧なご回答、ありがとうございます。 急きょ、ネット・参考書で勉強しました。 「NOBNNN」さんのご教示のとうりで実現できそうです。 だた、私の技量ではまだ少し無理みたいです。 勉強中に下記の記述を発見しました。 http://support.microsoft.com/kb/207615/ja wherecondition:=でなく、filtername:=フォームA.Filter これだと、文字数に制限がないみたいで、エラーも発生しませんでした。 但し「Loopで回してIDを得る」が効率がいいとは思えませんが、「RecordsetClone」で回すのは瞬時で終わるので苦になっていません。 次にデータベースを組む時は「NOBNNN」さんのご回答を頭に入れて作りたいと思います。 誠にありがとうございました。

situmonnsya
質問者

補足

お礼の後の補足になってしまいました。申し訳ありません。 filtername:=フォームA.Filterでエラーにならずいけると思ったのですが、勘違いでした。 エラーにはならず、常に全表示になっていました。 filternameは「クエリの名前を文字列で指定」でした。 やはりクエリを勉強しないといけないみたいです。

  • NOBNNN
  • ベストアンサー率50% (93/186)
回答No.3

#1です。 >>例えばフォームBの検索条件に「お父さんの趣味=パソコン」とあってもフォームAに「お父さんの趣味」フィールドはないので。 こういう場合は、動的にクエリを作成してしまえばできます。 #1 でお答えしました CreateQueryDEF でクエリの中身を上書きしてしまう方法があります。 Access のクエリは 255文字が限界です。 だから 長い場合はあらかじある程度分割(別なクエリとして定義) するかデザイナでの入力はあきらめて 手動でSQLを書くことです・ デザイナのばあいは 中身が正規化されておらず かならずしも 最良のSQLではありません。 やたらと長く、短くはなりません。 デザイナに頼らず手動で行うには SQL が自分で書けることが条件です。 リレーショナル の記述法も知っている必要があります。 Access の場合は 長い SQL をひとつのクエリとして 保存し、それを再利用してひとつのクエリにできます。 初期の フォームA のクエリ を取り出して クエリを作製します。 初期の フォームB のクエリ を取り出して クエリを作製します。  例   フォームAデータ(家ID、氏名、住所、電話番号)これを クエリA基本 として作製してください。         フォームBデータ(家ID、族構成 お父さんの誕生日、お母さんの誕生日などなど)これを クエリB基本 として作製してください。    フォームB より条件が入力されたら 動的に抽出クエリ(求めたいフォームAデータ)を作成します。         フォームBから入力された条件(たとえば「お父さんの趣味=パソコン」)を作製したい場合。        SELECT TBL_A.* FROM クエリA基本 AS TBL_A      Inner JOIN クエリB基本 AS TBL_B           On TBL_A.家ID = TBL_B.家ID           WHERE TBL_B.お父さんの趣味=パソコン           Order BY TBL_A.家ID            とすれば良いのです。     これを 先にのべたCreateQueryDef で 抽出クエリ(求めたいフォームAデータ)を作成します。  これを仮に 「フォームA抽出クエリ」とします。    あらかじめ フォームAおよびレポートCのレコードソースを 「フォームA抽出クエリ」としてください。  最初はつくられていないのでエラーになる場合は適当な内容でデザイナで「フォームA抽出クエリ」を  作製してください。      あとは フォームBから抽出条件が入力され、クエリ「フォームA抽出クエリ」を作製しましたので  フォームAとレポートCを開くだけで 大丈夫です。    これでできるはずです。   ************ つづく *********

  • NOBNNN
  • ベストアンサー率50% (93/186)
回答No.2

#1 です。 気になる箇所があります 質問者さまの フォームBでフィルターをかけ、「家ID」を元にフォームAで該当するデータを表示させています。 ----------------------------------------------------   Set rs = Forms.フォームB.RecordsetClone   Do Until rs.EOF     フィルタ = フィルタ & "," & rs!家ID rs.MoveNext Loop ですが  これってフォームBのデータが1000件あったら 全部対象てことですよね。    わざわざ ループさせなくても フォームBのデータから抽出できませんか?         SELECT TBL_A.* FROM TBL家データ AS TBL_A      Inner JOIN TBL家族内データ AS TBL_B           On TBL_A.家ID = TBL_B.家ID           Order BY TBL_A.家ID       このクエリを フォームAおよびレポートCのレコードソースに指定すれば大丈夫では?      もうすこし フォームBの絞込みの方法を教えてください。  

situmonnsya
質問者

お礼

補足の2です 気が付いたのですが、 >SQL文を取り出して、それにフォームBの検索条件を追加 はダメでした。 例えばフォームBの検索条件に「お父さんの趣味=パソコン」とあってもフォームAに「お父さんの趣味」フィールドはないので。 う~~ん

situmonnsya
質問者

補足

早速のご回答ありがとうございます。 「Inner JOIN」は使ったこともなく、あわてて勉強してます。 フォームBで s = "SELECT * FROM フォームAのTB Inner JOIN フォームBのTB    On フォームAのTB.家ID = フォームBのTB.家ID" Forms.フォームA.RecordSource = s としましたが、フォームAを見にいくと「#Name?」がたくさんあり、レコード数も「フォームBのTB」分です。 「Inner JOIN」の意味を体験した次第です。 初期のフォームAのレコードソースはフォームAクエリを指定しています。かなり複雑です。 (クエリはデザインで作っています) この初期のクエリのSQL文を取り出して、それにフォームBの検索条件を追加したらと思っていますが、方法が?です。 >フォームBの絞込みの方法 専用の検索フォームを作り絞込みをしています。 例えば、お父さんの誕生日、趣味とか・・・です。

  • NOBNNN
  • ベストアンサー率50% (93/186)
回答No.1

たぶん文字列の長さ255文字の限界を超えているのでは? フィルターは使わず。 レコードソースのほうで工夫してみてはどうでしょう たとえば フォ-ムからレポートを 一旦開き。 レコードソースを変更してしまえばできるのでは VBA で クエリを 動的に作製する方法があります。(CreateQueryDefメソッド ) 参考:http://www.accessclub.jp/dao/CreateQueryDef.html あらかじめ 雛形になるクエリを登録しておきます。  これを「クエリ雛形A」とします。      SELECT * FROM 住所録 「クエリ雛形A」 から 「クエリ_レポートデータ」を作成します。 SELECT * FROM クエリ雛形A Where 家ID IN (2,5,7) フォームAとレポートCのレコードソースのプロパティをこのクエリ名に変更します。 フォームBより、フォームAとレポートCのRecordsourceのプロパティ    をあらかじめ「クエリ_レポートデータ」 とすればOKです。  VBAで変更する場合は下記のHPが参考になります。  参考:http://office.microsoft.com/ja-jp/access/HA012327891041.aspx 以上

関連するQ&A

  • Access2003レポートの連続印刷方法

    以下のような仕様にて、Access2003で取引案件管理データベースをつくっています。 一案件ごとにA,B,Cと三種類のレポートがあり、それを順番に印刷する機能を追加しようとしているのですが、方法がわからず、アドバイスをお願い致します。 *仕様* ・ユーザはアクセスオープン時に、自身のIDとパスワードを入力 ・認証が通ると、総合メニュー画面が起動される。 総合メニューには「入力フォーム起動ボタン」と「レポート印刷ボタン」がある ・DB内部でIDとユーザの所属部署の紐付けを行っており、入力フォームを起動すると、自分の所属部署の担当案件だけが表示される (フォームのコードで、グループごとにフィルタをかけている) ・レポートは案件ごとにA,B,Cと三枚に分かれている ・入力フォーム内にも、印刷ボタンがあり、それを押すと表示されている案件のレポートがA、B、Cの順番で出力される。 コードは以下の通り DoCmd.OpenReport "レポートA", acViewNormal, WhereCondition:="[案件名] ='" & Me.案件名 & "'" DoCmd.OpenReport "レポートB", acViewNormal, WhereCondition:="[案件名] ='" & Me.案件名 & "'" DoCmd.OpenReport "レポートC", acViewNormal, WhereCondition:="[案件名] ='" & Me.案件名 & "'" *今回つくりたい機能* 総合メニューの「レポート印刷ボタン」の中身を実装したいと考えています。 これを押すと、案件ID「001」のレポートA→B→C→案件ID「002」のレポートA→B→C→案件ID「003」・・というように、案件ごとにレポートA,B,Cがセット(連続)で印刷できるようにしたいのです。 上の構文と、レコード送りを組み合わせればいいのではないかと予想はついているのですが…緊急対応で、自分でコードを試行錯誤している時間がないもので、コードを上のような機能を実現できるコードを教えて頂けますと幸いです。宜しくお願い致します。

  • Access 複数条件のフィルタ

    フォーム[F_MENU]に非連結のテキストボックス検索用A~Cで3つあります。 検索用A 検索用B 検索用C AかつBかつCという全件一致でフィルターをかけてフォーム[詳細]を開きたいのですが DoCmd.OpenForm "F_詳細", , , "A = '" & Forms!F_MENU!検索用A & "'" And "B = '" & Forms!F_MENU!検索用B & "'" And "C = '" & Forms!F_MENU!検索用C & "'" とやると、実行時エラー'13':型が一致しません。 と出てしまいます。 Aだけ、Bだけ、Cだけ、それぞれひとつずつ書けば、エラーなく結果が得られます。 DoCmd.OpenForm "F_詳細", , , "A = '" & Forms!F_MENU!検索用A & "'" DoCmd.OpenForm "F_詳細", , , "B = '" & Forms!F_MENU!検索用B & "'" DoCmd.OpenForm "F_詳細", , , "C = '" & Forms!F_MENU!検索用C & "'" おそらくANDの使い方が誤っていると思うのですが、添削お願いいたします。 全てのテキストボックス及び元テーブルのデータ型はテキスト型です。 条件は3つとも完全一致のみで、検索用ABC、F_詳細のABCそれぞれのカラムにNULL値はありません。 よろしくお願いします。

  • Accessのレポート印刷について教えて下さい。

    Accessのフォームでフィルタを使い絞り込んだデータをレポートで 印刷する場合について教えて下さい。 DoCmd.OpenReport "レポート名", acViewPreview, , Me.Filter では、フォームとレポートが同じレコードソースだと使えるという事ですが、 フォームとレポートのレコードソースが別の場合はどのようにすると フィルタで絞り込んだ条件のレポートを印刷できますか? 教えて下さい。よろしくお願いします。

  • ACCESSフォームフィルタで抽出したデータのみをレポートで表示する方法

    フォームフィルターでデータを抽出した後,抽出されたデータのみをレポート上に表示させるコマンドボタンをフォーム上に作っています。 下記のコードを作成しましたが,これだと抽出前の全部のデータが表示されてしまいます。 どうしたら良いでしょうか。 Private Sub ラベルプレビュー_Click() Dim stDocName As String DoCmd.Echo False, stDocName = "rpt宛名ラベル" DoCmd.OpenReport stDocName, acViewDesign DoCmd.SelectObject acReport, stDocName, False ' Reports(stDocName).RecordSource = Me.RecordSource DoCmd.OpenReport stDocName, acViewPreview End Sub

  • Access レポート作成時のフィルタのかけ方

    Microsoft Accessでテーブルからレポートを作製する際のフィルターのかけ方がわかりません。 VBAにて DoCmd.OpenReport "領収記録", acPreview, , 領収日付 >= Forms!f_入力!開始日.Value, acWindowNormal を使用しており、「領収日付」は「領収記録」のフィールドの一つです。 フォーム「f_入力」のテキストボックス「開始日」で指定した日付以降のレコードのみを表示させたいのですが、 フィルタがかからず全レコードが表示されてしまいます。 「領収日付」、「開始日」共にデータ型は日付型です。 よろしくお願いします。

  • Accessでレポートの項目をVBAで変更したい

    Accessのレポートで年次集計を項目が可変になるため、VBAで書き換えるようにしたのですが、うまく出来ません。 お心当たりのかたいらっしゃいましたら教えて頂けないでしょうか。 フォームの概要(売上集計)     OO年 OO年 OO年 商品A 1,000 2,000 3,000  商品B 1,500 2,500 3,500 商品C 2,500 3,500 4,500 ※年は可変です 次のようにするとフォームが開いていないと言ったエラーが出ます。 stDocName = "年別売上集計レポート" Reports(stDocName).ラベル1.Caption = cstr(Year) + "年" DoCmd.OpenReport stDocName, acPreview, "", [フィルタ] 又次のようにするとエラーは出ませんが、ラベルは書き換わりません。 stDocName = "年別売上集計レポート" DoCmd.OpenReport stDocName, acHidden, "", [フィルタ] Reports(stDocName).ラベル1.Caption = cstr(Year) + "年" DoCmd.OpenReport stDocName, acPreview, "", [フィルタ]

  • Access2003のフォームからレポートに変数を渡したいのです。

    Access2003のフォームからレポートに変数を渡したいのです。 フォームに「結果」という名前の非連結コンボボックスがあり、値集合ソースは、「"承認";"却下";"保留"」です。 フォームの印刷ボタンはクリック時のイベントに以下を設定しています。 DoCmd.OpenReport ("R_レポート名"), acViewPreview このレポートでテキストボックスに「結果」の内容を表示させたいと思います。 テキストボックスのコントロールソースに、「=[Forms]![F_フォーム名]![結果]」と入れてみましたがエラーになります。 フォームのコンボボックスの値をレポートで表示させるにはどうすれば良いのでしょうか。 ご教示ください。よろしくお願いいたします。

  • ACCESS でフォームフィルターをレポートに引き継ぐ方法

    こんにちは。 いつもありがとうございます。 現在、ACCESSで名簿管理ソフトを作っています。 フォームで条件を指定し、該当する人を抽出できるようになっているのですが、その条件をそのままレポートのソースに使用するにはどうれすばいいでしょうか? DoCmd.OpenReport "rpt_名簿", acViewPreview,, Me.Filter としているのですが、実行時エラー 438が出てしまいます。

  • accessレポートの抽出条件

    こんにちわ。 いまaccess2000で, フォームからレポートを出力する処理をしています。 そのレポートは[コントロールソース]としてあるクエリを設定しています。 そこで, DoCmd.OpenReport "r_帳票", acPreview, , "[番号] = 'a100'" とコーディングしました。 なおレポートの[フィルタ]プロパティは"はい"にしています。 ところが,出力されたレポートには条件で抽出されずに 全件が出力されてしまいました。 抽出条件を効かせるためにはどうすれば良いでしょうか? 教えてください。お願いします。

  • Access 2重3重のポップアップフォームの場合

    Accessです。 フォームを3つ作りました。 フォーム1=「A] フォーム1=「B]>ポップアップ「はい」 作業ウインド固定「はい」 フォーム1=「C]>ポップアップ「はい」 作業ウインド固定「はい」 「A」が開くとき Private Sub Form_Open(Cancel As Integer) ____DoCmd.OpenForm "フォーム2", , , , , acHidden ____DoCmd.OpenForm "フォーム3", , , , , acHidden End Sub として 「A」にはボタンがあってクリックすると「B」が Visible=True になります。 Private Sub コマンド1_Click() ____Forms!フォーム2.Visible = True ____Forms!フォーム2.SetFocus End Sub さらに「B」にもボタンがあってクリックすると「C」が Visible=True になります。 Private Sub コマンド1_Click() ____Forms!フォーム3.Visible = True ____Forms!フォーム3.SetFocus End Sub 「C」が現れた後、マウスイベントがきかなくなります。 というより、閉じることもできなく、アクセス本体をCLT+ALT+DELで強制終了させなくてはいけなくなります。 対処方法を教えて下さい。