I've been retooling some older spreadsheet tools for filtering and formatting dynamic data outputs using Excel's newer Dynamic Array Formulas functionality. This has been helping remove some of the need for pre-allocating cells and lower amounts of helper columns (which has allowed for reduced file sizes and snappier performance).
One function type I am struggling to replace is pulling out dynamic, running duplicate counts.
For instance, say I have a column B of 20 names that can vary in length from a handful to say 200 names. There is also related data in columns C, D, etc that similarly varies in size. For use of filtering the Data in the later columns, we currently use a helper column in A consisting of the running count of the duplicates in A with a formula using semi-anchored ranges(ie. Beginning the range with an anchored cell that expands as the formula is copied down the helper column akin to the solution here with CountIf() and a semi-anchored range). The drawback here vs the new dynamic array formulas is that the helper column needs to be pre-allocated for the data.
Despite attempts with Index(), Aggregate(), Filter(), and a few more involved notations like Sumproduct(--(...)), the most straightforward method I can find to make helper column A seems to be by creating the running count via semi-anchored ranges, which unfortunately does not seem to translate well to the new dynamic array Formulas.
Has anyone had any luck adapting the use of semi-anchored ranges and formulas for use in dynamic array formulas?
To use the dynamic array formula we need to use OFFSET which is volatile.
=COUNTIFS(OFFSET(A1,0,0,SEQUENCE(COUNTA(A1#))),A1#)
Appreciate this is an old post, but for future reference (I personally at least couldn't find an answer elsewhere), the below seems to work as a non-volatile formula alternative.
=LET(InputArray,A1#,
RowCount,ROWS(InputArray),
Temp,1*(InputArray=TRANSPOSE(InputArray)),
MMULT(TRANSPOSE(IF(SEQUENCE(RowCount,1)>SEQUENCE(1,RowCount),0,Temp)),SEQUENCE(RowCount,1,1,0)))
Related
When I append arrays in google spreadsheets, all of the resulting elements are not rendered in cells. For example, if I enter the formula:
={{1,2,3}, {4,5,6}}
the values rendered in spreadsheet cells are 1,4,5,6. Any ideas about why this is happening, or alternatives? My broader problem is to accumulate rows from separate sheets into another sheet - I can do that via
={ImportRange(...), ImportRange(...)}
but the same problem is apparent (missing the second element and beyond from the first array).
Edit (2 Oct 2014)
I just happened upon this when someone upvoted. The information below is obsolete in the newest version of Sheets - you can now (have been able to for a few months) concatenate arrays inside embedded arrays. All the examples that I provided below will work, including the one I said "shouldn't work".
Embedded arrays in Google Sheets
An array of values may be populated by a single function using an embedded array. Each element in the embedded array (and this may be point of conjecture; it is more or less just my opinion) represents the value that will be populated in contiguous cells in the sheet. Semi-colons are row delimiters; commas (or backslashes in locales that use a comma for a decimal separator) are column delimiters. So this will successfully create a two-row, three-column array (all of the following examples assume a locale supporting comma column delimiters):
={1,2,3;4,5,6}
Embedded arrays within embedded arrays
As each element in an embedded array represents a cell in the spreadsheet, I think it is reasonable to assume that one should be able to populate a cell with another embedded array, as long as it does not overwrite other elements in the outer embedded array. So IMO something like this should (see point 3) be successful:
={{1;2;3},{4;5;6}}
However something like this shouldn't work (again IMO), as the second and third elements of the first embedded array would be "overwriting" the second embedded array:
={{1,2,3},{4,5,6}}
There is a bug associated with the first embedded array inside an embedded array
As +Jason pointed out, something like ={{1;2;3},{4;5;6},{7;8;9}} doesn't work in that the first embedded array only populates one element (but every other column is populated correctly). It is also interesting that that one element is auto-converted to a text string. This is (unfortunately) a long standing bug in Google Sheets. The same thing occurs when you attempt to invoke the SPLIT() function on an array (every element in the array is split successfully except for the first one).
I don't think embedded arrays within embedded arrays will help with your broader problem anyway
Embedded arrays can't really be used to append one array on to end of another anyway (due to the "overwriting" effect), and there is no native function that can do it directly. The VMERGE function which you can obtain via the Script gallery (credit to +ahab) will work out of the box:
=VMERGE(ImportRange(...);ImportRange(...);...)
or you can use native functions to do some string manipulation to achieve this. For example, for one-dimensional arrays:
=ArrayFormula(TRANSPOSE(SPLIT(CONCATENATE(ImportRange("key1";"A1:A10")&CHAR(9);ImportRange("key2";"A1:A10")&CHAR(9));CHAR(9))))
but as well as being clunky and not very readable, this type of formula can be very expensive performance-wise for large data sets (I would tend to recommend the VMERGE custom function option in preference).
It is possible to make a union in Google Spreadsheet very easily. For example:
={'Sheet1'!A2:A;'Sheet2'!A2:A;'Sheet3'!A2:A}
See more info in Google Docs Help: Using arrays in Google Sheets
Assuming you have 3 arrays A2:B7, D4:E12, and F2:G230 with the same number of columns but different lengths (often the case if you have the same table of data split into different tabs for each period), I think the easiest way is something like this:
=TRANSPOSE({TRANSPOSE(A2:B7), TRANSPOSE(D4:E12), TRANSPOSE(F2:G230)})
A truncated version of my data is in the form shown in the screenshot below: three columns of 5 unique names. The names appear in any order and in any position but never repeat in a single row.
My goal is to create an array that contains the number of times Adam appears in each row. I can fill down the formula=countif(A2:C2,$I$2) in a new column, or if I write the array manually for each row, it looks like:
={countif(A2:C2,$I$2);countif(A3:C3,$I$2);countif(A4:C4,$I$2);countif(A5:C5,$I$2);countif(A6:C6,$I$2)}
Where cell I2 contains "Adam". Of course, this is not feasible for large data sets.
I know that arrays are effectively cells turned into ranges, but my main issue is that the cell I'm trying to transform already references a range, and I don't know how to tell the software to apply the countif down each row (i.e. I intuitively would like to do something like countif((A2:C2):(A99:C99),"Adam") but understand that's not how spreadsheets work).
My goal is ultimately to perform some operations on the corresponding array but I think I'm comfortable enough with that once I can get the array formula I'm looking for.
try:
=ARRAYFORMULA(IF(A2:A="",,MMULT(IF(A2:C="Adam", 1, 0), {1;1;1})))
I've got a bigger table with one column that I want to focus on, containing designation and a number. I want to simply sum the numbers that meet the criteria based on a designation.
For the simplification, I made an exercising sheet (on the pic) where I split second column into two - one string and one numeric. Since my file is quite large with many columns that would need this it would be inconvenient.
In the left column it's easy to solve the problem, it could be even easier with simple SUMIF function, but an array SUM(IF... function is, at least I think, only viable option here.
So I solved the first table with array function, but what confuses me is how to modulate the TRUE statement. Simple replacement of C:C
with
VALUE(MID(F:F;4;4))
which would format my cells to get the numbers from string does not work that way - returns zero in E12 field. F12 is just application of string to number for last cell, F10.
THIS formula does not work, even adapting to different versions of the tool.
I could use VB but if possible anyhow I would like to avoid it since parts will be shared on mobile phones.
Any ideas? Thanks a lot!
Left table was split, right original format
The array formula which you used can be replaced by the SumIf formula like below...
=SUMIF(B:B,"B",C:C)
Also without the helper column, you can use the Sumproduct formula to achieve the desired output.
But don't refer the whole column in the formula like in the above SumIf formula.
Try this..
=SUMPRODUCT((B1:B10="B")*MID(F1:F10,FIND(",",F1:F10)+1,255)*1)
Change the ranges as per your requirement but remember to make them equal in size.
I'll try to explain the problem I'm facing best as I can.
A have a set of data that contains multiple duplicates extracted as an excel file. Within this data are "keys" that I want to use to filter out relevant data from another workbook.
I start by removing duplicates from the list of keywords and I think I got this working kind of satisfactory. I then try to extract and calculate the minimum from the values using the following array formula:
=MIN(VLOOKUP(Blad1!D2:D8,Blad2!A3:D9,2))
However, this doesn't work as expected. The value returns the minimum value from the target range, but seems to ignore the provided keywords. Instead it simply finds the minimum value of the entire range.
I am far from a professional when it comes to excel so any suggestions on how this could be done in a more efficient way are welcome.
Here is a link to a sample document.
These array formulas should be what you need.
'MINIF in F2,
=MIN(IF(COUNTIF($D$2:$D$8, Blad2!$A$2:$A$9&""), Blad2!$B$2:$B$9))
'MAXIF in G2
=MAX(IF(COUNTIF($D$2:$D$8, Blad2!$A$2:$A$9&""), Blad2!$C$2:$C$9))
'AVERAGEIF¹ in H2
=AVERAGE(IF(COUNTIF($D$2:$D$8, Blad2!$A$2:$A$9&""), Blad2!$D$2:$D$9))
Array formulas need to be finalized with Ctrl+Shift+Enter↵.
Try and reduce your full-column references to ranges more closely representing the extents of your actual data. Array formulas chew up calculation cycles logarithmically so it is good practise to narrow the referenced ranges to a minimum.
The results are 15, 35 and 23.6.
¹Note that this is NOT the native AVERAGEIF function or AVERAGEIFS function but an array formula. This approach was chosen due to the large number of criteria.
When I append arrays in google spreadsheets, all of the resulting elements are not rendered in cells. For example, if I enter the formula:
={{1,2,3}, {4,5,6}}
the values rendered in spreadsheet cells are 1,4,5,6. Any ideas about why this is happening, or alternatives? My broader problem is to accumulate rows from separate sheets into another sheet - I can do that via
={ImportRange(...), ImportRange(...)}
but the same problem is apparent (missing the second element and beyond from the first array).
Edit (2 Oct 2014)
I just happened upon this when someone upvoted. The information below is obsolete in the newest version of Sheets - you can now (have been able to for a few months) concatenate arrays inside embedded arrays. All the examples that I provided below will work, including the one I said "shouldn't work".
Embedded arrays in Google Sheets
An array of values may be populated by a single function using an embedded array. Each element in the embedded array (and this may be point of conjecture; it is more or less just my opinion) represents the value that will be populated in contiguous cells in the sheet. Semi-colons are row delimiters; commas (or backslashes in locales that use a comma for a decimal separator) are column delimiters. So this will successfully create a two-row, three-column array (all of the following examples assume a locale supporting comma column delimiters):
={1,2,3;4,5,6}
Embedded arrays within embedded arrays
As each element in an embedded array represents a cell in the spreadsheet, I think it is reasonable to assume that one should be able to populate a cell with another embedded array, as long as it does not overwrite other elements in the outer embedded array. So IMO something like this should (see point 3) be successful:
={{1;2;3},{4;5;6}}
However something like this shouldn't work (again IMO), as the second and third elements of the first embedded array would be "overwriting" the second embedded array:
={{1,2,3},{4,5,6}}
There is a bug associated with the first embedded array inside an embedded array
As +Jason pointed out, something like ={{1;2;3},{4;5;6},{7;8;9}} doesn't work in that the first embedded array only populates one element (but every other column is populated correctly). It is also interesting that that one element is auto-converted to a text string. This is (unfortunately) a long standing bug in Google Sheets. The same thing occurs when you attempt to invoke the SPLIT() function on an array (every element in the array is split successfully except for the first one).
I don't think embedded arrays within embedded arrays will help with your broader problem anyway
Embedded arrays can't really be used to append one array on to end of another anyway (due to the "overwriting" effect), and there is no native function that can do it directly. The VMERGE function which you can obtain via the Script gallery (credit to +ahab) will work out of the box:
=VMERGE(ImportRange(...);ImportRange(...);...)
or you can use native functions to do some string manipulation to achieve this. For example, for one-dimensional arrays:
=ArrayFormula(TRANSPOSE(SPLIT(CONCATENATE(ImportRange("key1";"A1:A10")&CHAR(9);ImportRange("key2";"A1:A10")&CHAR(9));CHAR(9))))
but as well as being clunky and not very readable, this type of formula can be very expensive performance-wise for large data sets (I would tend to recommend the VMERGE custom function option in preference).
It is possible to make a union in Google Spreadsheet very easily. For example:
={'Sheet1'!A2:A;'Sheet2'!A2:A;'Sheet3'!A2:A}
See more info in Google Docs Help: Using arrays in Google Sheets
Assuming you have 3 arrays A2:B7, D4:E12, and F2:G230 with the same number of columns but different lengths (often the case if you have the same table of data split into different tabs for each period), I think the easiest way is something like this:
=TRANSPOSE({TRANSPOSE(A2:B7), TRANSPOSE(D4:E12), TRANSPOSE(F2:G230)})