• ベストアンサー

Accessで一件の新規レコードのみを登録する方法

OS: win xp Access Version: 2003 フォームを使って新規レコード入力できるように   Private Sub Form_Load() Docmd.GoToRecord,, acNewRec End Sub として、開いています。 ここの際、問題なのですが、ホイールマウスを使っているとデータ入力中に誤ってホイールを回すことにより次の新規レコードに移ってしまいます。 これを制限したいと思います。 この類の過去で検索しましたが、解決に至っていません。 ご意見をください。

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

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

No.8です。 はじめにお詫びです(汗) 「c」を「ややトリッキー」と言いましたが、かなり【控えめ】な表現でした(汗) 「b」でも充分にトリッキーで、「c」はその発展(?)になります。 > テーブルに「1件だけレコードを登録しておく」とは、どのようなことでしょうか。 「b」と「c」の違いは、「新規登録用の編集枠(=予め登録しておくレコード)」を 「作業テーブル」に用意するか、「正規テーブル」に用意するか、になります。 つまり、作業テーブルに予め登録しておくレコードは、「c」で説明したのと同様 のダミーデータです。 仮に、  ・正規テーブルのフィールド構成:    ID / 氏名 / 生年月日 / 性別    (IDが主キーで、氏名に値要求あり)  ・作業テーブルのフィールド構成:    氏名 / 生年月日 / 性別    (IDは正規テーブルへの登録時に設定すればいいので、ここには不要) という形だった場合、作業テーブルには   "(入力必須)" / Null / Null というレコードを1件登録しておきます。 これで、メインフォームを開いたときには、このレコード1件のみが表示される ようになるので、実際の入力時には、ユーザーにはこのレコードを上書きして もらい、『登録』ボタンを押した時(又はフォームを閉じた時)に、正規テーブル に転記するとともに、上記レコードは元の値("(入力必須)"/Null/Null)に書き 戻す、という処理を行います。 (この「元の値に書き戻す」という処理は、フォームを開く際にも行うようにして  おくと、何らかのエラーでAccessが落ちた場合に「前回入力中だったものが  表示された」といった事態を防げます) ※正規テーブルへの転記を、フォームを閉じる時に行う場合は、明示的に   レコードの保存を行ってから、としておいた方が無難です。 なお、前回回答時は、データベースが「フロントエンド/バックエンド」の構成 (バックエンド側に正規テーブルのみを設置。フロントエンドはそのテーブルに 対するリンクテーブルと作業テーブル、フォームなどを設置)で、フロントエンド は各ユーザーの端末、バックエンドはLAN上などで共有、との先入観(汗)から 「1レコード」としましたが、「フロントエンド/バックエンド」に分割せずに、複数 のユーザーが同時に新規登録をしうる運用をしている場合は、ユーザーの 数だけレコードを用意すると共に、それぞれの端末用であることを特定する ためのフィールドを作業テーブルに追加する必要がありましたので、注意して ください(汗) ※フロントエンド/バックエンドに分割済みで、作業テーブルを端末側(ローカル)   に設置している場合は、ユーザー間の競合はないので、1レコードでOk。   (1つの端末内で新規レコードを同時登録しない前提:普通はしないはず) 例えば、ユーザーが3人(鈴木/佐藤/田中)がいた場合は、作業テーブルの フィールド構成を    氏名 / 生年月日 / 性別 / ユーザー名 とした上で、   "(入力必須)" / Null / Null / "鈴木"   "(入力必須)" / Null / Null / "佐藤"   "(入力必須)" / Null / Null / "田中" の3レコードを保存しておき、それぞれの端末ではユーザー名の合致するもの 1件を作業用として使用する、ということになります。 (1件を抽出するクエリを作成して、メインフォームのレコードソースにはこのクエリ  を指定、と) ※端末の情報を取得するには、Environ関数が使用できます:  http://office.microsoft.com/ja-jp/access-help/HA001228831.aspx  http://www.moug.net/tech/exvba/0150086.html (「Environ("UserName")」により、Windowsの『システムのプロパティ』の  『使用者』の名前が取得できます) ・・・なのですが、改めて手元のAccess2007のクエリでこの関数を使用して みたら「未定義の関数」とのエラーが出ましたので(汗)、以下のユーザー定義 関数を用意しておき、クエリの抽出条件ではこちらを使用して下さい。 (VBA上では、Environ関数をそのまま使用できます) Public Function ExEnviron(Parameter As Variant) As Variant ExEnviron = Environ(Parameter) End Function ・・・以上です。 長文、失礼致しました(汗)

その他の回答 (8)

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

横レス失礼致します。 > 1項目入力後、次の新規ページができます。  (中略) > これを防ぎたいと考えています。 フォームの『追加の許可』(AllowAdditions)プロパティが「はい」(True)になっている 限り、新規追加を行うと、新たに新規レコードが生成されてしまうため、ご希望の 動作にはなりません。 表示レコードを1件に限定してよい(=レコード移動をしない)前提であれば、以下の 3つの代替案が提示できます: a)メインフォームを非連結(=『レコードソース』(RecordSource)プロパティが空白の  フォーム)にした上で、クエリ(又はSQL)を使用して、テーブルにレコードを登録する  (各コントロールの『コントロールソース』プロパティも空白にする必要があります) b)新規登録専用の作業テーブルを別途作成して1件だけレコードを登録しておき、  メインフォームのレコードソースとするとともに、フォームの『追加の許可』プロパティ  を「いいえ」に設定することで、メインフォームの表示を1レコードに限定する  (「a」案と同様に、正規のテーブルへの登録はクエリ(又はSQL)を使用) c)現在のテーブルに「新規登録用」のレコードを予め用意しておき、メインフォーム  ではこのレコードのみを表示します(→「b」と同様に『追加の許可』プロパティを  「いいえ」にした上で、このレコードのみを抽出するクエリを新規作成し、フォーム  の『レコードソース』プロパティに使用)。  レコード確定時には、このレコードの主キーをクエリ(又はSQL)で書き換えると  ともに、改めて「新規登録用」のレコードを追加。  (メインフォームのテーブルとサブフォームのテーブルとの間のリレーションシップに   『参照整合性』が設定されている場合は、「連鎖更新」も許可する必要あり) 「a」の場合、メインフォームはレコードを表示しているわけではなくなるので、マウス ホイールでのレコード移動は、原理的に発生しなくなります。 これは、1レコードのみの追加・編集を行う場合に一般的と思われる手法ですが、 入力規則や値要求がフィールドに設定されている場合、そのチェックを行うコードが 必要(=入力規則等の変更に合わせてメンテが必要)なのが、やや面倒です(汗)。 「b」と「c」の場合は、どちらも表示レコードが1件のみ(本当の新規レコードは表示 されない)となるので、マウスホイールを回した場合の移動先がなくなります。 この方法の利点は、「a」と違って連結フォームのため、テーブルに設定されている 現状と同様に、入力規則などはテーブルからフォームに引き継がれることです。 なお、メインフォームのテーブルとサブフォームのテーブルの間にリレーションシップを 設定していて、『参照整合性』を持たせている場合、「a」「b」ではサブフォームに レコードを追加する前に、クエリ(SQL)による転記(保存)を実行する必要があります。 (専用のコマンドボタンを設置してもいいですし、ユーザーに意識させないという意味  ではサブフォームコントロールのフォーカス取得時イベントでやってしまう手もあります:  DoCmd.OpenQueryでやる場合、クエリ実行時の確認メッセージを非表示にする  には、「DoCmd.SetWarnings False」を実行します(クエリ実行後に「~ True」を  実行する必要あり)。なお、DoCmd.RunSQLを使用すればDoCmd.SetWarnings  は実行不要です) ・・・「c」は、ややトリッキーなので(汗)、若干追加説明しておきます。 仮に、現在のメインフォームのレコードソースにしているテーブルの主キーが「ID」で、 その最小値が「1」だったとします。 ここに、「新規追加用」としてIDが「0」のレコードを追加します。 そして、このレコードのみを抽出するクエリを新規作成して、メインフォームのレコード ソースとします。 そして、上記の通り、フォームの『追加の許可』を「いいえ」とします。 これで、メインフォームが表示するのは「ID=0」のレコード1件となります。 ユーザーは、このレコードに、新規で追加するはずのデータを上書きします。 (サブフォームでも一時的に「ID=0」で登録するため、「a」「b」のようにメインフォーム分  だけで一旦保存する必要はなくなります) その上で、全ての入力が終わったら、ユーザーには『保存』ボタンを押してもらいます。 このボタンには、  ・「ID」を、本来の値(=例えば「現在のIDの最大値」+1)で上書きする更新クエリ   (メインフォーム/サブフォームとも)  ・「ID=0」のレコードを改めて追加する追加クエリ を実行するコードを記述しておきます。 (メイン/サブの間のリレーションシップで参照整合性を設定している場合は、「連鎖  更新」も有効にしてやれば、メイン側のIDの更新と同時に、サブ側も更新されます) また、『取り消し』ボタンも設定しておき、  ・「ID」以外のフィールドをすべてNullにする更新クエリ を実行するコードを記述します。 (主キー以外に『値要求』が「はい」に設定されたフィールドがある場合は、「ここは  値必須」などをデフォルト値として設定するといった工夫が必要) 更に、フォームの読み込み解除時イベントでも、このレコードの保存/破棄を確認・ 実行するコードを記述します。 ・・・概略だけにもかかわらず長くなりましたが(汗)、以上です。 どれにするにしてもかなり手間が掛かりますので、参考までにということで・・・(汗)

kapatool
質問者

お礼

ありがとうございます。現状からB案を考えています。 「new_data」という入力専用テーブルのレコードソースとしています。 フォーム終了時にクエリにて、他のテーブルへ追加登録できるような 設計です。 B案 では、フォームの『追加の許可』プロパティ  を「いいえ」にするようになっていますが、これによって、フォームは は表示されなくなります。(コマンドボタン、ラベルのみ) テーブルに「1件だけレコードを登録しておく」とは、どのようなことでしょうか。 よろしくおねがいします。

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

#4です 遅くなりましたが、解決されていたでしょうか。 > ただ、フォーム内のサブフォームにフォーカスを移動することが出来ません。 サブフォームがあったんですか・・・ サブフォームがある場合、メインのレコードを確定させてからサブに移動しようとします。 サブからメインの場合も、サブを確定させてからメインに・・・ 厄介なものになりますが・・・以下、メインの「タイマ時」を使う方法となります。 マウスのホイールをいじってから更新前処理が動くのを利用します。 ホイールをいじった時、編集中であったら、 ・更新前処理で Cancel = True を設定する為の変数 bCancel を True とします。 ・bCancel が True の間はレコードがスクロールすることはなくなります。 ・この bCancel を False にするために「タイマ時」を利用します。 以下例では、20 ms を 5回まわったら False にしています。 ホイールのイベントと、タイマ時のイベントがどのタイミングで発生するか・・・ 詳細に検証したわけではないので、5回まわる途中でホイールのイベントが発生しても、その段階からさらに5回まわるようになります。 20 ms * 5 = 100 ms になりますが、100 ms を超えると思います。 (あくまでこの数値は目安です) ・時間が経過し bCancel が False になると、サブフォームに移ることが出来るようになります。  その際には、前述したようにメインのレコードは確定されます。 ※ レコードをいじっていない状態でホイールをいじると、レコードはスクロールされます。 以下がメインに記述する例になります。 Dim bCancel As Boolean Dim iCnt As Integer Private Sub Form_Timer()   iCnt = iCnt - 1   If (iCnt <= 0) Then     Me.TimerInterval = 0     bCancel = False   End If End Sub Private Sub Form_MouseWheel(ByVal Page As Boolean, ByVal Count As Long)   If (Me.Dirty) Then     bCancel = True     iCnt = 5     Me.TimerInterval = 20   End If End Sub Private Sub Form_Load()   bCancel = False End Sub Private Sub Form_BeforeUpdate(Cancel As Integer)   Cancel = bCancel End Sub ※ 上記は動きを説明する部分しか記述していません。  (Docmd.GoToRecord 等は追加してください) ※ 以下も参考になると思います。 MouseWheel イベントの使い道 http://www.f3.dion.ne.jp/~element/msaccess/AcTipsFrmMouseWheelEvent.html

  • chayamati
  • ベストアンサー率41% (254/607)
回答No.6

一項目にデータを入れた瞬間、下に新規ページが作成されます。 失礼しました。 これは新規レコードを入力するためで、 新規にレコードが作成されたのではありません。 テーブルを開いて直接入力しても同じではありませんか

kapatool
質問者

お礼

何度ありがとうございます。 1項目入力後、次の新規ページができます。 マウススクロールで次ページに移動が可能となり、 入力することで、2つのレコードとなります。 その後、3、4・・・・ページとなっていきますね。 これを防ぎたいと考えています。 よろしくお願いします。

  • chayamati
  • ベストアンサー率41% (254/607)
回答No.5

お礼 ありがとうございます。 結果的には、ダメです。 一項目にデータを入れた瞬間、下に新規ページが作成されます。 なにかいい方法がないでしょうか。 -------------------------------------------------------------------------- テキストボックスの 全てのタブストップ(その他タグ内)が「いいえ」になっていると [Enter]で新規レコードになります。 尚、タブストップが「はい」になっていると[Enter]でタブ移動順にカーソルが移動し、 最後の移動順のボックスで[Enter]により新規レコードになります。

kapatool
質問者

お礼

ありがとうございます。 すべて タブストップが「はい」 になっています。

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

以下が参考になると思います。 マウスホイールでレコード移動しないようにする http://hatenachips.blog34.fc2.com/blog-entry-162.html なお、フォームが新規入力専用なのであれば、 フォームのプロパティ「データ入力用」を「はい」としておけば、 Form_Load での記述はいらないと思います。 さらに、常に新規入力だけにしたい場合には、更新後処理で Private Sub Form_AfterUpdate()   Me.Requery End Sub のようにすると、連続して入力した場合でも、前に戻ることはできなくなります。 更新後処理でなくても、「登録ボタン」の処理で Me.Requery すれば良いと思います。

kapatool
質問者

お礼

ありがとうございます。 Form_Load  には、表示サイズ、位置も指定するようにしているため、 ついでに Docmd.GoToRecord,, acNewRec も記載して運用しています。 Private Sub Form_AfterUpdate()   Me.Requery End Sub   では元に戻れませんね。 連続入力することはありませんので、一回(1件)だけの入力と 考えていただけませんでしょうか。 よろしくお願いします。 マウススクロールで移動させないモジュールは一度試してみます。

kapatool
質問者

補足

マウスホイールを無効 Private Sub Form_BeforUpdate(cancel As Integer) cancel = True End sub で確かに、マウスホイールが無効になりました。 ただ、フォーム内のサブフォームにフォーカスを移動することが出来ません。 初心者ですので対応を教授ください。 お願いします

  • chayamati
  • ベストアンサー率41% (254/607)
回答No.3

テーブルのプロパティーを変更出来なければ フォームで新規レコードとせずに最後のレコードではダメですか  Private Sub Form_Load()   Docmd.GoToRecord,, acLast  End Sub

kapatool
質問者

お礼

ありがとうございます。 結果的には、ダメです。 一項目にデータを入れた瞬間、下に新規ページが作成されます。 なにかいい方法がないでしょうか。 宜しくお願いします。

  • chayamati
  • ベストアンサー率41% (254/607)
回答No.2

フォームではなくテーブルです。 フィールドの値要求を「はい」にするには テーブルを右クリックしてデザインビューで開き 添付のように [フィールドの一つ(生徒名)]→[値要求の右端]→[はい] と進みます。

kapatool
質問者

お礼

ありがとうございます。 テーブルで項目のプロパティで、値要求を「はい」または空文字列の許可を「いいえ」にしてみました。確かに有効ですが。 しかし、全て項目が必ずしも値が必要なく、場合によっては空白でいいのです。 したがって、この設定では運用上このましくありません。 他の案がありましたら宜しくお願いします。

  • chayamati
  • ベストアンサー率41% (254/607)
回答No.1

テーブルのデザインビューで フィールドの一つの値要求を「はい」または空文字列の許可を「いいえ」にします。

kapatool
質問者

お礼

ありがとうございます。 データに関して、値要求を「はい」または空文字列の許可を「いいえ」を適用することができません。また、サブフォームも組み込まれていますので、動作に不具合が生じます。

関連するQ&A

  • アクセス enterで次ページ(レコード)移動

    アクセスでformを使い最後の入力”失効有無”が終わったら次のレコードにenter keyで 移動したいのですがうまくいきません。 プロパティの更新後処理 イベントプロシージャのところに下記を書いています。 Private Sub 失効有無_AfterUpdate() DoCmd.GoToRecord , , acNewRec DoCmd.GoToControl "ID" End Sub 以前はこれでうまくいったと思います。。。 おかしいですか? よろしくお願いします、

  • サブフォームの新規レコードに移動したい アクセス

    親フォームのコマンドボタンをクリックしたら 親フォームにはまっているサブフォームの新規レコードに移動したいのですが、 うまくできません。 サブフォームのオブジェクト名は、"F_SubForm"です。 サブフォームはデータシートビューです。 VBAコードは Private Sub cmd_test_Click() DoCmd.SelectObject acForm, "F_SubForm" DoCmd.GoToRecord , , acNewRec End Sub です。 上記コードを実行すると DoCmd.SelectObject acForm, "F_SubForm" の部分で、 「実行時エラー 2489  オブジェクトが開いていません。」 となります。 だからと言って、 DoCmd.GoToRecord , , acNewRec だと、何も起こりません。(新規レコードに移動しません) 解決方法をご教授ください。

  • レコード移動について

    単票フォームで何件かレコードがあります。 それを DoCmd.GoToRecord , , acNext で1つずつ移動させ、今何番目のデータなのか?をメッセージで出し、 最後のレコードになったら「最後のレーコード」というメッセージの後に Exit Sub させたいのですが... F8 で1つ1つコンパイルさせるとできるのですが、 データベース画面から直接フォームをDBCLして開こうとすると いきなり「最後のレコード」になってしまいます。 記述のが悪いのでしょうか?それともフォーム自体が悪いのでしょうか? 教えてください Private Sub Form_Current() If Me.CurrentRecord >= Me.RecordsetClone.RecordCount Then MsgBox "最後のレコード" Exit Sub Else MsgBox "途中のレコード" DoCmd.GoToRecord , , acNext   End If End Sub

  • Accessレコードの削除(VBA)

    Accessで入力フォームを使用して入力をしていますが、 全項目の入力がされていない場合そのレコードを削除したいのです。 閉じるときに消そうと思い DoCmd.RunCommand acCmdDeleteRecord を入れてみたのですが、レコードの削除はできません、とメッセージが出てしまい消せません。 次のレコードを選択すれば消せるかと思い DoCmd.GoToRecord , , acNewRec を足してみたりしてみたのですが、やっぱりダメでした。 この場合はどのようにすればいいのでしょうか?

  • 新規レコードへ移動しない

    Access2010を使用しています。 サブフォームからメインフォームの「登録」ボタンプロシージャをCallした時、メイン・サブフォーム共に新規レコードへ移動しなくて困っています。 具体的には、サブフォームにフォーカスがある時に「F12」を押すと画面の入力項目の内容刃そのままでメインフォームの「注文番号」テキストボックスにフォーカスが移動します。 メインフォームにフォーカスがあるか、マウスで「F12」をクリックすると画面の入力項目がクリアされて新規レコードへ移動します。 コードは以下の内容が記述してあります。 ーーーーーサブフォーム----- Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case 123 Call Me.Parent.Form_KeyDown(KeyCode, Shift) KeyCode = 0 End Select End Sub -----メインフォーム----- Public Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case 123 Call 登録_Click KeyCode = 0 End Select End Sub Private Sub 登録_Click() DoCmd.GoToRecord , , acNewRec Me.注文番号.SetFocus End Sub

  • アクセスフォームのサイズの調整について

    一つは全画面表示(Maximize)で開きもう一つは普通の表示(Restore)で開くには? フォーム1とフォーム2があります。画像をご覧ください。 フォーム1は Private Sub Form_Load() DoCmd.Maximize End Sub で、 フォーム2は Private Sub Form_Load() DoCmd.Restore End Sub としてます。 フォーム1にコマンドボタンを設置して、 Private Sub フォーム2を開く_Click() DoCmd.OpenForm "フォーム2" End Sub として、フォーム2を開くのですが、 フォーム2が開くとフォーム1まで、元の大きさに戻ってしまいます。 行いたいことは、 フォーム1は全画面表示、フォーム2は、ノーマルな表示(全画面でも最小化でもない) にしたいのですが、不可能なのでしょうか?

  • サブサブフォームのレコード移動方法

     いつもお世話になっております。サブサブフォームのニューレコードに移動するボタンを作成しようとしているのですが、サブフォームは移動できるのですが、サブサブフォームを移動させることができません。 Me.sub1.Form.sub2.Form.コンボボックス名.SetFocus DoCmd.GoToRecord , , acNewRec で記述してみたのですが反応がありませんでした。指定方法が間違っているのでしょうか?よろしくお願いします。

  • Access レコード移動時イベントでサブフォーム

    お世話になります。 親フォーム Aがあります。(データソースが存在します) その中にサブフォームBがあります。(データソースが存在します) 親フォームのレコード移動時のイベントで、いつもサブフォームのレコードの最後を表示したいのです。そこで・・・ 親フォームAの レコード移動時イベントに Private Sub Form_Current() Me.B.SetFocus DoCmd.GoToRecord , , acLast End Sub 上記を記述すると、一番初めはきちんとサブフォームBのレコードは最後を表示するのですが、以後、親フォームのレコードを動かすと、親フォームの最後のレコードをさしっぱなしになってしまいます。 Me.B.SetFocus DoCmd.GoToRecord , , acLast これの後にどんな記述をすれば、親フォームのレコードを動かすと同時にサブフォームBも最後の行に移るようにできますでしょうか? 何卒よろしくお願いいたします。

  • access の 最終レコードの判定はどう記述しますか

    月間スケジュールテーブルを新規生成するルーチンです 月初~月末まで各日にちの曜日を[曜日TMP]に求めてこのルーチンに入ります ("マスタFORM"には週間計画のテーブルのフィールドを設定したフォームです。 (週間計画:月曜日の○○時~◎◎時に○○の作業) Private Sub 分析RTN() DoCmd.GoToRecord acForm, "マスタFORM", acFirst Do While Not EOF(1) ‘ここでエラーが発生します If 曜日No. = 曜日TMP Then 追加RTN ’レコードの追加ルーチンです End If DoCmd.GoToRecord acDataForm, "マスタFORM", acNext Loop End Sub 他にお気づきの点はご指導ください

  • Access 最後のレコードに到達するまでループ処理を行う方法

    いつもお世話になっております。 フォームでボタンをクリックすると、 計上年度と計上月をすべてのレコードに入力させようとしています。 下記のように、For~Nextで書いてみたのですが、 選択されているレコードが、一番最初のレコードではない場合、 エラーが返ってしまいます。 おそらく「レコードの数分繰り返す」という書き方のせいだと思います。 これを「最後のレコードに到達するまで」としたいのですが、 どのように書いたらよいでしょう?? ご存知の方がいらっしゃいましたら、教えてください。 Private Sub 計上年度月入力_Click() Dim Max As Integer Dim i As Integer Max = DCount("[計上月]", "年次請求集計Q") For i = 1 To Max If 計上月 <> 0 Then DoCmd.GoToRecord , , acNext Else 計上年度2 = 計上年度1 計上月2 = 計上月1 DoCmd.GoToRecord , , acNext End If Next i End Sub

専門家に質問してみよう