So-net無料ブログ作成
Form登録伝票版 ブログトップ

データ登録フォーム 伝票形式 その5 削除処理 [Form登録伝票版]

 伝票形式での、削除処理の詳細です。

 削除ボタンも登録ボタンと同様に、明細用と伝票用の2つがあります。
 画面中央右側の削除ボタンが、明細の削除用です。
 処理的には、「データ登録フォーム 1画面版 その5 データの削除」と、同じ要領ですので、ここでは省略します。

 次に、画面下部分にある「伝票削除」ボタン。こちらが伝票削除用です。
 このボタンをクリックすると、明細を含め、伝票全体のデータが削除されます。
 以下、削除処理の説明です。

Private Sub cmdDenDel_Click()
'伝票削除ボタン クリック

    Dim Cn    As New ADODB.Connection
    Dim recA  As New ADODB.Recordset
    Dim lngRC As Long

'1)モードチェック
    If Me.txtDENmode = "新規" Then
        MsgBox "新規登録時は削除はできません。", vbInformation
        Exit Sub
    End If
    
    If MsgBox("この売上伝票を削除します。", vbQuestion + vbYesNo + vbDefaultButton2) = vbNo Then
        Exit Sub
    End If
    
'2)トランザクション開始
    Set Cn = CurrentProject.Connection
    Cn.BeginTrans
   
'3)TD売上伝票 削除
    Cn.Execute "DELETE FROM TD売上伝票 WHERE 伝票番号 = " & Me.txt伝票番号, lngRC
    If lngRC <> 1 Then
        MsgBox "売上伝票を正しく削除できませんでした。", vbExclamation
        Cn.RollbackTrans
        Exit Sub
    End If
    
'4)TD売上明細 削除
    Cn.Execute "DELETE FROM TD売上明細 WHERE 伝票番号 = " & Me.txt伝票番号
    
'5)コミット
    Cn.CommitTrans
        
'6)後処理
    Cn.Execute "DELETE FROM TW売上明細 "
    Forms.F売上伝票一覧.subList.Requery
    DoCmd.Close acForm, Me.NAME
    
End Sub

 順番に処理を説明します。

1)モードチェック
 伝票の新規入力時、つまり新規の伝票を入力している途中は、まだテーブルにレコードが作成されていないので、削除処理はできません。
 なので、まず最初に、入力モードをチェックして、新規モードならメッセージを表示して、処理を中止します。
 最初から新規入力時は削除ボタンが表示されなければ良い話なんですが。

 その後で、削除処理の確認メッセージを表示させています。
 いちおう、いきなり削除するのはあれなんで。

2)トランザクション開始
 コネクションの準備と、トランザクションの開始です。
 伝票の削除処理では、TD売上伝票とTD売上明細の2つのテーブルからデータを削除するため、ここでもトランザクションで処理を行います。

3)TD売上伝票 削除
 画面上の伝票番号を条件にして、削除を実行します。
 この時、Executeのパラメタに指定しているlngRCには、削除されたレコード件数が返ります。
 TD売上伝票の削除は、必ず1件なので、削除後それをチェックしています。
 この処理の場合、削除件数が1件以外の場合は、何かがおかしいので、エラーメッセージを出して、ロールバックしています。

 いろんなケースの削除処理があると思いますが、このケースのように削除件数が必ず1件と決まっている場合は、私はこんなふうにチェックをするようにしています。
 削除処理は、条件の作り方を間違えると、消してはいけないデータを消してしまうリスクが常に潜んでいるので、念の為です。

4)TD売上明細 削除
 明細の削除処理です。こちらも伝票番号を条件にして、削除を実行しています。
 明細の場合は、複数件削除されることもあり、件数が不定なので、伝票のような削除件数のチェックは行っていません。

5)コミット
 トランザクションのコミット処理です。
 コミットにより、削除処理が確定します。

6)後処理
 入力画面で使用している明細表示用のワークテーブルの内容は、不要なので削除します。
 削除が完了したので、現在の画面を閉じて、一覧画面に戻ります。

 以上、伝票の削除処理でした。
 登録処理と同様、伝票と明細の2テーブルに対して処理を行います。登録に比べると簡単だと思います。
 ACCESSなんで、リレーションを設定しておけば、伝票の削除と同期して、明細も削除されるようにできるのですが、私はリレーションを使わないので、こういう処理になります。

 以上、ざっくりですが、伝票形式の例でした。 

 ぼちぼちサンプルのダウンロードが出来るように準備を始めようと思っています。
 もうしばらくお待ち下さい。


データ登録フォーム 伝票形式 その4 登録処理 [Form登録伝票版]

 伝票形式での、登録処理の詳細です。

 まず、画面中央右側にある「登録」ボタン。
 この登録ボタンは、明細登録を行うための物です。
 処理的には、「データ登録フォーム 1画面版 その4 データをテーブルに書き込む」と同じ要領なので、ここでの説明は省略します。

 次に、画面下部分にある「伝票登録」ボタン。(前回からちょっと画面修正しました。)
 このボタンで、伝票全体を登録します。
 伝票登録を行うまでは、明細の内容はワークテーブルに登録されており、本来のデータテーブルにはまだ登録されていません。
 伝票登録処理で、ワークから本来のデータテーブルへの反映と、伝票部分(ラベルが緑色の項目)の登録処理を行います。

 以下、伝票登録ボタンの処理を説明します。

Private Sub cmdDENENT_Click()
'売上伝票データ 登録処理
    
    Dim Cn       As New ADODB.Connection
    Dim recW     As New ADODB.Recordset
    Dim recD     As New ADODB.Recordset
    Dim lngDNO   As Long
    Dim lngCM    As Long
    Dim datNow   As Date
    
    datNow = Now
        
'1)入力項目チェック
    '顧客CDチェック
    If IsNumeric(Me.txt顧客CD) = False Then
        MsgBox "顧客CDを入力して下さい。", vbInformation
        Me.txt顧客CD.SetFocus
        Exit Sub
    End If

    '注文日チェック
    If IsDate(Me.txt注文日) = False Then
        MsgBox "注文日を入力して下さい。", vbInformation
        Me.txt注文日.SetFocus
        Exit Sub
    End If

    '納品日チェック
    If IsDate(Me.txt納品日) = False Then
        MsgBox "納品日を入力して下さい。", vbInformation
        Me.txt納品日.SetFocus
        Exit Sub
    End If
    
    '担当者CDチェック
    If IsNumeric(Me.txt担当者CD) = False Then
        MsgBox "担当者CDを入力して下さい。", vbInformation
        Me.txt担当者CD.SetFocus
        Exit Sub
    End If
    
    '明細行が入力されているかチェック
    If DCount("*", "TW売上明細") = 0 Then
        MsgBox "明細行が入力されていません", vbExclamation
        Exit Sub
    End If

'2)コネクション準備・トランザクション開始
    Set Cn = CurrentProject.Connection
    Cn.BeginTrans

    If Me.txtDENmode = "新規" Then
'3)伝票 新規登録
    '伝票番号作成
        recD.Open " SELECT MAX(伝票番号) AS DENNO FROM TD売上伝票 ", Cn, adOpenForwardOnly, adLockReadOnly
        If recD.EOF = True Then
            lngDNO = 1
        Else
            lngDNO = Nz(recD!DENNO, 0) + 1
        End If
        recD.Close
        
    'レコードセットオープン
        recD.Open "SELECT * FROM TD売上伝票 WHERE 伝票番号 = " & lngDNO, Cn, adOpenForwardOnly, adLockOptimistic
        If recD.EOF = False Then
            MsgBox "新規伝票番号の採番に失敗しました。", vbCritical
            recD.Close
            Cn.RollbackTrans
            Exit Sub
        End If
        
    '新規レコード作成、項目セット
        recD.AddNew
        recD!伝票番号 = lngDNO
        recD!登録日 = Now

    Else
'4)伝票 更新登録
    'レコードセットオープン
        lngDNO = Me.txt伝票番号
        recD.Open "SELECT * FROM TD売上伝票 WHERE 伝票番号 = " & lngDNO, Cn, adOpenForwardOnly, adLockOptimistic
        If recD.EOF Then
            MsgBox "変更する売上伝票データが見つかりません。", vbCritical
            recD.Close
            Cn.RollbackTrans
            Exit Sub
        End If
            
    End If
        
'5)項目セット
    recD!顧客CD = Me.txt顧客CD
    recD!注文日 = Me.txt注文日
    recD!納品日 = Me.txt納品日
    recD!担当者CD = Me.txt担当者CD
    recD!メモ = Me.txtメモ
    recD!備考欄 = Me.txt備考欄
    recD!税抜合計 = Me.txt税抜合計
    recD!消費税額 = Me.txt消費税額
    recD!総額合計 = Me.txt総額合計
    recD!変更日 = Now

    recD.Update
    recD.Close
                
'6)明細処理
    '明細を削除
    Cn.Execute "DELETE FROM TD売上明細  WHERE  伝票番号 = " & lngDNO
    
    'ワークテーブルOPEN
    recW.Open " SELECT * FROM TW売上明細  ORDER BY  明細番号 ", CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
    
    'TD売上明細 Open
    recD.Open " SELECT * FROM TD売上明細  WHERE  伝票番号 = " & lngDNO, Cn, adOpenForwardOnly, adLockOptimistic
    lngCM = 0
    
'7)ワークからTD売上明細へ
    While recW.EOF = False
        lngCM = lngCM + 1
        recD.AddNew
        recD!伝票番号 = lngDNO
        recD!明細番号 = lngCM
        recD!商品CD = recW!商品CD
        recD!数量 = recW!数量
        recD!単価 = recW!単価
        recD!金額 = recW!金額
        recD!消費税額 = recW!消費税額
        recD!総額 = recW!総額
        recD!備考欄 = recW!備考欄
        recD!変更日 = datNow
        
        recD.Update
        recW.MoveNext
    Wend
    recD.Close
    recW.Close
    
    'コミット
    Cn.CommitTrans
    
'8)後処理
    '変更の時は終了する
    If Me.txtDENmode <> "新規" Then
        DoCmd.Close acForm, Me.NAME
        Forms.F売上伝票一覧.subList.Requery
        Exit Sub
    End If
    
    '新規の時は初期化する
    'ワークテーブル削除
    Cn.Execute "DELETE FROM TW売上明細 "
    Call subMeiInit
    Call subDenInit
    Me.subMEI.Requery

End Sub

 以下、ブロックごとに説明です。

1)入力項目チェック
 実際にデータを登録する前に、入力項目への入力が正しく行われているかチェックします。
 このプログラムのチェックは、とりあえずのざっくりチェックですのでご了承下さい。
 また、明細が1件も登録されていない場合、伝票の登録はできないようにしています。

2)コネクション準備・トランザクション開始
 ADOで処理を行うための準備で、ここでは単純に、CurrentProjectのConnectionを利用しています。
 ここから先、データの更新を行うので、トランザクションを開始しています。
 今回の処理では、TD売上伝票テーブル・TD売上明細テーブルと、複数のテーブルに対して更新を行うのに加えて、TD売上明細テーブルへは、複数件のレコードを処理します。
 途中、何らかの原因で処理が中断してしまった場合や、処理中の判断で処理を中止した場合などに、テーブルの更新内容が中途半端な状態になってしまう可能性があります。
 トランザクションを行っておけば、更新内容を取り消したい場合は、ロールバックを行えば、トランザクションを開始した状態に簡単に戻すことができます。
 プログラムが途中で停止した場合も、コミットがされていない限り、元の状態に戻ります。
 バッチ処理など、複数の処理が一連で行われる場合も、トランザクションを利用すると便利です。

3)伝票 新規登録
 伝票データの処理で、新規登録の場合です。
 まず、キーとなる伝票番号を採番します。
 ここでは単純にテーブル中の最大の番号から、1を加えた値を伝票番号とするようにしています。
 採番した伝票番号を条件にして、TD売上伝票をオープンしています。
 この時、新規作成なので、この伝票番号でレコードは抽出されないはずです。
 念のため、レコードが抽出されてしまったときの処理を書いていますが、ここに来ることはまず無いと思われます。
 AddNewで新規レコードを作成して、新規登録の時のみ設定する項目、伝票番号を設定します。
 他の項目は、変更登録と共通の処理で設定します。

4)伝票 更新登録
 伝票データの変更登録の場合です。
 画面上に表示されている伝票番号を条件に、TD売上伝票をオープンしています。
 普通であればレコードが抽出されるはずですが、念のためチェックを行っています。

5)項目セット
 レコードの各盲目に、入力内容を設定しています。
 Updateして、Closeして、伝票の処理はここで終了です。

6)明細処理
 ここから明細の処理です。
 ワークからTD売上明細にレコードを作成するので、あらかじめTD売上明細側のレコードを削除しておきます。
 新規の場合は不要なんですが、念のため。
 ワークテーブルのレコードセットと、TD売上明細のレコードセットをオープンします。

7)ワークからTD売上明細へ
 ループでワークからTD売上明細へ、レコードを作成していきます。
 この処理では、明細番号をきれいに振り直すようにしています。

 明細レコードを作成し終えたら、更新処理は完了ですので、コミットを行っています。

8)後処理
 更新処理の後、画面をどうするかの処理です。
 新規の場合は、画面を初期化して、次の入力が行えるようにします。
 変更の場合は、入力画面を終了して、一覧画面に戻ります。
 戻る前に、一覧画面の一覧をRequeryして、最新の内容が表示された状態にしています。

 伝票形式タイプは、複数のレコードを処理するので、少々手間がかかります。
 処理が複数段階になっていますが、個々の処理は複雑ではないので、ADOによる基本的な処理ができれば、さほど難しくないと思います。

 次回は、削除処理で完了です。
 その5へつづく。


データ登録フォーム 伝票形式 その3 一覧画面から入力画面へ [Form登録伝票版]

 まず最初に一覧画面が表示されます。

 この画面は現在登録されているデータを確認する目的と、データを選んで編集画面へ展開する機能と、新規入力作業へ進む機能があります。
 一覧画面の作り方は、「データ一覧フォーム その1」あたりを参考にしてください。
 ここでは省略します。

 まずは新規入力ボタン。
 これがクリックされた時は、入力画面を新規入力として開きます。
 フォームを開くのには、DoCmd.OpenFormを使います。
 DoCmd.OpenFormは、最後のパラメタ(第7パラメタ)を使って、値を渡すことが出来ます。
 ここに値がセットされていない場合は、開かれるフォーム側で新規で開かれたと判断するようにします。

 新規入力ボタンの「クリック時」イベントに、以下のコードを記述します。

Private Sub cmdNEW_Click()
'新規入力ボタン クリック
    
    DoCmd.OpenForm "F売上伝票入力", acNormal
    
End Sub

 次に「編集」ボタン。
 既に登録されているデータを再度編集する場合は、一覧から該当データの編集ボタンをクリックします。
 入力画面が選択されたデータの編集として開かれます。
 入力画面を開くとき、先程のDoCmd.OpenFormの第7パラメタを使って、変更するデータのキーを渡すようにします。
 入力画面側では、これによってどのデータの編集であるか判断します。

 編集ボタンの「クリック時」イベントに、以下のコードを記述します。

Private Sub cmdEdit_Click()
'編集ボタン クリック時
    
    DoCmd.OpenForm "F売上伝票入力", acNormal, , , , , Me.txt伝票番号
    
End Sub

 今回のテーブルでは、伝票番号がキーになっているので、この項目の値があればどのデータなのか識別できます。
 キー項目が複数ある場合は、それなりに工夫が必要です。(カンマで区切るとか、ゼロ埋め固定長にして並べるとか)

 後は入力画面のプログラムに引き継がれます。

 新規入力で開いた場合の入力画面。
 何も入力されていない状態で画面が開きます。
 「注文日」に日付が表示されているのは、当日が初期値ということで。

 編集ボタンから開いた場合の入力画面。
 登録されている内容がコントロールにセットされた状態で開きます。

 画面が開かれたときの処理は、フォームのイベント「開く時」(Form_Open)で行っています。

Private Sub Form_Open(Cancel As Integer)
'フォームオープン 初期設定処理
    
    Dim Cn     As New ADODB.Connection
    Dim recD   As New ADODB.Recordset
    Dim recW   As New ADODB.Recordset
    Dim strSQL As String
        
'1)ワークテーブル削除
    Set Cn = CurrentProject.Connection
    Cn.Execute "DELETE FROM TW売上明細 "
    Me.subMEI.Requery

'2)入力コントロール初期化
    Call subMeiInit
    Call subDenInit
    
'3)変更モードならデータ呼び出し
    If Me.OpenArgs = "" Or IsNull(Me.OpenArgs) Then
        Exit Sub
    End If

'4)伝票データ読込
    recD.Open "SELECT * FROM TD売上伝票 WHERE 伝票番号 = " & Me.OpenArgs, Cn, adOpenForwardOnly, adLockReadOnly
    If recD.EOF Then
        MsgBox "変更伝票データが見つかりません。", vbExclamation
        DoCmd.Close acForm, Me.Name
        Exit Sub
    End If
    
    Me.txt伝票番号 = recD!伝票番号
    Me.txt顧客CD = recD!顧客CD
    Me.txt注文日 = recD!注文日
    Me.txt納品日 = recD!納品日
    Me.txt担当者CD = recD!担当者CD
    
    Me.txt税抜合計 = recD!税抜合計
    Me.txt消費税額 = recD!消費税額
    Me.txt総額合計 = recD!総額合計
    
    Me.txt備考欄 = recD!備考欄
    Me.txtメモ = recD!メモ
        
    recD.Close
    
'5)明細データをワークテーブルへ
    recW.Open "SELECT * FROM TW売上明細 ", Cn, adOpenForwardOnly, adLockOptimistic
    
    strSQL = " SELECT  MEI.* , SYO.商品名   " & _
             " FROM TD売上明細 AS MEI" & _
             " LEFT JOIN  TM商品 AS SYO  ON  MEI.商品CD = SYO.商品CD " & _
             " WHERE  MEI.伝票番号 = " & Me.OpenArgs & " ORDER BY  MEI.明細番号 "
    recD.Open strSQL, Cn, adOpenForwardOnly, adLockReadOnly
    Do While recD.EOF = False
        recW.AddNew
        
        recW!伝票番号 = recD!伝票番号
        recW!明細番号 = recD!明細番号
        recW!商品CD = recD!商品CD
        recW!商品名 = recD!商品名
        recW!数量 = recD!数量
        recW!単価 = recD!単価
        recW!金額 = recD!金額
        recW!消費税額 = recD!消費税額
        recW!総額 = recD!総額
        recW!備考欄 = recD!備考欄
                
        recW.Update
        recD.MoveNext
    Loop
    recW.Close
    recD.Close
    Me.subMEI.Requery

'6)モード表示
    Me.txtDENmode = "変更"
        
End Sub

 今回の説明に関係のない処理は省いてます。
 コメントの番号順に説明していきます。

1)ワークテーブル削除
 最初に、ワークテーブルを全件削除しておきます。
 このワークテーブルの内容が、画面の明細部分に表示されます。
 データが残っていた場合を考えて、まず削除を行っておきます。

2)入力コントロール初期化
 画面のコントロールの内容をクリアします。
 画面を開いたとき、通常であればコントロールの内容は空なわけですが、念のため空にする処理を通します。
 クリアの関数を準備しておき、それを呼び出します。
 初期値のある項目は、コントロールを空にする代わりに、クリア関数で初期値を設定するようにしておくと、コードで確認できてわかりやすいので、私はこのパターンを使ってます。

Private Sub subDenInit()
'伝票項目クリア
    Me.txt伝票番号 = Null
    Me.txt顧客CD = Null
    Me.txt注文日 = Date
    Me.txt納品日 = Null
    Me.txt担当者CD = Null
    
    Me.txt税抜合計 = Null
    Me.txt消費税額 = Null
    Me.txt総額合計 = Null
    
    Me.txtメモ = Null
    Me.txt備考欄 = Null

    Me.txtDENmode = "新規"
    Me.txt顧客CD.SetFocus

End Sub

Private Sub subMeiInit()
'明細項目クリア
    
    Me.txt明細番号 = Null
    Me.txt商品CD = Null
    Me.txt数量 = Null
    Me.txt単価 = Null
    Me.txt金額 = Null
    Me.txt明細消費税額 = Null
    Me.txt総額 = Null
    Me.txt明細備考欄 = Null
    
    Me.txtMEImode = "新規"
    Me.txt商品CD.SetFocus

End Sub

 こんなふうに、各項目を空にする処理を行います。
 「注文日」のみ、今日の日付が初期値として表示されるようにしています。
 フォーカスの位置もここで設定しています。

3)変更モードならデータ呼び出し
 DoCmd.OpenFormの第7パラメタで設定した値は、Me.OpenArgsを参照することで確認できます。
 Me.OpenArgsに値が設定されていなければ、新規で呼び出された事になります。
 新規入力画面の準備はここまでで完了しているので、新規の場合はここで終了です。
 Me.OpenArgsに値が設定されている場合は、その値をキーにして、データを読み込む処理を行います。

4)伝票データ読込
 Me.OpenArgsに伝票番号がセットされているので、それを条件にして、伝票情報(TD売上伝票)を読み込んでいます。

5)明細データをワークテーブルへ
 伝票データと同様に、Me.OpenArgsの伝票番号を条件にして、明細情報(TD売上明細)を読み込んで、それをワークテーブル(TW売上明細)に移し替えています。
 この時、TD売上明細に商品名項目を持たせていないので、クエリで取得してワークテーブルにセットしています。
 フォームのデータソースのクエリで商品マスタと結合して持ってきても良いのですが、今回は上記のようにしました。
 INSERT文で追加しても良いと思いますが、ここでは追加用と読込用の2つのレコードセットを使って行っています。
 ワークテーブルにデータができたら、サブフォームをRequeryして明細部分の表示を更新します。

6)モード表示
 伝票の方のモード表示を「変更」にしています。

 以上で画面表示の処理は完了です。
 データの読込を、伝票と明細の2つについて行わなければならない点と、明細が複数件あってワークに一旦移す点がちょっと面倒です。

 次回はデータ登録処理についてです。
 その4へつづく。


データ登録フォーム 伝票形式 その2 テーブルについて [Form登録伝票版]

 まず、この伝票タイプのデータを扱うためのテーブルについて説明しておきます。

 その1でも説明しましたが、この画面では、伝票情報部分と、明細部分の2種類のデータを扱います。
 画面の緑ラベルの部分が伝票情報で、青ラベルの部分が明細情報です。
 明細情報は、複数件登録できる前提です。

 これらの情報をテーブルに格納するわけですが、それぞれ、伝票情報部分をTD売上伝票、明細情報部分をTD売上明細、というテーブルに分けて登録します。
 伝票情報1件につき、明細情報は複数件(1件以上)登録します。

 また、画面で入力作業中の明細表示用に、TD売上明細テーブルとは別に、TW売上明細と言うワークテーブルを設けます。
 入力作業中の一時的な状態を、このワークテーブルに保存します。
 上の図の明細部分は、このワークテーブルから表示させています。
 最終的な登録段階まで、TD売上明細テーブルは更新せず、伝票の登録ボタンクリックでワークの内容をTD売上明細テーブルに反映させます。

 次からプログラムです。
 その3へつづく。


データ登録フォーム 伝票形式 その1 概要 [Form登録伝票版]

 まず、「伝票」とは。

 「会社・商店などで、金銭の出入や取引内容などを記入する一定の様式を備えた紙片。」
 大辞泉より引用(Yahoo)

 例えば、商品の販売を行う際に、売る商品の一覧や金額などが記入された紙のことを伝票と呼んでいます。
 会社が独自で作成した物や、業界で共通化された形式の物があります。
 また、文房具店に行くと、様々な形式・サイズの物が売られています。
 標準化された物では、チェーンストア伝票とか有名なんじゃないかと思います。

 ネットで拾ったイメージ。
 チェーンストア伝票ターンアラウンド用1型と言います。チェーンストア伝票という名前でも、いくつか種類があります。その中のひとつです。
 私は作る人なので、実際に使ったことは無いのですが、商品の発注や納品の際に使われている物なんだと思います。

続きを読む


Form登録伝票版 ブログトップ