SSブログ

アクセス小僧:月ごとの領収書番号(3) [コンピューター]

アクセス小僧:月ごとの領収書番号(2) 
http://cheese999.blog.so-net.ne.jp/2016-12-23-1

で紹介した、医療費控除の医療費を月ごとに集計するためのアクセスのデータベースにおいて
領収書番号を自動で入力するマクロですが、うまく動かないので見直し中です。

【データベース】
・病院、薬局でもらってくる領収書1枚ごとに、1レコード登録する。
・レコードは、受診した順番に登録し、ユニークな番号としてID(昇順)につける。
・レコードには、受診した日付も登録する。
・領収書番号は、月ごとに1,2,3,--と付ける。同じ日に複数受診した場合、IDの順に番号を振る。

【マクロの内容】
・領収書を登録するフォームに、領収書番号を自動で入力するマクロを呼ぶボタンを配置する。
・マクロは、データベースから、同じ月のレコードを検索して、配列に格納する。
・配列に格納されたレコードが1件なら、領収書番号を1にしてマクロを終了する。
・配列のレコードを日付、IDで昇順にソートし、領収書番号を1,2,3,--と振り、マクロを呼んだレコードの領収書番号を返す。

【マクロのコード】
(1) フォームのボタンをクリックしたら呼ばれるマクロ

Private Sub 領収書番号更新_Click()
  If IsNull([ID]) Then
    ' 新規レコードでは、IDがnullなので、9999としておく
    [領収書番号] = SetRyouSyuNo1([日付], [領収書番号], [日付], 9999)
  Else
    [領収書番号] = SetRyouSyuNo1([日付], [領収書番号], [日付], [ID])
  End If
End Sub

・日付とIDをレコードから拾って、SetRyouSyuNo1マクロに渡す。
・マクロはフォームに記述する。

(2) 日付とIDから、領収書番号を返すマクロ(SetRyouSyuNo1)
・マクロを標準モジュールに記述する。

Public Function SetRyouSyuNo1(Optional Ctl As Control, Optional Ctl2 As Control, _
Optional MyDate2 As Date, Optional myID As Integer) As Integer
  ' 【機能】月が変わったら、領収書番号を1にする
  ' 【引数】
  ' Ctl : 日付のコントロール
  ' Ctl2 : 領収書番号のコントロール
  ' MyDate2 : 現在のレコードの日付
  ' myID : ID
  ' 【変数】
  Dim myDate1(2) As Date ' 日付
  Dim myYear1(2) As Integer ' 年
  Dim myMonth1(2) As Integer ' 月
  Dim myDay1(2) As Integer ' 日
  Dim myRyNo1(3) As Integer ' 領収書番号
  Dim db1 As DAO.Database ' データベース
  Dim rs1 As DAO.Recordset ' レコードセット
  Dim rcdNo1(2) As Long ' レコード番号
  Dim myID1(2) As Integer ' ID
  Dim myCntRcd1 As Integer ' 同じ年月のレコード件数
  Dim i, j, k As Integer ' for文のカウンタ
  ' 【コード】
  '※ CodeContextObjectがエラーになるのでコメント化
  '※ カレントレコードのレコード番号が1以下だったら、終了
  '※ If CodeContextObject.CurrentRecord <= 1 Then
  '※ SetRyouSyuNo1 = 1
  '※ Exit Function
  '※ End If
  ' 医療費テーブルをレコードセットとして開く
  Set db1 = CurrentDb()
  ' dbOpenTableだと、absolutepositionが使えない
  ' Set rs1 = db1.OpenRecordset("T_医療費", dbOpenTable)
  Set rs1 = db1.OpenRecordset("T_医療費", dbOpenDynaset)
  If rs1.EOF Then
    MsgBox "医療費テーブルにレコードがありません。"
    SetRyouSyuNo1 = 1
    Exit Function
  Else
    rs1.MoveLast
    ' MsgBox "全レコード件数=" & rs1.RecordCount
    rs1.MoveFirst
  End If
  ' 最大の領収書番号
  myRyNo1(2) = 0
  ' myIDがnullなら、9999にしておく
  If IsNull(myID) Then
    myID1(1) = 9999
  Else
    myID1(1) = myID
  End If
  ' 現在のレコードの年、月、日
  myYear1(1) = Year(MyDate2)
  myMonth1(1) = Month(MyDate2)
  myDay1(1) = Day(MyDate2)
  ' 同じ年月のレコード件数
  myCntRcd1 = 0
  ' 1番の領収書番号のレコードのレコード番号、日、ID
  rcdNo1(2) = 9999 ' レコード番号
  myDay1(2) = 32 ' 日
  myID1(2) = 9999 ' ID
  Do Until rs1.EOF
    ' レコードの年、月、日
    myYear1(0) = Year(rs1!日付)
    myMonth1(0) = Month(rs1!日付)
    myDay1(0) = Day(rs1!日付)
    myID1(0) = rs1!ID
    ' 同じ年月
    If (myYear1(0) = myYear1(1)) And (myMonth1(0) = myMonth1(1)) Then
      myCntRcd1 = myCntRcd1 + 1 ' 同じ年月のレコード件数
      ' 1番の領収書番号のレコードを探す
      If (myDay1(0) < myDay1(2)) Or _
      ((myDay1(0) = myDay1(2)) And (myID1(0) < myID1(2))) Then
        rcdNo1(2) = rs1.AbsolutePosition ' レコード番号
        myDay1(2) = myDay1(0) ' 日
        myID1(2) = myID1(0) ' ID
      End If
    End If
    rs1.MoveNext
  Loop
  ' MsgBox myYear1(1) & "年" & myMonth1(1) & "月のレコード件数=" & myCntRcd1
  ' MsgBox "rcdNo1(2)=" & rcdNo1(2)
  ' 同じ年月のレコードが他に無い
  If myCntRcd1 = 1 Then
    MsgBox ("日付=" & MyDate2 & vbCrLf & _
    "領収書番号=1" & vbCrLf & _
    "ID=" & myID & vbCrLf & _
    "レコード番号=" & rcdNo1(2))
    ' 領収書番号を1にする
    SetRyouSyuNo1 = 1
    ' レコードセットを閉じる
    rs1.Close: Set rs1 = Nothing
    db1.Close: Set db1 = Nothing
    Exit Function
  End If
  rs1.MoveFirst
  ' 同じ年月のレコードを格納する配列を定義
  Dim myRcd1()
  i = 0 ' カウンタ初期化
  Do Until rs1.EOF
    ' レコードの年、月、日
    myYear1(0) = Year(rs1!日付)
    myMonth1(0) = Month(rs1!日付)
    myDay1(0) = Day(rs1!日付)
    myID1(0) = rs1!ID
    ' 同じ年月
    If (myYear1(0) = myYear1(1)) And (myMonth1(0) = myMonth1(1)) Then
      ' MsgBox "i=" & i ' debug
      ReDim Preserve myRcd1(4, i)
      myRcd1(0, i) = rs1.AbsolutePosition ' レコード番号
      myRcd1(1, i) = myDay1(0) ' 日
      myRcd1(2, i) = myID1(0) ' ID
      If myRcd1(0, i) = rcdNo1(2) Then
        myRcd1(3, i) = 1 ' 領収書番号
        If myRcd1(2, i) = myID Then
          SetRyouSyuNo1 = 1
          Exit Function
        End If
        ' MsgBox "myRcd1(0, i)=" & myRcd1(0, i)
      Else
        myRcd1(3, i) = 0 ' 領収書番号
      End If
      If myID1(0) = myID Then
        myRcd1(4, i) = 1 ' Flag(ID一致)
      Else
        myRcd1(4, i) = 0 ' Flag
      End If
      i = i + 1
    End If
    rs1.MoveNext
  Loop
  ' レコードセットを閉じる
  rs1.Close: Set rs1 = Nothing
  db1.Close: Set db1 = Nothing
  myDay1(2) = 32 ' 日
  myID1(2) = 9999 ' ID
  myRyNo1(3) = 1 ' 現在の領収書番号
  For i = 0 To myCntRcd1 - 2
    For j = 0 To myCntRcd1 - 1
       If (myRcd1(3, j) = 0) And _
       ((myRcd1(1, j) < myDay1(2)) Or _
       ((myRcd1(1, j) = myDay1(2)) And (myRcd1(2, j) < myID1(2)))) Then
          myDay1(2) = myRcd1(1, j) ' 日
          myID1(2) = myRcd1(2, j) ' ID
          k = j
      End If
    Next j
    myRyNo1(3) = myRyNo1(3) + 1 ' 現在の領収書番号
    myRcd1(3, k) = myRyNo1(3)
    If myID = myRcd1(2, k) Then
      SetRyouSyuNo1 = myRyNo1(3)
    End If
    ' MsgBox "k=" & k & " myID1(2) =" & myID1(2) & " myRcd1(3, k) =" & myRcd1(3, k)
    myDay1(2) = 32 ' 日
    myID1(2) = 9999 ' ID
  Next i
End Function
ヤバイぜ!(11)  コメント(1)  トラックバック(0) 
共通テーマ:パソコン・インターネット

ヤバイぜ! 11

コメント 1

cheese999

ヤバイぜ! ありがとうございます[__猫]
by cheese999 (2017-07-06 11:33) 

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字(英大文字の「オー」、英小文字の「ユー」、アラビア数字の「ハチ」、アラビア数字の「イチ」、アラビア数字の「ニ」)を入力してください。

Facebook コメント

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。