Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


1760 / 2272 ツリー ←次へ | 前へ→

【5385】縦方向(レコード)のデータを横方向(フィールド)に並べる さつき 05/6/15(水) 16:21 質問[未読]
【5389】Re:縦方向(レコード)のデータを横方向(... 小僧 05/6/15(水) 17:22 発言[未読]
【5391】Re:縦方向(レコード)のデータを横方向(... さつき 05/6/15(水) 18:07 質問[未読]
【5392】Re:縦方向(レコード)のデータを横方向(... 小僧 05/6/16(木) 9:49 回答[未読]
【5395】Re:縦方向(レコード)のデータを横方向(... さつき 05/6/16(木) 17:52 質問[未読]
【5396】Re:縦方向(レコード)のデータを横方向(... 小僧 05/6/16(木) 19:30 回答[未読]
【5400】Re:縦方向(レコード)のデータを横方向(... さつき 05/6/17(金) 14:31 質問[未読]
【5403】Re:縦方向(レコード)のデータを横方向(... 小僧 05/6/17(金) 15:00 回答[未読]
【5415】Re:縦方向(レコード)のデータを横方向(... さつき 05/6/20(月) 10:13 お礼[未読]

【5385】縦方向(レコード)のデータを横方向(フ...
質問  さつき  - 05/6/15(水) 16:21 -

引用なし
パスワード
   Access VBA初心者です。よろしくお願いいたします。

下記のように契約者の購入品レコードがあって、
区分  契約者 メーカー     品番    個数
1    佐藤  SONY     T05    10
2    加藤  HITACHI  K23   25
1    佐藤  TOSHIBA  N71   37
4    佐藤  SONY     R03   21
6    加藤  TOSHIBA  M52    8
1    神田  HITACHI  L12    5
2    中川  NATIONAL H95   12
3    神田  SONY     Q46    6

下のように契約者ごとに購入品を横方向に並べるアクセステーブルを作らなければなりません。
佐藤  SONY   T05 10  TOSHIBA  N71 37 SONY R03 21
加藤  HITACHI K23 25  TOSHIBA  M52  8
神田  HITACHI L12 5  SONY   Q46  6
中川  NATIONAL H95 12

下記のようにコードを書いてみましたが、rs2.Updateを実行することによって、行が変わってしまいます。どのようにしたらよいでしょうか。

  Do Until rs1.EOF

    If IsNull(rs1.Fields("区分").Value) = True Then
        rs1.MoveNext
    Else
      If keiyakusha <> rs1.Fields("契約者").Value Then
        j = 1
        rs2.AddNew
        rs2.Fields("契約者") = rs1.Fields("契約者")
        For i = 1 To 3
          rs2.Fields(j) = rs1.Fields(i)
          j = j + 1
        Next i
        rs2.Update
      Else
        j = j + 4
        rs2.AddNew
        For i = 1 To 3
          rs2.Fields(j) = rs1.Fields(i)
          j = j + 1
        Next i
        rs2.Update
      End If
      keiyakusha = rs1.Fields("契約者").Value
    End If
  rs1.MoveNext
  Loop

【5389】Re:縦方向(レコード)のデータを横方向(...
発言  小僧  - 05/6/15(水) 17:22 -

引用なし
パスワード
   ▼さつき さん:
こんにちは。
Accessになっちゃいましたか…。

>契約者ごとに購入品を横方向に並べるアクセステーブルを作らなければなりません。

まず言ってしまうと、止めたほうが良いです。
Accessに限らずデータベースにおいて、フィールドを増やす事は
大幅な仕様変更を伴ってしまう場合があります。

Excel の場合ですと縦横にデータを増やせますが、Accessの場合は
縦(レコード)のみと考えた方が良いです。

>佐藤  SONY   T05 10  TOSHIBA  N71 37 SONY R03 21
>加藤  HITACHI K23 25  TOSHIBA  M52  8
>神田  HITACHI L12 5  SONY   Q46  6
>中川  NATIONAL H95 12

こういったデータが必要な理由がレポートやExcelへの出力であるならば
クエリやオートメーションである程度は解決できると思われます。

【5391】Re:縦方向(レコード)のデータを横方向(...
質問  さつき  - 05/6/15(水) 18:07 -

引用なし
パスワード
   小僧 さんお久しぶりです。ご回答ありがとうございます。

>Accessになっちゃいましたか…。
いえいえ違います。小僧さんに以前教えていただいたExcelVBAはりっぱに活躍しております。大変業務が効率化して喜んでおります。ありがとうございました。
今回はまた別件です。わかりやすくするため、似たような例題にしましたが、実際はまったく違う目的で使います。
Accessでテーブルを作って、さらに他のテーブルとの関連付けをするため、今回はAccessVBAにしました。

>まず言ってしまうと、止めたほうが良いです。
>Accessに限らずデータベースにおいて、フィールドを増やす事は
>大幅な仕様変更を伴ってしまう場合があります。

最初からテーブル2の方に必要分だけフィールドを作っておいても難しいでしょうか?

【5392】Re:縦方向(レコード)のデータを横方向(...
回答  小僧  - 05/6/16(木) 9:49 -

引用なし
パスワード
   ▼さつき さん:
おはようございます。

下テーブルのフィールド数に変更がないのであれば
ワーク用のテーブルとして使うのもありだと思われますが、
上テーブルの結果によって可変するものであると
下テーブルに伴うクエリ・フォーム・レポート・モジュールと
大幅な変更が必要となってしまいます。

ご提示されたのは例としてあげているとの事で実際どのようなデータが
入るかは解りませんが、そのワークテーブルを何に使うのかによっては
もうちょっと良い方法があるかもしれません。

下記コードについてですが、

>  Do Until rs1.EOF
>
>    If IsNull(rs1.Fields("区分").Value) = True Then
>        rs1.MoveNext
>    Else
>      If keiyakusha <> rs1.Fields("契約者").Value Then
>        j = 1
>        rs2.AddNew
>        rs2.Fields("契約者") = rs1.Fields("契約者")
>        For i = 1 To 3
>          rs2.Fields(j) = rs1.Fields(i)
>          j = j + 1
>        Next i
>        rs2.Update
>      Else
>        j = j + 4
>        rs2.AddNew
>        For i = 1 To 3
>          rs2.Fields(j) = rs1.Fields(i)
>          j = j + 1
>        Next i
>        rs2.Update
>      End If
>      keiyakusha = rs1.Fields("契約者").Value
>    End If
>  rs1.MoveNext
>  Loop

今のままですとうまくいかないと思いますので、

「rs2」に対して「FindFirst」メソッドを使い、
結果が「Nomatch」プロパティの値が「True」でしたら「AddNew」で
「False」でしたら「Edit」で開いて「Update」すれば良いと思われます。

【5395】Re:縦方向(レコード)のデータを横方向(...
質問  さつき  - 05/6/16(木) 17:52 -

引用なし
パスワード
   小僧さん、教えていただいてありがとうございます。

>下テーブルのフィールド数に変更がないのであれば
>ワーク用のテーブルとして使うのもありだと思われますが、
>上テーブルの結果によって可変するものであると
>下テーブルに伴うクエリ・フォーム・レポート・モジュールと
>大幅な変更が必要となってしまいます。

下テーブルのフィールド数に変更はありません。品目は7個までに限定できます。
ワーク用のテーブルとして使う形にしたいです。

>そのワークテーブルを何に使うのかによっては
>もうちょっと良い方法があるかもしれません。

ワークテーブルは契約者をキーに担当者テーブルと関連付けます。

>「rs2」に対して「FindFirst」メソッドを使い、
>結果が「Nomatch」プロパティの値が「True」でしたら「AddNew」で
>「False」でしたら「Edit」で開いて「Update」すれば良いと思われます。

下記のようにしてみましたが、
rs2.FindFirst "取引先名編集=" & cr 
のところで「コンパイルエラー メソッドまたはデータメンバが見つかりません」とでます。
どのようにしたらよいでしょうか?

Public Function 横並び()

Dim cn As ADODB.Connection
Dim rs1 As ADODB.Recordset
Dim rs2 As ADODB.Recordset
Dim cr As String

  Application.Echo False
  DoCmd.Hourglass True 

  Set cn = Application.CurrentProject.Connection 
  Set rs1 = New ADODB.Recordset
  Set rs2 = New ADODB.Recordset
  
  rs1.Open "list", cn, adOpenStatic, adLockReadOnly
  rs2.Open "listyoko", cn, adOpenKeyset, adLockOptimistic
  Rst.MoveFirst

  keiyakusha = ""
  j = 1
   
  Do Until rs1.EOF

    If IsNull(rs1.Fields("区分").Value) = True Then
        rs1.MoveNext
    Else
      Set cr = rs1.Fields("契約者")
      rs2.FindFirst "契約者=" & cr
      If rs2.NoMatch = True Then
        j = 1
        rs2.AddNew
        rs2.Fields("契約者") = rs1.Fields("契約者")
        For i = 1 To 3
          rs2.Fields(j) = rs1.Fields(i)
          j = j + 1
        Next i
        rs2.Update
      ElseIf rs2.NoMatch = False Then
        j = 4
        rs2.Edit
        For i = 1 To 3
          rs2.Fields(j) = rs1.Fields(i)
          j = j + 1
        Next i
          j = j + 1
        rs2.Update
        keiyakusha = rs1.Fields("契約者").Value
      End If
    End If
  rs1.MoveNext
  Loop
  
  rs1.Close
  rs2.Close
  cn.Close
  
End Function

【5396】Re:縦方向(レコード)のデータを横方向(...
回答  小僧  - 05/6/16(木) 19:30 -

引用なし
パスワード
   ▼さつき さん:
ごめんなさい。ADOでしたね。

ADOには「FindFirst」メソッドがないので「Find」メソッドを使うか
「Filter」で新規か更新か判断する事になります。

以下参考にして下さい。

Public Function 横並び()

Dim cn As ADODB.Connection
Dim rs1 As ADODB.Recordset
Dim rs2 As ADODB.Recordset
Dim cr As String
Dim I As Long
Dim J As Long

  Application.Echo False
  DoCmd.Hourglass True

  Set cn = Application.CurrentProject.Connection
  Set rs1 = New ADODB.Recordset
  Set rs2 = New ADODB.Recordset
 
  rs1.Open "list", cn, adOpenStatic, adLockReadOnly
  rs2.Open "listyoko", cn, adOpenKeyset, adLockOptimistic

  Do Until rs1.EOF
  
  If Not IsNull(rs1![区分].Value) Then
    
'フィルタを掛けて新規か追加か判断
    rs2.Filter = "契約者 ='" & rs1![契約者] & "'"
    
'データなし(新規)
    If rs2.EOF Then
      rs2.AddNew
      For I = 1 To 4
        rs2(I - 1) = rs1(I)
      Next I
'データあり(追加)
     Else
      J = 0
'空のフィールドを検索
      Do Until rs2(J) = "" Or IsNull(rs2(J))
        J = J + 1
      Loop
      
      For I = 0 To 2
        rs2(I + J) = rs1(I + 2)
      Next
    End If
'更新
    rs2.Update
  End If
  rs1.MoveNext
  Loop

'オブジェクトの解放
  rs1.Close: Set rs1 = Nothing
  rs2.Close: Set rs2 = Nothing
  cn.Close: Set cn = Nothing
End Function

【5400】Re:縦方向(レコード)のデータを横方向(...
質問  さつき  - 05/6/17(金) 14:31 -

引用なし
パスワード
   小僧 さん、ありがとうございます。

できました。でも、ちょっと問題が出てきてしまいました。
せっかく空白フィールドを検索して、次の品目を並べるよう配慮して頂いたのですが。
データによって個数や品目の欄が空白になっている場合があるのです。

それで、1品目ごとに規則的に3つフィールドをとるために以下のようにしたのですが、上手く行きません。どうしたらよいでしょうか?
こんな基本的なこともわからず、すいません。よろしくお願いいたします。

>    If rs2.EOF Then
>      rs2.AddNew
>      For I = 1 To 4
>        rs2(I - 1) = rs1(I)
>      Next I
>'データあり(追加)
>     Else
>      For I = 0 To 2
>        rs2(J + 4) = rs1(I + 2)
         J = J + 1
>      Next
      J = J + 1
>    End If
     J = 0
>'更新
>    rs2.Update
>  End If
>  rs1.MoveNext
>  Loop
>

【5403】Re:縦方向(レコード)のデータを横方向(...
回答  小僧  - 05/6/17(金) 15:00 -

引用なし
パスワード
   ▼さつき さん:
こんにちは。

メーカー名は空白にならない事が前提なのですが、

>>      J = 0
>>'空のフィールドを検索
>>      Do Until rs2(J) = "" Or IsNull(rs2(J))
>>        J = J + 1
>>      Loop

この部分、現在は「0」「1」「2」…が空白の時、となっていますよね?

これを「1」「4」「7」…が空白の時、と判断させれば良いと思います。


>>      Do Until rs2(J) = "" Or IsNull(rs2(J))
→      Do Until rs2(J*3+1) = "" Or IsNull(rs2(J*3+1))

これで空白のセルを3つおきに調べていくと思います。
いかがでしょうか?

【5415】Re:縦方向(レコード)のデータを横方向(...
お礼  さつき  - 05/6/20(月) 10:13 -

引用なし
パスワード
   小僧 さん
できました。ありがとうございました。
またわからないことがあったらよろしくお願いいたします。

1760 / 2272 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
1078264
(SS)C-BOARD v3.8 is Free