質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

775閲覧

重複データ集約と照合

jabe

総合スコア43

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2022/05/10 02:44

編集2022/05/10 02:50

実現したいこと

やりたい事:4パターン、8パターンシートの内容を照合し、照合結果シートのボタンで照合結果を出力したいです。

前提環境①:照合結果シートのA3~E3項目は、フォーマットとして用意されている。
条件①:4パターン、8パターンシートの行数は300行数を想定
条件②:4パターン、8パターンシートの照合キーは、部品コード
条件③:4パターン、8パターンシート毎で、以下データ集約を行った後、4パターン、8パターンシートの照合を行いたい。
●第一データ集約条件
①重複部品コードがあった場合、1つに集約する。その際、数量は加算、部品名は上書き集約
②重複しない部品コードは、数量、部品名そのまま
●第二データ集約条件
①部品コードに対して、4パターン、8パターンシートの数量を表示
②部品名は、上書き
※8パターンシート11行名の部品_Fと4パターンシート11行目の部品Fとなっているが、部品コードは同一の為、どちらかに上書きされる形にしたい。
③照合結果は以下条件のように表示させたい
イメージ説明

完成イメージ
イメージ説明

詳細①
イメージ説明
詳細②
イメージ説明
詳細③
イメージ説明

発生している問題・エラーメッセージ

イメージ説明

実行時エラー450 引数の数が一致していません。または不正なプロパティを指定しています。

該当のソースコード

VBA

1Sub 重複データ集約し照合() 2 3Dim myDic As Object 'Dictionaryオブジェクト使用 4Dim myPc As Variant '部品コード変数 5Dim myQu As Variant '数量変数 6Dim myPn As Variant '部品名変数 7Dim myList As Variant '部品コード、数量、部品名配列 8Dim i As Long '配列カウント数 9Dim cWs As Worksheet '4パターンシート 10Set cWs = Worksheets("4パターン") '4パターン変数 11Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "4パターン_仮" '4パターン_仮シート作成 12Dim cWs1 As Worksheet '4パターンシートコピー 13Set cWs1 = Worksheets("4パターン_仮") '4パターン_仮変数 14 15 Set myDic = CreateObject("Scripting.Dictionary") 16 17 '数量,部品コード,部品名のデータを配列に格納※社内外列は照合に不要だが、列分割での格納方法が分からない 18 cWs.Activate 19 myList = Range("A4", Range("A" & Rows.Count). _ 20 End(xlUp)).Resize(, 4).Value 21 22 23 '連想配列にデータを格納 1次元 24 For i = 1 To UBound(myList, 1) 25 26 '部品コードが空欄かチェック 27 If Not myList(i, 3) = Empty Then 28 If Not myDic.exists(myList(i, 3)) Then '配列重複チェック 29 30 '重複しない部品コードを取得※数量,部品コード,部品名を取得したいが、複数Itemの場合エラー発生 31 myDic.Add Key:=myList(i, 3), Item:=myList(i, 1), Item:=myList(i, 4) 32 Else 33 34 '数量を加算 35 myDic(myList(i, 3)) = myDic(myList(i, 3)) + Val(myList(i, 1)) 36 End If 37 End If 38 Next 39 40 '[部品コード] 重複していないリストを格納 41 myPc = myDic.keys 42 43 '[部品名] 品目を格納 44 myPn = myDic.items 45 46 '[数量] 品目コードの合計を格納 47 myItem = myDic.items 48 49 'リストを出力 50 For i = 0 To UBound(myPc) 51 cWs1.Cells(i + 2, 1).Value = myPc(i) 52 cWs1.Cells(i + 2, 2).Value = myPn(i) 53 cWs1.Cells(i + 2, 3).Value = myQu(i) 54 Next 55 56 '開放※setで使用したものを閉じる(DBへのアクセス、変数) 57 Set myDic = Nothing 58 59End Sub 60 61

試したこと

やりたい事から、以下方針でプログラムを考えたのですが、初期段階でつまづきました。
また、やりたい事が複雑であるため、道筋も見えず、お力添えをお願いします。

第一データ集約条件を目指して、4パターン、8パターンシート毎で集約処理を実施しようとしたら、
部品コード、数量、部品名の2つ以上の変数処理を行うとことでエラーが発生しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

dictionaryを3つ使う方法にしました。
4パターン用(キー:部品コード、値:数量)
8パターン用(キー:部品コード、値:数量)
部品名用(キー:部品コード、値:部品名)

4パターンシートと8パターンシートは同じフォーマットであることが前提です。
データは4行目から開始

照合結果シートは、3行目までが見出し、データは4行目から開始とします。
(マクロが設定するのは4行目以降のみ)

シート名は、以下の通りとします。
4パターンシート:4パターン
8パターンシート:8パターン
照合結果シート:照合結果
(シート名が実際と異なる場合は、あなたのほうでマクロを修正してください)

1.4パターンの部品コードと数量を記憶(同一部品コードは1つにまとめる)
2.8パターンの部品コードと数量を記憶(同一部品コードは1つにまとめる)
3.4パターンの部品コードを基準に照合結果へ出力
その時、8パターンの部品コードがあれば、同時に出力し、8パターンにdictionaryから当該部品コードを削除
4.残りの8パターンの部品コードを照合結果へ出力
という流れになります。

VBA

1Option Explicit 2 3Public Sub 重複データ集約照合() 4 Dim Dic8 As Object '8パターン用 5 Dim Dic4 As Object '4パターン用 6 Dim dicN As Object '部品名用 7 Dim ws8 As Worksheet '8パターンシート 8 Dim ws4 As Worksheet '4パターンシート 9 Dim wsS As Worksheet '照合シート 10 Dim wrow As Long 11 Dim key As Variant 12 Dim res As String 13 Set Dic8 = CreateObject("Scripting.Dictionary") '連想配列の定義 14 Set Dic4 = CreateObject("Scripting.Dictionary") '連想配列の定義 15 Set dicN = CreateObject("Scripting.Dictionary") '連想配列の定義 16 Set ws8 = Worksheets("8パターン") 17 Set ws4 = Worksheets("4パターン") 18 Set wsS = Worksheets("照合結果") 19 Call MakeDict(ws4, Dic4, dicN) '4パターンシート読み込み 20 Call MakeDict(ws8, Dic8, dicN) '8パターンシート読み込み 21 '照合シートの4行目以降をクリア 22 wsS.Rows("4:" & Rows.count).ClearContents 23 '照合シート設定 24 wrow = 4 25 '4パターンを処理 26 For Each key In Dic4.keys 27 'A列数量 4パターン 28 wsS.Cells(wrow, "A").Value = Dic4(key) 29 'B列数量 8パターン 30 If Dic8.exists(key) = True Then 31 wsS.Cells(wrow, "B").Value = Dic8(key) 32 Dic8.Remove key 33 Else 34 wsS.Cells(wrow, "B").Value = 0 35 End If 36 'C列部品コード 37 wsS.Cells(wrow, "C").Value = key 38 'D列部品名 39 wsS.Cells(wrow, "D").Value = dicN(key) 40 'E列照合結果 41 If wsS.Cells(wrow, "B").Value = 0 Then 42 res = "部品コード不一致" 43 ElseIf wsS.Cells(wrow, "A").Value = wsS.Cells(wrow, "B").Value Then 44 res = "部品コード一致・数量一致" 45 Else 46 res = "部品コード一致・数量不一致" 47 End If 48 wsS.Cells(wrow, "E").Value = res 49 wrow = wrow + 1 50 Next 51 '8パターンの残りの部品コードを処理 52 For Each key In Dic8.keys 53 'A列数量 4パターン 54 wsS.Cells(wrow, "A").Value = 0 55 'B列数量 8パターン 56 wsS.Cells(wrow, "B").Value = Dic8(key) 57 'C列部品コード 58 wsS.Cells(wrow, "C").Value = key 59 'D列部品名 60 wsS.Cells(wrow, "D").Value = dicN(key) 61 'E列照合結果 62 res = "部品コード不一致" 63 wsS.Cells(wrow, "E").Value = res 64 wrow = wrow + 1 65 Next 66 MsgBox ("完了") 67End Sub 68'8/4パターンシート処理 69Private Sub MakeDict(ByVal ws As Worksheet, ByRef dicT As Object, ByRef dicN As Object) 70 Dim maxrow As Long 71 Dim wrow As Long 72 Dim key As String 73 maxrow = ws.Cells(Rows.count, "A").End(xlUp).Row 'A列の最大行取得 74 For wrow = 4 To maxrow 75 key = ws.Cells(wrow, "C").Value 76 '新規の部品コードなら数量クリア 77 If dicT.exists(key) = False Then 78 dicT(key) = 0 79 End If 80 dicT(key) = dicT(key) + ws.Cells(wrow, "A").Value '数量加算 81 '新規の部品名なら部品名登録 82 If dicN.exists(key) = False Then 83 dicN(key) = ws.Cells(wrow, "D").Value 84 End If 85 Next 86End Sub 87

投稿2022/05/10 05:49

編集2022/05/10 07:53
tatsu99

総合スコア5436

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jabe

2022/05/11 08:37

対応ありがとうございます。 また、私のやりたい事をプログラム化していただき、助かりました。 実行したことろ問題なく動作しました。 dictionaryを複数使用して、集約作業を簡潔に出来る事知りませんでした。 勉強し直します。
jabe

2022/05/11 09:14

すいません。聞き忘れていました。 お手数掛けますが、以下コードの狙いを教えて下さい。 Dic8.Remove key'Remove一部を削除するのは何の為でしょうか? 3.4パターンの部品コードを基準に照合結果へ出力 その時、8パターンの部品コードがあれば、同時に出力し、8パターンにdictionaryから当該部品コードを削除 ↑上記の”8パターンにdictionaryから当該部品コードを削除”するというところが理解出来ていなくて。
tatsu99

2022/05/11 09:59

ここで行っていることは ①4パターンにあって、8パターンにないもの(8パターン数量に0をセット) ②4パターンにあって、8パターンにあるもの(8パターン数量にその数をセット) です。 これが、終わった後で、 4.残りの8パターンの部品コードを照合結果へ出力をおこないますが、 これは、「8パターンにあって、4パターンにないもの」の処理です。 その為には、上記の②で4パターンにあり8パターンにもあるものを削除しておけば、 残りは、「8パターンにあって、4パターンにないもの」だけになります。
jabe

2022/05/13 02:22

回答ありがとうございます。 理解できました。 4の処理の為、②の削除が必要になってくるんですね。
guest

0

複雑な案件なので細かく精査はしてませんが、エラーの部分についてだけ解決策を。

vba

1 If Not myDic.exists(myList(i, 3)) Then '配列重複チェック 2 3 '重複しない部品コードを取得※数量,部品コード,部品名を取得したいが、複数Itemの場合エラー発生 4 myDic.Add Key:=myList(i, 3), Item:=myList(i, 1), Item:=myList(i, 4) 5 Else 6 7 '数量を加算 8 myDic(myList(i, 3)) = myDic(myList(i, 3)) + Val(myList(i, 1)) 9 End If

上記のコードで「引数の数が一致していません。」というエラーになるの、Addメソッドの引数は2つなのに無視して3つ指定しているのが原因ですね。

いろいろ方法はあると思いますが、
数量と部品名をArray関数で配列にまとめて、Itemに格納すればどうでしょう。

vba

1 Dim a As Variant 2 3 If Not myDic.exists(myList(i, 3)) Then '配列重複チェック 4 myDic.Add Key:=myList(i, 3), Item:=Array(myList(i, 1), myList(i, 4)) 5 Else 6 '数量を加算 7 a = myDic(myList(i, 3)) 8 a(0) = a(0) + 1 9 myDic(myList(i, 3)) = a 10 End If

投稿2022/05/10 04:06

編集2022/05/10 04:44
hatena19

総合スコア33692

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jabe

2022/05/11 08:31

対応ありがとうございます。 エラー解消されました。 3つ以上の項目がある場合、Array関数で対応する事ができる事知りませんでした。 勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問