この人頭いいなと思ったエピソード

宜しくお願いします。

使用環境:access(2002-2007)

前回の続きでもありますが、自動で番号を採番する仕組みを作りました。
(一応、前回分も・・)http://oshiete1.goo.ne.jp/qa5742518.html
「10AA0001」から始まり、あとは後ろの数字が0002,0003~と増えていく仕様で出来ました。
最初の「10」というのは2010年のうしろ二桁の「10」です。(date関数)

(相談)
これを2011年になったら、後ろの数字を0001に自動的にセットし直す仕様にしたいのです、
そこから0002,0003~と増えるようにして、また年が変わるごとに0001にセットされるような仕組みにしたいです。

検索サイトで調べるとやり方が出てくるのですが、
まだVBAの理解力がないので、まったくもってわかりません。
たぶんIfで示されるDcount関数に関係があるのかなー、という気はします。
(前置きの部分なので)
僕にはちょっとレベルが高いかも知れませんが、理解できるよう努力します。

以下に、構文を書きます。
また来年になるまで「実際、変わるか検証ができない」というのもアレなので、
テスト環境ではnow関数を使い「hhnn」でやってます。
「分」が変わるごとに0001に戻れば自分なりにOKだと思っています。
(now関数で連番動作することは確認できました)


・・・・・・・・・

'------------------------------------------------------------
' Form_BeforeInsert
'
'------------------------------------------------------------
Private Sub Form_BeforeInsert(Cancel As Integer)
On Error GoTo Form_BeforeInsert_Err

If (DCount("見積り番号", "案件") = 0) Then
見積り番号 = "00AA0001"
Exit Sub
End If
見積り番号 = Right(Format(Date, "yyyy", 2), 2) & Format(DMax("Right(見積り番号,4)", "案件") + 1, "AA" & "0000")


Form_BeforeInsert_Exit:
Exit Sub

Form_BeforeInsert_Err:
MsgBox Error$
Resume Form_BeforeInsert_Exit

End Sub

・・・・・・・・・


○ now関数の場合 ※一文のみ抜粋
・・・・・
見積り番号 = Right(Format(Now, "hhnn", 2), 2) & Format(DMax("Right(見積り番号,4)", "案件") + 1, "AA" & "0000")
・・・・・

教えてください、宜しくお願いします。

A 回答 (3件)

年が変わったというのは、操作している日付で判別して良いのでしょうか。



その条件で、
以下ではどうでしょうか。

 Dim vDt As Variant

 vDt = DMax("見積り番号", "案件", "見積り番号 Like '" & Format(Date, "yy") & "*'")
 If (IsNull(vDt)) Then
  見積り番号 = Format(Date, "yy") & "AA0001"
 Else
  見積り番号 = Left(vDt, 4) & Format(Val(Right(vDt, 4)) + 1, "0000")
 End If


※ 西暦下2桁で始まる最大を求めます。
なければ、その年の初期値を設定し、あれば、右4桁部分の数値を+1します。

この際、今日の西暦下2桁を使用します。

この回答への補足

回答ありがとう、ございます、出来ました!

now関数で分刻みで0001に戻る仕組みにして成功しました。
それで、差支えなければ講釈して頂けると幸いなのですが・・・。
VBA初心者なので私の解釈があってるのかもわかりません。

まず、今回、回答者様が定義されたvDtをshにしました。
特に意味はないのですが、ある程度、何でもいい(関数みたい文字列やめておこう)、
みたいなことが、(ネットで)書いてあったので、
自分なりに、とっつき易いように変更してみました。
で、shはバリアント型と宣言。

特にわからないのは、Elseの後の文です。

Else
見積り番号 = Left(sh, 4) & Format(Val(Right(sh, 4)) + 1, "0000")


ifで始まり、その構文の内容と違った場合はElseに行きますが、
なぜ、Left関数で左から四番目の文字を取るのか、
(2010年だと10AA0001の「A」の部分?)
またVal関数を入れた意味がわかりません(汗)
(というか使ったことがないので、用途をしらないのです・汗)

もしよかったら教えてください。


※以下、今回、成功した構文
・・・・・・・・・・・
Dim sh As Variant

sh = DMax("見積り番号", "案件", "見積り番号 Like '" & Format(Now, "nn") & "*'")

If (IsNull(sh)) Then
見積り番号 = Format(Now, "nn") & "AA0001"
Else
見積り番号 = Left(sh, 4) & Format(Val(Right(sh, 4)) + 1, "0000")
End If
・・・・・・・・・・・

補足日時:2010/03/14 21:22
    • good
    • 1

#2です



> vDt = DMax("見積り番号", "案件", "見積り番号 Like '" & Format(Date, "yy") & "*'")
↓これを今日固定で書きなおすと
vDt = DMax("見積り番号", "案件", "見積り番号 Like '10*'")
となります。

見積り番号が 10 で始まるものの中での最大見積り番号を得るものになります。

DMax のヘルプで使い方を見てください。
3番目の引数には、条件を指定できます。

vDt = DMax("Right(見積り番号,4)", "案件", "見積り番号 Like '10*'")
のように、得る段階で数字部分のみを抜き出すこともできますが、
私は素の値を得てから必要に応じて加工することを良くやります。
    • good
    • 0
この回答へのお礼

回答ありがございます!

親身に対応頂いて勉強になりました。

今、マクロからVBAに少しづつ移行しつつ(勉強しつつ)、
「2007でモジュールってどう動かすんだ?」みたいな
謎につつまれています。
最初からVBAで書くと書き易いんですが、マクロで作ったものを
VBAに変換して使用しようとすると訳がわからなくなりますね(苦笑)
というか、access2007のモジュールの使用の仕方がわからないだけですが。

というわけで、ありがとうございました。
また何かございましたら、宜しくお願いします。

お礼日時:2010/03/18 00:38

#1です



> 今回、回答者様が定義されたvDtをshにしました。
> 特に意味はないのですが、ある程度、何でもいい(関数みたい文字列やめておこう)、

これは何でもいいと思います。
ご自分のわかりやすい名前(文字列)を使えばいいと思います。

vData とかにしようかと思いましたが、短くていいや・・・程度で提示しました。
(VBAとかの命名規則がそれなりにあるようですが・・・・私には長すぎるので)

私は Variant なら、先頭に v
文字列(String)なら、先頭に s という命名にしています。
VBA での解釈では大文字小文字は関係ないようなので、予約語にならないように命名すればよいと思います。

ダメな例)

Top を表す文字列なので、sTop にしてみたら・・・・
これは STOP と同じなので・・・NG など

> なぜ、Left関数で左から四番目の文字を取るのか、
Left は、文字目ではなく文字分になります。

Left("10AA0001",4) なら、"10AA0001" の左から4文字分を取るので "10AA" になります。

> Val(Right(sh, 4))+1
右から4文字取ったものを数値にして・・・
実際には数値の文字列への足し算はできる(?)のかもしれませんが、
取った部分を数値にして足し算して、結果を・・・

1度ヘルプで Val を見てみてください。
Val ではなく CInt / CLng でも・・・


※ DCount ではなく、DMax ですることについては理解されましたでしょうか。
DMax の方が安全なのかなぁということで、使っていましたが・・・

"10AA0001"
"10AA0002"
の2つがあったとします。

DCount なら、次は 0003 になるのですが、ここで、"10AA0001" が削除されていたら?を考えると、
DCount では、1個しかないので,次の候補は "10AA0002" になり、重複することが考えられます。
DMax なら、どちらが削除されていたとしても、次の候補は重複したものにはなりません。


補足が必要なら、また書いてください。

この回答への補足

回答ありがとうございます、いろいろ調べました!

-----------------
(関数)
・Val関数
数字(String型)を適当な数値型のデータに変換します。
ただし、数値に変換できない文字を読み込んだ時点で変換を中止します。

・CInt関数
指定された式をバリアント型 (内部処理形式が整数型 (Integer) の Variant) に変換して返します。

・CLng関数
指定された式をバリアント型 (内部処理形式が長整数型 (Long) の Variant) に変換して返します。
-----------------

それぞれのサンプルコードもネット上にあったので、なんとなく雰囲気はつかめました。
VAlを使ったのは「数値にして”1”を足す」という安全・確実を取った感じですね。^^

・・・
DCountについては僕の最初に出した質問のコードで
試しましたが(5レコード目まで書いて、DCountにあたる一行目を削除しました)
問題なく、重複せずに次の数字(6だったかな)が当てられました^^
now関数で分刻みでやっていたので、素早さが求められましたが(苦笑)
ただ、安全に越したことはないですね^^
(あ、DCount関数を使って数字をセットし直すのはやっていません、
コードがわかりませんし・汗)

あとしいて言えば一行目が高度ですね^^;
それぞれの関数は使ったことがあるので、見て「あー」とわかるのですが、
この発想はなかったです、というかシンプルで高度です^^;
vDt = DMax("見積り番号", "案件", "見積り番号 Like '" & Format(Date, "yy") & "*'")

もしよかったら、講釈をください。(恥ずかしながら・・)

補足日時:2010/03/15 22:24
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す


おすすめ情報