ACCESSでサブフォームの編集中レコードの処理

このQ&Aのポイント
  • ACCESS2000で単票系メインフォームと帳票系サブフォームを連結し、サブフォームに入力した明細の金額累計をメイン側へ登録する処理を行っています。
  • 編集途中のレコードの金額は累計されずに保存されてしまう問題があります。
  • 保存コマンドボタンでサブフォームにRequeryをかけると累計金額がクリアされてしまいます。編集途中でもちゃんと累計されるような方法をご指導ください。
回答を見る
  • ベストアンサー

ACCESSでサブフォームの編集中レコードの処理

ACCESS2000で単票系メインフォームと帳票系サブフォームを連結し、サブフォームに入力した明細(複数レコード)の金額累計(サブフォームフッターの非連結コントロール)をメイン側へ登録する処理を行っています。メイン側(マスターテーブル)への保存は保存用のコマンドボタンで行っています。サブフォーム側で完全に編集完了した場合(カーソルが次レコードの入力ラインにある)は正常に処理されますが、編集途中のレコードの金額は累計されないで保存されてしまいます。また保存コマンドボタンでサブフォームにRequeryをかけると累計金額がクリアされてしまいます。編集途中(つまり入力後エンタキーを押さないで直接コマンドボタンを押下)でもちゃんと累計されるような方法をご指導ください。よろしくお願いします。

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

  • ベストアンサー
  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.6

#5です 基本的なデータ構成は#4でのものに、#5のサブフォームにボタン「btn01」を追加した状態。 (btn01 名がサブ・メイン両方にありますがご容赦を) 追加で、メインフォームに非連結のテキストボックス txt03 を配置しておきます。 サブフォームへ記述している内容) Private Sub btn01_Click()   Dim sTmp As String   If (Me.Dirty = True) Then '    Me.Parent.Form.txt03 = Me.txt01 ' ★1     MsgBox "累計 : " & Me.txt01   ' ★2     sTmp = Me.BeforeUpdate     Me.BeforeUpdate = ""     DoCmd.RunCommand acCmdSaveRecord     Me.BeforeUpdate = sTmp   End If End Sub Private Sub Form_AfterUpdate()   Me.Recalc End Sub Private Sub Form_BeforeUpdate(Cancel As Integer)   Cancel = True End Sub この状態での動きは、 サブフォーム側で編集状態になると、メイン側ボタンは押せなくなります。 ボタン btn01 (編集の確定)をクリックするまでは、他に制御が移りません。 数量または金額を打ち込んでいる最中、ボタン btn01 をクリックすると、 ★2 でのメッセージ表示は最新のものになってますが、メイン側の txt02 は以前のままです。 ★1 で、最新のものをメイン側に表示することができます。 ので、 > 1.サブフォーム側に展開しているレコードが複数の場合、1レコードづつ確定しなければならない > 4.NewRecにフォーカスが移動して更新済みの場合でも場合でも更新ボタンを押す必要がある は、その通りで #5でさらっと書きましたが、操作性は悪く?なる 部分となります。 でも、#5最後に書きましたが、複数レコードのある単票形式のフォームで、マウススクロールを無効にしているかのような処理ができます。 > 2.キャンンセルボタンも操作出来なくなる は、サブフォーム側にボタン設置できれば以下内容でフォームを閉じることはできます。 (ボタン名を btn02 とした場合:編集中のものは反映されません) Private Sub btn02_Click()   DoCmd.Close acForm, Me.Parent.Name, acSaveNo End Sub > 3.更新前処理での入力チェックにおいてエラーの場合でも更新確定されてしまう は、ちょっと意味がわかりませんでした。 更新前処理は2つあって、入力項目それぞれでのもの、レコードとしてのものがあります。 1)入力項目それぞれでのもの 例えば、金額の入力で 100 単位のチェックを行うものとします。 Private Sub 金額_BeforeUpdate(Cancel As Integer)   If ((Me.金額 Mod 100) <> 0) Then     Cancel = True     MsgBox "100円単位で入れてください"   End If End Sub とか、画面デザインでのテキストボックス(金額)のプロパティ 「入力規則」に、 ([金額] Mod 100)=0 「エラーメッセージ」に、 100円単位で入れてください とか。(入力規則は更新前処理の直前で判別されるようです(同じ判別を両方に設定しても意味ありません)) この Cancel = True を返す、入力規則に反する場合は、その項目から他へ制御が移らないので btn01 は押せません。 2)レコードとしてのもの Form_BeforeUpdate のことです。 今回、常に Cancel = True を返すようにしたので、従来の処理は★部分に記述します。 チェックをして OK の時に、★以下の4行を実行するようにします。 以下にイベントの発生順が記述されていますので、眺めてみてください。 http://office.microsoft.com/ja-jp/access/HA102389881041.aspx

bestguy00
質問者

お礼

ありがとうございます。 問題点1については、メインとの整合性チェック処理とCloseをサブフォーム側の編集確定処理に続けて行う事により解決出来そうですね。 (つまり、メインフォーム側には保存ボタンを設けないで、サブフォーム側だけにボタンを設ける) 問題点2につきましても、ご指摘のようにサブフォーム側にボタンを設ける事により解決出来ました。 問題点3は、私の勘違いで、ボタンの処理内にチェック処理を移す事により解決出来ました。 問題点4は、この考え方を採用する場合はどうしようもないという事ですね・・・。 この点につきましては、ユーザと調整してみます。 貴重なアドバイスを頂いて、大変勉強になりました。 とりあえず、この質問はクローズさせていただきますが、今後もまた質問させていただきますので、お目にとまりましたら、どうぞよろしくお願いします。 ありがとうございました。

その他の回答 (5)

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.5

まだ閉じられていなかったので、 おまけ) 操作性は悪く?なりますが、編集中にはメインのボタンなど操作できないようにする方法もあります。 サブフォーム側に、更新/登録用のコマンドボタンを新設します。 編集後には、このボタンで確定動作を行います。 (これ以外ではレコードの更新/登録はできません) (レコードが連結されたフォームであることが前提です) 細工1)サブフォームの更新前処理では必ず Cancel = True を返します Private Sub Form_BeforeUpdate(Cancel As Integer)   Cancel = True End Sub 従来チェック処理等入れていたら、以下細工2)へ移動します。 (記述する位置は適当に) 細工2)更新/登録用ボタンでの処理(ボタン名:btn01 とした場合) Private Sub btn01_Click()   Dim sTmp As String   If (Me.Dirty = True) Then     sTmp = Me.BeforeUpdate     Me.BeforeUpdate = ""     DoCmd.RunCommand acCmdSaveRecord     Me.BeforeUpdate = sTmp   End If End Sub 内容)編集中なら更新前処理を無効にし、レコードを保存後、更新前処理を有効に戻す。 レコードが編集中であった場合、そのレコード以外へ制御が移るのを抑止します。 (サブフォーム内のボタン等は、操作できるようです) この方法は、マウスのスクロールでレコードが移動するのを防ぐ時にも使える方法です。 (複数レコードのある単票形式のフォームの時など)

bestguy00
質問者

お礼

なるほど、この考え方だと手動でサブフォームの更新確定を制御するわけですから、メイン側で余計なサブフォームの動きを気にする必要はなくなりますね。 さらに、サブフォーム側の処理でメインフォームとの整合性チェックなども出来ると良いのですが・・・。 ただし、以下の点が問題だと思われます。 1.サブフォーム側に展開しているレコードが複数の場合、1レコードづつ確定しなければならない 2.キャンンセルボタンも操作出来なくなる 3.更新前処理での入力チェックにおいてエラーの場合でも更新確定されてしまう 4.NewRecにフォーカスが移動して更新済みの場合でも場合でも更新ボタンを押す必要がある このようなケースの対処法が何かあるのでしょうか?それとも私の設定ミス? なお、サブホーム側の金額を変更した場合にはメインフォーム(マスタレコード)との整合性チェックを行いエラーの場合は、修正入力を行うか、キャンセルボタンでCloseする方法を考えています。 当然、このフォームはメイン・サブともにダミーテーブルで処理しています。 このような事を考えると、やはりRecalcでの対処法がよいのでしょうか? 色々とアドバイスを頂き非常に感謝しております。

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.4

#3です 解決した方法は DoEvents を使ってループするものだったでしょうか。 以下、参考程度で) テーブル名:T1 フィールド名:品名、数量、金額 レコード数:567件 サブフォーム名:F_S1 レコードソース:T1 帳票形式 フィールド名とテキストボックス名は同じ ヘッダー部に累計用テキストボックス「txt01」を配置(書式:通貨) コントロールソースは以下 =Sum([数量]*[金額])+(Nz([数量])*Nz([金額]))-(Nz([数量].[OldValue])*Nz([金額].[OldValue])) フォームの更新後処理に Recalc Private Sub Form_AfterUpdate()   Me.Recalc End Sub メインフォーム名:F_M1 サブフォームコントロール名:fsub ソースオブジェクト:F_S1 単票形式 確認用ボタン名:btn01 ボタンのクリック処理は以下 Private Sub btn01_Click()   MsgBox "累計 : " & Me.fsub.Form.txt01 End Sub 検証) サブフォームの編集中等にかかわらず、最終の値がメッセージボックスに表示。 追加1)メインフォームにテキストボックス txt02 (書式:通貨)を配置し、  コントロールソースを以下  =[fsub].[Form]![txt01] この状態で再度検証 編集中(他に移動しない:数量または金額を打ち込んでいる最中)にボタンを押すと txt02 は、\0 の表示となった状態でメッセージボックスが表示。 メッセージの表示内容は正しい。 メッセージボックスを閉じると、txt02 の表示が更新される。 追加2)メッセージボックス表示で、参照先を以下のように変更 Private Sub btn01_Click()   MsgBox "累計 : " & Me.txt02 End Sub この状態で再度検証 txt02 表示、およびメッセージボックスでの表示は正しい。 (但し、txt02 の表示は若干遅れるがメッセージボックスが表示された時には同じ) 戻り1)最初の状態に戻り、サブフォームの更新後処理 Recalc を無効にしてみる この状態で再度検証 編集中(他に移動しない:数量または金額を打ち込んでいる最中)にボタンを押すと 編集前の累計が表示される。 メッセージボックスを閉じてから、最終結果が表示される。 以上 メインフォームの構成もわからないのに回答してました。 ※ この動きは私の環境だけかもしれませんが (Access2000+Win2k/Access2007+Vista のどちらも同じでしたけど)

bestguy00
質問者

お礼

更なる詳細なフォローアップ恐れ入ります。 私も色々と検証してきた状況はご指摘のとおりです。 DoEventsでタイミングをずらすのでも解決しますが、100%ではないように思えますので、Recalc メソッドでの処理にしました。 色々とありがとうございました。

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.3

#2です。 解決された方法を紹介してもらえませんか。 サブフォーム側に入れた処理と、 特にメイン側-保存ボタンでのサブフォームに対しての処理内容について、 お願いします。 ※保存ボタンでのサブフォームへの処理は要らなかったと思いますが

bestguy00
質問者

お礼

フォローアップありがとうございます。 色々と試してみましたが、最終的にはご指摘いただきましたRecalc メソッドで解決できました。 保存ボタンでのサブフォーム処理は参照だけになりました。 改めてありがとうございました。

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.2

#1です サブフォーム側のフォームの更新後処理で再計算させてみてください。 Private Sub Form_AfterUpdate()   Me.Recalc End Sub

bestguy00
質問者

お礼

大変ありがとうございました。 現在悩んでいた問題は解決いたしました。 新たに別途の問題が発生しましたが、これはもう少し自分なりに調査・検討して、どうしようもなくなりましたら、また質問させていただきます。 今後もよろしくお願いします。

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.1

細かい動きは質問内容からわかりませんが、以下の応用でできる気がします。 フォームでの集計をレコード保存する前に反映させる そもそも > 編集途中のレコードの金額は累計されないで保存されてしまいます の操作を可能とさせているのかが、いまひとつ分かりません。

bestguy00
質問者

お礼

早速のご回答ありがとうございました。 長い間悩んでいたことが、少し前に進むことが出来ました。 ただ、ご紹介のサンプルで試しましたが、レコードが更新される前にフォーカスが移動すると累計も更新されますが、フォーカスが移動しない場合はやはり累計は更新されません。 金額のコントロールなので自動タブも効きませんし・・・ 金額入力後フォーカスが移動しない状態でメイン側の保存ボタンで強制的にRequeryさせる方法はありませんでしょうか? 保存ボタンのクリックイベントを    サブフォームコントロール名.SetFocus    サブフォームコントロール名.Requery    ---マスタとサブフォームの整合性チェック処理    ---サブフォーム金額累計でマスター金額更新処理 というように試してみましたが、サブフォームフッターの金額累計はクリアされてしまい、チェック処理、更新処理が正常に行われませんでした。 抜けた後は、編集中のサブレコードは新規レコードとして作成され、サブフォームの表示は正しく表示されます。    あるいは、サブフォームの入力中レコードが完全に確定しない状態を、マスターが更新される前にエラーにする方法は無いでしょうか?  ちなみに、編集途中のレコードを保存可能にしている理由は、最終項目をエンターキーを押下しないまま保存ボタンを押してしまうケースもあるので、入力データが正しければ保存しても良いかなと思ってそうしています。  当然入力チェックはしています。 このようなケースを編集だという事でエラーに出来るのならばそれでもいいです。 再度、ご指導をよろしくお願いします。           

関連するQ&A

  • サブフォームの帳票のレコードを編集している時

    ここに、親フォームと子フォーム(サブフォーム)があって 子フォームのレコードソースは、Workテーブルとします。 子フォームを編集・新規レコード追加すると、 親フォームの保存ボタン処理で、子フォームのレコード内容をWorkから、元テーブルに更新をかける知りをつくろうと考えています。 この時、 子側の帳票のレコードを編集したり、新規レコードを追加している時には ■『親側で、別のレコードに移動出来ないようにし、親側にある「保存」ボタンを押して、上記の処理をしたあとに、親側で別レコードに移動できる』 ような作りにしたいです。 これを実現するために、上の■『・・・』を実現できるようにするのには、どのようにしたら良いでしょうか? よろしくお願いします。

  • Accessのサブフォームについて

    メインフォームとサブフォームのあるフォームを作成しました。メインフォームを入力してから、サブフォームを入力し、次のレコードへ移動するのにメインフォームの移動ボタンを押すと、次のレコードのカーソルがサブフォームのフィールドへ移動します。メインフォームに移動する方法はありませんか?

  • Access メインフォーム サブフォームにて

    お世話になります。 Accessにて メインフォームにコマンドボタンを置いて、クリックするとサブフォームのレコードが 次に行くようにしたいのですが、 コマンドボタン クリック Forms![メインフォーム]![サブフォーム名].Form!フィールド名.SetFocus DoCmd.GoToRecord , , acNext メインフォームとサブフォームのレコードが次に行ってしまいます。 サブフォームだけ次のレコードに行くには、どのようにすれば良いのでしょうか。 分かる方教えて下さい。 宜しくお願いします。

  • サブフォームをリクエリするには?

    アクセスのフォームにはサブフォームがあり、 親フォームの上にあるコマンドボタンで、テーブルに対してアクションクエリでレコードの削除やレコードの更新を行います。 サブフォームにはそのテーブルをソースとしたデータを表示させているのですが、 親フォームの上にあるコマンドボタンのイベントの最後に、 Me.Controls("サブフォーム").Requery を入れても、フォームのデータが#Deletedになります。 Me.Requery でも、サブフォームのデータは#Deletedになってしまいます。 フォームを開きなおしたり、並べ替えをすればデータが表示されますが コマンドボタン押下後にイベントを実行し終わったら、サブフォームのデータも更新されたデータを表示するさせるには どうすればいいでしょうか?

  • Accessのサブフォーム

    教えてください。 フォームの中にサブフォームを作っているのですが(入力用の)、 サブフォーム内のテキストボックスは、1件目のデータと新規レコード が表示されています。 この新規レコードのテキストボックスを表示しない方法はありますか? 2件目以降のデータ(新規レコード)を入力する際は「追加」の コマンドボタンを使用して、その都度、新規レコードを表示させたい のです。 よろしくお願いします。

  • サブフォームが見えなくなる。

    サブフォームが見えなくなる。 Access初心者です。 メインフォームにサブフォームを入れ込んだのですが、メインフォームを新しいレコードに移動すると、サブフォーム自体が出てこなくなります。 データがあるレコードではきちんとサブフォームが出ていることが確認出来ています。 どうしていいのか判らないので教えて下さい。 マクロで入力ボタンを押すとメインのフォームを開き、新しいレコードに移動することをやっていますが、関係あるでしょうか? やりたいことはメインを新しいレコードに移動した時に、サブフォームが表示されて入力できるようにしたいということです。

  • Access2000 フォーム/サブフォームについて

    質問させていただきます。 フォーム/サブフォーム形式で画面を作っています。サブフォームは帳票形式で、複数のレコードを表示しており、各行の左にコマンドボタンを用意し、それをクリックすると、更新クエリー、削除クエリーが動くようにしています。 しかし、更新、削除クエリーとも ”0件のレコード”で処理が正しく動作しません。 ちなみに、両クエリの抽出条件は・・・ [Forms]![メインフォーム]![サブフォーム]![商品コード] しかし、フォームを使わずクエリーから実行する(パラメータに条件を手入力する)と正しく動作します。 記述ミスがないか何度も見返したのですが・・・。 「サブフォームの目的の行の商品コードと一致するデータを処理する」としたいのですが・・・。

  • Access2013 vbaサブフォームのレコード

    [Access2013 vba] ■したいこと サブフォームのレコードの中から、一レコードだけをチェックボックスなどで選択したいのですが、どのようにしたら出来ますでしょうか。 複数行選択は出来ないようにしたいです。 選択したのち、メインフォームの選択ボタンを押すと、そのレコードのID番号を取得して、呼出元のフォームのIDフィールドに代入したいです。 ■画面の流れ・・・ Aフォーム → 帳票型Bフォームで、レコードを選び「開く」ボタンを押す→ B 'メインフォームとCサブフォーム)が開く Cサブフォームのレコードをチェックボックスにチェックを入れて選択する B ' メインフォームの「選択」ボタンを押すと B ' メインフォームと、その前のBフォームが閉じて Aフォームに戻り、AフォームのIDフィールドに選択したIDが格納される。 よろしくお願いします。

  • アクセス2003 - レコード追加について

    同期の代理質問です↓ 新規レコードを入力するフォーム(サブフォームも作成)を作り、コマンドボタンを押すと、サブフォーム(全レコード表示させている)に入力したレコードを追加させる場合、どうしたらいいのでしょうか?   ちなみに、サブフォームに追加されたレコードは、 自動的に昇順に並べ変わるしくみにしたいのですが・・・ 宜しくお願い致します☆

  • 【ACCESS】サブフォームについて

    あるフォームにてサブフォームを作り、そのサブフォームから直接次のレコードに飛ばすようなコマンドボタンを設定したいのですが、そのようなことは可能なのでしょうか?? 宜しくお願いします。 わけが分からない質問だったら、ごめんなさい。

専門家に質問してみよう