I have a portion of code that is like the following:
I am trying to return the cell directly below the cell that is "A" but I do not want to have any whitespace in between the cells.
I tried using =IF(A1="A",OFFSET(A1,1,0)) but this adds "FALSE" in between the cells where this is not true like so:
How do I remove the whitespace using a formula only to get the output of:
This standard formula will collect the values directly under each cell containing A.
Use this in B1 =IFERROR(INDEX(A:A,SMALL(INDEX(ROW(A:A)+(A:A<>"A")*1E+99,,),ROW(1:1))+1),"") and fill down as necessary.
The IFERROR return empty strings when it runs out of values to return. These are not the same as truly blank cells.
Although entered as a standard formula, this does use array processing and if you find calculation lag a problem pare down the full column range references to something closer to what the extents of your data represent.
If you would prefer to avoid VBA, you can perform this calculation using the following formulas, or some variant thereof:
The output will look like the following for the example you provided:
Related
Similar questions to this have been asked but not exactly like this. There is one that is very close, but that solution is not working for me.
I have a function which returns comma separated values into a cell. I would like to pass the elements in that cell as criteria to a SUMIFS function using an approach like this one.
My attempt is pictured below:
I believe that this is somehow tied to the way that the function is understanding what is in cell G8. It looks like it is adding some extra quotes. If I highlight G8 in the formula bar and press F9, I get:
There are extra quotes on each side of each criteria.
I am open to a custom VBA function solution, but I would prefer something which can be built as a worksheet function. The criteria are returned from a custom VBA function that pulls elements out of a list box and does some regex work to remove extra commas. The number of elements that can be selected is variable so I would like to avoid having to split the criteria into more than one cell. Thanks.
Seems that the raw comma-separated criteria is in G6, All you need is to split this criteria into an array and feed it to SUMIFS. Splitting is available in VBA, but not exposed to Excel. All we need is to write a little UDF that does the splitting of the CSV and use it in our formula:
Function splitCSV(str As String)
splitCSV = Split(str, ",")
End Function
Now the formula in F10 would be:
=SUM(SUMIFS(C3:C10, B3:B10, "blue", A3:A10, splitCSV(G6)))
EDIT
The above is an array formula (Ctrl+Shift+Enter). To have it a normal formula we can use SUMPRODUCT instead of SUM. This leads to more flexibility (normal formula vs array formula) as well as some "expected" performance improvement.
=SUMPRODUCT(SUMIFS(C3:C10, B3:B10, "blue", A3:A10, splitCSV(G6)))
I have an array formula that refers to a drop down cell ($AG$7) to determine which cells to evaluate. This works well, however, I need to include an additional item in the drop down which is "All".
When this is selected, I want the array formula to use "*" to return all instances from the array, but i can't get it to work.
This is the formula I'm currently using;
={SUM(IF((tblSkillsMatrix[Role]=[#Role])*(INDIRECT("tblSkillsMatrix["&V$2&"]")=$AG$7),1,0))}
I've tried using
={SUM(IF((tblSkillsMatrix[Role]=[#Role])*(INDIRECT("tblSkillsMatrix["&V$2&"]")="*"&$AG$7),1,0))}
and
={SUM(IF((tblSkillsMatrix[Role]=[#Role])*(INDIRECT("tblSkillsMatrix["&V$2&"]")="*"&$AG$7&"*"),1,0))}
But these don't work.
Does anybody have any ideas?
Thanks
A explicit = comparison cannot use wildcards. COUTIFS and SUMIFS can. As far as I see, you want to count only (conditional sum 1 and 0).
Problem is, COUTIFS and SUMIFS will not deal with INDIRECT ranges. But INDIRECT can and should (because of its volatile bahavior) often replaced by INDEX- MATCH.
So:
=COUNTIFS(tblSkillsMatrix[role],[#role],INDEX(tblSkillsMatrix,,MATCH($V$2,tblSkillsMatrix[#Headers],0)),"*"&$AG$7)
If $AG$7 is empty then it counts independent of the column named in $V$2.
Btw.: Within a table (ListObject) this needs not be entered as a array formula.
This is not 100% replacement of your formula since it not works if $V$2 is empty and so no table column title is given. Your formula will then look at all columns but this is not possible using COUNTIFS where each additional range must have the same number of columns as the criteria_range1 argument. So if $V$2 shall also can be empty, then this will not work.
If so then you could use
{=SUM((tblSkillsMatrix[role]=[#role])*(LEFT(INDIRECT("tblSkillsMatrix["&$V$2&"]"),LEN($AG$7))=$AG$7))}
Advantage: both $V$2 and $AG$7can be empty.
Disadvantage: Volatile behavior of INDIRECT and this formula then must be a array formula even in a ListObject-table. It must be confirmed using Ctrl+Shift+Enter.
It's probably best if I explain this with an example...
Say we have in a worksheet cells A1:C1 containing the values [1,2,3].
I want to take the square of each of these numbers but I do this using a cell-formula so in cell A2 I have {=A1:C1^2}. This is an array-formula. However, if I only press ctrl+alt+enter in cell A2, I see the first element of the array squared (i.e. A1^2 = 1^2 = 1).
If I select all of A2:C2 hit ctrl+alt+enter it expands out the entire array-formula across the three cells and we see the result of [1,4,9].
What I want is to only have to place the array formula in cell A2 and write VBA to be able to access the entire array for the entire operation (i.e. A1:C1^2).
I don't want to execute the function again in VBA as the array must already be stored in memory when we execute {=A1:C1^2} in cell A2 so how can I get the entire array result from a single cell that is part of a larger array?
Note: this is just an example, I plan to do this for large, unknown sized arrays.
Excel cells can only contain scalar values, so what you want to do is not possible without using EVALUATE in your VBA to execute the formula from A2.
And you need to be careful how you use EVALUATE: it has many peculiar quirks.
(see my blog post on EVALUATE )
Excel computes the entire array and displays what it can. This is based on what cells the user selects prior to the array confirmation.
Charles is correct in his answer. There is no way to get at the array without recalculating it with Evaluate(), like so:
MsgBox Join(Evaluate([a2].Formula))
VBA does have the HasArray property for the range object, and in your example with [a2] being the sole cell in the array formula, the HasArray property will return True.
Unfortunately, there is no corresponding GetArray property, which is exactly what you are after.
My take is that Excel's worksheet calculation engine does indeed maintain the array in memory, but this is a separate construct form the range and cells and VBA has no access to it.
Can't believe I don't know this, but is there a way to avoid repeating a formula in an if statement if the logical test is dependent on it?
i.e.
=IF((SUMIFS formula)=0,"",SUMIFs formula)
I want to replace that SUMIFS function in the false scenario with something short that will tell it to just programmatically repeat the formula it originally tested for. Repeating the formula twice has to have detrimental effects on processing speed. Negligible, maybe, but want to go for best-practices here. Thanks.
You can force an error like #DIV/0! and then use IFERROR, e.g.
=IFERROR(1/(1/SUMIFS_formula),"")
You can assign a Name to a formula and use the Name..............See:
Assigning a name to a formula
Relevant excerpt -
For example, let's suppose we frequently use a formula like:
=SUM(A1:A100)-SUM(B1:B100) and this resides in A101 and is copied across many columns on row 101. It would be better in this case to
create a custom formula that does this in each cell on row 101. Here
is how;
1) Select cell A101 (this is vital).
2) Go to Insert>Name>Define and
in the "Names in workbook" box type: SalesLessCosts
3) Now click in
the "Refers to" box and type: =SUM(A1:A100)-SUM(B1:B100) then click
Add.
Now you can replace the formula in cell A101 with: =SalesLessCosts.
You can also copy this across row 101 and it will change its relative
references just as the formula =SUM(A1:A100)-SUM(B1:B100) would. The
reason it does this is all down to the fact we selected A101 before
going to Insert>Name>Define and used relative references in
=SUM(A1:A100)-SUM(B1:B100) when we added it to the "Refers to" box.
If all you need to do is hide zeroes, there is an easy way:
Select all cells where you wish to hide zeroes
Go into Custom Number Formatting
Set format to "General;General;"
The custom formatting has a structure of [positive numbers];[negative numbers];[zeroes]
By making the last part blank you are effectively hiding zeroes, but showing everything else.
The advantage over conditional formatting is that you can use this on any background.
A neat trick which I sometimes use is to hide the cell value completely by using a custom format of ";;;". This way you can put images inside the cells, like the conditional formatting ones, and not see the value at all.
Try using the SUBSTITUTE function like this :
=SUBSTITUTE( VLOOKUP( H4; $D$5:$E$8; 2; 0 ); $H$1; $I$1 )
Here is an example:
Here the formula I don't want to repeat twice is the VLOOKUP function.
The result of VLOOKUP is a string found in another table (ex : "Green").
I want to check if that string matches a specific string value in $H$1 (here, "Yellow").
If it does, SUBSTITUTE replaces it with$I$1 (the error string you want. Here, "FORBIDDEN").
If it doesn't, it displays the VLOOKUP result string (the normal authorized output, like "Green").
This is useful for me because my actual formula is quite long, so I don't want to write it twice.
I also dont want to use two different cells, because I'm already applying this formula on 10 columns, meaning I should add an extra 10 columns to make it work.
In some scenarios, MAX() or MIN() can do a wonderful job.
E.g., something like this:
=IF(SUMIFSformula>0,SUMIFSformula, 0)
Can be shortened to this:
=MAX(0,SUMIFSformula)
The LET formula can be used for this exact scenario. You can define the formula as a variable and then within that same cell you can reference the variable in your formula.
The LET formula format looks like this:
=LET(name,name_value,calculation)
SUMIFS Example
Here's how it would work with your SUMIF example so that you don't have to repeat the formula:
In this screenshot we have an array A1:B7. We want to sum the values (Col B) if the name in ColA is "apple".
For this we have a standard SUMIFS formula of
=SUMIFS(B1:B7,A1:A7,"apple")
The formula is showing in E2. The result is shown in E3.
To put this into the IF statement without having to repeat the formula we can use LET as shown in the screenshot.
We create a variable with the SUMIFS formula as the value of that variable. We then write our IF statement using the variable name instead of rewriting the formula multiple times.
=LET(name,name_value,calculation)
Variable name: sumapples
Variable value: SUMIFS(B1:B7,A1:A7,"apple")
Calculation: IF(sumapples=0,"",sumapples)
Put together in the LET function it looks like this:
=LET(sumapples,SUMIFS(B1:B7,A1:B7,"apple"),IF(sumapples=0,"",sumapples))
This LET function can be used in any Excel formula, and is very useful for shortening long formulas that have repetition.
Optional: Extra complexity
If you want to you can get extra complicated by naming multiple variables.
=LET(name,name_value,name2,name_value2,calculation)
Since Excel 2007, the IFERROR statement does what the OP asked. From the help file:
Description:
Returns a value you specify if a formula evaluates to an error; otherwise, returns the result of the formula. [italics mine]
Syntax:
IFERROR(value, value_if_error)
I've since realised that this was already answered by #barry houdini above.
Here is a hack - depending on whether you are just interested in the displayed value, or whether you need to use the value in another formula:
Put your SUMIF formula in the cell (without the IF part)
Create a conditional formatting rule which sets the font color to the background color when the cell value is 0
And hey presto, you get the desired result.
As I said - it's a hack, but it does prevent the double evaluation.
There is no "clean" solution that I am aware of.
I've got a whole bunch of cells containing arbitrary length arrays stored as semicolon-delimited strings, ranging in length from 1 to 65 entries, like:
pcmsh15(232);pcmsh16(232);pcmsh17(136);
pcmsh12(40);
pcmsh12(40);
pcmsh12(5);pcmsh15(20);
I want a way to sum up the numbers in the parenthesis in Excel 2010 without using VBA, keeping in mind that they are arbitrary length strings, each contained in their own cell.
I've currently got a VBA function that I wrote that sums the numbers in parenthesis, but it's slowing my spreadsheet down. I know I can use Excel's SUBSTITUTE function to turn the semi-colon delimited arrays into something resembling Excel's internal array format, like
="{"&SUBSTITUTE([#[data]],";",",")&"}"
But unfortunately, Excel won't parse that as an array in SUM or COUNTIF, only as a string. One workaround I found makes a named range that references the cell with a string-formatted array, but since I also have an arbitrary number of these arrays in cells, I can't go naming every single cell.
Is something like this possible in "pure" excel functions?
You can actually do this with no VBA involved. The method is kind of ridiculous, though. But, just for fun...
In cell B4 I put one of the strings you want to "parse":
B4: pcmsh15(232);pcmsh16(232);pcmsh17(136);
Then I put the following formulas in the cells indicated:
B6: =SUBSTITUTE(B4,"pcmsh", """dummy")
B8: =SUBSTITUTE(B6,"(",""";")
B10: =SUBSTITUTE(B8,")","")
B12: =MID(B10, 1, LEN(B10)-1)
B14: ="{"&B12&"}"
That transforms the starting text into a text representation of a legal Excel array:
B14: {"dummy15";232;"dummy16";232;"dummy17";136}
You can make Excel evaluate that string and return an actual array with the following trick. Create a named formula that we'll call eval_left. Make sure cell C14 is selected when you create the named formula:
=EVALUATE(B14)
Note that the formula uses a relative reference, so if you use that name from a cell other than C14, you'll see that the B14 has changed to whatever cell is just to the left.
This uses the old Excel 4 macro function EVALUATE, which takes a string and returns the value that that string represents. Now we can put a final formula in cell C14:
C14: =SUM(eval_left)
Since SUM ignores non-numeric strings, you get the answer you want, with no VBA. (You do still get the macro warning though, because of the use of EVALUATE.)
Like I said, I consider this a just-for-fun curiousity. You're way better off using VBA for stuff like this.
EDIT:
In the unlikely event you wanted to actually do something like this, you'd run into the length limit of what EVALUATE can handle. You'd have to chop up your longer strings into less than 65 values, not use "dummy", etc., but it would still be doable.