Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Pro : Excel 2016)
構成データの紐づけについて
投稿日時: 23/05/24 15:52:51
投稿者: ひろまさ

書籍やネットで検索を行っても解決ができない処理があります。
次のような結果を求める事が可能なのかご教示をお願いできないでしょうか。
 
■データ
【溶接シート】
 子CD 時間
  100   1
  200   5
 
【切断シート】
 子CD 時間
 200  10
 300   5
 
■マスタ
【構成表シート】
 親CD 子CD 切断 溶接
 111  100    有
     200 有  有
 222  100    有
     300 有
 
■結果
【結果シート】
 親CD 時間
 111  16
 222   6
 
【手順】
 @【溶接シート】の子CDの「100」が【構成表シート】に紐づく親CDに存在するのか
   確認して、溶接”有”の場合、【溶接シート】の時間を【結果シート】の該当する
   親CDの時間に転記します。
   引続き、子CDの「200」も同様に処理を行います。
 
 【結果シート】
  親CD 時間
  111  6
  222  1
 
 A【切断シート】の子CDの「200」が【構成表シート】に紐づく親CDに存在するのか
   確認して、切断”有”の場合、【切断シート】の時間を【結果シート】の該当する
   親CDの時間に加算します。
   引続き、子CDの「300」も同様に処理を行います。
 
 【結果シート】
  親CD 時間
  111  16
  222   6
 
以上になりますが、アドバイスを頂けないでしょうか。
お手数をお掛けしますがよろしくお願い致します。

回答
投稿日時: 23/05/24 17:26:28
投稿者: sk

引用:
■マスタ
【構成表シート】
 親CD 子CD 切断 溶接
 111  100    有
     200 有  有
 222  100    有
     300 有

まず[親CD]列に空白セルを設けるのは
出来る限りやめた方がよいでしょう。
 
引用:
@【溶接シート】の子CDの「100」が【構成表シート】に紐づく親CDに存在するのか
  確認して、溶接”有”の場合、【溶接シート】の時間を【結果シート】の該当する
  親CDの時間に転記します。
  引続き、子CDの「200」も同様に処理を行います。

1. [構成表シート]上にあるテーブルのレコードのうち、
   [溶接]列の値が "有" であるレコードを抽出する。
 
2. 上記 1 の結果と[溶接シート]上にあるテーブルを、
   互いの[子CD]列をキーとして内部結合する。
 
3. 上記 2 の結果を[構成表シート]側の[親CD]列でグループ化し、
   グループごとに[溶接シート]側の[時間]列の値の合計を得る。
 
4. 上記 3 の結果を別のワークシート上に出力する。
 
引用:
A【切断シート】の子CDの「200」が【構成表シート】に紐づく親CDに存在するのか
  確認して、切断”有”の場合、【切断シート】の時間を【結果シート】の該当する
  親CDの時間に加算します。
  引続き、子CDの「300」も同様に処理を行います。

1. [構成表シート]上にあるテーブルのレコードのうち、
   [切断]列の値が "有" であるレコードを抽出する。
 
2. 上記 1 の結果と[切断シート]上にあるテーブルを、
   互いの[子CD]列をキーとして内部結合する。
 
3. 上記 2 の結果を[構成表シート]側の[親CD]列でグループ化し、
   グループごとに[切断シート]側の[時間]列の値の合計を得る。
 
4. 上記 3 の結果を別のワークシート上に出力する。
 
-------------------------------------------------------------
 
といった集計処理をなさりたいのであれば、Power Query によって
そういう結果を得るクエリを作成なさればよろしいのではないかと。

投稿日時: 23/05/24 20:50:00
投稿者: ひろまさ

sk様
ご回答ありがとうございます。
また、順にご説明をして頂きありがとうございます。
空白の件は承知しました。
親CDの空白セルは避けます。
大変申し訳ございませんが、やはりVBAでは難しいでしょうか。

回答
投稿日時: 23/05/24 21:37:53
投稿者: simple

横合いから失礼します。
色々なやりかたがあります。ワークシート関数だけでも十分対応可能です。
Dictionaryを使ったコード例を示します。
 

Sub test()
    Dim k       As Long
    Dim dic1    As Object
    Dim dic2    As Object
    Dim total   As Long
    Dim parent  As Long
    Dim child   As Long
    Dim s1      As String
    Dim s2      As String
    Dim dicTotal As Object

    '切断シートから所要時間を取得
    Set dic1 = CreateObject("Scripting.Dictionary")
    With Worksheets("切断")      
        For k = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
            dic1(.Cells(k, "A").Value) = .Cells(k, "B").Value
        Next
    End With

    '溶接シートから所要時間を取得
    Set dic2 = CreateObject("Scripting.Dictionary")
    With Worksheets("溶接")     
        For k = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
            dic2(.Cells(k, "A").Value) = .Cells(k, "B").Value
        Next
    End With

    '構成表シートをもとに合計時間を集計
    Set dicTotal = CreateObject("Scripting.Dictionary")
    With Worksheets("構成表")   
        For k = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
            parent = .Cells(k, 1)   '親CD
            child = .Cells(k, 2)    '子CD
            s1 = .Cells(k, 3)       '切断有無
            s2 = .Cells(k, 4)       '溶接有無
            If s1 = "有" Then total = dic1(child)
            If s2 = "有" Then total = total + dic2(child)
            dicTotal(parent) = dicTotal(parent) + total
        Next

        '合計をシートに書き出す
        .Range("F1:G1") = Array("親CD", "合計")
        .Range("F2").Resize(dicTotal.Count, 1) _
                = Application.Transpose(dicTotal.keys)
        .Range("G2").Resize(dicTotal.Count, 1) _
                = Application.Transpose(dicTotal.items)
    End With
End Sub

回答
投稿日時: 23/05/24 21:41:24
投稿者: simple

ちなみに、親CD,子CD等は 整数値としてコーディングしましたが、
英数が入っているのであれば、もちろんString型をそのまま辞書のKeyとして使えます。

回答
投稿日時: 23/05/24 21:44:18
投稿者: simple

ああ、結果シートに書き出すんですね。そちらで修正してください。

投稿日時: 23/05/24 21:58:39
投稿者: ひろまさ

simple様
2日続けてご回答を頂きありがとうございます。
記述して頂いたコードを基に実際の処理に修正を行ってみます。
ありがとうございました。