プロが教える店舗&オフィスのセキュリティ対策術

OS: win xp
Access Version: 2003


フォームを使って新規レコード入力できるように 

 Private Sub Form_Load()
Docmd.GoToRecord,, acNewRec
End Sub

として、開いています。

ここの際、問題なのですが、ホイールマウスを使っているとデータ入力中に誤ってホイールを回すことにより次の新規レコードに移ってしまいます。
これを制限したいと思います。
この類の過去で検索しましたが、解決に至っていません。

ご意見をください。

A 回答 (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/HA …
 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


・・・以上です。
長文、失礼致しました(汗)
    • good
    • 0

横レス失礼致します。



> 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にする更新クエリ
を実行するコードを記述します。
(主キー以外に『値要求』が「はい」に設定されたフィールドがある場合は、「ここは
 値必須」などをデフォルト値として設定するといった工夫が必要)

更に、フォームの読み込み解除時イベントでも、このレコードの保存/破棄を確認・
実行するコードを記述します。


・・・概略だけにもかかわらず長くなりましたが(汗)、以上です。
どれにするにしてもかなり手間が掛かりますので、参考までにということで・・・(汗)
「Accessで一件の新規レコードのみを登」の回答画像8
    • good
    • 0
この回答へのお礼

ありがとうございます。現状からB案を考えています。

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

テーブルに「1件だけレコードを登録しておく」とは、どのようなことでしょうか。
よろしくおねがいします。

お礼日時:2012/12/03 12:01

#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/AcTip …
    • good
    • 0

一項目にデータを入れた瞬間、下に新規ページが作成されます。



失礼しました。
これは新規レコードを入力するためで、
新規にレコードが作成されたのではありません。
テーブルを開いて直接入力しても同じではありませんか
    • good
    • 0
この回答へのお礼

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

よろしくお願いします。

お礼日時:2012/11/30 11:15

お礼



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

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

お礼日時:2012/11/29 17:29

以下が参考になると思います。



マウスホイールでレコード移動しないようにする
http://hatenachips.blog34.fc2.com/blog-entry-162 …


なお、フォームが新規入力専用なのであれば、
フォームのプロパティ「データ入力用」を「はい」としておけば、
Form_Load での記述はいらないと思います。
さらに、常に新規入力だけにしたい場合には、更新後処理で

Private Sub Form_AfterUpdate()
  Me.Requery
End Sub

のようにすると、連続して入力した場合でも、前に戻ることはできなくなります。
更新後処理でなくても、「登録ボタン」の処理で Me.Requery すれば良いと思います。

この回答への補足

マウスホイールを無効

Private Sub Form_BeforUpdate(cancel As Integer)
cancel = True
End sub

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

補足日時:2012/11/30 11:19
    • good
    • 0
この回答へのお礼

ありがとうございます。

Form_Load  には、表示サイズ、位置も指定するようにしているため、
ついでに Docmd.GoToRecord,, acNewRec
も記載して運用しています。

Private Sub Form_AfterUpdate()
  Me.Requery
End Sub   では元に戻れませんね。

連続入力することはありませんので、一回(1件)だけの入力と
考えていただけませんでしょうか。
よろしくお願いします。

マウススクロールで移動させないモジュールは一度試してみます。

お礼日時:2012/11/29 16:44

テーブルのプロパティーを変更出来なければ



フォームで新規レコードとせずに最後のレコードではダメですか

 Private Sub Form_Load()
  Docmd.GoToRecord,, acLast
 End Sub
    • good
    • 0
この回答へのお礼

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

お礼日時:2012/11/29 14:36

フォームではなくテーブルです。



フィールドの値要求を「はい」にするには

テーブルを右クリックしてデザインビューで開き
添付のように
[フィールドの一つ(生徒名)]→[値要求の右端]→[はい]
と進みます。
「Accessで一件の新規レコードのみを登」の回答画像2
    • good
    • 0
この回答へのお礼

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

お礼日時:2012/11/29 14:40

テーブルのデザインビューで


フィールドの一つの値要求を「はい」または空文字列の許可を「いいえ」にします。
    • good
    • 0
この回答へのお礼

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

お礼日時:2012/11/29 11:34

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

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A