- ベストアンサー
(ACCESS)連番取得について
アクセスで顧客管理をしています。 DMax関数を用いて、レコードを追加する度に自動で連番を振る設定に したいと思っていますが、上手くいかないため質問させてください。 【テーブル名】T_顧客一覧 【入力用のフォーム名】F_顧客登録 【連番を入力させたい項目(フィールド名)】No(テーブルでは主キーに設定) とし、フォームの”No”の既定値に =DMax("No","T_顧客一覧")+1 と入力するのですが、フォームには1としか表示されません。 非常に初歩的な質問だとは思うのですが、 何か原因として考えられることがありますでしょうか? 情報が足りないようでしたら補足させていただきます。 よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
追記。 一番小さい「空き番号」から埋めて行く方法を書いておきます。 フォームのテキストボックス「No」の「フォーカス取得時」のイベントプローシジャに、以下のコードを追加して下さい。 Private Sub No_Enter() Dim db As Database Dim rs As Recordset Dim i As Integer If Me.NewRecord Then Set db = CurrentDb Set rs = db.OpenRecordset("SELECT T_顧客一覧.[No] FROM T_顧客一覧 ORDER BY T_顧客一覧.[No];") rs.MoveFirst i = 1 Do Until rs.EOF If rs.Fields(0) <> i Then Exit Do End If i = i + 1 rs.MoveNext Loop [No] = i rs.Close db.Close Set rs = Nothing Set db = Nothing End If End Sub これは「頭から1、2、3…になってるか見ていって、抜けてる番号があったら、その番号をテキストボックスにセットする」と言う事をしています。 テーブル、レコードにはセットせず、テキストボックスにセットするだけなので「ユーザーが手入力した場合と同じ動作」をする為、ユーザーがフォーム上で「ESCキーを押す」などすれば、セットした値は無効になり、レコードの追加をキャンセル出来ます。
その他の回答 (4)
補足: 出来ればオートナンバーではなく採番方式を! 私は、採番方式は、[DMax]->[DBMax]->[採番方式]と進化すると思います。 ・テーブルが破損した場合の対策が容易です。 ・なんと言っても高速処理が実現できます。 [id管理表] id_name_____final_value 顧客一覧_ID___________0 Private Sub Form_BeforeInsert(Cancel As Integer) If Nz(Me.ID) = 0 Then Me.ID = NewID("ID", "顧客一覧_ID") End If End Sub これですと、[final_value]を更新するだけですので超高速で処理できます。 なお、欠番対策なんて意味ないですから、それは考えられないことです。
お礼
ご回答ありがとうございます。 勉強不足のため理解するのに時間がかかってしまいました。 参考にさせていただきます! ありがとうございました。
- chie65536
- ベストアンサー率41% (2512/6032)
>オートナンバーはレコードを削除した場合などに欠番が発生すると聞いたので、出来ればそれ以外の方法で設定したいと思っています。 最大値を求める関数を使用しても、欠番が出るのは同じです。 だって「1、3、4、5、6、7、9、10」の「最大値+1」は「11」ですから。でも、貴方の欲しいのは11でなく「2」でしょう? だったら「オートナンバーにしても、結果は同じ」ですよ。 問題なのは「規定値をどうするか?」ではなく「欠番が出た場合に、どう欠番を埋めるか?」であって、貴方は見当違いな事をしてます。 だって「欠番を埋める方法」は「オートナンバーでも、貴方のやりたい方式でも、方法は同じ」なんですから。 「方法が同じ」なら「楽な方法を使う」のが「賢い方法」ですよ。
DMax()ではなく 次の DBMax()を使えば試み自体は成功するでしょう。 Public Function DBMax(ByVal strField As String, _ ByVal strTable As String, _ Optional strWhere As String = "", _ Optional ReturnValue = 0) As Variant On Error GoTo Err_DBMax Dim N Dim strQuerySQL As String Dim rst As ADODB.Recordset Set rst = New ADODB.Recordset strQuerySQL = "SELECT MAX(" & strField & ") FROM " & strTable If Len(strWhere) > 0 Then strQuerySQL = strQuerySQL & " WHERE " & strWhere End If With rst .Open strQuerySQL, _ CurrentProject.Connection, _ adOpenStatic, _ adLockReadOnly If Not .BOF Then .MoveFirst N = Nz(.Fields(0), "") End If End With Exit_DBMax: On Error Resume Next rst.Close Set rst = Nothing DBMax = IIf(N <> "", N, ReturnValue) Exit Function Err_DBMax: MsgBox "SELECT 文の実行時にエラーが発生しました。(DBMax)" & Chr$(13) & Chr$(13) & _ "・Err.Description=" & Err.Description & Chr$(13) & _ "・SQL Text=" & strQuerySQL, _ vbExclamation, " 関数エラーメッセージ" Resume Exit_DBMax End Function もちろん、 DBMax = IIf(N <> "", N, ReturnValue) と同じヌル対策をすれば DMax()でもOKです。 が、DMax()は実行速度がえらく遅いのでお勧めではありません。 なお、既定値を0にしておいて何かデータが入力されたら主キー値を更新するという手法もあります。 (主キーの列名は予約語と重複しない'ID'にしています) Private Sub Form_BeforeInsert(Cancel As Integer) If Nz(Me.ID) = 0 Then Me.ID = DBMax("ID", "顧客一覧") + 1 End If End Sub
- naminami01
- ベストアンサー率0% (0/1)
オートナンバー型で管理するのではだめなのですか?
補足
はい。オートナンバーはレコードを削除した場合などに欠番が発生すると聞いたので、出来ればそれ以外の方法で設定したいと思っています。
お礼
ご回答ありがとうございます。 追記いただいた方法で満足のいく結果が得られました! おまけに、今まで手入力していたデータのミスも見つかり 非常に助かりました。 勉強不足で恥ずかしい限りです。 どうもありがとうございました。