Conditional Index/Match trouble - excel

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))

Related

How to reproduce the equivalent of a Countif excel function in Business Objects?

I'm from France (sorry for my english) and I am currently working on the latest version of Business Objects (business-intelligence suite from SAP).
I would like to transpose an Excel formula to Business Objects, but I cannot. Could someone be able to answer me how to reproduce the equivalent of a Countif function, please ?
In my example, I have a whole list of repeating social security numbers to which I have appended a variable number taken from another field. I would like to do a count for each security number and know how many of them have the "2" value attached to them in my other field.
Example :
For 1741111111100 | 17411111111001, the result in a new field will be 2.
For 1741111111100 | 17411111111001, the result in a new field will be 2.
For 1741111111100 | 17411111111002, the result in a new field will be 2.
For 1741111111100 | 17411111111002, the result in a new field will be 2.
For 1741111111100 | 17411111111003, the result in a new field will be 2.
For 1751111111100 | 17511111111001, the result in a new field will be 1.
For 1751111111100 | 17511111111002, the result in a new field will be 1.
For 1751111111100 | 17511111111003, the result in a new field will be 1.
For 1761111111100 | 17611111111001, the result in a new field will be 0.
For 1761111111100 | 17611111111001, the result in a new field will be 0.
For 1761111111100 | 17611111111003, the result in a new field will be 0.
In excel it's easy to do with a Countif function but how could I do this in Business Objects, please ?
Thank you in advance because I spent a whole afternoon in vain.
RE-EDIT
Here's the same example with excel :
1741111111100|1|17411111111001|2|
1741111111100|1|17411111111001|2|
1741111111100|2|17411111111002|2|
1741111111100|2|17411111111002|2|
1741111111100|3|17411111111003|2|
1751111111100|1|17511111111001|1|
1751111111100|2|17511111111002|1|
1751111111100|3|17511111111003|1|
1761111111100|1|17611111111001|0|
1761111111100|1|17611111111001|0|
1761111111100|3|17611111111003|0|
A column :
there are my security numbers (1741111111100 repeated 5 times, 1751111111100 repeated 3 times, 1761111111100 repeated 3 times)
B column :
It's a number between 1 and 3.
C column :
I concatenated A column + B column like =CONCATENATE(A1;B1)
D column :
Here are my countif functions done like this :
=COUNTIF(C$1:C$11;CONCATENATE(A1;"2")) that gives a quantity of "2".
=COUNTIF(C$1:C$11;CONCATENATE(A2;"2")) that gives a quantity of "2".
=COUNTIF(C$1:C$11;CONCATENATE(A3;"2")) that gives a quantity of "2".
=COUNTIF(C$1:C$11;CONCATENATE(A4;"2")) that gives a quantity of "2".
=COUNTIF(C$1:C$11;CONCATENATE(A5;"2")) that gives a quantity of "2".
=COUNTIF(C$1:C$11;CONCATENATE(A6;"2")) that gives a quantity of "1".
=COUNTIF(C$1:C$11;CONCATENATE(A7;"2")) that gives a quantity of "1".
=COUNTIF(C$1:C$11;CONCATENATE(A8;"2")) that gives a quantity of "1".
=COUNTIF(C$1:C$11;CONCATENATE(A9;"2")) that gives a quantity of "0".
=COUNTIF(C$1:C$11;CONCATENATE(A10;"2")) that gives a quantity of "0".
=COUNTIF(C$1:C$11;CONCATENATE(A11;"2")) that gives a quantity of "0".
I was interested by the "2" value attached to the security number and the number of security numbers concerned by this attachment.
So, it's easy to do with excel but so so so hard to do with B.I. !
Thanx for any help.
Background:
Context Operators:
ForEach
ForAll
In
Operate on "Sets" of data allowing you to parse out data into subsets and aggregate. in SQL this is similar to "Over Partition By" if you're familiar with it.
Answer:
If we assume you create a variable in the report [Concat] as follows:
=Concatenation([A];"2")
Then we can use formula:
=Sum(If([C]=[Concat];1;0)) ForEach([Concat]) In ([C])
Where [C] is your concatenated columns A+B.
Explanation
The above essentially says if [C] = [Concat] return a 1 otherwise return a 0 and then sum the results of those evaluations together.
This occurs ForEach unique value within [Concat]; found in [C].
Logically the system finds all the unique values in [Concat] in then iterates though [C] evaluating if [C]=[Concat] for each case. it then sums the results for each [concat] and then renders those results for each [C]
Additional Point:
In my example the report data was being "combined" due to duplicate values So row 1, row 2 in your example were combined. I had to turn off BO's combining of this row data or my results were skewed. This can be accomplished by formatting the result table and checking the top checkbox "Avoid Duplicate row Aggregation" If you have other values which make each row unique, you will not have this problem. You can turn this off at a query level as well in the query properties of the edit data provider. I believe it depends on what source you use as to which method must be used... But I'm not positive.
So below you can see results from [Cnt] match your expected results in column D using the aforementioned formula.

Excel formula to calculate values based on other cells

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]])
)

Using tbl.Lookup to match just part of a column value

This question relates to the Schematiq add-in for Microsoft Excel.
Using =tbl.Lookup(table, columnsToSearch, valuesToFind, resultColumn, [defaultValue]) the values in the valuesToFind column have a consistent 3 characters to the left and then varying characters after (e.g. 908-123456 or 908-321654 - i.e. 908 is always consistent)
How can I tell the function to lookup the value based on the first 3 characters only? The expected answer should be the sum of the results of the above, i.e. 500 + 300 = 800
tbl.Lookup() works by looking for an exact match - this helps ensure it's fast but in this case it means you need an extra step to calculate a column of lookup values, something like this:
A2: =tbl.CalculateColumn(A1, "code", "x => LEFT(x, 3)", "startOfCode")
This will give you a new column that you can use for the columnsToSearch argument, however tbl.Lookup() also looks for just one match - it doesn't know how to combine values together if there is more than one matching row in the table, so I think you also need one more step to group your table by the first 3 chars of the code, like this:
A3: =tbl.Group(A2, "startOfCode", "amount")
Because tbl.Group() adds values together by default, this will give you a table with a row for each distinct value of startOfCode and the subtotal of amount for each of those values. Finally, you can do the lookup exactly as you requested, which for your input table will return 800:
A4: =tbl.Lookup(A3, "startOfCode", "908", "amount")

Excel - 2 tables - If 2 cells in a single row match, return another cell of same row

Working with 2 separate data sets (with duplicates)
Dataset is unique identified by an ID.
There may not be an entry for the timestamp I require.
Datasets are quite large, and due to duplicates, can't use vlookup.
Samples:
Table 1:
Device Name|Time Bracket| On/Off?
ID1 |06:20:00 |
ID2 |06:20:00 |
ID3 |06:30:00 |
Table 2:
Device Name |Timestamp |On/Off?
ID1 |06:20:00 |On
ID2 |06:50:00 |Off
ID3 |07:20:00 |Off
What I want to achieve:
I want an if statement to check if:
1) device ID matches AND
2) timestamp matches
If so, return the value of On/Off from Table 2.
If not, then I want it to return the value of the cell above it IF it's the same device, otherwise just put "absent" into the cell.
I thought I could do this with some IF statements like so:
=if(HOUR([#[Time Bracket]]) = HOUR(Table13[#[Timestamp Rounded (GMT)]]) and
minute([#[Time Bracket]]) = minute(Table13[#[Timestamp Rounded (GMT)]]) and
[#[Device Name]]=Table13[#[Device Name]], Table13[#[On/Off?]],
IF([#[Device Name]]=Table13[#[Device Name]], INDIRECT("B" and Rows()-1), "absent"))
(I put some newlines in there for readability)
However, this doesn't seem to resolve at all... what am I doing wrong?
Is this even the correct way of achieving this?
I've also tried something similar with a VLookUp, but that failed horribly.
Thanks all!
To not deal with array formulas or merging strings which, (not in your case) can still be wrong at the end, I suggest the use of COUNTIFS due to the fact, you have a very small amount of outcomes (just on or off)...
for the first table (starting at A1, so the formula is at C2):
=IFERROR(CHOOSE(
OR(COUNTIFS(Table13[Device Name],[#[Device Name]],Table13[Timestamp],[#[Time Bracket]],Table13[On/Off?],"On"))+
OR(COUNTIFS(Table13[Device Name],[#[Device Name]],Table13[Timestamp],[#[Time Bracket]],Table13[On/Off?],"Off"))*2
,"On","Off","Error"),IF(A1=[#[Device Name]],C1,"Absent"))
this will also show "Error" of a match for "On" and "Off" is shown... to skip that and increase the speed, you also could use:
=IF(COUNTIFS(Table13[Device Name],[#[Device Name]],Table13[Timestamp],[#[Time Bracket]],Table13[On/Off?],"On"),"On",
IF(COUNTIFS(Table13[Device Name],[#[Device Name]],Table13[Timestamp],[#[Time Bracket]],Table13[On/Off?],"Off"),"Off",
IF(A1=[#[Device Name]],C1,"Absent")))
For both the "Device Name" is at column A, "Time Bracket" at column B and "On/Off?" at column C while the table starts at row 1... If that is not the case for you, then change A1 and C1 so they match
(Also inserted line-breaks for better reading)
Picture to show the layout:
I picked the second formula to show how it works... also, this formula should not be able to return 0's... I'm confused
Couple of good suggestions, however using the helper column as suggested in the topic by Scott Craner above worked.
Created a helper column of concat'd device ID and timestamp for both tables, then did a simple VlookUp.
Another lesson learned: Think outside of the box, and go with simple solutions, rather than try + be too clever like I was doing... :)

Finding the next result from a MATCH

I am trying to produce a sorted table in excel, which depend on the selected year and category.
My methodology has been to sequentially find largest values in order, within the selected year and category parameters, doing the following:
Column E
{=LARGE(IF(('Master Data'!A$1:A$500 = $B$1) * ('Master Data'!B$1:B$500 = $B$2),'Master Data'!C$1:C$500), $B10)}
This works fine, $B$1$ is where I store the year, $B$2 is where I store the category, $B10 references a hard coded 1-25 in column B.
Column F
{=MATCH(E10,IF(('Master Data'!A$1:A$500 = $B$1) * ('Master Data'!B$1:B$500 = $B$2),'Master Data'!C$1:C$500),FALSE)}
This returns the row number of the result I need, which I then use in conjunction with INDEX to find related data.
The problem with this is that Match only returns the first row number, and if you have two results with the same value this clearly becomes an issue.
Column G
To resolve this I used an example from dailydoseofexcel which looks like this:
=IF(F10<>F11, F11, G10+MATCH(E11,INDIRECT("'Master Data'!C"&(G10+1)&":C500"),0))
This works to a limited extent, for my purposes, as it is unable to take into account the year and category filter I need to apply, so I tried:
{=IF(F10<>F11, F11, G10+MATCH(E11,IF((INDIRECT("'Master Data'!A"&(G10+1)&":A500") = $C$2) * (INDIRECT("'Master Data'!B"&(G10+1)&":B500") = $C$3), INDIRECT("'Master Data'!C"&(G10+1)&":C500")),0))}
But I am just getting #N/A as a result.
I think SUMPRODUCT may be what you are looking for:
Charley Kyd XL Legend: Use SUMPRODUCT to get the Last item in a list

Resources