Microsoft Access 掲示板

複数選択後、項目毎の自動採番について

5 コメント
views
4 フォロー

以前に下記のような質問を見つけ、項目毎の自動採番に転用し運用していたのですが、

二つの項目を選択後、選択した項目ごとに自動採番したい。
テーブル名:発行簿
フィールド名:
コード [テキスト型] リストボックスより選択 A;B;C
区分 [テキスト型] リストボックスより選択 前;中;後
発行番号 [テキスト型] 主キー 自動採番

発行番号 に
A-前-001
A-前-002
A-中-001
A-後-001
B-前-001
B-中-001
C-前-001

回答
区分の更新後処理に、

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(Val(Right(Nz(DMax("発行番号", "発行簿","コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'" )),3)) + 1, "000")

と、言ううものでした。

ここで、例えば 区分 が 「後」 の時のみ、連番を 501 から始めるという方法はあるのでしょうか?
全くの見様見真似で、理解できておりません。よろしくお願いいたします。
A-後-001 これを A-後-501

勉強しています。
作成: 2020/09/18 (金) 15:27:20
最終更新: 2020/09/18 (金) 15:28:59
通報 ...
1
hiroton 2020/09/18 (金) 19:08:01 622cc@f966d

式をバラバラにしてみましょう
処理は一番内側の括弧から順に処理されます。

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & 
              Format(
                Val(
                  Right(
                    Nz(
                      DMax(

バラバラにするなら下から順に処理を書けばいいということですね。

Dim strWhere As String '//発行番号のグループの条件

Dim retDMax
Dim retNz
Dim retRight As String
Dim retVal As Long
Dim retFomat As String

strWhere = "コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'"

'//条件の中から一番大きいモノを取り出す
retDMax = DMax("発行番号", "発行簿", strWhere)

'//条件に一致するものがないときはNULLになっているので文字列に統一する
retNz = Nz(retDMax)

'//ほしいのは数字部分だけなので右から3文字取り出す
retRight = Right(retNz, 3)

'//計算できるように文字から数値に変換して1増やす
retVal = Val(retRight) + 1

'//出来上がった連番を登録用に整形する(3桁0詰め)
retFormat = Format(retVal, "000")

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & retFormat

気を付ける点は、DMax関数は「値かNULL」が返ってくるところです。今回の場合、発行番号を対象にしているので「文字列かNULL」ですね。

条件に一致する発行番号がないとき(項目が新規の組み合わせの場合)、DMax関数がNULLを返すわけですが、この時の動きを調べてみてください。

結果を言うと項目が新規の組み合わせの場合、最新の番号として0(になる値)がとれるため、最新の番号+1で連番を作るということになっています。

この部分に条件分岐をいれてあげればいいですね。

Dim strWhere As String '//発行番号のグループの条件

Dim varLastNoString
Dim varNzLastNoString
Dim strLastNo As String
Dim nNewNo As Long
Dim strNewNo As String

strWhere = "コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'"

varLastNoString = DMax("発行番号", "発行簿", strWhere)

'//新規(条件グループの連番が見つからなかった時)の連番を区分によって切り変える
varNzLastNoString = Nz(varLastNoString, IIf(Me!区分 = "後", 500, 0))

strLastNo = Right(varNzLastNoString, 3)
nNewNo = Val(strLastNo) + 1
strNewNo = Format(nNewNo, "000")

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & strNewNo

ここまで何でもかんでも変数にして、とする必要はないですが、VBAで記述するなら適宜変数を置くと理解しやすくなります。

Dim tempLastNo As Long '//条件により連番の初期値を変えたい

Dim lastNo
Dim newNo As Long

'//新規(条件グループの連番が見つからなかった時)の仮の連番を設定する
If Me!区分 = "後" Then
    tempLastNo = 500
Else
    tempLastNo = 0
End If

'//発行番号は「[コード]-[区分]-[連番(3桁0詰め)]」形式の文字列なのでうまいことなんやかんやする
lastNo = Nz(DMax("発行番号", "発行簿", "コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'"), tempLastNo)
newNo = Val(Right(lastNo, 3)) + 1

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(newNo, "000")
2
勉強しています。 2020/09/19 (土) 14:38:52 cd439@00650

詳しく書いて説明して頂き、ありがとうございます。
出先のため、後日じっくりと勉強させていただきます。

3
勉強しています。 2020/09/23 (水) 09:07:51 0227b@96e2f >> 2

hiroton様
回答頂きましてありがとうございます。
簡単に、どこかに条件分岐を入れるといいのかな~、などと考えていました。
式を分解して考える事が基本に繋がるのですね。
マネだけせずに、考えていきたいと思います。

5
hiroton 2020/09/23 (水) 10:33:29 7416f@f966d >> 2

3つ目のブロックに回答っぽいものがありますが1行で書くなら

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(Val(Right(Nz(DMax("発行番号", "発行簿","コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'" )),3)) + 1, "000")

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(Val(Right(Nz(DMax("発行番号", "発行簿","コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'" ),IIf(Me!区分 = "後", 500, 0)),3)) + 1, "000")

'//コード表示
Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(Val(Right(Nz(DMax("発行番号", "発行簿","コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'" ),IIf(Me!区分 = "後", 500, 0)),3)) + 1, "000")

フォーム上のテキストボックスだとか、レポートで一発表示だけしたいとか、どうしても計算式1行で済ませなければいけないという要件がでることもままあります。どっちも同じことをやっているのでどっちが基本ということもないですがVBAで記述するなら柔軟性を活用すべしということですね

自分でも見直したコードを追記してみた(やっていることは変わらない)ので見比べてみてください

4
hiroton 2020/09/23 (水) 10:02:54 7416f@f966d

後から見直したらもっといいコードがあったんじゃないかなと思うことはよくあること。なので

Dim lastID As String
Dim newNo As Long

lastID = Nz(DMax("発行番号", "発行簿", "コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'"))
If lastID = "" Then
    '//新規(条件グループの連番が見つからなかった時)なので初期値を設定する
    If Me!区分 = "後" Then
        newNo = 501
    Else
        newNo = 1
    End If
Else
   '//連番部分を取り出して1増やす
    newNo = Val(Right(lastID, 3)) + 1
End If

Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(newNo, "000")

先のコードよりわかりやすくなってると思います

区分で設定を変えたいということでそこだけ条件分岐にしましたが、元々の「連番+1の処理」をそのまま残して初期値側を「後でプラス1されるからマイナス1しておく」ように弄ったところも条件分岐させてあげたほうが直感的に書けますね

ついでにlastIDAs String指定できるので変な使い方ができないよう(バグのもとにならないよう)に制限できるのも良い点かなと


余談
変数名も「lastNo」と「newNo」だとそっくりなのに中身別物じゃないかってなるので手を加えてみました