VBA-style range selection in Excel - vba

In a spreadsheet formula, (namely SumIfs) I would like to be able to select a column range using its delimiters instead of a A1:A3456 style, like I would do in VBA [Range("A1:A3456")~Range(Cells(1,1),Cells(3456,1))].
If this is not possible, is there any workaround to use the result of a 'Match' function to get the column number where I want to apply certain criteria?
My function would look like
=Sumifs(A2:A10;*{range(cells(1,match(Z5;A1:T1)), cell(10,match(Z5;A1:T1))}*,"="&1)
...if only I could add vba formulas inside the spreadsheet.

You can use a combination of Address and Indirect, like this:
=SUM(INDIRECT(ADDRESS(1,1) & ":" & ADDRESS(3456,1)))
which is equivalent to =SUM(A1:A3456)
ADRESS transforms from style Cells(i,j) to style A1.
INDIRECT serves to interpret the resulting string as a range address.
SUM here is an example of usage.
Well It's a bit ugly, but if you want to do that occasionally and don't want to switch completely to RC-style, it's probably the easiest way.

Use Offset, which is much richer as a worksheet function than it is in VBA.
Syntax
OFFSET(reference, rows, cols, [height], [width])
The OFFSET function syntax has the following arguments:
Reference Required. The reference from which you want to base the
offset. Reference must refer to a cell or range of adjacent cells;
otherwise, OFFSET returns the #VALUE! error value.
Rows Required. The number of rows, up or down, that you want the
upper-left cell to refer to. Using 5 as the rows argument specifies
that the upper-left cell in the reference is five rows below
reference. Rows can be positive (which means below the starting
reference) or negative (which means above the starting reference).
Cols Required. The number of columns, to the left or right, that
you want the upper-left cell of the result to refer to. Using 5 as the
cols argument specifies that the upper-left cell in the reference is
five columns to the right of reference. Cols can be positive (which
means to the right of the starting reference) or negative (which means
to the left of the starting reference).
Height Optional. The height, in number of rows, that you want the
returned reference to be. Height must be a positive number.
Width Optional. The width, in number of columns, that you want the
returned reference to be. Width must be a positive number.
from https://support.office.com/en-us/article/OFFSET-function-c8de19ae-dd79-4b9b-a14e-b4d906d11b66

Related

SUMIFS returns 0 using dynamic criteria, with criteria range and sum range on another sheet

Anyone,
I've chatted with and called excel customer service with no luck. I used the formula builder (please see attached screenshot) to make sure each element of the formula is correct and returns the value for the criteria I'm trying to reference.
Everything is accurate, but it returns a value of 0. When I do the same thing in the actual sheet the data is stored in (and click a criteria cell within the criteria range) it returns the accurate value?! I'm not sure why it won't work on the other sheet. The values I am using to select are dynamic and change with a drop down. I have another, advanced, workbook (I did not create) that does the same thing and completes an even more complicated formula, but actually works so I'm not sure why this is returning a 0 value.
Photos and code/syntax: Dynamic Selection, Example 2 of it working, Example 1 of it working, Formula Builder, CountIFs, Advanced Spreadsheet working, VLOOKUP
=SUMIFS('GFEBS Pull'!Q:Q,'GFEBS Pull'!G:G,FMCOP!$C$20,'GFEBS Pull'!H:H,FMCOP!B23)
or:
=SUMIFS('GFEBS Pull'!Q:Q,'GFEBS Pull'!G:G,'FMCOP'!$C$20,'GFEBS Pull'!H:H,'FMCOP'!B23)
When I type ' around FMCOP sheet name, they disappear? I've also tried to lock the columns on the 'GFEBS Pull' sheet with no luck. Cell B23 is not locked because I'm going to copy the formula down to reference other cells. Any help is appreciated!
In this screenshot you can clearly see that both FMCOP!C20 ansd FMCOP!B23 have prefacing spaces; e.g. " HHC".
Since " HHC" will never match "HHC", fix the data returned from 'the lower table in the same screenshot'.
A Text-to-Columns, Fixed Width, Finish should do this. You could adjust the original formula like,
=SUMIFS('GFEBS Pull'!Q:Q, 'GFEBS Pull'!G:G, TRIM(FMCOP!$C$20), 'GFEBS Pull'!H:H, TRIM(FMCOP!B23))
I would caution against the latter 'bandaid' fix. Fix the original data; do not apply bandaids on-the-fly.

Excel 2016: IF function using position of cell relative to another cell

I'm trying to use IF to return a value that depends on the position of one cell relative to another in the same column.
Spreadsheet Example
If you click the above image, you'll see a number of columns with the possible values of "No," "Yes," "Yes>No," and "No>Yes."
The equation will go in the "Category of Change," row, one equation for each column. If the "Yes>No," is lower in the column than the "No>Yes," I want to return "Less Frequently," and if the opposite is true, I want to return "More Frequently" ("Same," if there is no "Yes>No," or "No>Yes").
I've tried using ARRAY and INDEX functions, but I'm not sure how to get Excel to "look" for each of those values, and then compare their ranking in the column.
Thank you in advance for your help!
MATCH will return the relative row number. This assumes the first column of data is in E2:E8.
=IFERROR(IF(MATCH("Yes>No",E2:E8,0)>MATCH("No>Yes",E2:E8,0),"Less Frequently","More Frequently"),"Same")
It is looking for exact matches, so if you have typos, it will always default to Same. If only one is found then it will still produce Same
You would put int he first cell and copy/drag over, the references will change automatically.

How to keep named range formula from changing cell values with VBA

I noticed an interesting problem while trying to debug a VBA routine that sorts the list of worksheets in a range and then redraws the border around that range.
The range containing is defined in Name Manager with the formula as shown below
=Tables!$L$2:$L$22
The problem that is occurring is that while doing the sheet name work, sometimes cells are deleted and sometimes cells are inserted. This CHANGES the cell address values in the named range. So if I deleted two cells and inserted one cell, the formula changes to
=Tables!$L$2:$L$21
And if I happen to insert into the first cell (L2), then the formula changes to
=Tables!$L$3:$L$22
I'm certain that problem can be solved using the header range name and offsetting by one, but I'm not sure how to do that in the formula for a named range as I've tried numerous ways and can't get it right. But I also need the ending range address to be static.
Any help appreciated.
One thing to try is to use:
=Indirect("Tables!$L$2:$L$22")
rather than
=Tables!$L$2:$L$22
It is an acceptable Name, but I am not sure you will get the same functionality.
Found a better way than the comment using the static header range. You simply define the whole range using the offset function from the header.
=OFFSET(AllSheetsHeader,1,0,21,1)
Where the 1,0,21,1 are 1 row offset from header, 0 column offset, 21 is row height, and 1 is just that one column

Column references in formulas

I am a little stuck at the moment. I am working on an array of data and need to find a way to input column numbers into formulas.
-I have used the match function to find the corresponding column number for a value.
ex. "XYZ" matched with Column 3, which is equivalent to C1:Cxxxxxx
-now for inputing the C1:Cxxxxxx into a formula to get data for that particular column, I would like to be able to directly reference the Column 3 part, because I plan on using this workbook in the future and the column needed to run the calculation may or may not be column 3 the next time I use it.
- is there any way to tell excel to use a formula to tell excel which column to use for an equation?
so a little more detail, I have the equation
=AND(Sheet3!$C$1:$C$250000=$A$4,Sheet3!$B$1:$B$250000=$B$4)
instead of specifying to use column C, is there a way to use a formula to tell it to use C?
EDIT: more additional info;
"i am basically running the equivalent of a SQL where statement where foo and bar are true, I want excel to spit out a concatenated list of all baz values where foo and bar are true. ideally i would like it to ONLY return baz values that are true, then I will concat them together separately. the way I got it now, the expression will test every row separately to see if true; if there is 18K rows, there will be 18K separate tests.. it works, but it's not too clean. the goal is to have as much automated as possible. *i do not want to have to go in and change the column references every time I add a new data arra*y"
Thanks
You can use INDEX, e.g. if you have 26 possible columns from A to Z then this formula will give you your column C range (which you can use in another formula)
=INDEX(Sheet3!$A$1:$Z$250000,0,3)
The 0 indicates that you want the whole column, the 3 indicates which column. If you want the 3 can be generated by another formula like a MATCH function
Note: be careful with AND in
=AND(Sheet3!$C$1:$C$250000=$A$4,Sheet3!$B$1:$B$250000=$B$4)
AND only returns a single result not an array, if you want an array you might need to use * like this
=(Sheet3!$C$1:$C$250000=$A$4)*(Sheet3!$B$1:$B$250000=$B$4)
You could use ADDRESS to generate the text, you then need to use INDIRECT as you are passing a string rather than a range to the fomula
=AND(INDIRECT(ADDRESS(1,3,,,"Sheet3") & ":" & ADDRESS(250000,3))=$A$4
,INDIRECT(ADDRESS(1,2,,,"Sheet3") & ":" & ADDRESS(250000,2))=$B$4)
Obviously replace the 3s and 2s in the ADDRESS formulae with your MATCH function you used to get the column number. The above assumes the column for $B$1:$B$25000 is also found using `MATCH', otherwise it is just:
=AND(INDIRECT(ADDRESS(1,3,,,"Sheet3") & ":" & ADDRESS(250000,3))=$A$4
,Sheet3!$B$1:$B$25000=$B$4)
Note a couple of things:
You only need to use "Sheet3" on the first part of the INDRECT
Conditions 3 and 4 in the ADDRESS formula are left as default, this
means they return absolute ($C$1) reference and are A1 style as
opposed to R1C1
EDIT
Given the additional info maybe using an advanced filter would get you near to what you want. Good tutorial here. Set it up according to the tutorial to familiarise yourself with it and then you can use some basic code to set it up automatically when you drop in a new dataset:
Paste in the dataset and then use VBA to get the range the dataset uses then apply the filter with something like:
Range("A6:F480").AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:= _
Sheets("Sheet1").Range("A1:B3"), Unique:=False
You can also copy the results into a new table, though this has to be in the same sheet as the original data. My suggestion would be paste you data into hidden columns to the left and put space for your criteria in rows 1:5 of the visible columns and then have a button that gets the used range for your data, applies the filter and copies the data below the criteria:
Range("A6:F480").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Sheets _
Range("H1:M3"), CopyToRange:=Range("H6"), Unique:=False
Button would need to clear the destination cells first etc, make sure you have enough hidden columns etc but it's all possible. Hope this helps.

google spreadsheet array length varies. I'm left with -- after shorter array calculations

In google spreadsheet, my array length varies. I'm left with -- or a double dash after a shorter input is calculated and placed into the array or if i clear the input entirely.
Ex.formula =iferror(if(E10="",transpose(split(upper(D1),",")),query(vlist)),"")
The above will either take input from E10 or D1. If i clear all the input im left with -- in some cells. If shorter input is calculted I'm also left with -- in previous longer array positions.
Is there any way I can eliminate the possibliity of -- appearing in
cells?
Maybe I the original question should be, How can a fixed array
ignore null values and not output -- or double dash.
I have been struggling with this, too. And now i found a workaround to it in this forum answer.
The workaround is not to suppress the -- directly, but to handle them in the cells that use this data. You can handle them with the ARRAYFORMULA(IFERROR( functions.
I realized that if you have several cells where you use this data, instead of changing all these cells, a more comfortable way to do this is to
create an (invisible?) "helper" array somewhere else in your sheet, where you put your formula that creates the --
apply the workaround in the cell where you originally had your formula.
Example:
Cell A1 contains =SORT(UNIQUE(Sheet2!X:X)) (which eventually results in -- in the cells A2, A3,... if the number of unique values in column X on sheet 2 decreases).
Workaround: Use your formula =SORT(UNIQUE(Sheet2!X:X)) e.g. in cell B1 and put =ARRAYFORMULA(IFERROR(B:B)) in A1.