Access (VBA)

Access VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(Windows 10 Pro : Access 2021)
連番が振れません
投稿日時: 23/07/12 18:54:19
投稿者: human

いつもお世話になっております
humaと申します
 
 弊社は機械を取り扱う会社で
在庫を扱うシステムを入れ替える事になりました
その移行用データを作成しております
その在庫機械のシリアル番号(SID)について
 
現行システムは20桁で、英数から漢字までなんでも入りますが
新システムでは15桁で半角英数のみの制約です
 
 下表、左から[一時SID]までのデータは作成できていますが
その右の『新SID』ができません
 
SEQ    SID(元の機械シリアル)         変換#    変換内容        一時SID                 新SID
                                    
820    a b c 0 0 9        →    4    大文字+空白    ABC009            →    ABC009_001
821    ABC 009        →    3    空白飛ばし    ABC009            →    ABC009_002
823    AxyzA-SBe1        →    2    大文字変換のみ    AXYZA-SBE1        →    AXYZA-SBE1
825    c r W            →    4    大文字+空白    CRW            →    CRW_001
826    CRW            →    1    元と同じ変換なし    CRW            →    CRW_002
827    CT145XP xxxxya        →    4    大文字+空白    CT145XPXXXXYA        →    CT145XPXXXXYA
:    :            :    :        :        :        :    :
957    mthrXOma        →    2    大文字変換のみ    MTHRXOMA        →    MTHRXOMA
959    1SP987semi123456-A    →    5    長い        NEWNO==        →    NEWNO==001
1084    全角文字            →    6    全角        NEWNO==        →    NEWNO==002
1085    全角カナ            →    6    全角        NEWNO==        →    NEWNO==003
1086    全角かな            →    6    全角        NEWNO==        →    NEWNO==004
1087    漢字含む            →    6    全角        NEWNO==        →    NEWNO==005
1088    カタバン100-125        →    7    半角カナ        NEWNO==        →    NEWNO==006
:    :            :    :    :            :        :    :
1098    NG123987654        →    1    元と同じ変換なし    NG123987654        →    NG123987654
(画面では折り返しがいびつかも知れませんので
 必要に応じて適宜テキストエディタにコピペしてご覧ください)
 
(ちなみに、下記コードのようなもので(宣言等略)作成すると
 同じ[XXXX001]や[NEWNO==001]、
 また、[XXXX002]や[NEWNO==137(重複数)] になってしまいます)
 
●[一時SID]重複の場合は、現行番号はユニークですので
 連番が振られるようにしたいです
 
 もう、2週間この件にはまっていまして・・
どうか、ご教授の程よろしくお願い致します。
 
 
Sub 新SID_作成()
 
srtsort = "[一時SID] asc,[SID] asc"
 
Set CurDb = CurrentDb()
 
Set CurRSQ = CurDb.OpenRecordset("TBL_展開_元", DB_OPEN_DYNASET)
Set CurRST = CurDb.OpenRecordset("TBL_展開_先", DB_OPEN_DYNASET)
(『TBL_展開_先』はTBL_展開_元に[新SID]を追加しただけのテーブルで、
 もちろん、元のテーブルに書き込めるのが一番いいです)
 
 
    CurRSQ.Sort = srtsort
     
    RecCnt = 0
 
Set CurRSQ = CurRSQ.OpenRecordset()
 
    CurRSQ.MoveFirst
 
 
Do
' 初めて読み込むSIDの場合はフィールドNoを指定する変数iiを初期化しておきます
    ii = 0
    KCnt = 0
    NewLOT = ""
    LenNK = 0
 
    KIBAN = CurRSQ![SID]
    TmpKBN = CurRSQ![一時SID]
    CgNo = CLng(CurRSQ![変換#])
    TmCgCom = CurRSQ![変換内容]
 
    LDCount = 0
 
        ' */ データで1SIDのレコードが終わるまで続けます
            Do While CurRSQ![一時SID] = TmpKBN
                            
            ' */ 初めて読むSIDならばTempテーブルに新しいレコードを作り、SIDコードを書き込む
                If ii = 0 Then
                 
                        CurRST.AddNew
                        CurRST![SID] = KIBAN
                        CurRST![一時SID] = TmpKBN
                        LenNK = Len(TmpKBN)
                         
                    ii = ii + 1
                         
                CurRST!F_ii = ii
                         
                        LDCount = DCount("*", "TBL_展開_元", "[一時SID] = '" & TmpKBN & "'")
                         
                        NewLOT = TmpKBN
                         
                         
                        CurRST![変換#] = CgNo
                        CurRST![変換内容] = TmCgCom
                         
                                If ((LDCount = 1) And (CgNo < 5)) Then
                                 
                                     
                                ElseIf ((LDCount > 1) And (CgNo >= 5)) Then
         
                                     
                                    NewLOT = NewLOT & "_1行目_==001"
                                     
                                     
                                ElseIf ((LDCount > 1) And (CgNo < 5)) Then
                                 
                                    Select Case True
                                     
                                        Case ((LenNK < 12) And (LDCount < 1000))
                                         
                                            NewLOT = NewLOT & "_1行目__001"
                                 
                                        Case ((LenNK = 12) And (LDCount < 100))
                                         
                                            NewLOT = NewLOT & "_1行目__01"
                                             
                                        Case ((LenNK = 13) And (LDCount < 10))
                                         
                                            NewLOT = NewLOT & "_1行目__1"
                                             
                                        Case ((LenNK = 14) And (LDCount < 10))
                                         
                                            NewLOT = NewLOT & "_1行目_1"
                                             
                                        Case Else
                                         
                                            NewLOT = "NEWLOT==" & "_1行目__001"
                                             
                                    End Select
                                 
     
                                End If
                             
                        CurRST![新SID] = NewLOT
                         
                        CurRST!LenNK = LenNK
                        CurRST!LDCount = LDCount
                        CurRST!NewLOT = NewLOT
                        CurRST!TmpKBN = TmpKBN
 
               Else
 
                    ii = ii + 1
                     
'--------------------------------------------------------------------------------------------------
    KIBAN = CurRSQ![SID]
    TmpKBN = CurRSQ![一時SID]
    CgNo = CLng(CurRSQ![変換#])
    TmCgCom = CurRSQ![変換内容]
'-------------------------------------------------------------------------------------------------
                 
                        CurRST.AddNew
                        CurRST![SID] = KIBAN
                        CurRST![一時SID] = TmpKBN
                        LenNK = Len(TmpKBN)
                         
                    CurRST!F_ii = ii
                         
                        LDCount = DCount("*", "TBL_展開_元", "[一時SID] = '" & TmpKBN & "'")
                         
                        NewLOT = TmpKBN
                         
                         
                        CurRST![変換#] = CgNo
                        CurRST![変換内容] = TmCgCom
                         
                                If ((LDCount = 1) And (CgNo < 5)) Then
                                     
                                ElseIf ((LDCount > 1) And (CgNo >= 5)) Then
 
         
                                    NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "#00")
                                     
                                     
                                ElseIf ((LDCount > 1) And (CgNo < 5)) Then
                                 
                                            Select Case True
                                             
                                                Case ((LenNK < 12) And (LDCount < 1000))
                                                 
                                                    NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "#00")
                                         
                                                Case ((LenNK = 12) And (LDCount < 100))
                                                 
                                                    NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "#0")
                                                     
                                                Case ((LenNK = 13) And (LDCount < 10))
                                                 
                                                    NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "0")
                                                     
                                                     
                                                Case Else
                                                 
                                                    NewLOT = "NEWLOT=2行目以降=" & "001"
                                                     
                                            End Select
                                 
        '
                                End If
 
                        CurRST![新SID] = NewLOT
                                 
                        ii = ii + 1
                         
                        CurRST!LenNK = LenNK
                        CurRST!LDCount = LDCount
                        CurRST!NewLOT = NewLOT
                        CurRST!TmpKBN = TmpKBN
                                                 
                End If
                 
                        KCnt = KCnt + 1
                         
                        CurRST![KCount] = KCnt
                        TmpKBN = ""
 
 
                RecCnt = RecCnt + 1
                CurRST![KID] = RecCnt
                CurRST.Update
                     
                CurRSQ.MoveNext
                 
                 
                    If CurRSQ.EOF Then
         
                        Exit Do
         
                    End If
                         
            Loop
             
                 
Loop Until CurRSQ.EOF
 
よろしくお願い致します

投稿日時: 23/07/13 11:34:00
投稿者: human

 追記です
「連番」は全件通してではなく、各『機番』毎に振りたいです
よろしくお願い致します

回答
投稿日時: 23/07/13 16:14:30
投稿者: sk

現時点では「まず[SID]の変換の規則と順序を矛盾も破綻もしない形で明文化するのが先」
としかお答えできません。
 

引用:
821 ABC 009 → 3 空白飛ばし ABC009

1. [SID]の値に含まれている全ての半角/全角スペースを空文字列に置換する。
 
引用:
現行システムは20桁で、英数から漢字までなんでも入りますが
新システムでは15桁で半角英数のみの制約です

引用:
959 1SP987semi123456-A → 5 長い NEWNO==

2. 全てのレコードに対して上記 1 の置換処理を施した状態において
   [SID]の値の長さが 15 文字を超える場合は、
   [SID]の値を "NEWNO==" という文字列に書き換える。
 
引用:
1098 NG123987654 → 1 元と同じ変換なし NG123987654

3. 全てのレコードに対して上記 1 の置換処理を施した状態において、
   [SID]の値の長さが 15 文字以内である場合は、上記 2 の処理を実行しない。
 
とりあえずここまではいいとして、
 
引用:
823 AxyzA-SBe1 → 2 大文字変換のみ AXYZA-SBE1 → AXYZA-SBE1

引用:
1084 全角文字 → 6 全角 NEWNO==

全角のアルファベット、全角の算用数字、全角のハイフンの扱いが不明瞭です。
(どこにも例示されていない)
 
引用:
ABC009_001

引用:
ABC009_002

また「変換後の[SID]の値が同一であるレコードが他にも存在する場合は、
それらのグループごとに連番(区切り記号としての半角アンダースコアと、1 から始まる
ゼロ埋め整数連番 3 桁)を付加する」というルールを適用しようとしているとして、
上記 3 に該当するケースにおいて、そのレコードの[SID]の値の長さが
12 〜 15 文字である場合、単純にグループ別連番(区切り記号込みで 4 文字)を
付加すれば、当然 15 桁の制限を超えることになります。
その場合はどのようにされるつもりなのでしょうか。

投稿日時: 23/07/13 20:03:56
投稿者: human

sk様
お世話になります
 
長文に関わらずご回答賜りまして
誠にありがとうございます
 
もちろん、実際のデータは情報量も多く
一部を抜粋し、更に内容を『手入力』にて加工している為
不自然な例示でした事、お詫び申し上げます。
 
 加えて『SID(元の機械シリアル)』から『一時SID』への変換は
自作のつたないFunctionですが、一応問題なく動作しておる(はず)でありまして
今のところは、期待通りのデータを出力しております
 
 そのFunctionをクエリのフィールドに設定し
実は、そのクエリを『TBL_展開_元』としております
 
-----------------------------------------------
※ 変換ルールは主に
・小文字→大文字変換のみ
・スペース除去のみ
・小文字→大文字変換+スペース除去のみ
 は、元のSIDのイメージに近いものを残すため
 a bc 123 →ABC123 となるようにしています
 
他、以下はすべて"NEWLOT=="にしています
・全角が含まれる
・半角カナが含まれる
・(スペースを除去しても)16文字以上
・システムの予約文字が含まれる
・システムの予約文字の(数字一文字)の場合
-----------------------------------------------
 
 さて、
上記 3 に該当するケースにおいて、そのレコードの[SID]の値の長さが
12 〜 15 文字である場合、単純にグループ別連番(区切り記号込みで 4 文字)を
付加すれば、当然 15 桁の制限を超えることになります。
その場合はどのようにされるつもりなのでしょうか。…につきまして
 
@ LDCount = DCount("*", "TBL_展開_元", "[一時SID] = '" & TmpKBN & "'") で
 一時SIDの重複数=連番の桁数をみて
 
ALenNK = Len(TmpKBN) で、一時SIDの長さをはかり
 
                                   Select Case True
                                      
                                        Case ((LenNK < 12) And (LDCount < 1000))
                                          
                                            NewLOT = NewLOT & "_1行目__001"
                                  
                                        Case ((LenNK = 12) And (LDCount < 100))
                                          
                                            NewLOT = NewLOT & "_1行目__01"
                                              
                                        Case ((LenNK = 13) And (LDCount < 10))
                                          
                                            NewLOT = NewLOT & "_1行目__1"
                                              
                                        Case ((LenNK = 14) And (LDCount < 10))
                                          
                                            NewLOT = NewLOT & "_1行目_1"
                                              
                                        Case Else
                                          
                                            NewLOT = "NEWLOT==" & "_1行目__001"
                                              
                                    End Select
 
 の部分にて15桁を超えないようにしている『つもり』でした。
 
 さて、例示させて頂きました内容は悪いのですが
あのまま、勘弁して頂くとしまして
 
●「『新SID』の変換ができない。」というよりも、
  すべて変換後の『新SID』が、
 『NEWNO==001』や(一時SIDのCRWのように)『CRW_001』のように
 『1行目』の変換のみになってしまい、
 『2行目以降』の変換が行われない状況です

 
 引き続き、よろしくお願い致します

回答
投稿日時: 23/07/14 10:13:50
投稿者: sk

引用:
他、以下はすべて"NEWLOT=="にしています
・全角が含まれる
・半角カナが含まれる
(スペースを除去しても)16文字以上
・システムの予約文字が含まれる
・システムの予約文字の(数字一文字)の場合

例えば、[一時SID]の値が "0123456789ABCDE" であるレコードが
2 件以上存在した場合、それぞれのレコードの[新SID]の値は
どのようになればよいのでしょうか。

回答
投稿日時: 23/07/14 12:00:19
投稿者: Suzu

求めたい値と、例の間に 違いが見えます。
 

human さんの引用:
●「『新SID』の変換ができない。」というよりも、
  すべて変換後の『新SID』が、
 『NEWNO==001』や(一時SIDのCRWのように)『CRW_001』のように
 『1行目』の変換のみになってしまい、
 『2行目以降』の変換が行われない状況です

 
例との対比をすると
 
引用:
959    1SP987semi123456-A    5    長い    NEWNO==    NEWNO==001
1084    全角文字    6    全角    NEWNO==    NEWNO==002

 
SEQ 959 が 1行目、1084が、2行目 という認識で良いでしょうか?
 
 
一時SID NEWNO== に当てはめると
 
その時、の処理コードは
NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "0")
の様な形であり、求めたい値は
 
NOWNO==_2行目以降_2
 
と言う事でしょうか?
 
 
 
100件目だと?
 
NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "#00")
 
NOWNO==_2行目以降_100 ・・・ 17桁と読めますが良いのでしょうか?

回答
投稿日時: 23/07/14 12:21:37
投稿者: Suzu

分岐先が違いましたね。
 
その時、の処理コードは
NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "#00")
の様な形であり、求めたい値は
 
NOWNO==_2行目以降_02
 
と言う事でしょうか?
 
 
100件目だと?
 
NewLOT = NewLOT & "_2行目以降_" & Format((CStr(ii)), "#00")
 
NOWNO==_2行目以降_100 ・・・[/quote]
 
どちらも、例には無かった【_2行目以降_】が含まれており、
共に、16桁、17桁 となっています。
 
フィールドにサイズ制限 15 を設けており、
エラートラップや、エラー無視 を掛けているなら、
 
フィールドへの代入に失敗し、そのまま続けて処理を続け
下記の状態になっているのではありませんか?
 

引用:
 『1行目』の変換のみになってしまい、
 『2行目以降』の変換が行われない状況です

回答
投稿日時: 23/07/14 17:39:26
投稿者: Suzu

SQL で求める時
 
SELECT
    SEQ,
    一時SID,
    IIF(GRP=1, "", IIF([変換#]>=5,"","_")) AS 文字,
    SWITCH
        (
            15-LenNK-LEN(CSTR(GRP_SORT))>=3, 2,
            15-LenNK-LEN(CSTR(GRP_SORT))=2, 1,
            15-LenNK-LEN(CSTR(GRP_SORT))=1, 0
        ) AS 0繰返数,
    GRP_SORT
FROM
    (
        SELECT
            SEQ,
            一時SID,
            新SID,
            LEN(新SID) AS LenNK,
            [変換#],
            (SELECT COUNT(*) FROM TBL_展開_元 AS AA WHERE AA.一時SID = A.一時SID) AS GRP,
            (SELECT COUNT(*) FROM TBL_展開_元 AS AA WHERE AA.一時SID = A.一時SID AND AA.SEQ < A.SEQ) AS GRP_SORT
        FROM TBL_展開_元 AS A
    );
 
ここまでできますから、
 
あとは、
「0繰返数」を引数として、STRING関数を使い、「0」の繰り返し文字列を作成
 
一時SID と、文字と、その作成された文字、同じ一時SID を持ったレコード中、SEQの昇順の順番
 
を連結すれば・・
 
 
自己連結を使っているので、更新クエリには応用できませんので
追加クエリ等を使い、一時テーブルに レコードを作成
その作成したレコードと元テーブルのSEQをキーとして更新クエリ実行
が宜しいかと。

投稿日時: 23/07/18 10:32:07
投稿者: human

sk様
Suzu様
 
 まず、
【_2行目以降_】や【_1行目_】は
今回の作成途中で目印として『今だけ』付加しているものでございますので
移行用データ完成すれば取ります
 
Q:
例えば、[一時SID]の値が "0123456789ABCDE" であるレコードが
2 件以上存在した場合、それぞれのレコードの[新SID]の値は
どのようになればよいのでしょうか。
A:"NEWLOT==001"・・・"NEWLOT==002"
 
現時点ではTEST段階なので
フィールド制限は設けておりません
 
●すみません、例示が酷かったのでしょう
 スレを締めることも考えましたが
 お問合せをできるだけシンプルにして
再度<あらためて>お伝え致しますので
宜しくお願い致します
================================
●(グループを見つけ)そのグループ毎に連番を振りたい
 連番付加後、16文字以上なら、一時SIDが『NEWNO==』だったものと同様に考え、
NEWNO==001、NEWNO==002 と、したい。
 
一時SID             | 新SID    
               
ABC009            | ABC009_001        同じコードが存在する(グループがある)ので連番を振る
ABC009            | ABC009_002        同じコードが存在する(グループがある)ので連番を振る
AXYZA-SBE1        | AXYZA-SBE1        (グループなし且つ15桁以内なので:そのまま)
CRW            | CRW_001        同じコードが存在する(グループがある)ので連番を振る
CRW            | CRW_002        同じコードが存在する(グループがある)ので連番を振る
CT145XPXXXXYA        | CT145XPXXXXYA    (グループなし且つ15桁以内なので:そのまま)
:    :    :    |
MTHRXOMA        | MTHRXOMA        (グループなし且つ15桁以内なので:そのまま)
NEWNO==        | NEWNO==001    同じコードが存在する(グループがある)ので連番を振る
NEWNO==        | NEWNO==002    同じコードが存在する(グループがある)ので連番を振る
NEWNO==        | NEWNO==003    同じコードが存在する(グループがある)ので連番を振る
NEWNO==        | NEWNO==004    同じコードが存在する(グループがある)ので連番を振る
NEWNO==        | NEWNO==005    同じコードが存在する(グループがある)ので連番を振る
NEWNO==        | NEWNO==006    同じコードが存在する(グループがある)ので連番を振る
:    :    :    
123456789ABCABC    | 123456789ABCABC    (グループなし且つ15桁以内なので:そのまま)
            
1234567890ABCDE    | 1234567890ABCDE    同じコードが存在する(グループがある)ので連番を振るが
1234567890ABCDE    | 1234567890ABCDE    アンダーバーとグループ数(この場合は[2]の1桁が追加できないので
一時SIDが『NEWNO==』だったものと同様に考え、NEWNO==001、NEWNO==002 と、したいです。
 
 何卒よろしくお願い申し上げます。
 
 

回答
投稿日時: 23/07/18 11:11:33
投稿者: hatena
投稿者のウェブサイトに移動

human さんの引用:

123456789ABCABC | 123456789ABCABC (グループなし且つ15桁以内なので:そのまま)
 
1234567890ABCDE    | 1234567890ABCDE    同じコードが存在する(グループがある)ので連番を振るが
1234567890ABCDE    | 1234567890ABCDE    アンダーバーとグループ数(この場合は[2]の1桁が追加できないので
一時SIDが『NEWNO==』だったものと同様に考え、NEWNO==001、NEWNO==002 と、したいです。

 
同じコードが存在する場合は、"_001"という書式の連番を追加するということですね。
ただし、『NEWNO==』だった場合は、"001"という書式(ハイフンがなくなる)ということですね。
 
コードが12桁以上だと"_001"という書式の連番を付加すると15桁をオーバーするので、"NEWNO=="に変換して"001"という書式の連番を追加するということでいいですか。
 
 
 

投稿日時: 23/07/18 13:19:27
投稿者: human

hatena様
ご回答、誠にありがとうございますッ!
 
>同じコードが存在する場合は、"_001"という書式の連番を追加するということですね。
>ただし、『NEWNO==』だった場合は、"001"という書式(ハイフンがなくなる)ということですね。
  
>コードが12桁以上だと"_001"という書式の連番を付加すると15桁をオーバーするので、
>"NEWNO=="に変換して"001"という書式の連番を追加するということでいいですか。
 
 シンプルにすると言ってまだ、シンプルでない部分ございましたねすみません
仰る通りですが、シンプルにする為、
連番との接続部分は『無視して下さい』どちらも[_]なしで結構です
 
よろしくお願い致します。

回答
投稿日時: 23/07/18 15:26:34
投稿者: sk

引用:
Q:
例えば、[一時SID]の値が "0123456789ABCDE" であるレコードが
2 件以上存在した場合、それぞれのレコードの[新SID]の値は
どのようになればよいのでしょうか。
A:"NEWLOT==001"・・・"NEWLOT==002"

引用:
連番との接続部分は『無視して下さい』どちらも[_]なしで結構です

(標準モジュール)
--------------------------------------------------------------------
Sub ConvertSerialId()

    '定数の宣言
    
    Const SourceTableName As String = "TBL_展開_元"         '参照元テーブル名
    Const DestinationTableName As String = "TBL_展開_先"    '出力先テーブル名
    Const KeyPrefixOnError As String = "NEWNO=="            'エラー時のキー接頭辞
    
    Dim db As DAO.Database
    Dim strSQL As String
            
    'カレントデータベースの参照
    
    Set db = CurrentDb

    '出力先テーブルの全てのレコードを削除
    
    strSQL = "DELETE * FROM [" & DestinationTableName & "];"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError
    
    '参照元テーブルのレコードを出力先テーブルに追加する。
    'その際、[一時SID]には[SID]と同じ値を出力する。
    strSQL = "INSERT INTO [" & DestinationTableName & "] " & _
             "([SEQ],[SID],[一時SID],[新SID])" & _
             " SELECT t1.[SEQ], t1.[SID], t1.[SID], Null" & _
             " FROM [" & SourceTableName & "] t1;"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError
             
    '出力先テーブルの全てのレコードの[一時SID]の値に含まれる
    '半角/全角スペースを取り除く
    '([一時SID]の値が Null である場合は空文字列として扱う)
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[一時SID] = Replace(Nz(t1.[一時SID],""""),"" "","""",1,-1,1);"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError
    
    '出力先テーブルのレコードのうち、[一時SID]の値が空文字列であるレコードの
    '[一時SID]の値をエラー時キー接頭辞に書き換える
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[一時SID] = """ & KeyPrefixOnError & """" & _
             " WHERE t1.[一時SID]="""";"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError
    
    '出力先テーブルのレコードのうち、[一時SID]の値に2バイト文字が含まれているレコードの
    '[一時SID]の値をエラー時キー接頭辞に書き換える
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[一時SID] = """ & KeyPrefixOnError & """" & _
             " WHERE Len(t1.[一時SID]) < LenB(StrConv(t1.[一時SID],128))" & _
             " AND [一時SID] <> """ & KeyPrefixOnError & """;"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError

    '出力先テーブルのレコードのうち、[一時SID]の値に
    'ハイフン、アルファベット、数字のどれにも該当しない文字が含まれるレコードの
    '[一時SID]の値をエラー時キー接頭辞に書き換える
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[一時SID] = """ & KeyPrefixOnError & """" & _
             " WHERE t1.[一時SID] Like ""*[!-0-9a-z]*""" & _
             " AND [一時SID] <> """ & KeyPrefixOnError & """;"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError

    '出力先テーブルのレコードのうち、[一時SID]の値の長さが 15 文字を超えるレコードの
    '[一時SID]の値をエラー時キー接頭辞に書き換える
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[一時SID] = """ & KeyPrefixOnError & """" & _
             " WHERE Len(t1.[一時SID]) > 15" & _
             " AND t1.[一時SID] <> """ & KeyPrefixOnError & """;"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError

    '出力先テーブルの全てのレコードの[一時SID]の値に含まれる
    'アルファベットを大文字に変換する
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[一時SID] = StrConv(t1.[一時SID],1)" & _
             " WHERE t1.[一時SID] <> """ & KeyPrefixOnError & """;"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError

    '出力先テーブルのレコードのうち、[一時SID]の値の長さが 12 文字を超え、
    'かつ「[一時SID]の値が等しく[SEQ]の値が等しくない(他の)レコード」が存在するレコードの
    '[一時SID]の値をエラー時キー接頭辞に書き換える
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[一時SID] = """ & KeyPrefixOnError & """" & _
             " WHERE Len(t1.[一時SID]) > 12" & _
             " AND t1.[一時SID] <> """ & KeyPrefixOnError & """"
             
    strSQL = strSQL & _
             " AND EXISTS(" & _
             "SELECT t2.* " & _
             " FROM [" & DestinationTableName & "] t2" & _
             " WHERE t2.[一時SID] = t1.[一時SID]" & _
             " AND t2.[SEQ] <> t1.[SEQ]" & _
             ");"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError

    '出力先テーブルのレコードのうち、「[一時SID]の値が等しく
    '[SEQ]の値が等しくない(他の)レコード」が存在しないレコードの
    '[新SID]の値を[一時SID]と同じ値に書き換える
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[新SID] = t1.[一時SID]"
    
    strSQL = strSQL & _
             " WHERE NOT EXISTS(" & _
             "SELECT t2.* " & _
             " FROM [" & DestinationTableName & "] t2" & _
             " WHERE t2.[一時SID] = t1.[一時SID]" & _
             " AND t2.[SEQ] <> t1.[SEQ];" & _
             ")"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError

    '出力先テーブルのレコードのうち、[新SID]の値が Null である
    '(前述の SQL における条件に該当しない)レコードの
    '[新SID]の値を「[一時SID]の値の後ろにゼロ埋め3桁連番([SEQ]の昇順)を
    '付加した文字列」に書き換える
    
    strSQL = "UPDATE [" & DestinationTableName & "] t1" & _
             " SET t1.[新SID] = t1.[一時SID] & Format(DCount(""*"",""" & DestinationTableName & """,""[一時SID]='"" & t1.[一時SID] & ""' AND [SEQ]<="" & t1.[SEQ]),""000"")"
    
    strSQL = strSQL & _
             " WHERE t1.[新SID] IS NULL;"
    Debug.Print strSQL
    db.Execute strSQL, dbFailOnError

    Set db = Nothing

End Sub
--------------------------------------------------------------------
 
以上のようなコードを実行できればよい、ということでしょうか。

回答
投稿日時: 23/07/18 15:27:09
投稿者: Suzu

23/07/14 17:39:26 のSQL でも 一通りの分岐 条件を得る所までは
できるかと思うのですが不足でしたでしょうか?
 
 
 
 
あくまで、レコードセットのみ で実行するにしても
 
当方なら、RecordsetOpen の段階で 同一のSIDが
 他に存在するかどうかの判定を レコードセット内に含めたい。
 
 1件目なのか2件目以降なのかで分ける必要も感じないので・・
 
以下の様な感じで良いのではないかと。。
 
少なくとも、ループ内で 別のテーブルを参照しそこでもループさせる 二重ループの必要は無いでしょう。
 

strSQL =  "SELECT *, " & _
    "(" & _
      "SELECT COUNT(*) " & _
      "FROM TBL_展開_元 AS AA " & _
      "WHERE AA.一時SID = A.一時SID" & _
    ") AS LDCount " & _
  "FROM TBL_展開_元 AS A " & _
  "ORDER BY 一時SID ASC, SEQ ASC;"

Set rs = DB.OpenRecordset(strSQL, dbOpenDynaset)

Do While Not rs.EOF
  i = i + 1
  rs.Edit

  If rs![LDCount] = 1 Then
    rs![新SID] = rs![一時SID]
  Else
    If rs![新SID] = NewLOT Then
      ii = ii + 1
    Else
      ii = 1
    End If

    If rs![変換#] < 5 Then Moji = "_"

    Select Case Len(rs![一時SID] & Moji)
      Case Is < 13
        rs![新SID] = rs![一時SID] & Moji & Format(ii, "000")
      Case 13
        rs![新SID] = rs![一時SID] & Moji & Format(ii, "00")
      Case 14
        rs![新SID] = rs![一時SID] & Moji & Format(ii, "0")
      Case Else
    End Select
  End If
  rs.Update

  NewLOT = rs![新SID]

  rs.MoveNext
Loop

投稿日時: 23/07/18 18:38:37
投稿者: human

sk様
Suzu様
長文の御回答、誠にありがとうございました
 
まず、sk様のは
一瞬で終了し
レコードができませんでした
 
次にSuzu様のは
 
@ If CurRSQ![新SID] = NewLOT Then の
 でエラーになりましたので
 Do While Not CurRSQ.EOF
  i = i + 1
   
  NewLOT = CurRSQ![一時SID] と、しました
 
A 書き込みできないクエリ エラーになりましたので
 書き込み先を本来の書き込み先テーブルに変更しました
 (その時、editを CurRST.AddNew 等に適宜変更しております)
 
結果は、私と同じような・・・新SIDが(変換したものはすべて)
 NEWLOT==_001 と、なりました
 
おそらく、私の設定ミスだと存じます
いろいろ、ありがとうございました
 
※ ちなみに、繰り返しになりますが
●『SID(元の機械シリアル)』から『一時SID』への変換は
自作のつたないFunctionですが、一応問題なく動作しておる(はず)でありまして
今のところは、期待通りのデータを出力しております
 
 
Simpleに連番が振れればと存じますので
 
●(グループを見つけ)そのグループ毎に連番を振りたい
 連番付加後、16文字以上なら、一時SIDが『NEWNO==』だったものと同様に考え、
NEWNO==001、NEWNO==002 と、したい。
  
一時SID   | 新SID
     
AXYZA-SBE1 | AXYZA-SBE1 (グループなし且つ15桁以内なので:そのまま)
ABC009 | ABC009_001 同じコードが存在する(グループがある)ので連番を振る
ABC009 | ABC009_002 同じコードが存在する(グループがある)ので連番を振る
 
CRW | CRW_001 同じコードが存在する(グループがある)ので連番を振る
CRW | CRW_002 同じコードが存在する(グループがある)ので連番を振る
: : : |
NEWNO== | NEWNO==001 同じコードが存在する(グループがある)ので連番を振る
NEWNO== | NEWNO==002 同じコードが存在する(グループがある)ので連番を振る
NEWNO== | NEWNO==003 同じコードが存在する(グループがある)ので連番を振る
NEWNO== | NEWNO==004 同じコードが存在する(グループがある)ので連番を振る
NEWNO== | NEWNO==005 同じコードが存在する(グループがある)ので連番を振る
NEWNO== | NEWNO==006 同じコードが存在する(グループがある)ので連番を振る
: : :
123456789ABCABC | 123456789ABCABC (グループなし且つ15桁以内なので:そのまま)
             
1234567890ABCDE | 1234567890ABCDE
1234567890ABCDE | 1234567890ABCDE 同じコードが存在する(グループがある)ので連番を振るが
                     アンダーバーとグループ数(この場合は[2]の1桁でも16桁となり、追加できないので
                     一時SIDが『NEWNO==』だったものと同様に考え、NEWNO==001、
                     NEWNO==002 と、したいです。
 
何卒よろしくお願い申し上げます。

回答
投稿日時: 23/07/19 14:43:03
投稿者: sk

引用:
まず、sk様のは
一瞬で終了し
レコードができませんでした

・ConvertSerialId プロシージャを実行したが、いずれかのステートメントにおいて
 何らかの実行時エラーが発生し、コードの実行が中断された。
 
・最後のステートメントまで実行されたが、[TBL_展開_先]には
 何のレコードも出力されなかった。
 (レコード件数が 0 件である)
 
・最後のステートメントまで実行されたが、[TBL_展開_先]に出力された
 一部の(または全ての)レコードの[新SID]の値が変換規則通りに出力されなかった。
 
・上記以外。
 
いずれの意味でおっしゃっているのでしょうか。

投稿日時: 23/07/19 14:49:05
投稿者: human

sk様
いつもお世話になっております
 
 もちろん、2番目でございます

回答
投稿日時: 23/07/19 15:15:41
投稿者: sk

引用:
もちろん、2番目でございます

引用:
・最後のステートメントまで実行されたが、[TBL_展開_先]には
 何のレコードも出力されなかった。
 (レコード件数が 0 件である)

その場合、「参照元であるテーブル[TBL_展開_]には
そもそも何のレコードも格納されていない」
(INSERT INTO 文によって[TBL_展開_]に追加されるべき
レコードが 1 件もない)以外の原因はあり得ません。

回答
投稿日時: 23/07/19 15:39:38
投稿者: Suzu

テストが不十分でした。 失礼しました。
 

strSQL = _
  "SELECT *, DCOUNT(""*"",""TBL_展開_元"",""一時SID='"" & TBL_展開_元.一時SID & ""'"") AS LDCount " & _
  "FROM TBL_展開_元 " & _
  "ORDER BY 一時SID ASC, SEQ ASC;"

Set rs = DB.OpenRecordset(strSQL, dbOpenDynaset)

Do While Not rs.EOF
  i = i + 1

  rs.Edit

  If rs![LDCount] = 1 Then
    rs![新SID] = rs![一時SID]
  Else
    If rs![一時SID] = NewLOT Then
      ii = ii + 1
    Else
      ii = 1
    End If

    If rs![変換#] < 5 Then
      Moji = "_"
    Else
      Moji = ""
    End If

    Select Case Len(rs![一時SID] & Moji)
      Case Is < 13
        rs![新SID] = rs![一時SID] & Moji & Format(ii, "000")
      Case 13
        rs![新SID] = rs![一時SID] & Moji & Format(ii, "00")
      Case 14
        rs![新SID] = rs![一時SID] & Moji & Format(ii, "0")
      Case Else
    End Select
  End If
  rs.Update

  NewLOT = rs![一時SID]

  rs.MoveNext
Loop

 
ここまでコードを書ける方であれば、
 
条件分岐 変換# の分岐で、Else時の分岐が必要 であり
5の時とそれ以外の時 で、 変数 Moji が「_」「何もない」となる必要がある
これは 理解できると思いっていただけに残念です。
(当方の検討が不十分なのを棚に上げてなので・・すみません)
 
希望動作のコード そのモノも提示しましたので、当方はここまでの区切りとさせていただきます。

投稿日時: 23/08/26 15:06:06
投稿者: human

いろいろありがとうございました
結論から申し上げますと、できました。
本来、そのコーd-を載せたいところですが
実際の内容と名称等かなり変更していますので
それを実行するまで今暫くお時間ください
よろしくお願い致します

トピックに返信