[[20250222134808]] 『データレコードからの月別カウント』(POKO) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『データレコードからの月別カウント』(POKO)

初めまして。
データのカウントについてご教示ください。

データレコードの列に下記のようなレコードがございます。

氏名  スキル 所要月 終了月
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
TBD   S    4月
TBD   A    5月
TBD   A    5月
TBD   S    6月
あ    A    4月  5月
あ A    6月
い S    4月  6月
い S    7月  8月
う    S    5月 6月
え    A    5月 7月
お    A    4月 7月

まず一つは、氏名がTBDのレコードに対し、各月の集計値を下記のような
表にまとめたいです。
スキル 4月 5月 6月
ーーーーーーーーーーーーーーーーーーーーーーーー
S    1  0  1
A    0  2  0

もう一つは、氏名がTBD以外のレコードで、終了月がブランク以外で
かつ同じ氏名でブランクのレコードがない方の月別カウントを表にしたいです。
例えば、”あ”さんは終了月の入っているレコードがあるが、終了月の入っていない
レコードもあるので対象外
”い”さんについては6月と8月に終了月が入っているが、より大きい8月だけをカウントしたい

スキル 4月 5月 6月 7月 8月
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
S    0  0  1  0  1 
A    0  0  0  2  0

お手数ですが、どうぞよろしくお願いいたします。

< 使用 Excel:Microsoft365、使用 OS:Windows11 >


 Power Queryで出来そうですが、
 数式での回答を希望でしょうか。
(マナ) 2025/02/23(日) 06:44:44

 おはようございます。
取り敢えず書いてみましたけど、、途中で分からなくなっちゃったので無駄が多いかも?です。
後は応用していただけますと助かります。
一応、こんな感じになりました。
では、、では、、

     |[A] |[B]   |[C]   |[D]   |[E]|[F]   |[G]|[H]|[I]|[J]|[K]|[L]   |[M]|[N]|[O]
 [1] |氏名|スキル|所要月|終了月|   |スキル|4月|5月|6月|   |   |スキル|6月|7月|8月
 [2] |TBD |S     |4月   |      |   |S     |  1|  0|  1|   |   |A     |  0|  2|  0
 [3] |TBD |A     |5月   |      |   |A     |  0|  2|  0|   |   |S     |  1|  0|  1
 [4] |TBD |A     |5月   |      |   |      |   |   |   |   |   |      |   |   |   
 [5] |TBD |S     |6月   |      |   |      |   |   |   |   |   |      |   |   |   
 [6] |あ  |A     |4月   |5月   |   |      |   |   |   |   |   |      |   |   |   
 [7] |あ  |A     |6月   |      |   |      |   |   |   |   |   |      |   |   |   
 [8] |い  |S     |4月   |6月   |   |      |   |   |   |   |   |      |   |   |   
 [9] |い  |S     |7月   |8月   |   |      |   |   |   |   |   |      |   |   |   
 [10]|う  |S     |5月   |6月   |   |      |   |   |   |   |   |      |   |   |   
 [11]|え  |A     |5月   |7月   |   |      |   |   |   |   |   |      |   |   |   
 [12]|お  |A     |4月   |7月   |   |      |   |   |   |   |   |      |   |   |   

 Option Explicit
Sub てすと()
Dim v As Variant
Dim vv As Variant
Dim vvv As Variant
Dim w As Variant
Dim z As Variant
Dim i As Long
Dim j As Long
v = Range("A1").CurrentRegion.Resize(, 4).Value
ReDim q(0)
ReDim g(0)
ReDim x(0)
ReDim y(0)
ReDim xx(0)
ReDim yy(0)
ReDim 氏名(0)
ReDim 終了月(0)
ReDim qq(0)
ReDim gg(0)
ReDim ss(0)
ReDim bb(0)
For i = LBound(v, 1) + 1 To UBound(v, 1)
    If v(i, 1) = "TBD" Then
        z = Application.Match(v(i, 2) & "," & v(i, 3), q, 0)
        If IsError(z) Then
            ReDim Preserve q(UBound(q) + 1)
            ReDim Preserve g(UBound(g) + 1)
            q(UBound(q)) = v(i, 2) & "," & v(i, 3)
            g(UBound(g)) = 1
        Else
            g(z - 1) = g(z - 1) + 1
        End If
        z = Application.Match(v(i, 2), x, 0)
        If IsError(z) Then
            ReDim Preserve x(UBound(x) + 1)
            x(UBound(x)) = v(i, 2)
        End If
        z = Application.Match(v(i, 3), y, 0)
        If IsError(z) Then
            ReDim Preserve y(UBound(y) + 1)
            y(UBound(y)) = v(i, 3)
        End If
    Else
        If v(i, 4) <> "" Then
            z = Application.Match(v(i, 1) & "," & v(i, 2), qq, 0)
            If IsError(z) Then
                ReDim Preserve qq(UBound(qq) + 1)
                ReDim Preserve gg(UBound(gg) + 1)
                ReDim Preserve ss(UBound(ss) + 1)
                ReDim Preserve bb(UBound(bb) + 1)
                qq(UBound(qq)) = v(i, 1) & "," & v(i, 2)
                gg(UBound(gg)) = 1
                ss(UBound(gg)) = v(i, 4)
                bb(UBound(bb)) = v(i, 2) & "," & v(i, 4)
            Else
                If Val(v(i, 4)) > Val(ss(z - 1)) Then
                    qq(z - 1) = ""
                    gg(z - 1) = ""
                    qq(UBound(qq)) = v(i, 1) & "," & v(i, 2)
                    gg(UBound(gg)) = 1
                    ss(UBound(gg)) = v(i, 4)
                    bb(UBound(bb)) = v(i, 2) & "," & v(i, 4)
                End If
            End If
            z = Application.Match(v(i, 1), 氏名, 0)
            If IsError(z) Then
                ReDim Preserve 氏名(UBound(氏名) + 1)
                ReDim Preserve 終了月(UBound(終了月) + 1)
                氏名(UBound(氏名)) = v(i, 1)
                終了月(UBound(終了月)) = v(i, 4)
            Else
                If Val(v(i, 4)) > Val(終了月(z - 1)) Then
                    終了月(z - 1) = v(i, 4)
                End If
            End If
        Else
            z = Application.Match(v(i, 1), 氏名, 0)
            If Not IsError(z) Then
                氏名(z - 1) = ""
            End If
            z = Application.Match(v(i, 1) & "," & v(i, 2), qq, 0)
            If Not IsError(z) Then
                qq(z - 1) = ""
                gg(z - 1) = ""
                ss(z - 1) = ""
            End If
        End If
        z = Application.Match(v(i, 2), xx, 0)
        If IsError(z) Then
            ReDim Preserve xx(UBound(xx) + 1)
            xx(UBound(xx)) = v(i, 2)
        End If
        If v(i, 3) <> "" Then
            z = Application.Match(v(i, 3), yy, 0)
            If IsError(z) Then
                ReDim Preserve yy(UBound(yy) + 1)
                yy(UBound(yy)) = v(i, 3)
            End If
        End If
        If v(i, 4) <> "" Then
            z = Application.Match(v(i, 4), yy, 0)
            If IsError(z) Then
                ReDim Preserve yy(UBound(yy) + 1)
                yy(UBound(yy)) = v(i, 4)
            End If
        End If
    End If
Next
ReDim w(1 To UBound(x) + 1, 1 To UBound(y) + 1)
w(1, 1) = "スキル"
For i = LBound(x) + 1 To UBound(x)
    w(i + 1, 1) = x(i)
Next
For j = LBound(y) + 1 To UBound(y)
    w(1, 1 + j) = y(j)
Next
For i = LBound(x) + 1 To UBound(x)
    For j = LBound(y) + 1 To UBound(y)
        z = Application.Match(x(i) & "," & y(j), q, 0)
        If Not IsError(z) Then
            w(i + 1, j + 1) = g(z - 1)
        Else
             w(i + 1, j + 1) = 0
        End If
    Next
Next
Range("F1").Resize(UBound(w, 1), UBound(w, 2)).Value = w
ReDim w(1 To UBound(xx) + 1, 1 To UBound(yy) - 1)
For i = LBound(xx) + 1 To UBound(xx)
    w(i + 1, 1) = xx(i)
Next
For j = LBound(yy) + 2 To UBound(yy)
    w(1, j - 1) = yy(j)
Next
w(1, 1) = "スキル"
無二リスト v, vv, vvv
For i = LBound(w, 1) + 1 To UBound(w, 1)
    For j = LBound(w, 2) + 1 To UBound(w, 2)
        z = Application.Match(w(i, 1) & "," & w(1, j), vv, 0)
        If Not IsError(z) Then
            w(i, j) = vvv(z - 1)
        Else
            w(i, j) = 0
        End If
    Next
Next
Range("L1").Resize(UBound(w, 1), UBound(w, 2)).Value = w
Erase v, vv, vvv, w, q, g, x, y, xx, yy, 氏名, 終了月, qq, gg, ss, bb
End Sub
Sub 無二リスト(ByVal v As Variant, ByRef qq As Variant, ByRef gg As Variant)
Dim z As Variant
ReDim q(0)
ReDim g(0)
ReDim qq(0)
ReDim gg(0)
Dim i As Long
For i = LBound(v, 1) To UBound(v, 1)
    If v(i, 4) <> "" Then
        z = Application.Match(v(i, 1), q, 0)
        If IsError(z) Then
            q(UBound(q)) = v(i, 1)
            g(UBound(g)) = v(i, 2) & "," & v(i, 4)
            ReDim Preserve q(UBound(q) + 1)
            ReDim Preserve g(UBound(g) + 1)
        Else
            If Val(v(i, 4)) > Val(q(z - 1)) Then
                q(z - 1) = ""
                g(z - 1) = ""
                q(UBound(q)) = v(i, 1)
                g(UBound(g)) = v(i, 2) & "," & v(i, 4)
                ReDim Preserve q(UBound(q) + 1)
                ReDim Preserve g(UBound(g) + 1)
            End If
        End If
    Else
        z = Application.Match(v(i, 1), q, 0)
        If Not IsError(z) Then
            q(z - 1) = ""
            g(z - 1) = ""
        End If
    End If
Next
For i = LBound(g) To UBound(g)
    z = Application.Match(g(i), qq, 0)
    If IsError(z) Then
        qq(UBound(qq)) = g(i)
        gg(UBound(gg)) = 1
        ReDim Preserve qq(UBound(qq) + 1)
        ReDim Preserve gg(UBound(gg) + 1)
    Else
        gg(z - 1) = gg(z - 1) + 1
    End If
Next
End Sub
(SoulMan) 2025/02/23(日) 08:38:59

 もしもPIVOTBY,GROUPBYが使える環境なら...

 最初の式
=LET(a,A2:D12,
PIVOTBY(INDEX(a,,2),INDEX(a,,3),INDEX(a,,3),COUNTA,,0,-1,0,,INDEX(a,,1)="TBD"))

 2番目の式
=LET(a,A2:D12,
b,GROUPBY(TAKE(a,,2),TAKE(a,,-1),LAMBDA(r,INDEX(TAKE(r,-1),1)),,0,,
 (TAKE(a,,1)<>"TBD")*(COUNTIFS(TAKE(a,,-1),"",TAKE(a,,1),TAKE(a,,1))=0)),
PIVOTBY(INDEX(b,,2),INDEX(b,,3),INDEX(b,,3),COUNTA,,0,-1,0))
(んなっと) 2025/02/23(日) 09:13:47

 2番目の式は、[い]の[6月],[8月]のうち「下の方」の[8月]を採用しています。
[12月]の次が[1月]になるかもしれないからです。

 実は[6か月],[8か月]という意味で、「大きい方」の[8か月]を採用するなら
=LET(a,A2:D12,
b,GROUPBY(TAKE(a,,2),TAKE(a,,-1),LAMBDA(r,MAX(SUBSTITUTE(r,"月",)*1)&"月"),,0,,
 (TAKE(a,,1)<>"TBD")*(COUNTIFS(TAKE(a,,-1),"",TAKE(a,,1),TAKE(a,,1))=0)),
PIVOTBY(INDEX(b,,2),INDEX(b,,3),INDEX(b,,3),COUNTA,,0,-1,0))
(んなっと) 2025/02/23(日) 09:48:35

 vbaでもう一例

 Sub test()
    Dim s$(1), i&, n&, ws As Worksheet
    Application.ScreenUpdating = False
    Set ws = ActiveSheet
    ws.[f:f].Resize(, 13).ClearContents
    s(0) = "Transform IIf(Count(*),Count(*),0) Select スキル From `^$` Where 氏名= 'TBD' " & _
           "Group By スキル Order By スキル Desc Pivot Format(所要月,'m月');"
    s(1) = "Provider=Microsoft.Ace.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & _
         ";Extended Properties='Excel 12.0;HDR=Yes';"
    With CreateObject("ADODB.Recordset")
        .Open Replace(s(0), "^", ws.Name), s(1)
        For i = 0 To .Fields.Count - 1
            ws.Cells(1, i + 6) = .Fields(i).Name
        Next
        ws.[f2].CopyFromRecordset .DataSource
        .Close
        s(0) = "Transform IIf(Count(*),Count(*),0) Select スキル From (Select 氏名, スキル, " & _
               "Max(終了月) As `終了月` From `^$` Where 氏名 <> 'TBD' Group By 氏名, スキル " & _
               "Having Count(終了月) = Count(氏名))" & _
               "Group By スキル Order By スキル Desc Pivot Format(終了月,'m月');"
        .Open Replace(s(0), "^", ws.Name), s(1), 3, 3, 1
        n = ws.Range("f" & Rows.Count).End(xlUp)(3).Row
        For i = 0 To .Fields.Count - 1
            ws.Cells(n, i + 6) = .Fields(i).Name
        Next
        ws.Cells(n + 1, 6).CopyFromRecordset .DataSource
    End With
    Application.ScreenUpdating = True
End Sub
(jindon) 2025/02/23(日) 19:22:20

皆さま

色々とご教示いただきありがとうございます。
諸事情でvbaが使用できなく、関数で実施出来ればと思っております。
PIVOTBY,GROUPBYについては、調査してみましたが、使用できませんでした。

申し訳ございませんが、今一度、関数での対応方法をご教示いただければと思います。
(POKO) 2025/02/26(水) 19:32:12


 最初の式
=LET(a,A2:D12,
b,FILTER(CHOOSECOLS(a,2,3),INDEX(a,,1)="TBD"),
c,SORT(UNIQUE(TAKE(b,,1)),,-1),
d,TRANSPOSE(SORT(UNIQUE(TAKE(b,,-1)))),
e,MAP(c&d,LAMBDA(i,COUNT(0/BYROW(b,LAMBDA(r,CONCAT(r)=i))))),
VSTACK(HSTACK("",d),HSTACK(c,e)))

 2番目の式...[い]の[6月],[8月]のうち「下の方」の[8月]を採用
=LET(x,A2:D12,
a,FILTER(x,(TAKE(x,,1)<>"TBD")*(COUNTIFS(TAKE(x,,-1),"",TAKE(x,,1),TAKE(x,,1))=0)),
b,FILTER(CHOOSECOLS(a,2,4),XMATCH(TAKE(a,,1),TAKE(a,,1),,-1)=SEQUENCE(ROWS(a))),
c,SORT(UNIQUE(TAKE(b,,1)),,-1),
dd,UNIQUE(TOROW(TAKE(x,,-2),3),TRUE),d,SORTBY(dd,SUBSTITUTE(dd,"月",)*1),
e,MAP(c&d,LAMBDA(i,COUNT(0/BYROW(b,LAMBDA(r,CONCAT(r)=i))))),
VSTACK(HSTACK("",d),HSTACK(c,e)))

 2番目の式...実は[6か月],[8か月]という意味で、「大きい方」の[8か月]を採用
=LET(x,A2:D12,
a,FILTER(x,(TAKE(x,,1)<>"TBD")*(COUNTIFS(TAKE(x,,-1),"",TAKE(x,,1),TAKE(x,,1))=0)),
y,UNIQUE(TAKE(a,,2)),
b,HSTACK(TAKE(y,,-1),BYROW(y,LAMBDA(r,
 LET(p,FILTER(TAKE(a,,-1),BYROW(TAKE(a,,2),LAMBDA(i,AND(i=r)))),
  MAX(SUBSTITUTE(p,"月",)*1)&"月")))),
c,SORT(UNIQUE(TAKE(b,,1)),,-1),
dd,UNIQUE(TOROW(TAKE(x,,-2),3),TRUE),d,SORTBY(dd,SUBSTITUTE(dd,"月",)*1),
e,MAP(c&d,LAMBDA(i,COUNT(0/BYROW(b,LAMBDA(r,CONCAT(r)=i))))),
VSTACK(HSTACK("",d),HSTACK(c,e)))

(んなっと) 2025/02/26(水) 21:06:45


 関数ではないですが、[データ]→[テーブルまたは範囲から]→PowerQueryエディターで[詳細エディター]

 let
    ソース = Excel.CurrentWorkbook(){[Name="テーブル1"]}[Content],
    fil = Table.SelectRows(ソース, each ([氏名] <> "TBD")),
    mon = List.Sort(List.RemoveNulls(List.Distinct(fil[所要月] & fil[終了月]))),
    grp = Table.Group(fil, {"氏名"}, {{"group", each _, type table}}),
    trs =Table.TransformColumns(grp,{"group", each  
        if List.Contains(_[終了月],null) then null             
        else Table.LastN(_, 1)}),
    sel = Table.SelectRows(trs,each Value.Is(_[group],Table.Type)),
    cmb = Table.Combine(sel[group]),
    del = Table.RemoveColumns(cmb,{"氏名"}),
    piv = Table.Pivot(del, mon, "終了月", "所要月", List.Count),
    srt2 = Table.Sort(piv,{{"スキル", Order.Descending}})
 in
    srt2
(んなっと) 2025/02/26(水) 21:12:19

んなっとさま

ご教示いただきありがとうございます。

一旦のリスト表示ができること、確認できました。

出来れば、下記のようなフォーマットにカウントが表示されるようにしたいのですが、可能でしょうか?

スキル 4月 5月 6月 7月 8月 9月 10月 11月 12月 1月 2月 3月
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
S    
A    

恐れ入りますが、今一度のご教示、どうぞよろしくお願いいたします。
(POKO) 2025/03/03(月) 10:55:37


それに対するデータはどうなっていますか。
氏名別なのかスキルだけにするのかはっきりさせた方がいいのでは
(?) 2025/03/03(月) 11:35:55

 ●
=LET(a,A2:D12,
b,FILTER(CHOOSECOLS(a,2,3),INDEX(a,,1)="TBD"),
c,SORT(UNIQUE(TAKE(b,,1)),,-1),
d,MOD(SEQUENCE(,12,3),12)+1&"月",
e,MAP(c&d,LAMBDA(i,SUM(1*BYROW(b,LAMBDA(r,CONCAT(r)=i))))),
VSTACK(HSTACK("",d),HSTACK(c,e)))

 ●
=LET(x,A2:D12,
a,FILTER(x,(TAKE(x,,1)<>"TBD")*(COUNTIFS(TAKE(x,,-1),"",TAKE(x,,1),TAKE(x,,1))=0)),
b,FILTER(CHOOSECOLS(a,2,4),XMATCH(TAKE(a,,1),TAKE(a,,1),,-1)=SEQUENCE(ROWS(a))),
c,SORT(UNIQUE(TAKE(b,,1)),,-1),
d,MOD(SEQUENCE(,12,3),12)+1&"月",
e,MAP(c&d,LAMBDA(i,SUM(1*BYROW(b,LAMBDA(r,CONCAT(r)=i))))),
VSTACK(HSTACK("",d),HSTACK(c,e)))

 ●
let
    ソース = Excel.CurrentWorkbook(){[Name="テーブル1"]}[Content],
    fil = Table.SelectRows(ソース, each ([氏名] <> "TBD")),
    mon = List.Transform({3..14}, each Text.From(Number.Mod(_,12)+1) & "月"),
    grp = Table.Group(fil, {"氏名"}, {{"group", each _, type table}}),
    trs =Table.TransformColumns(grp,{"group", each  
        if List.Contains(_[終了月],null) then null             
        else Table.LastN(_, 1)}),
    sel = Table.SelectRows(trs,each Value.Is(_[group],Table.Type)),
    cmb = Table.Combine(sel[group]),
    del = Table.RemoveColumns(cmb,{"氏名"}),
    piv = Table.Pivot(del, mon, "終了月", "所要月", List.Count),
    srt2 = Table.Sort(piv,{{"スキル", Order.Descending}})
in
    srt2

(んなっと) 2025/03/03(月) 11:45:11


うんなっと様

関数のご提示ありがとうございます。
実際に問題なく表示できること、確認できました。

ありがとうございました。
(POKO) 2025/03/03(月) 13:09:39


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.