14

Let's say I have a table like this:

Country Region  Mytext
USA     North   a
USA     South   b
Brasil  North   c
Brasil  South   d

How can I obtain a pivot like this in Excel?

Country  North         South
USA      a             b
Brasil   c             d

If 'mytext' were a number, I could do a pivot table: since there is only one row per combination of country and region, min = max = sum = avg and any of these aggregate functions would, in fact, show me the result I want.

But what when the field I want is non-numeric? With Python's pandas library, I can use the dataframe.pivot() method even on non-numerical fields, but I haven't found a way to do the same in Excel. I could associate a number to each row, do the pivot in Excel to show that number, and then do a lookup to get the associated text, but it seems a rather convoluted process for something which should really be easier!

Pythonista anonymous
  • 8,140
  • 20
  • 70
  • 112
  • 3
    I respectfully disagree with your edit. The way you have edited my title makes it impossible to understand if the question refers to Excel, to SQL, or to one of the gazillion software and languages available. You may argue I could have written 'Pivot [...] in Excel' rather than 'Excel: Pivot' (small things amuse small minds...) but I remain convinced that mentioning Excel in title is important, otherwise the title becomes too ambiguous. – Pythonista anonymous Sep 24 '15 at 17:19

4 Answers4

8

you can use the MS Power Query Add-in*. Pivoting tables is without vba right easy. It's free and very effective for data Transformation.

the M-Code

 let
    Source = Excel.CurrentWorkbook(){[Name="table1"]}[Content],
    #"Pivot column" = Table.Pivot(Source, List.Distinct(Source[Region]), "Region", "Mytext")
in
    #"Pivot column"

your Output enter image description here

´* from MS Office 2016, it's fully integrated in Excel as Get & Transform function.

Community
  • 1
  • 1
visu-l
  • 424
  • 1
  • 5
  • 15
  • 4
    To do it with the GUI: select the table -> power query -> excel data -> from table -> select the column 'region' -> transform -> pivot column -> values column: mytext -> advanced options: don't aggregate. If you change the original source and right click refresh on the output table, the output gets refreshed. – Pythonista anonymous Sep 30 '15 at 09:02
  • In MS Office 2016, you'll need a single column for the headers. Delete redundant columns (or the table will be sparse), then pivot the header column, selecting the value field and "Don't aggregate". – Dave Burt Feb 02 '18 at 00:28
4

Add the MyText as a row label underneath the Country label, then display the PivotTable in Tabular format under the Pivot Table design tab. Repeat item labels for the country row label field.

cronos2546
  • 1,088
  • 7
  • 16
  • 2
    Could you be a bit more specific? I'm afraid I haven't followed. I have played around with the tabular format but I can't see a way to get the output I need. Thanks! – Pythonista anonymous Sep 24 '15 at 17:25
4

For future readers - use two features together:

Ribbon > PivotTable Tools > Report Layout > Show in Tabular Form

and

Ribbon > PivotTable Tools > Report Layout > Repeat all Item Labels

Row fields will be presented left-to-right as vertically repeated text.

2

This can be done, but requires VBA to temporarily overwrite a numerical 'placeholder' value in your PivotTable with some text. To enable this, you need to set EnableDataValueEditing = True for the PivotTable. On refresh, you then do a lookup on the numerical placeholder value, and replace it with text. Convoluted, yes. Workaround, yes. But it does the trick. Note that this only 'sticks' until the next time the PivotTable is refreshed, so this code needs to be triggerred on every refresh.

Here's the code I use to do this in one of my own projects. Put this in a Standard Code Module:

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

And here's the result: a PivotTable with Text in the VALUES area:

enter image description here

Here's the 'conversion' table that tells the code what to display for each number:

enter image description here

I have assigned two named ranges to these, so that my code knows where to find the lookup table:

  • tbl_PivotValues.TextValue
  • tbl_PivotValues.NumericValue

...and here's how I trigger the Function and pass in the required arguments:

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

That code goes in the Worksheet Code Module that corresponds to the worksheet where the PivotTable is:

enter image description here

jeffreyweir
  • 4,668
  • 1
  • 16
  • 27
  • Thanks, but , if I understand correctly, it seems my idea of adding a numerical column with unique numbers, creating a pivot to show the min (or max, or sum, or avg, it's the same), and then doing a lookup to retrieve the text associated to each number is almost identical but less convoluted as it doesn't involve any VBA hacking. I'm probably better off doing it in Python whenever I can: it's just a one-line command! Goes to show how poor Excel is at data analysis and manipulation... – Pythonista anonymous Sep 28 '15 at 10:55
  • @jeffreyweir Where do you run this code? I put it in a module but it doesn't run. Does it get the pivottable name automatically? – jjjjjjjjjjj Nov 10 '17 at 18:52
  • This is a function that must be called by another routine. – jeffreyweir Nov 10 '17 at 18:58
  • @jeffreyweir Not sure where to go with that. Can you give me the syntax or terms to google? – jjjjjjjjjjj Nov 10 '17 at 20:32
  • Probably best you write up a new question outlining what it is you're trying to achieve (including specifics such as "I want to replace *these* specific numbers in the Data field with *this* list of text terms", and I'll respond to that. – jeffreyweir Nov 10 '17 at 21:15
  • I'll add some info to syntax to my answer above shortly. – jeffreyweir Nov 10 '17 at 21:16
  • Don't worry about a new question unless you can't get the above to work. I've just updated my answer to include more info on how the function needs to be called. – jeffreyweir Nov 10 '17 at 21:33
  • I'll try it. My data can't be converted from numeric to text unfortunately. I have [posted my question here](https://stackoverflow.com/questions/47231443/excel-2013-pivot-hierarchical-nonnumerical-data). Can your code be modified to use `VLOOKUP` for the row and column names? – jjjjjjjjjjj Nov 10 '17 at 21:41