How to use a reference for GetPivotData's Data_Field argument? - excel-2007

I'm trying to use GetPivotData to query "Foo Bar" values from a pivot table. Just by typing = in a cell and clicking on the pivot table does most of the legwork, as Excel writes most of the formula. For example I get:
=GETPIVOTDATA("Foo Bar", 'Pivot Table'!D1, "Day", DAY(2010,10,10)) → 42
I need to have the first and last argument referenced to other cells and some extra dollars. I tried:
=GETPIVOTDATA($A$1, 'Pivot Table'!$D$1, "Day", $C3) → #REF!
...where A1 contains Foo bar and C3 contains =DAY(2010,10,10).
This obviously gives a nice #REF!. Hardcoding the field name in the formula instead gives the correct value instead:
=GETPIVOTDATA("Foo Bar", 'Pivot Table'!$D$1, "Day", $C3) → 42
Is this an undocumented shortcoming of the function (all examples use an hardcoded field name, but nowhere is mentioned I can't use references for the first argument) or am I doing something wrong?

To fix this problem, you can concatenate an empty string ( "" ) at the end of the cell reference:
=GETPIVOTDATA(B10 & "" ,$B$3,"Region",A11)`
from http://www.contextures.com/xlpivot06.html

Related

vba - Get row number of a cell with certain value in a named range

Is there a way to find the row of a cell containing certain value in a named range (Table)?
I have a table named "Table1" from C4 to D10.. I want to return the row number of a cell in column c that contains the value "CCC".. This value is found at the third row (C6).. So I want the code to return the number "3" which means the third row in the table "Table1" and not the number "6" that means it's found in cell "C6".
Thank you in advance.
Edit:
I missed the part about "relative to the table" but that's even easier...
Here's one that will work:
=MATCH("CCC",Table1,0)
or, referring to the cell range instead of the table directly:
=MATCH("CCC",C4:C10,0)
Original Answer:
If you want to know the row number of the first cell in Column C that contains CCC, you could use the MATCH function, either in a worksheet formula, or in VBA.
On the worksheet:
=MATCH("CCC",C:C,0)
or, in VBA:
WorksheetFunction.Match("CCC",Range("C:C"),0)
The fact that it's in a table is irrelevant since you've identified the column.
Incidentally, I can think of at least half a dozen other ways to get the same data just as easily.
Here's one that refers to the table directly:
=ROW(INDEX(Table1,MATCH("CCC",Table1,0)))
...and more variations:
=MATCH("CCC",C4:C10,0)-1+ROW(C4)
or
=MATCH("CCC",Table1,0)-1+ROW(Table1)
Note that a big difference between MATCH and VLOOKUP is that MATCH returns a range object, whereas VLOOKUP only returns the value of the matched cell, and therefore isn't suitable for a task like this.
More Information:
Office Support : MATCH Function
Microsoft Docs : WorksheetFunction.Match Method (Excel)
Office Support : INDEX Function

Data Validation of a Filtered table

I have a Data table with an Auto Filter (shown Below).
Sub Tariff_Filter()
Dim columnNumber, tableRow, tableColumn, tableWidth As Integer
Dim tableName, columnName As String
tableName = "Tariff_Table"
columnName = ActiveSheet.Range("A1").Value
'This clears the existing filter
ActiveSheet.ListObjects(tableName).Range.AutoFilter
'Assign some numbers we need to know about the table to check the headers
tableRow = ActiveSheet.ListObjects(tableName).Range.Row
tableColumn = ActiveSheet.ListObjects(tableName).Range.Column
tableWidth = ActiveSheet.ListObjects(tableName).Range.Columns.Count
'If a column title with the specified value does not exist VBA throws an error which we need to catch
On Error GoTo ErrorHandler
'Search through the table column header row to find the specified column and assign the number to columnNumber
columnNumber = Application.WorksheetFunction.Match(columnName, Range(Cells(tableRow, tableColumn), Cells(tableRow, tableColumn + tableWidth)), 0)
'Apply the filter "1" to the found columnNumber
ActiveSheet.ListObjects(tableName).Range.AutoFilter field:=columnNumber, Criteria1:="1"
'Exit the sub otherwise the "error handling" will be provoked
Exit Sub
ErrorHandler:
MsgBox columnName & "Please Specify Required Channel"
End Sub
As i cant seem to figure out how to get my combo-box's to show only the visible cells after filtering the table i was wondering if there is a way i can create a a validation box to show the visible cells or copy the visible data into a seperate table underneath. I can then use the validation box/ secondary table as a focus point for the combo-box's on the user-form.
Thanks in advance
If I'm understanding your question correctly, you would like to have a data-validation drop-down list that updates as the table is filtered and only displays visible items for a given column.
You can do this by using the following formula in Data Validation (I'm assuming your table header row starts in A1 and it's col A you need to display):
=OFFSET($A$2,,,SUBTOTAL(103,TableName[column name]))
This formula expands from the starting cell (A2) by a specified height in number of rows. We are defining the height using SUBTOTAL with function number 103 - this means that the height is defined using COUNTA, but only on visible cells, so it will expand and collapse as the table is filtered.
Be aware: since the height is defined using a counta function, it will only count cells containing data, therefore if you have blanks in your table, the range will not be defined correctly. Also if you have any repeated data, these will be repeated in your drop-down box, this method will not condense them into a neat, unique list.
Hope this is helpful.
D

Return a list of column headers across a row when cells have text

I want to get a list of column headers for each cell that contains a text value.
Eg.
A--------------B-------------C-------------BC (desired output)
1 Header1 Header2 Header3
2 M T Header1, Header3
3 T MT Header1, Header2
4 TMW Header2
In the final product I want to use two final columns with formulas listing headers from cells with values across 9 columns and a second with the other 40 odd columns.
I have the vague notion that I might need to use INDEX, MATCH and IF functions - but as a novice have no idea how to string them together coherently.
Here I will make use of VBA's Join function. VBA functions aren't directly available in Excel, so I wrap Join in a user-defined function that exposes the same functionality:
Function JoinXL(arr As Variant, Optional delimiter As String = " ")
JoinXL = Join(arr, delimiter)
End Function
The formula in D2 is:
=JoinXL(IF(NOT(ISBLANK(A2:C2)),$A$1:$C$1&", ",""),"")
entered as an array formula (using Ctrl-Shift-Enter). It is then copied down.
Explanation:
NOT(ISBLANK(A2:C2)) detects which cells have text in them; returns this array for row 2: {TRUE,FALSE,TRUE}
IF(NOT(ISBLANK(A2:C2)),$A$1:$C$1&", ","") converts those boolean values to row 1 contents followed by a comma delimiter; returns the array {"Header A, ","","Header C, "}.
JoinXL joins the contents of that array into a single string.
If you want to use worksheet functions, and not VBA, I suggest returning each column header in a separate cell. You can do this by entering a formula such as:
This formula must be array-entered:
BC: =IFERROR(INDEX($A$1:$C$1,1,SMALL((LEN($A2:$C2)>0)*COLUMN($A2:$C2),COUNTBLANK($A2:$C2)+COLUMNS($A:A))),"")
Adjust the range references A:C to reflect the columns actually used for your data. Be sure to use the same mixed address format as in above. Do NOT change the $A:A reference, however.
Then fill right until you get blanks; and fill down as far as required.
You can reverse the logic to get a list of the "other" headers.
To array-enter a formula, after entering
the formula into the cell or formula bar, hold down
ctrl-shift while hitting enter. If you did this
correctly, Excel will place braces {...} around the formula.
If you really need to have the results as comma-separated values in two different columns, I would suggest the following User Defined Function.
To enter this User Defined Function (UDF), alt-F11 opens the Visual Basic Editor.
Ensure your project is highlighted in the Project Explorer window.
Then, from the top menu, select Insert/Module and
paste the code below into the window that opens.
To use this User Defined Function (UDF), enter a formula like
=Headers($A2:$BA2,$A$1:$BA$1,True)
or, to get the headers that do NOT contain text:
=Headers($A2:$BA2,$A$1:$BA$1,FALSE)
in some cell.
=====================================================
Option Explicit
Function Headers(rData As Range, rHeaders As Range, Optional bTextPresent As Boolean = True) As String
Dim colHeaders As Collection
Dim vData, vHeaders
Const sDelimiter As String = ", "
Dim sRes() As String
Dim I As Long
vData = rData
vHeaders = rHeaders
Set colHeaders = New Collection
For I = 1 To UBound(vData, 2)
If (Len(vData(1, I)) > 0) = bTextPresent Then colHeaders.Add vHeaders(1, I)
Next I
ReDim sRes(1 To colHeaders.Count)
For I = 1 To colHeaders.Count
sRes(I) = colHeaders(I)
Next I
Headers = Join(sRes, sDelimiter)
End Function
==========================================
You should probably add some logic to the routine to ensure your range arguments are a single row, and that the two arguments are of the same size.

Remove all rows not containing values from range

Sheet "Data" has 3000+ rows containing 100+ customers in column O. Assume "Customers" A1 through A26 is:
a
b
c
d
e
...
z
The code is removing all except z, instead of all except a through z. I need to remove all customers from "Data" that aren't listed in column A on "Customers" sheet. Where am I going wrong? Changing "dontDelete" to below yields the same result. 26 can be substituted for 14, 7, etc and then that row's value becomes the only one remaining.
dontDelete = Array(Range("Customers!A1:A26")
I tried to paste the sub in here but it keeps giving me a formatting error in spite of the preview looking correct.
Without your exact sub, its hard to see what you need to change to correct this. However, if you are statically assigning the size of the array like this
Dim dontDelete(26) As String
you are actually defining the array as dontDelete(0,1,2...24,25,26). Then if your loop goes through 26 iterations, it will always end at 25, not 26.
I'd suggest starting off by declaring your array like this
Dim dontDelete(1 to 26) as String
and trying again to see if it resolves the issue.

How to replace every existing values of a column with formula?

My sheet already has data. Unfortunately, later I realized that all the values in column E should be validated and changed as necessary by calling my own user-defined function and passing the values as the function parameter. For example, say I have the following data in column E:
E1: "This is a text in (E1)"
E2: "This is a text in (E2)"
...
E7000: "This is a text in (E7000)"
Now, I want every value in column E to be changed by a formula like this:
E1: = RemoveBrackets("This is a text in (E1)")
E2: = RemoveBrackets("This is a text in (E2)")
...
E7000: = RemoveBrackets("This is a text in (E7000)")
Supposing Excel supports Regex, my problem can be solved easily. but unfortunately Excel doesn't. Could someone propose possible solutions to my problem?
Thanks in advance
1) Insert a new column "F"
2) Copy column E into F
3) Write in E1
=RemoveBrackets(F1)
4) Drag the E1 value through E7000
5) Hide column F.
Edit 1
You can do it with several passes of the Find/Replace feature:
Select the Column E before each PASS.
PASS 1
Find: <"This is a text in>
Replace with: <RemoveBrackets("This is a text in>
PASS 2
Find: <)">
Replace with: <)")>
PASS 3
Find: <RemoveBrackets(>
Replace with: <=RemoveBrackets(>
Edit 2
VB Regex substitute string function can be used from Excel.
You may dowload a toolpack such as Morefunc which supports a REGEX.SUBSTITUTE udf, or you could do your own udf using THIS as guideline.
I am posting here the code from the second reference, just for link independence:
Public Function SearchNReplace1(Pattern1 As String, _
Pattern2 As String, Replacestring As String, _
TestString As String)
Dim reg As New RegExp
reg.IgnoreCase = True
reg.MultiLine = False
reg.Pattern = Pattern1
If reg.Test(TestString) Then
reg.Pattern = Pattern2
SearchNReplace1 = reg.Replace(TestString, ReplaceString)
Else
SearchNReplace1 = TestString
End If
End Function
Please read the full article, as you should turn on the Microsoft VBScript Regular Expressions 5.5 option in Excel first.
HTH
Similar to belisarius' method, but doesn't leave a trace:
Insert column F
Insert into F1 the value =RemoveBrackets(F1)
Copy down through F7000.
Copy column F
Right click cell E1, Paste Special, choose "Values".
Delete column F