• ベストアンサー

Accessで指示書番号の自動採番

入力フォームで指示書番号が自動採番され、テーブルにも保存されるようにするための方法を教えていただけないでしょうか。 テーブル:T_指示書 フィールド:指示書番号 フィールドはテキスト型で、番号の構成は8桁の番号で "年(二桁)" + "月(二桁)" +"部署番号(一桁、固定の数字)"+ "連番(三桁)" (例:09091001) という感じで、 年月が変われば、連番が001になるようにしたいです。 どなたか、ご教授いただければありがたいです。 よろしくおねがいします。 Access2002 winXP

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

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

#2です > >現在部署番号は "1" 固定ですが、パラメータ渡し、グローバル変数化は自由です。 > 固定ではなく、任意の番号を入力する方法 1)パラメータ渡し 既に部署番号を参照できる構成になっていた場合 (フォームに部署番号の入力/選択欄がある場合など) 変更するのは以下2行 Public Function GetNewNum() As String   sD = Format(Date, "yymm") & "1" ↓ 整数で受け渡す場合 Public Function GetNewNum(iBuNum As Integer) As String   sD = Format(Date, "yymm") & iBuNum ↓ 長整数で受け渡す場合 Public Function GetNewNum(iBuNum As Long) As String   sD = Format(Date, "yymm") & iBuNum ↓ 文字で受け渡す場合 Public Function GetNewNum(sBuNum As String) As String   sD = Format(Date, "yymm") & sBuNum ↓ NULL を渡す可能性がある場合 Public Function GetNewNum(vBuNum As Variant) As String   sD = Format(Date, "yymm") & vBuNum ※ NULL なら部署番号を 1 にするなど処理の追加が必要 1-1)呼び出し方 Me.指示書番号 = GetNewNum(Me.txt_部署番号) とか(部署番号が入っているテキストボックス名を txt_部署番号 とした場合) 2)グローバル変数利用 その1 操作を始めた時、その人が扱える部署番号を固定した作りになっている場合や、複数のフォームにまたがって同じ部署番号を使いたい場合など 標準モジュールに以下を宣言(整数として扱う場合:型については上記同様に) Public iPubBuNum As Integer この変数を  sD = Format(Date, "yymm") & iPubBuNum  部分で参照します。 iPubBuNum には、部署番号を得た時点で代入しておきます。 2-1)呼び出し方 変更ありません 2-2)コメントは書いておきましょう(同じ標準モジュールに書いた時の例) ' 処理中部署番号 ' 設定:XXXXのタイミング ' 参照:指示書番号生成(GetNewNum)/ YYYY ' Public iPubBuNum As Integer ・・・ ' 指示書番号生成 ' iPubBuNum は部署番号(グローバル変数) ' Public Function GetNewNum() As String   ・・・・   sD = Format(Date, "yymm") & iPubBuNum   ・・・・   GetNewNum = sRet End Function とか、 3)グローバル変数利用 その2(複合) 処理中部署番号をグローバル変数で持って置き、GetNewNum を呼ぶ時にパラメータにする ' 処理中部署番号 ' 設定:XXXXのタイミング ' Public iPubBuNum As Integer ・・・ ' 指示書番号生成 ' Public Function GetNewNum(iBuNum As Integer) As String   ・・・・   sD = Format(Date, "yymm") & iBuNum   ・・・・   GetNewNum = sRet End Function 3-1)呼び出し方 Me.指示書番号 = GetNewNum(iPubBuNum) ※ この辺の書き方/内容については、会社なり、部、課、チームなどにルールがあると思いますので、それに従ってください ※ 関数(モジュール)の結合度等ルールがあれば、それに従ってください。 ※ 変数/関数名は適宜変更してください ※ 説明になってたでしょうか

asada1057
質問者

お礼

ありがとうございます。 上記を参照して試してみます。 ご丁寧な説明をありがとうございました、本当に助かりました。

すると、全ての回答が全文表示されます。

その他の回答 (2)

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

新しい番号をどのように使っていくのかわからないので、新しい番号を取得する部分について以下に。 T_指示書には、採番済みの指示書番号が、ずらずらっと複数登録されているものとします。 標準モジュールに記述します。 Public Function GetNewNum() As String   Dim sRet As String   Dim sD As String   Dim vTmp As Variant   On Error Resume Next   sRet = ""   sD = Format(Date, "yymm") & "1"   vTmp = DMax("指示書番号", "T_指示書", "指示書番号 like '" & sD & "*'")   If (IsNull(vTmp)) Then     sRet = sD & "001"   Else     sRet = sD & Format((CInt(Right(vTmp, 3)) + 1), "000")   End If   GetNewNum = sRet End Function 処理としては、今日の yymm & 部署番号 で始まる文字列最大を求めます。 なければ、年月が変わったということで初期の 001 を、 あったら、右3桁に1加算したものを文字列として返します。 現在部署番号は "1" 固定ですが、パラメータ渡し、グローバル変数化は自由です。 フォームとの連携 1)既定値を使う方法 指示書番号という名のテキストボックスがあった場合です。 (単純にフォームウィザードで作成すると、テキストボックス名=フィールド名のものになります) (コントロールソースに指示書番号が設定されたテキストボックスが対象で、以下そのテキストボックス名に置き換えてみてください) 連結した単票形式で使うのなら、指示書番号のプロパティ既定値に =GetNewNum() とします。 帳票形式なら上記だけでは処理足りないので、フォームの更新後処理でこの既定値を書き換えます。 Private Sub Form_AfterUpdate()   Me.指示書番号.DefaultValue = "'" & GetNewNum & "'" End Sub 2)値をそのまま代入する方法 フォームのレコード移動時で新規レコードの時のみ値を代入します。 Private Sub Form_Current()   If (Me.NewRecord) Then     Me.指示書番号 = GetNewNum   End If End Sub これをすると、新規レコードへ移動した時には常に編集状態になるので、追加しないのならキャンセルする操作が必要になります。 共通) 仕様書番号が、主キー(orインデックス重複なし)の時、 複数人で操作して保存時に競合が発生したことはフォームのエラーイベントでわかります。 (他のフィールドにエラー要因となるものがなかった場合) Private Sub Form_Error(DataErr As Integer, Response As Integer) ' DataErr は 3022 で呼ばれます End Sub 3022 なら、再度 GetNewNum() で求めなおすとか、いろいろ方法はあると思います。 パラメータの意味は、ヘルプ等で確認してください。 ※ 関数名は適宜変更してください

asada1057
質問者

補足

回答ありがとうございます。 やりたいことのほとんどができました。 ありがとうございます。 >現在部署番号は "1" 固定ですが、パラメータ渡し、グローバル変数化は自由です。 重ね重ね申し訳ございませんが、固定ではなく、任意の番号を入力する方法を教えていただけたら助かります。

すると、全ての回答が全文表示されます。
  • nda23
  • ベストアンサー率54% (777/1416)
回答No.1

オートナンバーを使う方法と、採番テーブルを使う方法があります。 オートナンバーは文字通り、自動的に一意な数値が発生する項目で、 これをテーブル上に定義して使えば、直ぐにも実現しますが、値を リセットするのに面倒な手順が必要です。 採番テーブルはキー(年月と部署)+連番から成るもので、自力で 値を参照/更新します。この方法では月替わりのリセット処理は不要 ですが、処理を自作しなければなりません。また、番号を採る度に 他のスレッドとの競合を抑える処置が必要です。オートナンバーの 場合もリセット時にはこういう処置を実施しなければなりません。 ということで、個人的には「採番テーブルを使う方法」を薦めます。 (1)独占処理権の獲得 (2)採番テーブルから、キーを指定してレコードを取得 (3)読めなければ連番=1とし、レコードを挿入する。読めた場合は  連番+1を採用し、レコードを更新する。 (4)独占処理権の放棄 このような手順です。独占処理件は各PCで参照可能な共通ファイルを 排他的にOpenすることで実現できます。ファイル内容は不要です。 排他的なOpenなので、唯一つのプロセスだけがファイルを開けます。 他のプロセスはエラーになりますが、100ミリ秒ほど待機して、成功 するまでリトライすれば、いずれは処理されます。レコードのロック でも排他可能ですが、設定/解除、ロックの認識がファイル方式に比べ 非常に遅く、ロックしたプロセスが途中で停止した時の解除が面倒 です。ファイル方式ではプロセスが終了すると、それが掴んでいた 資源は自動的に解放される(OSがやってくれる)ので、その心配は 不要です。

asada1057
質問者

お礼

回答ありがとうございます。 こちらの勉強不足で正確には理解ができていないかもしれませんが、 採番テーブルを作る方法もあるということ参考になりました。

すると、全ての回答が全文表示されます。

関連するQ&A