SUMIFS Values from non consecutive Column Cells - sumifs

I need tu sum several cells that are separated one from another, these cells are
C3,F3,I3,L3,O3,R3,U3,X3,AA3,AD3,AG3,AJ3,AM3,AP3,AS3,AV3,AY3,BB3,BE3,BH3,BK3,BN3,BQ3,BT3,BW3,BZ3,CC3,CF3,CI3,CL3,CO3
if this other cells $C$1,$F$1,$I$1,$L$1,$O$1,$R$1,$U$1,$X$1,$AA$1,$AD$1,$AG$1,$AJ$1,$AM$1,$AP$1,$AS$1,$AV$1,$AY$1,$BB$1,$BE$1,$BH$1,$BK$1,$BN$1,$BQ$1,$BT$1,$BW$1,$BZ$1,$CC$1,$CF$1,$CI$1,$CL$1,$CO$1
that are on the same column but different row are >= to certain number given and <= to other given number, but it returns #Value, can somebody help me find out what am I doing wrong?
This is the function i am writing:
=SUMIFS((C3,F3,I3,L3,O3,R3,U3,X3,AA3,AD3,AG3,AJ3,AM3,AP3,AS3,AV3,AY3,BB3,BE3,BH3,BK3,BN3,BQ3,BT3,BW3,BZ3,CC3,CF3,CI3,CL3,CO3),($C$1,$F$1,$I$1,$L$1,$O$1,$R$1,$U$1,$X$1,$AA$1,$AD$1,$AG$1,$AJ$1,$AM$1,$AP$1,$AS$1,$AV$1,$AY$1,$BB$1,$BE$1,$BH$1,$BK$1,$BN$1,$BQ$1,$BT$1,$BW$1,$BZ$1,$CC$1,$CF$1,$CI$1,$CL$1,$CO$1),">="&B55,($C$1,$F$1,$I$1,$L$1,$O$1,$R$1,$U$1,$X$1,$AA$1,$AD$1,$AG$1,$AJ$1,$AM$1,$AP$1,$AS$1,$AV$1,$AY$1,$BB$1,$BE$1,$BH$1,$BK$1,$BN$1,$BQ$1,$BT$1,$BW$1,$BZ$1,$CC$1,$CF$1,$CI$1,$CL$1,$CO$1),"<="&C55)

I'm not 100% certain, but it looks like the problem here is that SUMIFS requires arguments to be expressed in continuous-range form, e.g. A3:CO3. It looks like you're trying to work with every third column in the dataset, yes? As far as I can tell, this is best (only?) done as an array function, so that you can tell it to filter on "every third column."
Enter this in the cell, then press CTRL+SHIFT+Enter (CSE) to evaluate it as an array function:
=SUM(($A$1:$CO$1>=B55)*($A$1:$CO$1<=C55)*(MOD(COLUMN(A3:CO3),3)=0)*(A3:CO3))
You'll also need to hit CSE every time you evaluate or change it. There's a decent tutorial for array functions at https://support.office.com/en-za/article/Guidelines-and-examples-of-array-formulas-7d94a64e-3ff3-4686-9372-ecfd5caa57c7, which may help if you're unfamiliar with them.

Related

Is there a way to specify an input is a single cell in Google Sheets?

I want to iterate over an array of cells, in this case B5:B32, and keep the values that are equal to some reference text in a new array.
However, SPLIT nowadays accepts arrays as inputs. That means that if I use the array notation of "B5:B32" within ARRAYFORMULA or FILTER, it treats it as a range, rather than the array over which we iterate one cell at a time.
Is there a way to ensure that a particular range is the range over which we iterate, rather than the range given at once as an input?
What I considered was using alternative formulations of a cell, using INDEX(ROW(B5), COLUMN(B5)) but ROW and COLUMN also accept array values, so I'm out of ideas on how to proceed.
Example code:
ARRAYFORMULA(
INDEX(
SPLIT(B5:B32, " ", 1), 1
) = "Some text here"
)
Example sheet:
https://docs.google.com/spreadsheets/d/1H8vQqD5DFxIS-d_nBxpuwoRH34WfKIYGP9xKKLvCFkA/edit?usp=sharing
Note: In the example sheet, I can get to my desired answer if I create separate columns containing the results of the SPLIT formula. This way, I first do the desired SPLITS, and then take the values I need from that output by specifying the correct range.
Is there a way to do this without first creating an output and then taking a cell range as an input to FILTER or other similar functions?
For example in cell C35 I've already gotten the desired SPLIT and FILTER done in one go, but I'd still need to find a way to sum up the values of the first character of the second column. Doing this requires that I take the LEFT value of the second column, but for that I need to output the results and continue in a new cell. Is there a way to avoid this?
Ralph, I'm not sure if your sample sheet really reflects what you are trying to end up with, since, for example, I assume you are likely to want the total of the hours per area.
In any case, this formula extracts all of the areas, and the hours worked, and is then easy to do further calculations with.
=ArrayFormula({REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9},"(.*) \d"),
VALUE(REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9}," (\d+)hrs"))})
Try that in cell E13, to see the output.
The first REGEXEXTRACT pulls out all the text in front of the first space and number, and the second pulls out all the digits in a string of " #hr" in each cell. These criteria could be modified, if necessary, depending on your actual requirements. Note that it requires the use of VALUE, to convert the hours from text to numeric values, since REGEXEXTRACT produces text (string) results.
It involved concatenating your multiple data columns into one long column of data, to make it simpler to process all the cells in the same way.
This next formula will give you a sum, for whatever matching room/task you type into B6, as an example.
=ArrayFormula(QUERY({REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9},"(.*) \d"),
VALUE(REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9}," (\d+)hrs"))},
"select Col1, sum(Col2) where Col1='"&B6&"' group by Col1 label sum(Col2) '' ",0))
I will also answer my own question given what I know from kirkg13's answer and other sources.
Short answer: no, there isn't. If you want to do really convoluted computations with particular cell values, there are a few options and tips:
Script your own functions. You can expand INDEX to accept array inputs and thereby you can select any set of values from an array without outputting it first. Example that doesn't use REGEXMATCH and QUERY to get the SUM of hours in the question's example data set: https://docs.google.com/spreadsheets/d/1NljC-pK_Y4iYwNCWgum8B4NJioyNJKYZ86BsUX6R27Y/edit?usp=sharing.
Use QUERY. This makes your formula more convoluted quite quickly, but is still a readable and universally applicable method of selecting data, for example particular columns. In the question's initial example, QUERY can retrieve only the second column just like an adapted INDEX function would.
Format your input data more effectively. The more easily you can get numbers from your input, the less you have to obfuscate your code with REGEXMATCHES and QUERY's to do computations. Doing a SUM over a RANGE is a lot more compact of a formula than doing a VALUE of a LEFT of a QUERY of an ARRAYFORMULA of a SPLIT of a FILTER. Of course, this will depend on where you get your inputs from and if you have any say in this.
Also, depending on how many queries you will run on a given data set, it may actually be desirable to split up the formula into separate parts and output partial results to keep the code from becoming an amalgamation of 12 different queries and formulas. If the results don't need to be viewed by people, you can always choose to hide specific columns and rows.

Is there a way to use ARRAYFORMULA to find the most-recent even input of a column?

SOLVED EDIT
Thank you for the help. Solution here.
ORIGINAL POST
I have made a google sheet to describe the issue I am facing linked here (https://docs.google.com/spreadsheets/d/1yK6ZAX8BFnEqiuQO9HIxuY0l62ewDDccj-8EN1r2i2w/edit?usp=sharing).
I will also describe in words, below, the problem I am facing, along with the solutions I have tried.
The data of column A are random single-digit (0-9). I would like column B to show the most recent even number from column A, but only up to a specific row. That specific row is the row corresponding to the row of the cell in column B. In other words, in cell B7, I want to find the most recently entered even number of column A, specifically only on the range A2:A7 (A1 contains a column header).
This is actually a pretty simple formula, and I can get the desired outputs by simply checking if the value in a cell in column A is even and then returning the value of that cell if it is, or the output of the cell above if it isn't. So the formula would look something like: ​=IF(ISEVEN(A7),A7,B6)​
However, my problem is that the length of the data in column A will be growing as more data are entered, and my current solution of using the fill handle to copy the formula to new cells is inelegant and time-consuming. So my desired solution is to use an array formula entered into the first cell of column B (B2), capable of returning the same value as the other formula. The formula I tried to enter to perform this was the following: ​=ARRAYFORMULA(IF(ISEVEN(A2:A),A2:A,INDIRECT(ADDRESS(ROW(A2:A)-1,2))))​
However, as some of my previous work with arrays has taught me, not all formulas iterate as expected down the array. The formula seems to be able to return the correct output on lines which are already even, but it is unable to return the expected most-recently entered even number for all the other lines. It appears that the formula is not able to appropriately interpret the ​value_if_false​ argument of the ​IF​ formula.
I'm a little new to scripting, so I'm still trying to learn, but I also tried to dabble around with custom functions to no avail. I'm still wet behind the ears when it comes to coding, which is why I've been so lenient on the built-in formulas of Google Sheets, but I fear I may have reached the limit of what Sheets formulas can do.
I am open to trying new approaches, but my only real constraint is that I would really like for this to be a one-touch (or even better no-touch) solution, hope that's not too far beyond the scope of this issue. Any assistance would be much appreciated.
EDIT
After rubber-ducking the problem here, I went back and tried to use the OFFSET formula, hoping I could get it to play nicely with the array formula. Alas, I was unable, but I thought I should at least post my progress here for reference.
Attempt with offset
Still working at it!
Doing a vlookup on the row number seems to work for me
=ArrayFormula(if(A2:A="","",vlookup(row(A2:A),{if(iseven(A2:A),row(A2:A)),A2:A},2)))
Note: if there are no even numbers in range for some rows, it will produce #N/A for those rows.

Google Sheets Recursive Array Formula

I'm trying create a list of sequential dates from a set date to the most recent date in another column.
=ARRAYFORMULA(IF(OR(A2:A=MAX(C:C),A2:A=""),"",DATEVALUE(A2:A+1)))
I use MAX() to find the dates most recent date in column C. What I'm trying to get this formula to do is to recursively check the date in the cell above to determine if the max date has been reached. I've made sure A2 already has the set starting date.
The output is in only one cell though and I don't know why.
Thank you for the help.
What appears to be troubling your current array formula is that as defined it goes on forever and is self-referential. There may be a way to make it by setting preferences to be iterative and helping it interpret getting to repeated cells with "" as convergence.
Here is a way to sidestep those issues. You can bulletproof it more (for example, by encasing it in an IFERROR), but basically you can calculate exactly how many entries you need, and then set your range in the Array formula accordingly. In A3 you place the following:
=arrayformula(DATEVALUE(Row(indirect("A3:A"&(max(C:C)-A2+2)))+A2-2))
which will construct the exact range you want, then calculate each entry with an explicit rather than recursive formula.
EDIT: the above implementation assumes you need at least 2 dates. You can handle that case and other weird ones with the following, less readable formula, =if(max(C:C)>A2,iferror(arrayformula(DATEVALUE(Row(indirect("A3:A"&(max(C:C)-$A$2+2)))+$A$2-2))),"")

How to Find out if a column contains any duplicates

I have a column of numbers. I want to know if there are any duplicates. I don't need to know how many or what their value is. I just want to know if there are any.
The best way I could figure out was to have another column of equal height to the column of numbers, with the formula:
=countif(A:A,A1)>1
So this will put a TRUE next to every number that has one or more duplicates in the list.
From here I need to see if this second column contains a TRUE.
So I have a final cell with this formula in it:
=lookup(true, B:B)
This always displays FALSE, even when there are duplicates in the list, with corresponding "TRUE" values next to them in column B.
Also, is there a simpler way of solving this problem?
Note: I can get it to work if the single cell result simply does an =OR(B:B) but I still want to know why my first way won't work and if there is an all around simpler way of doing this.
you can use both =unique(A:A) and also =counta(unique(A:A))
note: the A:A is just a dummy array i threw in for example, replace with whatever column you want to refer to.
to get a final yes or no, you could nest it together by putting =if(eq(counta(A:A),counta(unique(A:A))),"No Duplicates", "Contains Duplicates")
I'm not sure whether simpler (I am confident the formula could be simplified!) but copy/pasting the following might be deemed so:
=sum(if(ARRAYFORMULA(countif(A:A,A1:A)>1),1,0))
This should return 0 only if there are no duplicates. If a single entry is repeated twice (three instances) and all other values are unique, the result should be 3.
TRUE is curious as the behaviour is not what I expected and I differs from Excel where true would be converted to TRUE, which normally indicates an automatic change from text to function. I don't have an explanation but it may be connected with lookup because the boolean behaves as I would expect in say an if formula.

Google Sheets - get the right-most value of a row

I have a sheet where the columns are months in a year and the rows are various metrics. Every month, we add another column on the right.
I need something that I can give a ROW and it will always return the right most value. That is, it automatically updates whenever we add a column for a new month.
There's a few ways of doing it, but one way (considering row 2 in this example):
=FILTER(2:2,COLUMN(2:2)=MAX(FILTER(COLUMN(2:2),LEN(2:2))))
I was very happy to have found #AdamL's answer and it did make my day, but I have since found a simpler way that works fine for my data sample, and that is using the LOOKUP function.
The LOOKUP function will look for a certain value in a given range, but if you pass it a humongous value, a value that is over your data range, it returns the last, rightmost value by default.
The answer is then very simple, just pass it the range - or row if that's what you need - and a huge value (many people do this using the biggest number that Excel can handle, but Google sheets is not Excel, and since I don't know what is the biggest number Google sheets can handle, I'll just give it a value well outside of my data set). Assuming you need to lookup into the entire row number 2:
=LOOKUP(999999999,2:2)
And that's it.
This function will throw an error if there isn't any data, so if you (like me) need to get that particular value only if it exists, you can combine this with a simple IF function:
=IF(ISERROR(LOOKUP(999999999,2:2)),"EMPTY",LOOKUP(999999999,2:2))
You can replace the string "EMPTY" with any value or function you want in there if the LOOKUP function returns an error.
I hope this simpler method is of any help, and thanks again to #AdamL for his original answer.
Adding this one for future readers. The formula I found years ago for obtaining the rightmost value was:
=index(2:2,1,COUNT(2:2))
However for each blank cells in amongst the cells with data, the returned value is the Nth last value (2 blank cells in row 2 and the formula will return the 3rd last value from the right, not the rightmost value). It appears to work, but won't be accurate in all cases.
As such, I do not recommend this formula as you can not depend on it if ever there will be an empty cell before the right-most within your data.

Resources