アクセスのMoveLastの使い方について

このQ&Aのポイント
  • アクセスでリストを登録するツールを作成しています。
  • フォームを開く際に、IDのフォームに自動的にID番号を採番したいです。
  • しかし、4番目のデータを登録する際にIDが表示されません。原因を教えてください。
回答を見る
  • ベストアンサー

アクセスのMoveLastの使い方について

初めてアクセスでツールを作っています。 リストを登録するツールを作っており、フォームに入れた情報を 「テーブル」に登録する仕様となっております。 フォームを開く際、自動的にIDのフォームにID番号を採番したいです。 ID番号はリストを登録する「テーブル」を参照し、既存のレコードの最後の行を検索し 最後の行に+1をした番号を振るようにしました。 下記のようにプログラムを組み、最初のID:1、2、3まではフォームを開いた際に自動的に採番できました。 ところが次の4番目のデータを登録する際にフォームを開くと 何故かIDは3のまま表示されてしまいます。 デバックしたところ、Debug.Print rs!ID の箇所は何故か数字が2が入っております。 MoveLast でレコード末尾を参照しようとしているのですが、 何故か末尾であるはずの3にはなりません。 アクセスでこのようなツールを作るのは初めてになるため、原因がわかる方お願い致します。 Private Sub Form_Load() 'フォーム読み込み時にID番号を付与 Dim rs As New ADODB.Recordset Me.ID.Value = Null rs.Open "テーブル", CurrentProject.Connection If rs.EOF = True Then Me.ID.Value = 1 Else rs.MoveLast Debug.Print rs!ID Me.ID.Value = rs!ID.Value + 1 End If rs.Close End Sub

noname#217863
noname#217863

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

  • ベストアンサー
回答No.1

1、一般的な採番手法。 私は、テーブル「主キー管理表」や「id管理表」等を用意して管理するんだろうと認識しています。 Public Function NewID(ByVal strIDName As String) As Long On Error GoTo Err_NewID   Dim N   As Long   Dim strSQL As String   Dim cnn  As ADODB.Connection   Dim rst  As ADODB.Recordset      Set cnn = CurrentProject.Connection   Set rst = New ADODB.Recordset   strSQL = "SELECT final_value FROM id管理表 WHERE id_name='" & strIDName & "'"   cnn.Errors.Clear   cnn.BeginTrans   With rst     .Open strSQL, _        cnn, _        adOpenDynamic, _        adLockOptimistic     If Not .BOF Then       N = .Fields(0) + 1       .Fields(0) = N       .Update     End If   End With   cnn.CommitTrans Exit_NewID: On Error Resume Next   rst.Close   cnn.Close   Set rst = Nothing   Set cnn = Nothing   NewID = N   Exit Function Err_NewID:   N = -1   If cnn.Errors.Count > 0 Then     ErrMessage cnn.Errors(0), strSQL     cnn.RollbackTrans   Else     MsgBox "プログラムエラーが発生しました。システム管理者に報告して下さい。(NewID)", _         vbExclamation, " 関数エラーメッセージ"   End If   Resume Exit_NewID End Function 2、安直な採番手法。 それは、テーブルの最後のレコードの列[id]の値ではなく最大値を求める手法。もちろん、列[id]で逆順に ORDER BY して先頭のレコードを参照する手もあります。しかし、安直な普通のやり方は最大値を求める手法です。 Public Function DBLookup(ByVal strQuerySQL As String, _              Optional ByVal ReturnValue = Null) As Variant On Error GoTo Err_DBLookup   Dim DataValue   Dim rst     As ADODB.Recordset   Set rst = New ADODB.Recordset   With rst     .Open strQuerySQL, _        CurrentProject.Connection, _        adOpenStatic, _        adLockReadOnly     If Not .BOF Then       .MoveFirst       DataValue = .Fields(0)     End If   End With Exit_DBLookup: On Error Resume Next   rst.Close   Set rst = Nothing   DBLookup = IIf(Len(DataValue & ""), DataValue, ReturnValue)   Exit Function Err_DBLookup:   MsgBox "SELECT 文の実行時にエラーが発生しました。(DBLookup)" & Chr$(13) & Chr$(13) & _       "・Err.Description=" & Err.Description & Chr$(13) & _       "・SQL Text=" & strQuerySQL, _       vbExclamation, " 関数エラーメッセージ"   Resume Exit_DBLookup End Function (注意)テーブルの並びは、必ずしも登録順、あるいは主キー昇順ではない。その状況は、変化する。 ***********************  PS、主キーの追加、参照とCnnExecute() *********************** ? CnnExecute("INSERT INTO id管理表 VALUES ('Test2', 2);") True ? DBLookup("final_value", "id管理表", "id_name='Test2'") 2 ? CnnExecute("INSERT INTO id管理表 (id_name, final_value) VALUES ('Test3', 3);") True ? DBLookup("final_value", "id管理表", "id_name='Test3'") 3 ? CnnExecute("DELETE FROM id管理表 WHERE id_name='Test2';") True ? DBLookup("final_value", "id管理表", "id_name='Test2'") NULL ? CnnExecute("DELETE FROM id管理表 WHERE final_value=3;") True ? DBLookup("final_value", "id管理表", "id_name='Test3'") NULL このように私はSQL文を実行する関数(CnnExecute、)でもって主キーの参照、追加を行っていました。 Public Function CnnExecute(ByVal strSQL As String) As Boolean On Error Goto Err_CnnExecute   Dim isOK As Boolean   Dim cnn As ADODB.Connection      isOK = True   Set cnn = CurrentProject.Connection   With cnn     .Errors.Clear     .BeginTrans     .Execute strSQL     .CommitTrans   End With Exit_CnnExecute: On Error Resume Next   cnn.close   Set cnn = Nothing   CnnExecute = isOK   Exit Function Err_CnnExecute:   isOK = False   If cnn.Errors.Count > 0 Then     ErrMessage cnn.Errors(0), strSQL     cnn.Rollbacktrans   Else     MsgBox "プログラムエラーが発生しました。" & _         "システム管理者に報告して下さい。(CnnExecute)", _         vbExclamation, " 関数エラーメッセージ"   End If   Resume Exit_CnnExecute End Function

関連するQ&A

  • 自前採番処理について

    Access2013で、自前で採番処理をスル場合 以下のどちらが正しいでしょうか? 1) フォームの保存ボタンで、採番管理テーブルを参照して、現在の主キーのID番号を取得して、それに+1したものを採番管理テーブルに保存し、エラーがなければ、画面にセットして保存。 2) フォームのレコードソースのID番号の最大値を取得して、それに+1加算したものを採番管理テーブルに保存し、エラーがなければ、画面にセットし保存。 1) 2)どちらも、採番管理テーブルに+1した番号を保存する時にエラーが起きたら、画面は Me.Undoする。 よろしくお願いします。

  • Accessでメイン、サブフォームへの入力について

    accessほぼ初心者です。 取引先の会社情報を管理するために、access2007で顧客管理を作成しています。現在、取引先本社情報とその支店情報を登録するフォーム「会社登録フォーム」を作成していますが、次のようなことで困っています。 <問題としていること>: 「サブフォーム」をクリックした瞬間に、テーブルにレコードが追加されてしまう。 <改善したいこと>: 本社テーブルの会社名が未入力ならば、上記の操作でレコードを追加しない。(会社名に主キーは設定していません。) <会社登録フォームの環境>: 会社の本社情報をメインフォーム、その会社の支店情報をサブフォームに、単票形式のタブコントロールで複数画面にして支社ごとに分けて入力できる登録フォームを作成しました。本社テーブルの会社IDを主キーに、支店テーブルの支店IDを主キーにしてリレーションシップを設定しています。 <会社情報の入力に関して行っていること>: ・メインフォームに「新規」「更新」「削除」ボタンを設置。 ・新規ボタンでメインフォームの「会社ID」に自動採番。 ・会社(本社)名がないと困るので、未入力の状態で「新規」「更新」及び「サブフォーム」をクリックされた際に「会社名が未入力です。」のメッセージを表示され「OK」で元の状態にもどります。 ・会社(本社)名が入力済みならば、「更新」ボタンで、メッセージ「OK」「キャンセル」が表示され、「OK」ならば本社テーブルにレコードが追加され「キャンセル」ならばそのままの状態になります。 上記の<問題としていること>の補足ですが、新規ボタンで新規登録フォームに会社IDが自動採番(末番)されるのですが、「会社名」を入力せず、先にサブフォームの支店情報から(タブ名「支店(1)」)入力しようとした場合、「会社名が未入力です。」のメッセージを表示されますが、この時点で本社テーブルに、この採番でレコードが追加されてしまいます。入力者がそのまま会社名(本社)から入力するも、途中でキャンセルした場合、再度新規登録をする際、登録フォームの自動採番がキャンセルされた採番の次の番号になります。 キャンセルされた会社情報空白のレコードができるということになります。これを回避したいのです。 出来るだけ詳細をとおもい説明が長くなりましたが、よろしくお願いいたします。

  • Accessでの質問

    ID ----- 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A このようなテーブルがあり、フォームにいくつかのテキストボックスと登録というコマンドがあります。登録ボタンをクリックしたときtxtidというテキストボックスに何も入力されていないとき上のテーブルを参照してIDを採番し、登録できるようにするにはどうすればいいですか?ちなみIDコードの登録は16進数で登録できるようになっています。上の場合だと000Bを採番したいのです。仮に0007がないときは0007を採番したいんですが…初心者なので本当に困っています。お願いします。説明不足でわかりにくい時は質問していただければ大変助かります!

  • ACCESS ADOのMovePreviousについて

    毎度お世話になっております。 ACCESS2003を使用しています。 ACCESS ADOにて、レコードセットがeofになった後、 MovePreviousをし、MoveNextをし、 さらにもう一度MovePreviousをすると、 最終レコードの一つ前に戻ってしまいます。 テーブル1 フィールド1 フィールド2    1     あ    2     い    3     う    4     え    5     お コード Sub test()   Dim cn As New ADODB.Connection   Dim rs As New ADODB.Recordset   Set cn = CurrentProject.Connection   rs.Open "select * from テーブル1 order by フィールド1", cn, adOpenDynamic, adLockReadOnly   Do Until rs.EOF    rs.MoveNext   Loop   rs.MovePrevious   Debug.Print rs.Fields("フィールド1").Value   rs.MoveNext   rs.MovePrevious   Debug.Print rs.Fields("フィールド1").Value   rs.Close: Set rs = Nothing   cn.Close: Set cn = Nothing End Sub 一度目のdebug.printは5に、 二度目のdebug.printは4になります。 このような仕組みなのでしょうか。 ご教授お願いいたします。

  • Access アクセス VBA レコード追加

    Access フォームからのレコードの追加方法を教えてください。 テーブル1 ・ID(主キー) ・窓口 ・コストセンター ---------- テーブル2 ・コストセンター(主キー) ・目的 ---------- リレーションシップ テーブル1のコストセンターとテーブル2のコストセンターを一対多 ---------- メインのフォームに”ID”を入力したときにテーブル1に一致するレコードがない場合、新規登録用のフォームが表示されるようになっています。 新規登録用のフォームにレコードを入力してもテーブルに反映されません。 新規登録用のフォームは下記のように作成しています。 また、フォームに”コストセンター”を入力したときに入力したレコードがテーブル2にあっても自動で”目的”が表示されません。 メインフォームにはサブフォームで各テーブルが表示されています。 フォーム ・ID(初期値•••メインで入力したID) ・窓口 ・コストセンター ・目的 ・コストセンター(非表示) 上から順に ・テーブル1 ・テーブル1 ・テーブル2 ・テーブル2 ・テーブル1

  • Access EOFの判定がうまくいかない

    お世話になります。 Access2010 テーブルのEOFの判定がうまくいきません。  If TMP.EOF = False Then   MsgBox "EOFではありません"  Else   MsgBox "EOFです"  End If TMPには1レコードありますが、なぜかTrueになってしまいます。 なお、TMP.MoveLastしてもエラーにならず、その後、イミディエイト ウィンドウで?TMP.EOFとしてみると、Falseが返ってきます。 本来であればEOFでMoveLastするとカレントレコードが無い旨のエラーに なるかと思うので、EOFではないと思うのですが。。 どのようなことが考えられますでしょうか。 <TMPについて> ・(訳あって)主キーは設けておりません。 ・0レコードか1レコードです。1レコード以上になることはありません。 ・TMPはあるフォームのレコードソースとしています。  ※フォーム上の登録ボタンが押されたら、フォームのレコードソースを   ""としフォームを閉じます。このタイミングでTMPにレコードが生成   されます。   上記の判定処理は、フォームを閉じた直後に行っています。 ご教示の程、宜しくお願い致します。

  • 2回目に画面のレコードセットの値が読めない

    メインフォームとサブフォームの画面゛て レコードソースは、ワークテーブルを参照し メインフォームの保存ボタンの処理で、 Private Sub 保存ボタン_Click()  Set mySubFm = Me![テーブル子].Form  Set myParFm = Forms(Me.name) '<== 親フォーム  Set Rec1 = myParFm.RecordsetClone  Set Rec2 = mySubFm.RecordsetClone  Lng受注ID = Rec1.Fields("受注ID").Value  Dim Rtn As Integer  ・レコードセットのデータを、本テーブルに更新する処理  ・自動採番した番号を、レコードセットのIDのフィールドにセット   Rec1.Edit   Rec1.Fields("ID").value = newID   Rec1.Update  ・Me.Requery '<== メインフォームの画面を更新  ・mySubFm.Requery '<==サブフォームの画面を更新  Set Rec1 = Nothing   Set Rec2 = nothing End Sub この処理を一度行い、更に、画面のサブレコードの値を変更して、保存ボタンを再度押すと、 Lng受注ID = Rec1.Fields("受注ID").Value の行で、 「オブジェクトが正しくないか、現在設定されていません」というエラーになります。 この原因はどうしたら解決出来ますでしょうか? よろしくお願いします。

  • RecordCount(ADO)が変わる?ADP+SQLServer

    ACCESS2000(ADP)+SQLServerにて作成したものですが、 あるクライアント(1台)だけRecordCountがおかしいのです。 <フォームAのボタンクリック時の処理> DoCmd.OpenForm "フォームB", , , , , , Me!コード <フォームBの読み込み時の処理> Dim rs AS ADODB.Recordset Set rs = Me.RecordsetClone rs.Find "コード=" & Me.OpenArgs, 0, adSearchForward If not rs.EOF then Me.Bookmark = rs.Bookmark End if 問題のないクライアント(他の2台)では、 フォームBにてOpenArgに指定したコードが検索され, 該当のレコードが表示されます。 問題のクライアントでは、 「一部」のレコードを指定した場合にレコードが検索されず、 最初のレコードが表示されました。 原因を調べているうちに分かったことは、 Set rs = Me.RecordsetClone で取得したレコードセットがあるタイミングでは、 一部かけた状態になっているということです。 その際に使用した方法は、 Set rs = Me.RecordsetClone rs.MoveLast MsgBox rs.RecordCount MsgBox rs.RecordCount としてレコードの件数を調べて判明しました。 MsgBox rs.RecordCountが2つあるのは記述ミスではありません。 該当のテーブル(レコード)は757件ありますが、 問題のないクライアントでは2回ともに757を返します。 問題のクライアントでは、 1回目のRecordCountは500 2回目のRecordCountは757を返してきます。 しかも、何回も実行していると 1回目が400、450、500とランダムで変化します。 (500が2回続いたりするときもあります) 以上のことから、考えられる原因は何かありますでしょうか。 よろしくお願いいたします。

  • Access フォームの表示順をなおしたい

    いつもお世話になっています。 Access フォームを利用していたのですが、テーブルの既存データを更新してから、そのフォームでのデータ表示順が変わってしまいました。 レコードにはIDとして番号データがあるので、小さい順にフォームに表示させたいと思います。 ちなみに、元となるテーブルはID番号が小さい順に並んでいます。 よろしくお願いします。

  • アクセス97

    データ入力フォームからデータ検索をして同フォームに表示させる。一部書き換えた後 新しいレコードとして登録したいのですがどうしても同じレコードが書き換わってしまいます 助けてください。 具体例: 登録フォーム”A”に入力項目がID(主キー、オートナンバー)会員番号、名前、購入品、 購入日時等があります。”A”フォームから会員番号で名前を抽出して他の項目内容を 新たに入力し、追加レコードとして登録したい。 ”A”フォームにデータ抽出は出来るのですがレコード内容の書き換えになってしまいます。 回答よろしくお願いします。

専門家に質問してみよう