Excel formula to calculate values based on other cells - excel

I've got the following table:
I'm using the following formula in column F to get the sum of the values in column E: =SUMIFS(E:E,C:C,LEFT(TRIM(RIGHT([#[Object Name]],LEN([#[Object Name]])-FIND("=",[#[Object Name]]))),4),A:A,INT([#[Result Time]])) but it doesn't seem to work.
Evaluating the formula gives me the following result:
Can someone please take a took at the for

You are looking for an object name of "T054", when they all appear to be "CELL=T054CID"... so no results are being returned.
What exactly is it you are trying to do?
Is there any reason you cannot just do:
=SUMIFS([3G_Traffic_CS],[Object Name],[#[Object Name]],[Result Time],[#[Result Time]])
You will also notice that I am referencing just the column cells within the table, rather than the entire column. This is more efficient and will prevent any extra values which appear under the table being counted (unlikely but not impossible).
ALTERNATIVE (Using a Helper Column)
Add a helper column which contains a trimmed value of the Object Name and compare to that:
=SUMIFS([3G_Traffic_CS],[Trimmed Object Name],[#[Trimmed Object Name]],[Result Time],[#[Result Time]])
ANOTHER ALTERNATIVE (Using FIND and SUMPRODUCT)
If you want to include any Object Name which CONTAINS your trimmed value, you can do this using the FINDfunction with SUMPRODUCT:
=SUMPRODUCT(
([Result Time]=[#[Result Time]])*
(ISNUMBER(
FIND(LEFT(TRIM(RIGHT([#[Object Name]],LEN([#[Object Name]])-FIND("=",[#[Object Name]]))),4),
[Object Name]
)
))*
[3G_Traffic_CS]
)
YET ANOTHER ALTERNATIVE (Using a Wildcard as per #Jvdv's comment)
Again, this assumes that you want to include all Object Names which CONTAIN your trimmed site ID. Simply add a "*" to the start and end of your trimmed Object Name.
=SUMIFS([3G_Traffic_CS],
[Object Name],
CONCAT("*",
LEFT(TRIM(RIGHT([#[Object Name]],LEN([#[Object Name]])-FIND("=",[#[Object Name]]))),4),
"*"
),
[Result Time],
INT([#[Result Time]])
)

Related

Comparing two columns and their values and outputting the greater value

I'm trying to compare two columns ("Shows") from different tables and showing which one has the greater number ("Rating") associated with it in another table.
Ignore the operation column above as part of the solution that I'm trying to get, it's just to illustrate for you what I'm trying to compare.
Important note: If the names are duplicated. Compare the matching pair in their corresponding order. (1st with 1st, 2nd with 2nd, 3rd with 3rd etc..) illustrated in the table below:
Thanks
You can try the following in cell F3 for an array solution that spills the entire result at once:
=LET(sA, A3:A6, rA, B3:B6, sB, C3:C6, rB, D3:D6, CNTS, LAMBDA(x,
LET(seq, SEQUENCE(ROWS(x)), MAP(seq, LAMBDA(s,ROWS(FILTER(x,(x=INDEX(x,s))
*(seq<=s))))))), cntsA, CNTS(sA), cntsB, CNTS(sB), eval, MAP(sA, rA, cntsA,
LAMBDA(s,r,c,IF(r > FILTER(rB, (sB=s) * (cntsB=c)), "Table 1", "Table 2"))),
HSTACK(sA, eval))
Here is the output:
Explanation
The main idea is to count repeated show values. We use a user LAMBDA function CNTS, to avoid repetition of the same formula twice. Once we have the counts (cntsA, contsB), we use MAP to iterate over Table 1 elements with the counts and look for specific show and counts to compare with Table 2 columns. The FILTER function will return always a single value (based on sample data). Finally, we prepare the output as expected using HSTACK.
Try-
=IF(INDEX(FILTER($B$3:$B$6,$A$3:$A$6=G3),COUNTIFS($G$3:$G3,G3))>INDEX(FILTER($E$3:$E$6,$D$3:$D$6=G3),COUNTIFS($G$3:$G3,G3)),"Table-1","Table-2")

how to transform a table in Excel from vertical to horizontal but with different length

i would like to get table 2 from Table 1 in a quicker way. can people help? thanks
so far i have done pivot tables and manually copy and paste transpose, but this is really time consuming/
Here, a solution that uses DROP/REDUCE/VSTACK pattern to generate each row. Check for example #JvdV's answer from this question: How to split texts from dynamic range? and a similar idea DROP/REDUCE/HSTACK pattern to generate the columns for a given row. In cell E2 put the following formula:
=LET(set, A2:B13, IDs, INDEX(set,,1), dates, INDEX(set,,2),
HREDUCE, LAMBDA(id, arr, REDUCE(id, arr, LAMBDA(acc, x, HSTACK(acc, x)))),
output, DROP(REDUCE("", UNIQUE(IDs), LAMBDA(ac, id, VSTACK(ac, LET(
idDates, FILTER(dates, ISNUMBER(XMATCH(IDs, id))), HREDUCE(id, idDates)
)))),1), IFERROR(VSTACK(HSTACK("ID", "Dates"), output), "")
)
and here is the output:
Update
As #JdvD pointed out in the comments section there is a shorted way:
=LET(set, A3:B13, title, A1:B1, IDs, INDEX(set,,1), dates, INDEX(set,,2),
IFERROR(REDUCE(title, UNIQUE(IDs),LAMBDA(ac, id,
VSTACK(ac,HSTACK(id,TOROW(FILTER(dates,IDs=id)))))),"")
)
The main idea is to use the title as a way to initialize the VSTACK accumulator (no need to use DROP), and have all the dates for a given id all at once via the FILTER function. As a side note, it can be expressed in terms of the pattern we explained in the Explanation section (see below), as follow:
=LET(set, A3:B13, title, A1:B1, IDs, INDEX(set,,1), dates, INDEX(set,,2),
HREDUCE, LAMBDA(id, HSTACK(id, TOROW(FILTER(dates,IDs=id)))),
IFERROR(REDUCE(title, UNIQUE(IDs),LAMBDA(ac,id, VSTACK(ac, HREDUCE(id)))),"")
)
Note: Keeping the same name of the user LAMBDA function (HREDUCE) for sake of consistency with the Explanation section, but there is no need to use REDUCE. A more appropriate name would be PIVOT_DATES.
Explanation
HREDUCE is a user LAMBDA function that implements the DROP/REDUCE/HSTACK pattern. In order to generate all the columns for a given row, this is the pattern to follow:
DROP(REDUCE("", arr, LAMBDA(acc, x, HSTACK(acc, func))),,1)
It iterates over all elements of arr (x) and uses HSTACK to concatenate column by column on each iteration. DROP function is used to remove the first column, if we don't have a valid value to initialize the first column (the accumulator, acc). The name func is just a symbolic representation of the calculation required to obtain the value to put on a given column. Usually, some variables are required to be defined, so quite often the LET function is used for that.
In our case we have a valid value to initialize the iteration process (no need to use DROP function), so this pattern can be implemented as follow via our user LAMBDA function HREDUCE:
LAMBDA(id, arr, REDUCE(id, arr, LAMBDA(acc, x, HSTACK(acc, x))))
In our case the initialization value will be each unique id value. The func will be just each element of arr, because we don't need to do any additional calculation to obtain the column value.
The previous process can be applied for a given row, but we need to create iteratively each row. In order to do that we use a DROP/REDUCE/VSTACK pattern, which is a similar idea:
DROP(REDUCE("", arr, LAMBDA(acc, x, VSTACK(acc, func))),1)
Now we append rows via VSTACK. For this case we don't know how to initialize properly the accumulator (acc), so we need to use DROP to remove the first row. Now fun will be: HREDUCE(id, idDates), i.e. the LAMBDA function we created before to generate all the dates columns for a given id. Now we use a LET function to name the selected dates for a given id (idDates).
At the beginning of each row (first column), we are going to have the unique IDs (UNIQUE(IDs)). To find the corresponding dates for each unique ID (id) we use the following:
FILTER(dates, ISNUMBER(XMATCH(IDs, id)))
and name the result idDates.
Finally, we build the output including the header. We pad non existing values with the empty string to avoid having #NA values. This is the default behavior of V/HSTACK functions. We use IFERROR function for that.
IFERROR(VSTACK(HSTACK("ID", "Dates"), output), "")
Note: Both patterns are very useful to avoid Nested Array Error (#CALC!) usually produced by some of the new Excel array functions, such as BYROW, BYCOL, MAP when using TEXTSPLIT for example. This is one of the effective ways to overcome it.

How to find each string in a table and display them only once?

I have a table which displays names, 0s and 1s, as shown here:
I would like to find each string in the middle table, and add it to the pointed table. I'm doing it by hand for now.
I tried to achieve this by using FILTER, COUNTIF and TYPE, according to what I saw on internet, but there is nothing about using data in multiple columns, so all i got is a #VALUE error.
=sort(filter(d3:l999; (countif(filtre(d3:l999; type(d3:l999) = 2); d3:l999) < 1)))
Could anyone help for that? Thanks.
We can use LET to simplify using UNIQUE and FILTER:
=LET(
rng, D2:L18,
rws, ROWS(rng),
seq, SEQUENCE(ROUNDUP(COLUMNS(rng)/2,0)*rws,,0),
it, INT(seq/rws)*2+1,
md, MOD(seq,rws)+1,
idx, INDEX(rng,md,it)&"",
SORT(UNIQUE(FILTER(idx,idx<>""))))
And with a little change we can get the whole table with one formula:
=LET(
rng, D2:L18,
rngN, E2:M18,
rws, ROWS(rng),
seq, SEQUENCE(ROUNDUP(COLUMNS(rng)/2,0)*rws,,0),
it, INT(seq/rws)*2+1,
md, MOD(seq,rws)+1,
idx, INDEX(rng,md,it)&"",
nm, SORT(UNIQUE(FILTER(idx,idx<>""))),
cnt, COUNTIFS(rng,nm),
wn, SUMIFS(rngN,rng,nm)/cnt,
CHOOSE({1,2,3},nm,cnt,wn))
if you don't need the table format
You could use solution "How to get distinct values in Excel (unique + 1st duplicate occurrences)"
https://www.ablebits.com/office-addins-blog/2016/04/21/get-list-unique-values-excel/
And use a countif function to get the amounts
Create an array of every other column of your data table
Create an XML by using TEXTJOIN
Turn it into an array using FILTERXML
Use UNIQUE and SORT on the results
=SORT(UNIQUE(FILTERXML("<t><s>"&TEXTJOIN("</s><s>",TRUE,INDEX($D$3:$L$17,SEQUENCE(ROWS($D$3:$L$17)),{1,3,5,7,9}))&"</s></t>","//s")))
If your data table might have a varying number of columns, there are ways of handling that also. I wrote this for a known array occupying D3:L17
If the string length created by TEXTJOIN > 32,767, this formula will return an error.

Conditional Index/Match trouble

Hello, I am trying to solve an issue that has my brain fried. I have two tables, Table1 and Table2. Table1 has a list of SKUs as well as a department/class/fine which are essentially a breakdown of product groups. There is a hierarchy here. Each department has a sub-CLASS and each class can be broken up into smaller fine lines. Department > class > Fine line. Table2 contains markup information. I am trying to match the correct markup in table 2 with the corresponding DCF in table1. Here's the kicker: Not all markups correspond to an exact DCF, some markups just apply to the specific department/class or even just the department.
Here's my logic:
IF DCF(Dept / class/ fine) from table1 match table2, find the cus1 markup record with the matching DCF and return it to table1.
If Fine is missing, return the value for matching Dept TRUE/ Class True / Fine NULL.
If both Class and Fine are missing, return the value of just the department TRUE / Class NULL / Fine NULL.
I can get this equation to work every time if all 3 DCF match but when I start throwing logical tests into the mix, I cannot seem to find a way to get excel to find the correct cell to index. Here is my current iteration of this formula (I am missing the final criteria here. I only have steps 1 and 2 from my logic in this equation, will need to add the final criteria once I get it ironed out).
Here is my formula:
=IF(AND(
COUNTIFS(Table2[dept],[#dept],Table2[class],[#class])>0,
COUNTIFS(Table2[fine],[#fine])<1),
INDEX(Table2[markup],MATCH(Table1[[#Headers],[cus1]]&[#dept]&[#class],Table2[custype]&Table2[dept]&Table2[class],0)),
INDEX(Table2[markup],MATCH(Table1[[#Headers],[cus1]]&[#dept]&[#class]&[#fine],Table2[custype]&Table2[dept]&Table2[class]&Table2[fine],0)))
Formula breakdown:
If table2[dept] matches [#dept] and table2[class] matches [#class] and table2[fine] != [#fine] then match the values in table2 and return the markup index. The issue with this formula is that it returns the first instance of department/class and ignores whether or not the class is missing or not. Line 3 on Table1 is returning 0.65 and should be returning 0.4.
You can try following formula:
=INDEX(M:M,
AGGREGATE(15,6,
ROW(Table2[markup])/
(((([#dept]=Table2[dept])*4+(([#class]=Table2[class])*3)+(([#fine]=Table2[fine])*2+(""=Table2[class])+(""=Table2[fine]))))=
MAX(((([#dept]=Table2[dept])*4+(([#class]=Table2[class])*3)+(([#fine]=Table2[fine])*2+(""=Table2[class])+(""=Table2[fine])))))),1))

Excel: Applying dynamic array function UNIQUE in excel to a table with rows & columns >1

I have a survey of rents in the table called "Rent Survey Data" which is defined as a name "TBL_RentSurvey".
I use the new dynamic array function "FILTER" to output data that is filtered with various AND/OR criteria according to the fields: W/D, Attchd Garage, SS Appliances, Den, Rehab, and a start/end date. Note that "*" operator refers to AND and "+" operator refers to OR. I have 2 rows for my filter because sometimes I would like to output various combinations of 1 criteria and hence use the "+" operator.
When I apply the UNIQUE function (also a new dynamic array function), I do not get a unique array outputted. You can see that Vizcaya is outputted twice.
Can someone please tell me what I am doing wrong. I was expecting to have a unique table based on all of those arguments.
You can see below that Vizcaya was outputted twice. I'm not sure why.
I was expecting this output:
Code for the two scenarios:
((TBL_RentSurvey[W/D]=C4)+(TBL_RentSurvey[W/D]=C5))
*((TBL_RentSurvey[Attchd Garage]=D4)+(TBL_RentSurvey[Attchd Garage]=D5))
*((TBL_RentSurvey[SS Appliances]=E4)+(TBL_RentSurvey[SS Appliances]=E5))
*((TBL_RentSurvey[Den]=F4)+(TBL_RentSurvey[Den]=F5))
*((TBL_RentSurvey[Rehab]=G4)+(TBL_RentSurvey[Rehab]=G5))
*(TBL_RentSurvey[Unit Type]=H4)
*(TBL_RentSurvey[[Date ]]>=L4)
*(TBL_RentSurvey[[Date ]]<=L5))
=UNIQUE(FILTER(TBL_RentSurvey[[Property]:[Unit Type]],
((TBL_RentSurvey[W/D]=C4)+(TBL_RentSurvey[W/D]=C5))
*((TBL_RentSurvey[Attchd Garage]=D4)+(TBL_RentSurvey[Attchd Garage]=D5))
*((TBL_RentSurvey[SS Appliances]=E4)+(TBL_RentSurvey[SS Appliances]=E5))
*((TBL_RentSurvey[Den]=F4)+(TBL_RentSurvey[Den]=F5))
*((TBL_RentSurvey[Rehab]=G4)+(TBL_RentSurvey[Rehab]=G5))
*(TBL_RentSurvey[Unit Type]=H4)
*(TBL_RentSurvey[[Date ]]>=L4)
*(TBL_RentSurvey[[Date ]]<=L5)))
Thank you!

Resources