Excel (VBA) |
![]() ![]() |
(Windows 10 Pro : Excel 2016)
各シート毎の明細の集計について
投稿日時: 23/07/25 23:14:19
投稿者: ひろまさ
|
---|---|
大変申し訳ございませんが、以下の結果を表示させる処理のご教示を
|
![]() |
投稿日時: 23/07/26 09:50:32
投稿者: Suzu
|
---|---|
Dictionary は 基本 2次元であり、2列 の 処理はできますが、3列の処理を行うには テクニックが必要です。
親図番 子図番 抜き 曲げ 1P015-1 1P015-1 1P015-1 1P015-1-KA A 2P064-1 2P064-1 2P064-1 2P064-1-KA A A 2P064-1 2P064-1-KI A に、 図番 子図番 抜き 曲げ 抜2 曲2 1P015-1 1P015-1 0 0 1P015-1 1P015-1-KA A 10 0 2P064-1 2P064-1 0 0 2P064-1 2P064-1-KA A A 20 30 2P064-1 2P064-1-KI A 0 20 抜2、曲2 を追加 抜2:=IF(C2="A",SUMIF(抜き!A$2:B$100000,"="&$B2,抜き!B$2:B$100000),0) 曲2:=IF(D2="A",SUMIF(曲げ!A$2:B$100000,"="&B2,曲げ!B$2:B$100000),0) ここま出てしまえば シート「結果」でも、同じ SUMIF関数を使えば良いですよね。 |
![]() |
投稿日時: 23/07/26 11:37:43
投稿者: ひろまさ
|
---|---|
Suzu様
|
![]() |
投稿日時: 23/07/26 12:39:21
投稿者: Suzu
|
---|---|
引用: それで、「抜き」なのか「曲げ」なのか を dTotal の中で、どう判断しようとされたのでしょうか? 引用: 引用: Dictionry の 構造 で行うとして、先に提示した コンテンツの 具体的に どこが判らないのでしょうか? どの箇所修正すれば という発言では、マスターをする意識を感じる事はできません。 過去のやりとりを拝見しても、 https://www.moug.net/faq/viewtopic.php?t=82260 https://www.moug.net/faq/viewtopic.php?t=82261 https://www.moug.net/faq/viewtopic.php?t=82262 https://www.moug.net/faq/viewtopic.php?t=82264 https://www.moug.net/faq/viewtopic.php?t=82296 https://www.moug.net/faq/viewtopic.php?t=82362 ご自身の考慮の跡が見えません。 Dictionary は、2列なら簡単です。 基本は、2列しか扱えない事 すら ご存じでは無いように拝見される方に Dictionary を使う前提の コードを提示しても、とてもマスターできるとは思えません。 Dictionry に拘らずに どことどこの値を比較し、同じだったら ある変数に その値を入れる こことここの値を比較し、同じだったら また別の変数に そこの値を入れる の様に、 その条件とその時の動作を、ご自身で考えましょう。 |
![]() |
投稿日時: 23/07/26 13:23:20
投稿者: ひろまさ
|
---|---|
Suzu様
|
![]() |
投稿日時: 23/07/26 14:54:57
投稿者: hatena
|
---|---|
全時間 は 抜き計+曲げ計 で計算できますので、必要なデータは抜き計と曲げ計ですね。
Public Sub Sample() Dim ko As Worksheet, sh1 As Worksheet, sh2 As Worksheet, sh3 As Worksheet Dim d1 As Object, d2 As Object, dTotal As Object Dim parent As String, child As String, s1 As String, s2 As String Dim k As Long Dim mage As Long, nuki As Long Set ko = ThisWorkbook.Sheets(1) Set sh1 = ThisWorkbook.Sheets(2) Set sh2 = ThisWorkbook.Sheets(3) Set sh3 = ThisWorkbook.Sheets(4) '抜きシートから時間を取得 Set d1 = CreateObject("Scripting.Dictionary") With sh2 For k = 2 To .Cells(Rows.Count, 1).End(xlUp).Row d1(.Cells(k, "A").Value) = .Cells(k, "B").Value Next k End With '曲げシートから時間を取得 Set d2 = CreateObject("Scripting.Dictionary") With sh3 For k = 2 To .Cells(Rows.Count, 1).End(xlUp).Row d2(.Cells(k, "A").Value) = .Cells(k, "B").Value Next k End With '構成シートより図番の合計時間を集計 Set dTotal = CreateObject("Scripting.Dictionary") With ko For k = 2 To .Cells(Rows.Count, 1).End(xlUp).Row parent = .Cells(k, 1) '親図番 child = .Cells(k, 2) '子図番 s1 = .Cells(k, 3) '抜き s2 = .Cells(k, 4) '曲げ If s1 <> "" Or s2 <> "" Then If s1 <> "" Then nuki = d1(child) Else nuki = 0 If s2 <> "" Then mage = d2(child) Else mage = 0 If dTotal.Exists(parent) Then dTotal(parent) = Array(dTotal(parent)(0) + nuki, dTotal(parent)(1) + mage) Else dTotal(parent) = Array(nuki, mage) End If End If Next k End With '結果をシートに転記 sh1.Range("A1:D1") = Array("図番", "全時間", "抜き", "曲げ") sh1.Range("A2").Resize(dTotal.Count, 1) _ = Application.Transpose(dTotal.keys) sh1.Range("C2").Resize(dTotal.Count, 2) _ = Application.Transpose(Application.Transpose(dTotal.items)) With sh1.Range("B2").Resize(dTotal.Count, 1) .FormulaLocal = "=C2+D2" .Value = .Value End With End Sub Transposeを入れ子にして、配列の配列(ジャグ配列)を二次元配列に展開するという部分はちょっと裏技的なので、ループ処理で書き出した方が分かりやすかったかもしれません。 |
![]() |
投稿日時: 23/07/26 15:15:26
投稿者: Suzu
|
---|---|
引用: 何を確認されたのでしょうか? それぞれの 値でしょうか? じゃぁ、その中で、抜き・曲げ の区別ができる事を確認したという事なのでしょうか? もっていない事を確認なさったと言う事なのでしょうか? 確認した上で、何をどうされようとしたのでしょうか? 動作の判らないコードの確認は必要ですが 変数の 何を確認をされているのでしょうか? 値の中身 を確認し、この変数の値なら、条件分岐は ここを通る とか そのさきに、分岐を判定するのに、変数をこんか使い方をする とか 他の方が作った コードの動作を確認し、参考にするのです。 身につく事で、 引用: の様な、ロジックを知る事ができる様になります。 そのロジックを自分で思いつく事ができれば、 ここの変数は 本来こうなんなきゃいけないのに、別の値になってしまっているから 思い通りにならないんだ となり、 回答 投稿日時: 23/05/24 23:20:25投稿者: simple ああ、そうでしたね。totalが初期化されていませんでしたね。ケアレスミス。 修正してください。 投稿日時: 23/05/24 23:30:45投稿者: ひろまさ simple様 遅くにご回答を頂きありがとうございます。 恐縮ではございますが、その個所だけでも具体的にご教示をお願いできないでしょうか。 よろしくお願い致します。 回答 投稿日時: 23/05/24 23:44:54投稿者: simple え? 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) '溶接有無 total = 0 If s1 = "有" Then total = dic1(child) If s2 = "有" Then total = total + dic2(child) dicTotal(parent) = dicTotal(parent) + total Next です。 こんな やりとりにはならないと思います。 当方もまだまだなので、Dictionary の 多次元配列 は お教えできる程ではありません。 当方もその事は判っていますし、別の方法を採ると言っています。 PowerQuery 然り、一般関数然り。 どうしても Dictionary を使うのであれば 抜き と 曲げ の間に 区切り文字 を入れて Itemに 入れて使うでしょうか。 1.Exists の際に、Itemの 値を取り出し 2.区切り文字 にて分割、対象側だけ取り出し、加算 3.区切り文字を含め Item に戻す 4.B列に その値を吐き出す 5.吐き出した文字列から、Excelの一般関数 を使い、C列、D列の 抜き/曲げ の部分を抜き取り、 値貼り付けを行い、数値にしています。 6.B列にC列+D列の加算式を入れ計算させ、値貼り付けを実施 と・・書いている間に、hatenaさんから・・Arrayのコード・・ Arrayの方が楽ですが、書いていたので、参考までに。 With ko For k = 2 To .Cells(Rows.Count, 1).End(xlUp).Row parent = .Cells(k, 1) '親図番 child = .Cells(k, 2) '子図番 s1 = .Cells(k, 3) '抜き s2 = .Cells(k, 4) '曲げ If s1 <> "" Then If dTotal.Exists(parent) = True Then dTotal(parent) = Split(dTotal(parent), ";")(0) + d1(child) & ";" & Split(dTotal(parent), ";")(1) Else dTotal(parent) = d1(child) & ";0" End If End If If s2 <> "" Then If dTotal.Exists(parent) = True Then dTotal(parent) = Split(dTotal(parent), ";")(0) & ";" & Split(dTotal(parent), ";")(1) + d2(child) Else dTotal(parent) = Split(dTotal(parent), ";")(0) & ";" & d2(child) End If End If Next k End With '結果をシートに転記 With sh1 k = dTotal.Count .Range("A1:D1") = Array("図番", "全時間", "抜き", "曲げ") .Range("A2").Resize(k) = Application.Transpose(dTotal.Keys) .Range("B2").Resize(k) = Application.Transpose(dTotal.Items) .Range("C2").Resize(k).FormulaR1C1 = "=MID(RC[-1],1,FIND("";"",RC[-1])-1)" .Range("D2").Resize(k).FormulaR1C1 = "=MID(RC[-2], Find("";"", RC[-2]) + 1, 100)" .Range("C2").Resize(k, 2).Value = sh1.Range("C2").Resize(5, 2).Value .Range("B2").Resize(k).FormulaR1C1 = "=RC[1]+RC[2]" .Range("B2").Resize(k).Value = sh1.Range("B2").Resize(k).Value End With total を Double で 宣言されているので 実処理の際には、小数点以下桁も含まれているのであれば 取り出し&計算 の所で、明示的な型変換を含めた方が無難かもしれません |
![]() |
投稿日時: 23/07/26 16:12:34
投稿者: hatena
|
---|---|
Itemに2つ以上の値を格納するという方法は、配列をつかったり区切り文字で区切ったり、で操作が理解しづらいなら、
|
![]() |
投稿日時: 23/07/26 16:19:02
投稿者: simple
|
---|---|
# 過去のやりとりまで言及されて恥ずかしい思いですww。
・構成シートに、抜きと曲げの列を追加し、IFとVLOOKUP関数で数値を取得します。 ・集計シートの作成には、重複を除いた親図番コードが必要ですが、 重複排除とかでなんとかなります。 ・集計シートに、SUMIF関数を使った集計式を埋め込みます。これで十分機能しますよね。 もちろん、手作業を推奨するものではなく、式をマクロで設定します。数値化もマクロにさせます。 ワークシート関数を適宜利用するのも適切なことであって、 なにからなにまで"ゴリゴリ"とコードで書くのは、慣れないと時間ばかりがかかります。 そうした手法も幅広く検討されることを推奨します。 もともとExcelはスプレッドシートですから、ワークシートという広大な記憶領域や、 そのうえの関数を適宜利用すべきかな、と思います。 既に適切なコードが提示されていますが、 この場合に限定した方法として、 作成する ・親図番 -> 抜き ・親図番 -> 曲げ ・親図番 -> 合計 という3つのdictionaryを作る、と問題を単純化してしまえば、 やることが分かりやすくなるのではないかと思います。 (無論、曲げ、抜きの数値を取得するときに、子図番をキーとするDictionaryを 途中で使うのはもちろんのことです。) |
![]() |
投稿日時: 23/07/26 22:12:51
投稿者: ひろまさ
|
---|---|
お返事が大変遅くなりましたが、今回も多くの方々からアドバイスを頂き
|