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

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.

Related

How do I group rows based on a fixed sum of values in Excel?

I am trying to find another solution to below Excel formula that was already provided here:
How do I create groups based on the sum of values?
It is the same requirement, but the grouping criteria needs to be an exact value.
Here's the sample data:
Column A | Column B
Item A | 1
Item B | 2
Item C | 3
Item D | 4
Item E | 5
Item F | 1
Item G | 2
Item H | 3
Item I | 4
Item J | 5
I need to group the rows if their Column B sum = 5.
Expected result:
Group 1 = Item A, Item D (1 + 4) = 5
Group 2 = Item B, Item C (2 + 3) = 5
Group 3 = Item E = 5
Group 4 = Item F, Item I (1 + 4) = 5
Group 5 = Item G, Item H (2 + 3) = 5
Group 6 = Item J = 5
If a row's Column B exceeds 5 or does not have another matching row to equal 5 when added then it will have no Group value.
Groupings can be interchangeable, ie. Group 1 = Item A, Item I can be made since 1 + 4 = 5.
I assume this can be achieved using Excel formulas but I am struggling to find which formula(s) can be used. Any help is appreciated!
I believe I was able to understand your question after some comments exchanged. Anyway I would recommend to update your question, it is an interesting problem, but the question was difficult to follow.
Before looking for an Excel solution, I took the approach of understanding the problem as a state machine with the transition from one state to another. I considered the following states that represent the position the item in the group. A group is defined as consecutive items that the sum of all items is equal to 5.
EMPTY: Just the initial situation
START: Start of the group
MIDDLE: A middle element of the group
END: The end of the group
START-END: A group with a single element
NA: Not applicable group
I follow the same idea of: How do I create groups based on the sum of values?, but slightly different helper columns:
Total (Column D), but for this case it is used the following formula: IF(SUM(C3,D2)>5,C3,SUM(C3,D2))
Status or item position within Group (Column G). Here is where it is calculated the corresponding status for each element
Checks for Valid Groups (Column H): Evaluates if a group is valid. When there is no match to 5, the group is not valid. It is indicated at the row that represents the beginning of the group (START or START-END states). If TRUE it means a valid group, if FALSE it is not a valid group, and NA for an NA value from Status column. If empty represents any element of the group that is not the first one.
Group # (Column I): To identify the group the row (Item) belongs to. Notice that we start counting the group from 1 and I also consider the case a group can not be formed (NA).
Here is a screenshot with the solution and the formula on G3:
=LET(total, D3, prevS, G2, QTY, C3,
IF(C3="", "",
IF(OR(AND(total=5, QTY<5, prevS="START"), AND(total=5, prevS="MIDDLE")), "END",
IF(OR(AND(total>5, total=QTY, OR(prevS="START", prevS="MIDDLE")),AND(total>5, OR(prevS="", prevS="END", prevS="NA", prevS="START-END"))), "NA",
IF(OR(AND(total<5, total=QTY, OR(prevS="START", prevS="MIDDLE")),AND(total<5, OR(prevS="", prevS="END", prevS="NA", prevS="START-END"))), "START",
IF(AND(total<5, OR(prevS="START", prevS="MIDDLE")), "MIDDLE",
IF(OR(AND(total=5, total= QTY, OR(prevS="START", prevS="MIDDLE")),AND(total=5, OR(prevS="", prevS="END", prevS="NA", prevS="START-END"))), "START-END", "UNDEFINED")
)
)
)
)
)
)
Notes::
LET Excel function is used to have something more readable
The IF blocks should to be ordered from the most specific case of total and QTY values to the most generic ones. For the case with same total condition, make sure the second condition for prevS are not repeated.
Added as a last resort UNDEFINED case, to check if any transition was not covered, if that is the case it has to be reviewed, so far in the sample data all cases are covered
Column K-Q is just for documenting purpose to identify all possible transitions. Column K-M provides all possible transitions organized them by previous status. The columns O-Q represent all possible transitions ordered by current status, so it is easier to formulate each portion of the IF blocks.
Maybe the formula can be simplified, compared to the solution provided by the similar question is more complex, but this question has more specific conditions. Some transitions maybe not relevant for the final result, but it is preferred to consider all positions in the group to make sure all transitions are covered.
The following state machine diagram shows all possible transitions:
Notes:
As you can see the solution also considers when a group cannot be created or non valid groups (NA values). The solution considers that Item column has only positive values, it is not stated in the question any restriction, but looking at the example they are all positives. To consider zero values, this solution needs to be adjusted.
Checks for Valid Groups column is calculated as follow:
= IF(G3="", "",
IF(G3="START-END", TRUE,
IF(G3="NA", "NA",
IF(G3="START",
LET(endRow, IFNA(MATCH("START", LEFT(G4:$G$1000,5),0), MATCH("", LEFT(G4:$G$1000,5),0))+ ROW()-1,
value, VLOOKUP("END", G4:INDIRECT( "G" & endRow),1,0),
IF(ISNA(value), FALSE, TRUE)
), ""
)
)
)
)
It identifies the start and end of the group, and then finds any NA values, if there are, then it is not a valid group. If the end of the candidate group is not found (the first MATCH returns N/A), then is searches until a blank row
Group # column is calculated has follow:
=IF(C3="","", LET(value, MAX($I$2:I2), IF(G3="NA", "NA",
IF(H3=TRUE, value + 1, IF(H3=FALSE, "NA",
IF(I2="NA", "NA", value))))))
This way only valid transaction are considered, i.e. the following status transitions starting from START but not ending in END : START->NA, START->MIDDLE[one or more]...->NA and NA are not considered valid groups (NA).
I added more examples from the original sample file provided, more can be added to further test all possible scenarios, but I guess you get the idea about this approach. As you sated "I assume this can be achieved using Excel formulas" yes it is possible, but I would say for more complex conditions I would suggest to implement a state machine algorithm in VBA. Even it is possible to do it with Excel functions, you have to deal with several nested IF blocks and helper columns, something that can be achieved with a simple for-loop in VBA.
Here is a link to online Excel file I used.

How can I extract a total count or sum of agents who made their first sale in a specified month?

I am trying to extract some data out of a large table of data in Excel. The table consists of the month, the agent's name, and either a 1 if they made a sale or a 0 if they did not.
What I would like to do is plug in a Month value into one cell, then have it spit out a count of how many agents made their first sale that month.
Sample Data and Input Output area
I found success by creating a secondary table for processing a minif and matching to agent name, then countif in that table's data how many sales months matched the input month. However I would like to not have a secondary table and do this all in one go.
=IF(MINIFS(E2ERawData[Date Group],E2ERawData[Agent],'Processed Data'!B4,E2ERawData[E2E Participation],1)=0,"No Sales",MINIFS(E2ERawData[Date Group],E2ERawData[Agent],'Processed Data'!B4,E2ERawData[E2E Participation],1))
=COUNTIFS(ProcessedData[Month of First E2E Sale],H4)
Formula in column F is:
=MAX(0;COUNTIFS($A$2:$A$8;E3;$C$2:$C$8;1)-SUM(COUNTIFS($A$2:$A$8;"<"&E3;$C$2:$C$8;1;$B$2:$B$8;IF($A$2:$A$8=E3;$B$2:$B$8))))
This is how it works (we'll use 01/03/2022 as example)
COUNTIFS($A$2:$A$8;E3;$C$2:$C$8;1) This counts how many 1 there are for the proper month (in our example this part will return 2)
COUNTIFS($A$2:$A$8;"<"&E3;$C$2:$C$8;1;$B$2:$B$8;SI($A$2:$A$8=E3;$B$2:$B$8)) will count how many 1 you got in previous months of the same agents (in our example, it will return 1)
Result from step 2, because it's an array formula, we sum up using SUM() (in our example, this return 1)
We do result from step 1 minus result from step 3 (so we get 1)
Finally, everything is inside a MAX function to avoid negative results (February would return -1 because there were no sales at all and agent B did a sale on January, so it would return -1. To avoid this, we force Excel to show biggest value between 0 and our calculation)
NOTE: Because it's an array formula, depending on your Excel version maybe you must introduce pressing CTRL+ENTER+SHIFT
If one has got access to the newest functions:
=LET(X,UNIQUE(C3:C9),VSTACK({"Month","Total of First time sales"},HSTACK(X,BYROW(X,LAMBDA(a,SUM((C3:C9=a)*(MINIFS(C3:C9,D3:D9,D3:D9,E3:E9,1)=C3:C9)))))))

lookup value based on partial value

I have a set of batch numbers in a sheet which are alphanumeric code as follows
sdc234
fgh345
ght587
jki876
The alphabets of the batch number represent a product code. For example
sdc = 20499999
fgh = 45999999
ght = 67999992
jki = 56700000
The above relation is in another sheets.
I want to match product code with batch number directly. How do i lookup a product code based on this partial info ?
You can sort your second table in an alphabetical order and use VLOOKUP with TRUE (approximate match) as your third argument.
Assuming the second table is in column A and B:
D E
sdc234 =VLOOKUP(D1,A:B,2,TRUE)
fgh345 =VLOOKUP(D2,A:B,2,TRUE)
ght587 =VLOOKUP(D3,A:B,2,TRUE)
jki876 =VLOOKUP(D4,A:B,2,TRUE)
The output is as below:
D E
sdc234 20499999
fgh345 45999999
ght587 67999992
jki876 56700000
EDIT:
Assuming your product code is always 3 letters, you can use the LEFT function to get the first 3 letters and then use that as the lookup value. This way you can use the exact match as your third argument:
sdc234 =VLOOKUP(LEFT(D1,3),A:B,2,FALSE)
fgh345 =VLOOKUP(LEFT(D2,3),A:B,2,FALSE)
ght587 =VLOOKUP(LEFT(D3,3),A:B,2,FALSE)
jki876 =VLOOKUP(LEFT(D4,3),A:B,2,FALSE)
Credits to Mladen Savic's comment for making me think of this solution.

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

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