下記のようなデータがあります。
2004/02/17 A社 苺 10個
2004/02/17 A社 桃 10個
2004/02/17 B社 梨 10個
2004/02/18 A社 苺 10個
このデータの先頭に下記のような連番を付けたいと思います。
001 2004/02/17 A社 苺 10個
001 2004/02/17 A社 桃 10個
002 2004/02/17 B社 梨 10個
003 2004/02/18 A社 苺 10個
フォーム上に同じ日付及び会社名をキーとしてデータを抽出後、連番を付け処理を行ったのですが、
手間と時間が掛かり過ぎるとの事で却下されてしまいました。
このような条件の場合、皆様はどのように作成されるか是非ご意見を伺いたく思います。
宜しくお願い致します。
テキストファイルですよね?
これ、どういう規則があるんでしょうか?
"会社名が同じで、日付も同じうちは同じ番号"ということでしょうか?
データーベースであれば、通常はタイムスタンプで処理
すると思います。データーのフィールドをもう一つ作って
作成時間をmSecまで入れるとか。
回答ありがとございます。
データはACCERSSにあり、注文番号を作成する際に必要な連番です。
「たかみちえ」さんが書いていらっしゃる通り、会社名が同じで、日付も同じ
レコードには同じ番号を付けなくてはいけないそうなのです・・・。
「ねろ」さんが書かれている回答に対してなのですが、本来の1レコードには
何時:何分:何秒に入力したと言う事も登録されています。
タイムスタンプの処理方法が私には分かりません。
宜しければ詳細を教えて下さい。
分かりづらい説明で申し訳ありませんが宜しくお願い致します。
修正
ACCERSS→ACCESSです。
A社の注文書には品名レコードが2件となりますが、注文番号は同じ連番で
フィールドに保存したいと考えています。
良い考えがありましたら宜しくお願い致します。
タイムスタンプ
http://www.nifty.com/webapp/digitalword/word/023/02316.htm
>タイムスタンプの処理方法が私には分かりません。
Now とかで処理した時点でコンピュータのシステム時刻を取るだけのような
気もしますが…。
要はフォームに表示して連番を手入力(?)するのを自動化すれば良いんですか?。
1. 日付及び会社名を条件としてデータを抽出。
2. 同じ日付及び会社名が見つかった場合はその連番を採用。
3. 見つからなかった場合は連番の最大値(数値型なら『MAX(連番)』文字列なら
『ORDER BY 連番 DESC』で『TOP 1』)に+1して登録。
ただし日付が同じ条件は何時:何分:何秒のデータは引っかからないように
しないといけないですね。
タイムスタンプについて
http://www.ipa.go.jp/security/pki/093.html
ああ、こーゆーのも関係あるのか…
…まぁ、今回の質問とは直接関係無いでしょうね。
主キーに作成時間を利用する場合とかは参考に…
やや..少し質問の意味を読み間違えた様な............ (^^;
取り扱うデーターの数にもよりますが、このような場合は'受注マスター'
の様なレコードを作製して、フィールドは
「受注連番、顧客コード、受注数、トータル金額、作成日、作成時間、変更日、変更時間」
こんな感じで、各注文のフィールドは
「受注連番、顧客コード、品目コード、数量、金額、作成日、作成時間」
(受注連番は一顧客に対して、一日一つ取られる)
はこんな感じにして、注文を入力するときは、既にその日の受注連番が取られていれば、
受注数とトータル金額を更新する、受注連番が無ければ前の番号に一つ足して新しく作成する。
こうしておけば、その日のデーターは作成日をキーにして抽出して、受注連番順に並べれば
良いし、伝票番号は受注連番を使用することも出来る。
こんなのではどうですか。
根本的に…[受注連番]を[会社コード]&[日付]にしてしまう。
会社コード
A社 001
B社 002
検索する必要なし、A社の注文が2004/02/18に入れば
[受注連番]は00120040218に決定。その時点でデータ書き込み。
伝票番号が[受注連番]なら人間が見て間違ってないことも確認可能。
ただし複数端末で運用する場合ちょっと注意が必要かも。まぁ、
INSERT してれば後は主キーとか他の条件でなんか考えればいいだろうけど…
あと、情報が公開されたも同然なので伝票偽造が簡単w
ってゆーか注文受付のときに注文受付システムが伝票番号作る
必要が無いんだよね。
伝票作る時点で伝票作成システムが連番作れば良いわけで…
注文テーブルの日付と会社名で GROUP BY してください。
[伝票コード作成用テーブル]
日付 会社名 伝票コード(主キー)
2004/02/17 A社 001
2004/02/17 B社 002
2004/02/17 C社 003
2004/02/18 A社 004
2004/02/18 C社 005
2004/02/19 A社 006
…これだとねろさんのやり方に近い…
皆様、回答ありがとうございます。
実際にはテーブルが二つ存在し、
見積りテーブル
-------------------------------------------
日付 業者名 品名 個数
2004/02/17 A社 苺 10個
2004/02/17 A社 桃 10個
2004/02/17 B社 梨 10個
2004/02/18 A社 苺 10個
注文テーブル
-------------------------------------------
注文番号 日付 業者名 品名 個数
001 2004/02/16 C社 柿 10個
としております。
私はまだ未熟ですので、フォームに注文テーブルの内容をリストボックスで表示し、最終連番を見える状態にしておいて、日付と業者をキーとして見積りテーブルから該当するデータを抽出し、テキストボックスに+1した連番を入力して、それを使用し注文テーブルに保存するという方法をしておりました。
本当は、フォーム上にデータを表示する事無く、ボタン一つで連番を登録したいと考えています。
そこで・・・・・
見積りテーブルのデータと注文テーブルの最終レコードの日付・業者を比較して違う条件の場合、連番に+1して注文テーブルへと登録すると言った用にしたいと思います。常に注文テーブルの最終レコードの日付、業者の値と比較して条件が同じでなければ+1して登録すると良いのでは無いかと考えたのですが・・・。
見積りテーブルのフィールドに比較が終了するとチェックして再び比較出来ないようにするとか・・・。
説明が不十分で大変ご迷惑をおかけしているかと思います。
「特攻隊長まるるう」さんが書き込まれている通り1.2.3.の自動化と同じ事だと思います。
自動化する方法について教えて下さい。
宜しくお願い致します。
…いや、あの…自動化の方法が1.2.3.なんですが(^^;)
順番にコーディングすれば自動化できます。
それ以上は VB のバージョンや接続の仕方で変わってきますし、
コードもプログラマの数だけ存在します。
稲兎さんの書いた簡単なサンプルを載せていただければ修正しますが…
一から作れと言われても…ボクは面倒なので放置しちゃう方です(ぉ
Dim strData As String
strData = "select Atable.* " & _
"from Atable "
Dim recData As ADODB.Recordset
Set recData = New ADODB.Recordset
recData.Open strData, cnn, adOpenStatic, adLockPessimistic
recData.MoveLast
Dim strBase As String
strBase = "select Btable.* " & _
"from Btable " & _
"where(Btable.Check=0)"
Dim recBase As ADODB.Recordset
Set recBase = New ADODB.Recordset
recBase.Open strBase, cnn, adOpenStatic, adLockPessimistic
If recData!Day = recBase!Day And recData!Gyousya = recBase!Gyousya Then
Do Until recBase.EOF
With recBase
recBase!tCD = Format(recData!tCD, "000")
recBase!Check = 1
With recData
.AddNew
.Fields!tCD = recBase!tCD
.Fields!Day = recBase!Day
.Fields!Gyousya = recBase!Gyousya
.Fields!Hinmei = recBase!Hinmei
.Fields!suuryo = recBase!suuryo
.Update
End With
.Update
.MoveNext
End With
Loop
Else
End if
Atable(注文テーブル)
tCD Day Gyousya Hinmei suuryou
001 2002/02/16 A社 苺 10
002 2002/02/16 B社 柿 10
-------------------------------------------
002 2002/02/16 B社 桃 10 ←行いたい結果
003 2002/02/17 A社 梨 10 ←行いたい結果
Btable(見積りテーブル)
tCD Day Gyousya Hinmei suuryou
2002/02/16 B社 桃 10
2002/02/17 A社 梨 10
上記プログラムを実行すると、
注文テーブルに見積もりテーブルの全てのデータが注文番号002で登録されてしまいます。
取り合えず、見積りテーブルの最初のレコードが002で登録が出来ないかと思って作ってみたのですが、上手く実行しません。
不適切な箇所が多々あるかと思いますので、ご指導宜しくお願い致します。
Dim strData As String
strData = "select Atable.* " & _
"from Atable "
Dim recData As ADODB.Recordset
Set recData = New ADODB.Recordset
recData.Open strData, cnn, adOpenStatic, adLockPessimistic
recData.MoveLast
Dim strBase As String
strBase = "select Btable.* " & _
"from Btable " & _
"where(Btable.Check=0)"
Dim recBase As ADODB.Recordset
Set recBase = New ADODB.Recordset
recBase.Open strBase, cnn, adOpenStatic, adLockPessimistic
Dim strNum As String
strNum = Format(recData!tCD, "000")
Do Until recBase.EOF
If recData!Day = recBase!Day And recData!Gyousya = recBase!Gyousya Then
With recData
.AddNew
.Fields!tCD = strNum
.Fields!Day = recBase!Day
.Fields!Gyousya = recBase!Gyousya
.Fields!Hinmei = recBase!Hinmei
.Fields!suuryo = recBase!suuryo
.Update
.MoveLast
End With
With recBase
recBase!tCD = strNum
recBase!Check = 1
.Update
.MoveNext
End With
Else
strNum = Format(recData!tCD + 1, "000")
With recData
.AddNew
.Fields!tCD = strNum
.Fields!Day = recBase!Day
.Fields!Gyousya = recBase!Gyousya
.Fields!Hinmei = recBase!Hinmei
.Fields!suuryo = recBase!suuryo
.Update
.MoveLast
End With
With recBase
recBase!tCD = strNum
recBase!Check = 1
.Update
.MoveNext
End With
End If
Loop
これで解決出来ました。
皆様、ご意見ありがとうございました。
また、もっと良い方法がありましたら「解決」としておりますが、ご指導お願い致します。
はいっ!せんせぇっ!以下の操作をするときに
マズいと思いますっ!!(>△<)
Atable(注文テーブル)
tCD Day Gyousya Hinmei suuryou
001 2002/02/16 A社 苺 10
002 2002/02/16 B社 柿 10
-------------------------------------------
002 2002/02/16 B社 桃 10 ←行いたい結果
001 2002/02/16 A社 梨 10 ←行いたい結果
Btable(見積りテーブル)
tCD Day Gyousya Hinmei suuryou
2002/02/16 B社 桃 10
2002/02/16 A社 梨 10
データベースのレコードの順番は必ずしも順番通りとは限りません。
上のコードのように何の条件の指定も無く
>注文テーブルの最終レコード
という考え方は非常に危険です。ORDER BY で並べ替えるのは必須事項です。
また、データベースを変更する時は、トランザクション処理を考えます。
トランザクション処理を省くということは、途中でエラーが発生した場合、
データベースの整合性が取れなくなるということです。壊れます。
データベースの機能をもう少し利用しましょう。ただの入れ物ではありません。
必要な条件を限定すればするほど、必要最小限のテーブルの処理で済み、
速度アップに繋がります。
SQL文について、データベースの処理について、ほとんど学んでおられないよう
ですが、入門書を1冊買って読むだけでだいぶ違います。
ORDER BY
GROUP BY
INNER JOIN 〜 ON
の文を書けるだけでかなり苦労が減ります。
あと…[数量]のフィールド名は[suuryo]ですか?[suuryou]ですか?
[suuryou]でファイル作ったのでコードもこちらにしてます。
' テスト.mdbのパスは環境に合わせて変更してください。
' Form1 に MSFlexGrid1 と Command1,Command2 を貼り付けてください。
' ただしデータに Null が含まれていた場合、正常に動作しません。
' テーブル内のフィールド [Day] は日付型です。
Option Explicit
Private cnn As New ADODB.Connection
Private recData As ADODB.Recordset ' 注文テーブル用
Private recBase As ADODB.Recordset ' 予約テーブル用
Private Const con_tCDMax As Integer = 3 ' tCD の桁数最大(4桁になるとメッセージが出る:エラー処理はしないで4桁で登録)
Private Sub Form_Load()
cnn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=C:\Data\テスト.mdb"
cnn.Open
MitumoriHyouji
End Sub
Private Sub Form_Unload(Cancel As Integer)
cnn.Close
End Sub
Private Sub Command1_Click()
Dim strData As String
Dim str_tCD As String
Dim dtmDay As Date
Dim strGyousya As String
Dim lngNewCode As Long
Dim lngUpDateCode As Long
Dim i As Integer
dtmDay = 0
strGyousya = ""
' 新規追加時の tCD を最初に求めてしまう。
'SELECT TOP 1 tCD FROM Atable ORDER BY tCD DESC
strData = " SELECT TOP 1 tCD" & _
" FROM Atable" & _
" ORDER BY tCD DESC"
Set recData = New ADODB.Recordset
With recData
.Open strData, cnn, adOpenStatic, adLockPessimistic
If .RecordCount <= 0 Then
lngNewCode = 0
Else
lngNewCode = CLng(.Fields("tCD").Value) + 1
End If
End With
' トランザクション処理開始
cnn.BeginTrans
On Error GoTo Rollback
With recBase
.MoveFirst
For i = 1 To .RecordCount
' 日付か業者名が違った場合は tCD が存在するか検索
If dtmDay <> CDate(.Fields("Day").Value) _
Or strGyousya <> CStr(.Fields("Gyousya").Value) Then
dtmDay = CDate(.Fields("Day").Value)
strGyousya = CStr(.Fields("Gyousya").Value)
'SELECT TOP 1 tCD FROM Atable WHERE Day = #xx/xx/xxxx# AND Gyousya = 'xx'
strData = "SELECT TOP 1 tCD" & _
" FROM Atable" & _
" WHERE Day = #" & Format(dtmDay, "mm/dd/yyyy") & "#" & _
" AND Gyousya = '" & strGyousya & "'"
Set recData = New ADODB.Recordset
recData.Open strData, cnn, adOpenStatic, adLockPessimistic
If recData.RecordCount <= 0 Then
' 過去に同じ tCD が存在しなかった場合 lngNewCode で UpDate
lngUpDateCode = lngNewCode
lngNewCode = lngNewCode + 1
If Not (AtableUpDate(lngUpDateCode)) Then
GoTo Rollback
End If
Else
' 過去に同じ tCD が存在した場合その tCD で UpDate
lngUpDateCode = CLng(recData.Fields("tCD").Value)
If Not (AtableUpDate(lngUpDateCode)) Then
GoTo Rollback
End If
End If
Else
' 日付と業者名が前のレコードと同じ場合は lngUpDateCode で UpDate
If Not (AtableUpDate(lngUpDateCode)) Then
GoTo Rollback
End If
End If
' 見積もりテーブルにチェック
BtableUpDate
.MoveNext
Next i
End With
' トランザクション処理コミット
cnn.CommitTrans
MitumoriHyouji
Exit Sub
Rollback:
Debug.Print Err.Description
' トランザクション処理ロールバック
cnn.RollbackTrans
MitumoriHyouji
End Sub
' 見積もりテーブル(Btable)でチェックの無いものをリストアップ
Private Sub MitumoriHyouji()
Dim strBase As String
Dim i As Integer
'SELECT * FROM Btable WHERE Check = 0 ORDER BY Day, Gyousya
strBase = " SELECT *" & _
" FROM Btable" & _
" WHERE Check = 0" & _
" ORDER BY Day, Gyousya"
Set recBase = New ADODB.Recordset
With recBase
.Open strBase, cnn, adOpenStatic, adLockPessimistic
Me.MSFlexGrid1.Cols = 4
Me.MSFlexGrid1.Rows = .RecordCount + 1
Me.MSFlexGrid1.FormatString = "<日付 |<業者 |<品名 |<数量 "
For i = 1 To .RecordCount
Me.MSFlexGrid1.TextMatrix(i, 0) = .Fields("Day").Value
Me.MSFlexGrid1.TextMatrix(i, 1) = .Fields("Gyousya").Value
Me.MSFlexGrid1.TextMatrix(i, 2) = .Fields("Hinmei").Value
Me.MSFlexGrid1.TextMatrix(i, 3) = .Fields("suuryou").Value
.MoveNext
Next i
End With
End Sub
' 引数 tCDx で Atable にレコード追加
Private Function AtableUpDate(ByVal tCDx As Long) As Boolean
AtableUpDate = False
On Error GoTo ErrTrap
Set recData = New ADODB.Recordset
With recData
.Open "Atable", cnn, adOpenStatic, adLockPessimistic
.AddNew
.Fields("tCD").Value = Format_tCD(tCDx)
.Fields("Day").Value = recBase.Fields("Day").Value
.Fields("Gyousya").Value = recBase.Fields("Gyousya").Value
.Fields("Hinmei").Value = recBase.Fields("Hinmei").Value
.Fields("suuryou").Value = recBase.Fields("suuryou").Value
.Update
End With
AtableUpDate = True
Exit Function
ErrTrap:
Debug.Print Err.Description
End Function
' Btable にチェック
Private Function BtableUpDate() As Boolean
BtableUpDate = False
On Error GoTo ErrTrap
With recBase
.Fields("Check").Value = 1
End With
BtableUpDate = True
Exit Function
ErrTrap:
Debug.Print Err.Description
End Function
' tCD をデータベース登録の形にフォーマット
Private Function Format_tCD(ByVal tCDx As Long) As String
Dim strZero As String
Dim i As Integer
If Len(CStr(tCDx)) > con_tCDMax Then
MsgBox "コードが" & CStr(con_tCDMax) & "桁を越えました。"
End If
For i = 1 To con_tCDMax
strZero = strZero & "0"
Next i
Format_tCD = Format(tCDx, strZero)
End Function
Private Sub Command2_Click()
AtableDataCheck
End Sub
' 検証用関数
' 注文テーブル(Atable)で tCD が余分に発番されているものをリストアップ
Private Sub AtableDataCheck()
Dim strData As String
Dim i As Integer
'SELECT * FROM Atable WHERE Check = 0 ORDER BY Day, Gyousya
strData = " SELECT tCD, Day, Gyousya" & _
" FROM Atable" & _
" GROUP BY tCD, Day, Gyousya" & _
" ORDER BY Day, Gyousya"
Set recBase = New ADODB.Recordset
With recBase
.Open strData, cnn, adOpenStatic, adLockPessimistic
Me.MSFlexGrid1.Cols = 3
Me.MSFlexGrid1.Rows = .RecordCount + 1
Me.MSFlexGrid1.FormatString = "<tCD |<日付 |<業者 "
For i = 1 To .RecordCount
Me.MSFlexGrid1.TextMatrix(i, 0) = .Fields("tCD").Value
Me.MSFlexGrid1.TextMatrix(i, 1) = .Fields("Day").Value
Me.MSFlexGrid1.TextMatrix(i, 2) = .Fields("Gyousya").Value
.MoveNext
Next i
End With
With Me.MSFlexGrid1
For i = 2 To recBase.RecordCount
If .TextMatrix(i, 1) = .TextMatrix(i - 1, 1) _
And .TextMatrix(i, 2) = .TextMatrix(i - 1, 2) Then
.Row = i
.Col = 0
.CellBackColor = vbRed
End If
Next i
End With
End Sub
「特攻隊長まるるう」さま
返答頂きありがとうございます。
詳しい事も書かれてあり大変勉強になります。
並べ替えですが、ココでは要素だけを必要としたので記載しませんでした。
本来は並び替えてから処理を行います。
説明不足で申し訳ありません・・・。
マズいとご指摘頂いている件は、一度注文番号をつけて発行してしまうと、例え同じ条件のデータが発生しても新しい連番を付けるとの事でしたので最後のレコードと指定しました。
発行前の状態の時は同じ連番で、発行後は違う連番にしています。
「特攻隊長まるるう」さまのご指摘通り、SQLについて勉強不足だと思います。
ご指摘頂きありがとうございました。
参考書片手に頑張ります!!!
>一度注文番号をつけて発行してしまうと、例え同じ条件のデータが発生しても新しい連番を付ける
それって
>Atable(注文テーブル)
>tCD Day Gyousya Hinmei suuryou
>001 2002/02/16 A社 苺 10
>002 2002/02/16 B社 柿 10
>-------------------------------------------
>002 2002/02/16 B社 桃 10 ←行いたい結果
>003 2002/02/17 A社 梨 10 ←行いたい結果
>
>Btable(見積りテーブル)
>tCD Day Gyousya Hinmei suuryou
> 2002/02/16 B社 桃 10
> 2002/02/17 A社 梨 10
…ではなくて
Atable(注文テーブル)
tCD Day Gyousya Hinmei suuryou
001 2002/02/16 A社 苺 10
002 2002/02/16 B社 柿 10
-------------------------------------------
003 2002/02/16 B社 桃 10 ←行いたい結果(002→003)
004 2002/02/17 A社 梨 10 ←行いたい結果(003→004)
Btable(見積りテーブル)
tCD Day Gyousya Hinmei suuryou
2002/02/16 B社 桃 10
2002/02/17 A社 梨 10
…ではないの??
あと、[解決]で書かれているコードだと
Atable(注文テーブル)
tCD Day Gyousya Hinmei suuryou
001 2002/02/16 A社 苺 10
002 2002/02/16 B社 柿 10
-------------------------------------------
002 2002/02/16 B社 桃 10 ←結果(過去の番号と同じ)
Btable(見積りテーブル)
tCD Day Gyousya Hinmei suuryou
2002/02/16 B社 桃 10
…と
Atable(注文テーブル)
tCD Day Gyousya Hinmei suuryou
001 2002/02/16 A社 苺 10
002 2002/02/16 B社 柿 10
-------------------------------------------
003 2002/02/16 A社 桃 10
004 2002/02/16 B社 桃 10 ←結果(新しく発番)
Btable(見積りテーブル)
tCD Day Gyousya Hinmei suuryou
2002/02/16 A社 桃 10
2002/02/16 B社 桃 10
…で同じ『2002/02/16 B社』の結果が変わってきますけど?
まぁ、どちらも見積りテーブルの1レコード目を無条件で新しい tCD で
登録すれば解決します。気づいてて、説明不足なだけならいいのですが…
一応書き込みしておきます。
「特攻隊長まるるう」さま
ご返答ありがとうございます。
再度、依頼者と打合わせをしたところ・・・
注文テーブルには注文書を発行後のデータが登録されるのみ。
見積りテーブルに注文番号を登録後、注文テーブルへとレコードを追加する。
同じ日付・業者などの条件に従って連番を付けるのは見積りテーブルでした。
注文テーブルの最終レコードと見積りテーブルのレコードとの照合は行わず、ただ注文テーブルの最終レコードの連番を取得して見積りテーブルのレコードに続きを連番すればよいとの事でした。
詳細なご意見を頂きまして本当にありがとうございました。
参考に、もう一度作成しなおします。
本当にありがとうございました。