このようなテーブルがあるとしましょう:
Country Region Mytext
USA North a
USA South b
Brasil North c
Brasil South d
Excelでこのようなピボットを取得するにはどうすればよいですか?
Country North South
USA a b
Brasil c d
「mytext」が数値の場合、ピボットテーブルを作成できます。国と地域の組み合わせごとに1行しかないため、min = max = sum = avgで、これらの集計関数のいずれかが実際に結果を表示しますが欲しいです。
しかし、必要なフィールドが非数値の場合はどうなりますか? Pythonのpandasライブラリでは、数値以外のフィールドでもdataframe.pivot()メソッドを使用できますが、Excelで同じことを行う方法が見つかりませんでした。各行に番号を付け、Excelでピボットを実行してその番号を表示してから、関連するテキストを取得するためにルックアップを実行しますが、実際にはもっと簡単なはずの何かの複雑なプロセスのようです!
MS Power Query Add-in *を使用できます。テーブルのピボットは、vbaなしで簡単に行えます。無料で、データ変換に非常に効果的です。
mコード
let
Source = Excel.CurrentWorkbook(){[Name="table1"]}[Content],
#"Pivot column" = Table.Pivot(Source, List.Distinct(Source[Region]), "Region", "Mytext")
in
#"Pivot column"
MS Office 2016の ´*は、Excelに Get&Transform 関数として完全に統合されています。
将来の読者のために-2つの機能を一緒に使用してください:
リボン>ピボットテーブルツール>レポートレイアウト>表形式で表示
そして
リボン>ピボットテーブルツール>レポートレイアウト>すべてのアイテムラベルを繰り返す
行フィールドは、縦に繰り返されるテキストとして左から右に表示されます。
国ラベルの下に行ラベルとしてMyTextを追加し、ピボットテーブルデザインタブの下にテーブル形式でピボットテーブルを表示します。国の行ラベルフィールドのアイテムラベルを繰り返します。
これは可能ですが、VBAでピボットテーブルの数値の「プレースホルダー」値を一時的にテキストで上書きする必要があります。これを有効にするには、ピボットテーブルのEnableDataValueEditing = Trueを設定する必要があります。更新時に、数値プレースホルダー値を検索し、テキストに置き換えます。複雑です、はい。回避策、はい。しかし、それはトリックを行います。これは、次回ピボットテーブルが更新されるまで「固定」されるだけなので、更新するたびにこのコードをトリガーする必要があることに注意してください。
これは、自分のプロジェクトの1つでこれを行うために使用するコードです。これを標準コードモジュールに入れます。
Function Pivots_TextInValuesArea(pt As PivotTable, rngNumeric As Range, rngText As Range, Optional varNoMatch As Variant)
Dim cell As Range
Dim varNumeric As Variant
Dim varText As Variant
Dim varResult As Variant
Dim bScreenUpdating As Boolean
Dim bEnableEvents As Boolean
Dim lngCalculation As Long
On Error GoTo errHandler
With Application
bScreenUpdating = .ScreenUpdating
bEnableEvents = .EnableEvents
lngCalculation = .Calculation
.ScreenUpdating = False
.EnableEvents = False
.Calculation = xlCalculationManual
End With
varNumeric = rngNumeric
varText = rngText
pt.EnableDataValueEditing = True
'Setting this to TRUE allow users or this code to temporarily overwrite PivotTable cells in the VALUES area.
'Note that this only 'sticks' until the next time the PivotTable is refreshed, so this code needs to be
' triggerred on every refresh
For Each cell In pt.DataBodyRange.Cells
With cell
varResult = Application.Index(varText, Application.Match(.Value2, varNumeric, 0))
If Not IsError(varResult) Then
cell.Value2 = varResult
Else:
If Not IsMissing(varNoMatch) Then cell.Value2 = varNoMatch
End If
End With
Next cell
errHandler:
If Err.Number > 0 Then
If gbDebug Then
Stop: Resume
Else:
MsgBox "Whoops, there was an error: Error#" & Err.Number & vbCrLf & Err.Description _
, vbCritical, "Error", Err.HelpFile, Err.HelpContext
End If
End If
With Application
.ScreenUpdating = bScreenUpdating
.EnableEvents = bEnableEvents
.Calculation = lngCalculation
End With
End Function
結果は次のとおりです。VALUESエリアにテキストがあるピボットテーブル:
以下に、各数値に対して何を表示するかをコードに指示する「変換」テーブルを示します。
これらに2つの名前付き範囲を割り当てたので、コードはルックアップテーブルの場所を知っています。
...そして、関数をトリガーして必要な引数を渡す方法は次のとおりです。
Option Explicit
Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)
If Target.Name = "GroupView" Then Pivots_TextInValuesArea Target, [tbl_PivotValues.NumericValue], [tbl_PivotValues.TextValue]
End Sub
そのコードは、ピボットテーブルがあるワークシートに対応するワークシートコードモジュールに入れられます。