先日から、マクロによるピボットテーブルの扱いを纏めている(備忘録)。
先日は、作成したピボットテーブルの書式を整えることに挑戦した。
infoment.hatenablog.com
今日は、集計方法の変更に挑戦する。
さて、先日からサンプルとして扱っている「なんちゃって個人情報」の集計結果について。ピボットテーブル作成直後は、各県の性別・婚姻別者の「年齢の合計」が表示されている。
しかし例えば上記の例のように、この表における愛知県の既婚男性の年齢が合計で1843歳と言われても、全くピンと来ない。例えばここは合計ではなく、せめて平均年齢としたいところ。
というわけで、メソッドを一つ追加してみた。
Public Sub SetValueField(Optional consolidation_function _
As XlConsolidationFunction = xlSum, _
Optional data_field_index _
As Long = 0)
If data_field_index > Pvt.DataFields.Count Then Exit Sub
Dim arr As Variant
Select Case data_field_index
Case 0
Dim DataField As PivotField
For Each DataField In Pvt.DataFields
DataField.Function = consolidation_function
arr = Split(DataField.Caption, " / ")
DataField.Caption = AggregateMethodNameDict(consolidation_function) & _
" / " & arr(UBound(arr))
Next
Case Else
With Pvt.DataFields(data_field_index)
.Function = consolidation_function
arr = Split(.Caption, " / ")
.Caption = AggregateMethodNameDict(consolidation_function) & _
" / " & arr(UBound(arr))
End With
End Select
End Sub
Private Property Get AggregateMethodNameDict() As Object
Dim Dict As Object
Set Dict = CreateObject("Scripting.Dictionary")
Dict(xlSum) = "合計"
Dict(xlCount) = "データの個数"
Dict(xlAverage) = "平均"
Dict(xlMax) = "最大値"
Dict(xlMin) = "最小値"
Dict(xlProduct) = "積"
Dict(xlCountNums) = "数値の個数"
Dict(xlStDev) = "標本標準偏差"
Dict(xlStDevP) = "標準偏差"
Dict(xlVar) = "標本分散"
Dict(xlVarP) = "分散"
Set AggregateMethodNameDict = Dict
End Property
それでは早速、実験してみよう。
Sub Test()
Dim PvtTable As VBAProject.PvtTable
Set PvtTable = New VBAProject.PvtTable
If PvtTable.MakePivotTable(ActiveSheet.ListObjects(1)) = False Then
MsgBox "ピボットテーブルの作成に失敗しました。"
Exit Sub
End If
With PvtTable
.SetFields xlPageField, "カレーの食べ方", "キャリア"
.SetFields xlRowField, "都道府県", "性別"
.SetFields xlColumnField, "婚姻"
.SetFields xlDataField, 6
.SetRowAxisLayout layout_row_type:=xlTabularRow
.SetSubTotals subtotal_visible:=False
.SetValueField xlAverage
End With
End Sub
今回は、↓ この部分が追加となっている。
.SetValueField xlAverage
結果が ↓ こちら。
小数点以下の表示など、修正すべき点はあるが、取り敢えず平均値への切り替えは上手く行ったので良しとしよう。
なお今回までのコードは、まとめてこちらに畳んでおく。
Option Explicit
Public Pvt As Excel.PivotTable
Dim PvtField As Excel.PivotField
Dim PvtItem As Excel.PivotItem
Public Function MakePivotTable(source_data As ListObject, _
Optional sheet_name As String = vbNullString, _
Optional table_destination As String = "R3C1", _
Optional table_name As String = vbNullString) _
As Boolean
Dim Sh As Worksheet
Dim Ws As Worksheet
If sheet_name = vbNullString Then
Set Sh = Sheets.Add
Sh.Name = "SheetForPivot_" & Format(Now, "yyyymmdd_hhmmss")
Else
For Each Ws In Worksheets
If Ws.Name = sheet_name Then
Set Sh = Ws
Exit For
End If
Next
If Sh Is Nothing Then
Set Sh = Sheets.Add
Sh.Name = sheet_name
End If
End If
If table_name = vbNullString Then
table_name = "PivotTable_" & Format(Now, "yyyymmdd_hhmmss")
End If
On Error GoTo er:
Set Pvt = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, _
SourceData:=source_data, _
Version:=PvtVersion).CreatePivotTable _
(TableDestination:=Sh.Name & "!" & table_destination, _
TableName:=table_name, _
DefaultVersion:=PvtVersion)
MakePivotTable = True
Exit Function
er:
MakePivotTable = False
On Error GoTo 0
End Function
Public Sub SetFields(field_orientation As XlPivotFieldOrientation, _
ParamArray field_names())
If Pvt Is Nothing Then Exit Sub
Dim i As Long
Select Case field_orientation
Case xlPageField
For i = UBound(field_names) To 0 Step -1
Pvt.PivotFields(field_names(i)).Orientation = field_orientation
Next
Case Else
For i = 0 To UBound(field_names)
Pvt.PivotFields(field_names(i)).Orientation = field_orientation
Next
End Select
End Sub
Public Sub SetRowAxisLayout(Optional layout_row_type As XlLayoutRowType = xlTabularRow)
If Pvt Is Nothing Then Exit Sub
Pvt.RowAxisLayout layout_row_type
End Sub
Public Sub SetSubTotals(Optional subtotal_visible As Boolean = False, _
Optional subtotal_location As XlSubtototalLocationType = xlAtBottom)
Select Case subtotal_visible
Case True
Pvt.SubtotalLocation subtotal_location
Case False
On Error Resume Next
For Each PvtField In Pvt.PivotFields
PvtField.Subtotals(1) = True
PvtField.Subtotals(1) = False
Next
End Select
End Sub
Public Sub SetValueField(Optional consolidation_function _
As XlConsolidationFunction = xlSum, _
Optional data_field_index _
As Long = 0)
If data_field_index > Pvt.DataFields.Count Then Exit Sub
Dim arr As Variant
Select Case data_field_index
Case 0
Dim DataField As PivotField
For Each DataField In Pvt.DataFields
DataField.Function = consolidation_function
arr = Split(DataField.Caption, " / ")
DataField.Caption = AggregateMethodNameDict(consolidation_function) & _
" / " & arr(UBound(arr))
Next
Case Else
With Pvt.DataFields(data_field_index)
.Function = consolidation_function
arr = Split(.Caption, " / ")
.Caption = AggregateMethodNameDict(consolidation_function) & _
" / " & arr(UBound(arr))
End With
End Select
End Sub
Private Property Get AggregateMethodNameDict() As Object
Dim Dict As Object
Set Dict = CreateObject("Scripting.Dictionary")
Dict(xlSum) = "合計"
Dict(xlCount) = "データの個数"
Dict(xlAverage) = "平均"
Dict(xlMax) = "最大値"
Dict(xlMin) = "最小値"
Dict(xlProduct) = "積"
Dict(xlCountNums) = "数値の個数"
Dict(xlStDev) = "標本標準偏差"
Dict(xlStDevP) = "標準偏差"
Dict(xlVar) = "標本分散"
Dict(xlVarP) = "分散"
Set AggregateMethodNameDict = Dict
End Property
Private Property Get PvtVersion() As Long
Select Case CLng(Application.Version)
Case 14
PvtVersion = xlPivotTableVersion14
Case 15
PvtVersion = xlPivotTableVersion15
Case 16
PvtVersion = 6
End Select
End Property
Private Sub Class_Terminate()
With Pvt.TableRange2
.Font.Name = "メイリオ"
.Font.Size = 10
.RowHeight = 20
.EntireColumn.AutoFit
End With
End Sub
次回に続きます。
参考まで。