[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『リスト表からマトリクス表の作成マクロについて』(マリリ)
下記のSheet'リスト'からSheet'関東'のような表をマクロで作りたいのですが、教えていただけないでしょうか。宜しくお願いします。
Sheetリスト A B C D E F G H 1 2 3 番号 名称1 名称2 単位 数量 分類 4 200 東京 バナナ 本 2 関東 5 210 東京 ごぼう 本 20 関東 6 220 神奈川 バナナ 本 2 関東 7 250 京都 グローブ 個 39 関西 8 300 大阪 ボール 個 2 関西 9 300 神奈川 バナナ 本 5 関東 10 350 福岡 みかん 個 7 九州 11 400 東京 バナナ 本 5 関東 12 400 大阪 ゴムボール 個 1 関西
Sheet関東 A B C D E F G H 1 2 3 4 200 210 220 300 400 5 東京 6 バナナ 本 2 5 7 東京 8 ごぼう 本 20 9 神奈川 10 バナナ 本 2 5
< 使用 Excel:Excel2013、使用 OS:Windows10 >
若干異なりますが、ピボットテーブルではダメですか? (稲葉) 2019/02/17(日) 05:18
頭まわらんけど、一応 思ったより面倒ですね。 もっとスマートな書き方あると思います。 ピボットテーブル勧めます。
Option Explicit Sub ピボット() Dim dic As Object Dim w As Variant Dim 分類 As String, 名称 As String, 番号 As String Dim k分類 As Variant, k名称 As Variant, k番号 As Variant, k数量 As Variant Dim i As Long, n As Long, m As Long Dim ans As Variant Set dic = CreateObject("Scripting.Dictionary") w = Sheets("Sheet1").Range("H3", Sheets("Sheet1").Cells(Rows.Count, "C").End(xlUp)).Value For i = 2 To UBound(w, 1) 分類 = w(i, 6): 名称 = w(i, 2) & "_" & w(i, 3): 番号 = w(i, 1) If Not dic.exists(分類) Then Set dic(分類) = CreateObject("Scripting.Dictionary") If Not dic(分類).exists(名称) Then Set dic(分類)(名称) = CreateObject("Scripting.Dictionary") dic(分類)(名称)(番号) = dic(分類)(名称)(番号) + w(i, 5) Next i For Each k分類 In dic.keys n = 1: m = 2 ReDim ans(1 To n, 1 To m) For Each k名称 In dic(k分類).keys n = n + 2 ans = Application.Transpose(ans) ReDim Preserve ans(1 To m, 1 To n) ans = Application.Transpose(ans) For Each k番号 In dic(k分類)(k名称).keys m = m + 1 ReDim Preserve ans(1 To n, 1 To m) ans(1, m) = k番号 ans(n - 1, 1) = Split(k名称, "_")(0) ans(n, 1) = Split(k名称, "_")(1) ans(n, 2) = Application.Evaluate("=VLOOKUP(""" & ans(n, 1) & """,Sheet1!E:F,2,0)") ans(n, m) = dic(k分類)(k名称)(k番号) Next k番号 Next k名称 Sheets.Add after:=Sheets(Sheets.Count) Sheets(Sheets.Count).Name = k分類 With Sheets(k分類) .Range("B4").Resize(UBound(ans, 2), UBound(ans, 1)).Value = Application.Transpose(ans) .Range(.Range("B6").Resize(, UBound(ans, 2)), .Cells(Rows.Count, "B").End(xlUp)).Sort key1:=.Range("B6"), Header:=xlNo ans = .Range("B4").Resize(UBound(ans, 2), UBound(ans, 1)).Value .Cells.ClearContents .Range("B4").Resize(UBound(ans, 2), UBound(ans, 1)).Value = Application.Transpose(ans) End With Next k分類 End Sub (稲葉) 2019/02/17(日) 07:27
おはようございます。
一晩寝たら胸のカラータイマーがビンビンです。(嘘です。見栄はりました。弱弱しいです。(笑)
最近、体力がなくてね。。。。年だね。。。
ところで↓みたいになりましたけど、、、答えはあってますかぁ???
では、、では、、
関東 200 210 220 300 400 東京 バナナ 本 2 5 東京 ごぼう 本 20 神奈川 バナナ 本 2 5
関西 250 300 400 京都 グローブ 個 39 大阪 ボール 個 2 大阪 ゴムボール 個 1
九州 350 福岡 みかん 個 7
Option Explicit Sub 改造てすと() Dim MyTbl As Range Dim MyA As Variant Dim MyB As Variant Dim MyC As Variant Dim MyAry() As Variant Dim MyDic As Object Dim MyScaA As Object Dim MyScaB As Object Dim MyScaC As Object Dim MyScaD As Object Dim MyKey As Variant Dim 項目 As Variant Dim ws As Worksheet Dim x As Variant Dim y As Variant Dim z As Variant Dim w As Variant Dim q As Variant Dim i As Long Dim j As Long Dim ii As Long Dim k As Long Dim n As Long Dim MyTimer As Single MyTimer = Timer Set MyDic = CreateObject("Scripting.Dictionary") Set MyScaA = CreateObject("System.Collections.ArrayList") Set MyScaB = CreateObject("System.Collections.ArrayList") Set MyScaC = CreateObject("System.Collections.ArrayList") With Sheets("リスト") Set MyTbl = .Range("C3", .Range("C" & Rows.Count).End(xlUp)).Resize(, 6) MyA = MyTbl.Value MyB = Intersect(.Range("C:F"), MyTbl).Value MyC = Intersect(.Range("D:F"), MyTbl).Value End With For i = LBound(MyA, 1) + 1 To UBound(MyA, 1) If Not MyScaB.Contains(MyA(i, 6)) Then MyScaB.Add MyA(i, 6) If Not Evaluate("=ISREF('" & MyA(i, 6) & "'!A1)") Then Sheets.Add.Name = MyA(i, 6) End If Next w = MyScaB.ToArray For ii = LBound(w) To UBound(w) For i = LBound(MyA, 1) + 1 To UBound(MyA, 1) If w(ii) = MyA(i, 6) Then MyKey = Replace(Join(Application.Index(MyB, i, 0)), " ", "") MyDic(MyKey) = MyDic(MyKey) + Val(MyA(i, 5)) If Not MyScaA.Contains(MyA(i, 1)) Then MyScaA.Add MyA(i, 1) 項目 = Join(Application.Index(MyC, i, 0)) If Not MyScaC.Contains(項目) Then MyScaC.Add 項目 End If Next x = MyDic.keys y = MyDic.items MyScaA.Sort z = MyScaA.ToArray q = MyScaC.ToArray k = 1 ReDim MyAry(1 To (UBound(q) + 1) * 2 + 1, 1 To UBound(z) + 3) For j = LBound(MyAry, 2) + 2 To UBound(MyAry, 2) MyAry(k, j) = z(j - 3) Next For n = LBound(q) To UBound(q) k = k + 2 MyAry(k - 1, 1) = Split(q(n))(0) MyAry(k, 1) = Split(q(n))(1) MyAry(k, 2) = Split(q(n))(2) For j = LBound(z) To UBound(z) MyKey = z(j) & Split(q(n))(0) & Split(q(n))(1) & Split(q(n))(2) MyAry(k, j + 3) = MyDic(MyKey) Next Next With Sheets(w(ii)) .Cells.Clear .Range("B4").Resize(UBound(MyAry, 1), UBound(MyAry, 2)).Value = MyAry .Range("B4").CurrentRegion.EntireColumn.AutoFit End With MyDic.RemoveAll MyScaA.Clear MyScaC.Clear Next Set MyTbl = Nothing Set MyDic = Nothing Set MyScaA = Nothing Set MyScaB = Nothing Set MyScaC = Nothing Erase MyA, MyB, MyC, MyAry, x, y, z, w, q MyTimer = Timer - MyTimer MsgBox "完了!!! " & Format(MyTimer, "###0.000") & "秒" End Sub seiya さんのを参考にちょっと修正(^^; (SoulMan) 2019/02/17(日) 07:34
おはようござぁ〜す。^^ 検証マン発表! SoulMan様のコードは正常に作動致しており フイルターで視認した範囲で結果も合っていると 思います。 (#^.^#)お二方ともさえておられますね。。。 隠居じーさんは今も思案中 ( ̄▽ ̄;)。。。いかん ← 年のせいにしてますが。。。実はわかってない (隠居じーさん) 2019/02/17(日) 08:34
おはようございます。いつもありがとうございます。
昨夜は、諸事情(馬券外れ)からの体調不良で失神していました。(笑)
今日も、張り切って行きましょう!!!
P.S今日は、絶対に当てなあかん!!!!! (SoulMan) 2019/02/17(日) 08:41
ありゃ 私のは合ってなかったですか? 今日はこれから子守りなので、続きは隠居じーさんさんにお願いします!! (稲葉) 2019/02/17(日) 08:56
おはようございます。^^;稲葉さま 申し上げづらいのですが。。。 私のテスト環境では 関東の神奈川バナナの表示位置 関西の大阪ゴムボール。。。 などがすこぉ〜し違うのでは と思うのですが、何分、トピ主様の情報が解りませんので 一概には申し上げられないと。。。おもい、コメントは差し控えておりました。 あくまで、私のテスト環境での事で御座いますので。 お聞き流しくださりませ。 続きが出来るほどスキルもございませんで。。。恐れ多い事でございます。 完成させる事が出来ましたら(?ですが)アップ致しますので、ご批評など 賜れば幸甚で御座います m(__)m でわ
(隠居じーさん) 2019/02/17(日) 09:31
ようやく質問を理解できた...
Sub test() Dim a, e, s, v, i As Long, ii As Long, n As Long, t As Long Dim dic As Object, AL As Object, txt As String Set dic = CreateObject("Scripting.Dictionary") Set AL = CreateObject("System.Collections.ArrayList") a = Sheets("リスト").[c3].CurrentRegion.Value For i = 2 To UBound(a, 1) If Not AL.Contains(a(i, 1)) Then AL.Add a(i, 1) If Not dic.exists(a(i, 6)) Then Set dic(a(i, 6)) = CreateObject("Scripting.Dictionary") End If txt = Join(Array(a(i, 2), a(i, 3), a(i, 4)), Chr(2)) If Not dic(a(i, 6)).exists(txt) Then Set dic(a(i, 6))(txt) = CreateObject("Scripting.Dictionary") End If dic(a(i, 6))(txt)(a(i, 1)) = dic(a(i, 6))(txt)(a(i, 1)) + a(i, 5) Next AL.Sort For Each e In dic If Not Evaluate("isref('" & e & "'!a1)") Then Sheets.Add(, Sheets(Sheets.Count)).Name = e ReDim a(1 To dic(e).Count * 2 + 1, 1 To AL.Count + 2): n = 1 With Sheets(e).Range("b3") With .CurrentRegion .ClearContents .Borders.LineStyle = xlNone End With t = 2: n = 1 For ii = 0 To AL.Count - 1 For i = 0 To dic(e).Count - 1 If dic(e).items()(i).exists(AL(ii)) Then t = t + 1: a(1, t) = AL(ii): Exit For End If Next Next For Each s In dic(e) n = n + 1: a(n, 1) = Split(s, Chr(2))(0) n = n + 1: a(n, 1) = Split(s, Chr(2))(1) a(n, 2) = Split(s, Chr(2))(2) For ii = 3 To t If dic(e)(s).exists(a(1, ii)) Then a(n, ii) = dic(e)(s)(a(1, ii)) Next Next With .Resize(n, t) .Value = a .Borders.Weight = 2 End With End With Next End Sub (seiya) 2019/02/17(日) 14:24
SoulMan 様 seiya 様
皆様ありがとうございます。
SoulMan 様の .ArrayList の部分でオートメーションエラー というのが出ましたが 「Windows機能の有効化または無効化」の「.Net Framework 3.5の有効化」を行うことでエラー回避できました。ありがとうございます。
seiya 様、ファイルまでありがとうございます。問題なく動作できました。
稲葉 様のを動作させると 隠居じーさん 様 のおっしゃる通り一部異なる部分ができてしまいました。
>>稲葉 様 >>若干異なりますが、ピボットテーブルではダメですか?
ピボットでも同じようなことできるんですね(汗 恥ずかしながら知りませんでした(汗 勉強いたします。
皆様からの回答のおかげで希望通りできそうです。 ありがとうございました。 (マリリ) 2019/02/17(日) 15:07
あ、お返事いただいてから恐縮ですが、先ほどコード入れ替えいたしました。 15:12より前にコードをコピーされた場合は、今一度全文入れ替えていただけると助かります。
最後のソート部分で、範囲指定を誤っていました。申し訳ございません。
隠居じーさんさんありがとうございました。 (稲葉) 2019/02/17(日) 15:14
いえいえ 恐縮で御座います。 m(_ _)m
(隠居じーさん) 2019/02/17(日) 15:19
ちなみに、ピボットテーブルの場合の配置例 |[A] |[B] |[C] |[D] |[E]|[F]|[G]|[H]|[I] [1]|分類 |関東 | | | | | | | [2]| | | | | | | | | [3]|合計 / 数量| | |列ラベル| | | | | [4]|行ラベル |名称2|単位| 200|210|220|300|400|総計 [5]|神奈川 |バナナ|本 | | | 2| 5| | 7 [6]|東京 |ごぼう|本 | | 20| | | | 20 [7]| |バナナ|本 | 2| | | | 5| 7 [8]|総計 | | | 2| 20| 2| 5| 5| 34
手順は 1)Sheet1のC3:H12を範囲選択する 2)挿入>ピボットテーブル>新規シート 3)列ラベルに「番号」 行ラベルに「名称1」「名称2」「単位」 値に「数量」 レポートフィルタに「分類」 4)3)で配置した「名称1」の▼をクリック→フィールドの設定 [レイアウトと印刷]タブ [○アイテムのラベルを表形式で表示する] にチェック 5)「名称2」も4)の手順を行う 6)B2セルのコンボボックスから「関東」を選択
これで、B2のコンボボックスを選択することで、分類を切り替えて表示できます。
こうしておけば、行ラベルから名称1または名称2を入れ替えるだけで、 集計項目を変更できるので便利です。
ご参考になれば幸いです。 ちなみに、元の表が良い形に出来上がっていたので使えました。 (稲葉) 2019/02/17(日) 15:30
やっとできました ^^ もうすでに終了ですね。。。( ̄▽ ̄)。。。m(_ _)m AdvancedFilter使用
Option Explicit Sub main() Dim s1 As Worksheet Dim s2 As Worksheet Dim i As Long Dim j As Long Dim y As Long Dim No() Dim Ac() Dim rr As Range Dim sr As Range Dim r As Range Dim retu Dim cnt Ws_Delete_M Set s1 = Worksheets("リスト") Set rr = s1.Range("C3").CurrentRegion No = Master_Maker(rr.Columns(6), s1) For cnt = 0 To UBound(No) s1.Copy before:=Worksheets(1) Set s2 = ActiveSheet With s2 .Range("J1") = "分類" .Range("J2") = No(cnt) 'Filter '.Range("M:R").Clear rr.AdvancedFilter xlFilterCopy, .Range("J1").CurrentRegion, .Range("M1"), False .Range("A:L").Delete Set r = .Range("A1").CurrentRegion For i = 1 To r.Rows.Count .Cells(i, 10) = r(i, 2) & Chr(29) & r(i, 3) Next Ac = Master_Maker(.Range("J1").CurrentRegion, s2) .Range("J1").CurrentRegion.Clear r.Columns(1).Copy .Range("H1") .Range("H1").Sort key1:=.Range("H1"), Header:=xlYes .Range("l2").Resize(, .Range("H1").CurrentRegion.Rows.Count) = _ WorksheetFunction.Transpose(.Range("H1").CurrentRegion) .Range("G:L").Clear: y = 3 For i = 0 To UBound(Ac) .Cells(y, 11) = Split(Ac(i), Chr(29))(0) .Cells(y, 11).Offset(1) = Split(Ac(i), Chr(29))(1) For j = 2 To r.Rows.Count If (Split(Ac(i), Chr(29))(0) = r(j, 2)) * (Split(Ac(i), Chr(29))(1) = r(j, 3)) Then Set sr = .Range(.Cells(2, 13), .Cells(2, .Cells(2, .Columns.Count).End(xlToLeft).Column)) retu = WorksheetFunction.Match(r(j, 1).Value, sr, 0) retu = retu + 12 .Cells(y, 12).Offset(1) = r(j, 4) .Cells(y, retu).Offset(1) = r(j, 5) End If Next y = y + 2 Next .Range("A:I").Delete s2.Name = No(cnt) End With Next End Sub Private Function Master_Maker(target As Range, ws As Worksheet) As Variant Dim tmp() Dim r Dim i As Long With ws target.AdvancedFilter xlFilterCopy, , .Range("M1"), True Set r = .Range("M1").CurrentRegion For i = 2 To r.Rows.Count ReDim Preserve tmp(i - 2) tmp(i - 2) = r(i, 1).Value Next .Range("M1").CurrentRegion.Clear End With Master_Maker = tmp End Function (隠居じーさん) 2019/02/18(月) 19:15
お、私もAdvancedFilterで2案目に作っておいたので、答え合わせ! Option Explicit Sub 振替2() Dim wsCri As Worksheet, wsLst As Worksheet Dim r1 As Range, r2 As Range Dim mr As Long Dim n As Long Dim f As String Set wsLst = Sheets("Sheet1") Set wsCri = Sheets.Add(after:=Sheets(Sheets.Count)) wsCri.Range("A1:F1").Value = [{"分類","分類","番号","名称1","名称2","単位"}] '名前付き引数説明 AdvancedFilter Action , CriteriaRange , CopyToRange , Unique wsLst.Range("C3").CurrentRegion.AdvancedFilter xlFilterCopy, wsCri.Range("A1:A2"), wsCri.Range("A1"), True '重複のない分類を取得 For Each r1 In wsCri.Range("A2", wsCri.Cells(Rows.Count, "A").End(xlUp)) wsCri.Range("B2").Value = r1.Value With wsLst.Range("C3").CurrentRegion .AdvancedFilter xlFilterCopy, wsCri.Range("B1:B2"), wsCri.Range("C1"), True '重複のない分類別番号を取得 .AdvancedFilter xlFilterCopy, wsCri.Range("B1:B2"), wsCri.Range("D1:F1"), True '重複のない名称1名称2単位を取得 End With If Evaluate("=ISERROR(" & r1.Value & "!A1)") Then Sheets.Add after:=Sheets(Sheets.Count): Sheets(Sheets.Count).Name = r1.Value mr = wsCri.Cells(Rows.Count, "C").End(xlUp).Row '番号の最大行数 With Sheets(r1.Value) .Cells.ClearContents .Range("D4").Resize(, mr - 1).Value = Application.Transpose(wsCri.Range("C2:C" & mr).Value) 'D4から番号を入れる n = 4 'B4セル For Each r2 In wsCri.Range("D2", wsCri.Cells(Rows.Count, "D").End(xlUp)) n = n + 1 .Cells(n, "B") = r2.Value n = n + 1 .Cells(n, "B") = r2.Offset(, 1).Value .Cells(n, "C") = r2.Offset(, 2).Value 'Evaluate Ver. 'f = "=IF(COLUMN(" & Range("A1").Resize(, mr - 1).Address & "),SUMIFS(" & wsLst.Name & "!G:G," 'f = f & wsLst.Name & "!C:C," & r1.Value & "!" & Range("D4").Resize(, mr - 1).Address & "," 'f = f & wsLst.Name & "!D:D," & r1.Value & "!" & "B" & n - 1 & "," 'f = f & wsLst.Name & "!E:E," & r1.Value & "!" & "B" & n & "))" '.Cells(n, "D").Resize(, mr - 1).Value = Evaluate(f) ' '計算式Ver. .Cells(n, "D").Resize(, mr - 1).Formula = "=SUMIFS(" & wsLst.Name & "!$G:$G," & wsLst.Name & "!$C:$C,D4," & wsLst.Name & "!$D:$D,$B" & n - 1 & "," & wsLst.Name & "!$E:$E,$B" & n & ")" Next r2 End With Next r1 Application.DisplayAlerts = False wsCri.Delete Application.DisplayAlerts = True End Sub (稲葉) 2019/02/18(月) 19:26
おお!すごいですね。。。さすがですね。^^v 計算式埋め込みバージョンですね。 勉強させて戴きます。。。。 有難うございました。 m(_ _)m (隠居じーさん) 2019/02/18(月) 19:54
Dim dic As Object, c As Range, i As Long, j As Long, lett As String Set dic = CreateObject("Scripting.Dictionary") With Sheets("関東") .Cells.ClearContents For Each c In Sheets("リスト").Range("H:H").SpecialCells(2) If c.Value = "関東" Then If WorksheetFunction.CountIf(.Rows(4), c.Offset(, -5).Value) = 0 Then .Cells(4, j + 4).Value = c.Offset(, -5).Value: j = j + 1 End If lett = c.Offset(, -4).Value & "|" & c.Offset(, -3).Value If Val(dic(lett)) = 0 Then .Cells(i + 5, 2).Value = c.Offset(, -4).Value & "|" & c.Offset(, -3).Value .Cells(i + 6, j + 3).Value = c.Offset(, -1).Value .Cells(i + 6, 3).Value = c.Offset(, -2).Value dic(lett) = i + 5 i = i + 2 Else .Cells(dic(lett), 2).Value = c.Offset(, -4).Value & "|" & c.Offset(, -3).Value .Cells(1 + dic(lett), j + 3).Value = c.Offset(, -1).Value .Cells(1 + dic(lett), 3).Value = c.Offset(, -2).Value End If End If Next c For Each c In .Range("B:B").SpecialCells(2) If InStr(c.Value, "|") > 0 Then c.Offset(1).Value = Split(c.Value, "|")(1) c.Value = Split(c.Value, "|")(0) End If Next c End With End Sub (mm) 2019/02/21(木) 18:10
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.