Use a Dynamic Range in an Excel Formula - excel

I have a collection of tables with similar names: mytable1, mytable2, mytable3...
I need to create a VLOOKUP formula that uses one table or another depending of the value of a named cell ( Cell "A1" = rngChoice ) , for example:
If rngChoice = 1 then use mytable1
If rngChoice = 2 then use mytable2
If rngChoice = 2 then use mytable2
I could use the formula:
=IF(rngChoice=1;VLOOKUP("value";mytable1;"return column";FALSE);
IF(rngChoice=2;VLOOKUP("value";mytable2;"return column";FALSE);
IF(rngChoice=3;VLOOKUP("value";mytable3;"return column";FALSE) (...)
I can't use this formula because I may need to add or remove tables, so the formula should be changed every time, what's impossible to me.
What I need is something like:
=VLOOKUP("value";"mytable" & "table number";"return column";FALSE)

Use INDIRECT to return the range:
=VLOOKUP("value";INDIRECT("mytable" & "table number");"return column";FALSE)

Related

Excel PivotTables with Dynamic field names

I need to complete a large number of pivottable formula using criteria/fieldnames that are above/to left of cells. The base, static formula is as follows:
=GETPIVOTDATA("BDGT",'Pipeline PVT'!$A$6,"FiscalQuarter","FY16-Q3","AreaName","Western Europe")
I want to grab the value field (BDGT in this example) from the formula heading, which will be BDGT. But when I replace "BDGT" with a cell reference (ie: A4), I get #REF.
Any ideas why this is not working?
=GETPIVOTDATA(A4 & "",'Pipeline PVT'!$A$6,"FiscalQuarter","FY16-Q3","AreaName","Western Europe")
The & "" after A4 is the important bit...

Array Formula To Return List Based on Multiple Conditions

I have a spreadsheet that looks like the picture below. I have some formulas that perform counts on this sheet and compare this data to another data source. An example of one of these would be:
=Countifs(A2:A10676,"0",C2:C10676,"OPEN",D2:D10676,"Current")
How would I return the list of loan numbers associated with the count? For instance, the count above returns 3038. I tried the below formula. I selected C2:C3039, typed the formula and hit Shift + Ctrl + Enter:
=If(And(A2:A10676="0",C2:C10676="OPEN",D2:D10676="Current"),B2:B10676,"")
My thought was that this evaluates the logical for each line and builds an array of the values in column B. When I enter this, each cell in the array is blank.
Can someone please explain how to return an array with values based on multiple criteria?
I see two problems with your formula
=If(And(A2:A10676="0",C2:C10676="OPEN",D2:D10676="Current"),B2:B10676,"")
Firstly you can't use AND to return an array - AND (like OR) returns a single result (TRUE or FALSE), so you need either nested IFs or to use * to simulate AND, i.e. either
=IF(A2:A10676=0,IF(C2:C10676="OPEN",IF(D2:D10676="Current",B2:B10676,"")))
....or.....
=IF((A2:A10676=0)*(C2:C10676="OPEN")*(D2:D10676="Current"),B2:B10676,"")
Note: I used 0 without quotes for the first criteria - for COUNTIFS you can use "0" or 0 but here it needs to match the data type - only use quotes if the data is text formatted - I'm assuming that isn't the case
The second problem is that for both of those the resulting array still has 10675 values because it still includes all the blanks for rows when the criteria aren't met.
To get an array of just 3038 values you can use this formula array entered into the correct sized range:
=INDEX(B2:B10676,SMALL(IF(A2:A10676=0,IF(C2:C10676="OPEN",IF(D2:D10676="Current",ROW(B2:B10676)-ROW(B2)+1)),ROW(INDIRECT("1:"&E2))))
Where E2 contains your COUNTIFS formula
Note that this only works to return an array in worksheet range - it won't work to return an array to be used in another function
Here is an approach that uses a "helper column" rather than an array formula:
In E2 enter the formula:
=IF(AND(A2=0,C2="OPEN",D2="Current"),1+MAX($E$1:E1),"")
and copy down (this marks the multiple rows meeting the criteria)
In F2 enter:
=IFERROR(INDEX(B$2:B$24,MATCH(ROWS($1:1),$E$2:$E$24,0)),"")
and copy down.
You can set a data filter:
Dim wrk As Worksheet
Set wrk = ActiveSheet
If Not wrk.AutoFilterMode Then wrk.range("a1").AutoFilter
wrk.range("a1").AutoFilter field:=1, Criteria1:="0"
wrk.range("a1").AutoFilter field:=3, Criteria1:="OPEN"
wrk.range("a1").AutoFilter field:=4, Criteria1:="Current"
Set wrk = Nothing
Of course, you could manually turn on the filters to how you like, too.
Insert four blank rows at the top, copy A5:D6 into A1 and delete B2. DATA > Sort & Filter, Advanced, Copy to another location, List range: A5:D10680, Criteria range: A1:D2, Copy to: F1:I1, check Unique records only, OK.

How To Reference an Excel Table Cell by Row Number or Horizontal Header Using Table Notation?

I'd like to reference a single cell in a table, from outside the table, using square-bracket sheet-formula notation.
Something like:
[MyTable[MyField] 3]
or
[MyTable[MyField] 3:3]
-to reference the 3rd row of the MyField column, or:
[MyTable[MyField] MyRow]
-to reference the MyRow row (leftmost row-header) of the MyField column.
Needs to work from outside the table, ie can't use # or #ThisRow.
Not looking for methods involving MATCH, INDEX, OFFSET, etc. Not looking for VBA methods. Just straightforward table-notation. Not looking for manually creating named ranges.
Why? Because, Tables :)
Pre-2013 Excel.
(PS, didn't there used to be a way (pre-Tables) to reference cells by row and column headers? I think it was maybe called "auto-naming", or something like that.)
heh, well this works:
=Table1[Column2] 3:3
So that's progress :)
Just awesome would be a way to reference a row by the contents of left-most column.
Thx!
You can also use index() function as in:
index(MyTable[MyField], 3)
So you get row 3 from the column MyField in table MyTable.
Reference:
https://www.ozgrid.com/forum/forum/help-forums/excel-general/116365-reference-a-single-cell-in-a-table-using-structured-referencing
We can reuse the idea of the intersection operator (i.e. a space between two references) and improve it to have the relative row number of the targeted item in the table, referred to as row_nb here:
=tbl[col] OFFSET(tbl[[#Headers],[col]],row_nb,)
or just without intersection actually (cf. comment below):
=OFFSET(tbl[[#Headers],[col]],row_nb,)
E.g. =Table1[Column2] OFFSET(Table1[[#Headers],[Column2]],2,)
This way you do not depend on the position of the table in the worksheet. Well, it yields a more complicated formula where table name tbl and column name col appear twice. Here are some comments about it:
You can of course keep the OFFSET(...) part only. The downside is that the formula will never return any error if row_nb exceeds the actual number of line items in the table. It'll return e.g. just 0 if the cells below the table are empty.
Keeping a formula that throws an error when we refer to an off-table row, we can further improve it: make it "dynamic" by letting tbl, col and row_nb be parameters:
=INDIRECT(tbl&"["&col&"]") OFFSET(INDIRECT(tbl&"[[#Headers],["&col&"]]"),row_nb,)
Assuming that we've defined tbl, col and row_nb as named ranges. Or else just use cell addresses:
=INDIRECT(A1&"["&A2&"]") OFFSET(INDIRECT(A1&"[[#Headers],["&A2&"]]"),A3,)
I'm not a big fan of INDIRECT but in this case it really comes in handy to let the formula adapt to various tables, columns and line items.
To handle tables that don't start at the first row of a worksheet, we can use the ROW() function. We can determine the first row of the data in the table with:
=ROW(myTable)
Using this and the Indirect() Function we can identify the first cell in a named column with
= myTable[myField] INDIRECT(ROW(myTable) & ":" & ROW(myTable))
The 3rd cell in that column would be:
= myTable[myField] INDIRECT(ROW(myTable)+3 & ":" & ROW(myTable)+3)

Excel VBA changing my formulas in a table?

Has anyone come across a situation where Excel seems to manipulate your formulas.
I have a sheet where I have an Index value in Column A. The First row starts with any non zero Value. Subsequent rows in the column increment the value. Eg
A1 = 1000
A2= A1+ 1
A3= A2 + 1
and so on/
I have another column B whose values will either be blank or a formula pointing to column A(usually the subsequent rows)
Eg:
B1.Formula = "=A2"
B2.Formula = "=A3"
B3.Value = ""
B4.value = "=A6"
Now I have a backup-restore functionality that lets me write out the data/formulas to a text file and then read it back in another workbook.
In the case of columns A and B, I am checking if the text value starts with "=" and then set either the value or formula of that cell depending on whether there is a formula or not.
So far the functionality has worked fine. It lets me restore accurately.
Now, if I convert this data range to a table and modify the code accordingly the behaviour is strange. I am using the ListObject structure to refer to the table. So for Column B my restore code is:
If Left(soureString) = "=" Then
'This is a formula
Sheets("MySheet").ListObjects(1).ListColumns("Next").DataBodyRange(row).Formula = sourcestring
Else
'This is a value
Sheets("MySheet").ListObjects(1).ListColumns("Next").DataBodyRange(row).Value = soureString
End If
once I am done writing a row, I loop to the start and
Dim newRow AS listrow
Set newRow = Sheets("MySheet").Listrows.Add(AlwaysInsert:=False)
row = newRow.Index
But this time when I run the process. this is what I get:
B1.Formula = "=A5"
B2.Formula = "=A5"
B3.Value = ""
B4.value = "=A5"
Why are my formula values all changing to the same value when I use a table instead of a range?
I had the same issue when populating a ListObject (Table) from an Excel Add-in, setting AutoFillFormulasInLists was the solution.
My workaround is to save the current setting, set AutoFillFormulasInLists to false, populate the table with data, formulas etc, then set AutoFillFormulasInLists back to the original setting.
bool OriginalAutoFillFormulaInListsFlag = app.AutoCorrect.AutoFillFormulasInLists;
app.AutoCorrect.AutoFillFormulasInLists = false;
//[ListObject population code....]
if (OriginalAutoFillFormulaInListsFlag == true)
{
app.AutoCorrect.AutoFillFormulasInLists = true;
}
Hope this helps someone.
I faced a similar issue. Ideally you could tell excel to stop doing this but I haven't been able to figure out how. Supposedly doing the following is supposed to keep excel from copying the formulas:
xlApp.AutoCorrect.AutoFillFormulasInLists = false
but it didn't work for me.
Using the answer from this question How to create running total using Excel table structured references? helped me. It doesn't feel like the ideal solution but it does do the job.
I used this formula where Weight is a column name from my table. #This Row is a "Special item specifier" and has a special meaning. The syntax looks a little funky because it's what's called a Structured Reference:
=AVERAGE(INDEX([Weight],1):[[#This Row],[Weight]])
The INDEX([Weight],1) part gives the reference for the 1st row in the Weight column
While the [[#This Row],[Weight]] part gives the reference for the current row in the Weight column.
So for example, if Weight is column J, and the current row is, say, 7 then this is equivalent to
=AVERAGE(J1:J7)
and on the 8th row it will be equivalent to
=AVERAGE(J1:J8) and so on
I have found that the only way to solve the problem of formulas changing in Excel Tables when you insert in VBA is to insert at the first row of the table, NOT the bottom or the middle. You can sort after.
And I always select or reference the EntireRow to do my insert in the Worksheet object not in the table itself. I always put a table in its own Worksheet anyway using xx.Entirerow.Insert.

Import data between spreadsheets where column = value?

Note: My question is similar Googe Spreadsheets' ImportRange function.
Is it possible in Google Spreadsheets or Microsoft Excel to import data based on cell values?
For example, can I copy contents of Sheet1 to another sheet where column B == "foo"?
Target (Sheet1):
The destination sheet should only copy Row 2 and 4 since those are the only ones containing "foo"
Edit:
For Google Docs, I am looking to something like this:
=ImportRange("spreadsheetkey", QUERY('sheetname'!A6:E10, "SELECT A, B = 'foo'")) however I can't get it to work.
You can do this just how you said but instead of using a Query in the ImportRange, you use the ImportRange in the Query, so:
=QUERY((ImportRange("spreadsheetkey", "sheetname!A6:E10")), "Select columnnumbers like Col1,Col2 etc Where _Criteria for select, such as (B contains 'foo') order by which column if you want to")
you could do something like this:
first, in an extra column (for example, column D) identify the rows / cells to be copied:
range("D" & range("A" & activesheet.rows.count).end(xlup).row).formula= "=IF(B:B=""foo"", NA(),"""")
next, use SpecialCells to select the cells in Column A, and B where Column D shows NA#
range("D1:D6").specialcells(xlcelltypeformulas, xlerrors).offset(0,-2).copy
othersheet.range("A1").pastespecial xlpasteall
that should get you started with some code to play with
of course, you can also do it without VBA, just paste the formula in, the use F5, SpecialCells dialog...
You need to wrap the query with the importrange inside of it like this:
=QUERY(importrange("spreadsheet key","sheetname!A6:E10"), "SELECT A where B='foo'")
You can do it with FILTER function:
=FILTER(IMPORTRANGE("spreadsheet_url", "'sheet_name'!A6:E10"),
IMPORTRANGE("spreadsheet_url", "'sheet_name'!B6:B10")="foo")

Resources