I'm really spinning my wheels on this one. I'm trying to add 2 calculated columns in a Power Pivot table (in Excel 2013) to a loaded single column.
Setup (just first row shown):
Prd | Beg | End
1 | =CALCULATE(SUM([End]),Table[Prd]=EARLIER([Prd])-1) | =[Beg]+[Prd]
I want it to calculate like this:
Prd | Beg | End
1 | 1 | 2
2 | 2 | 4
3 | 4 | 7
But no matter what I do, I get a circular reference error because the [End] calculation is pointing to the [Beg] calculation and vice versa. I'm trying to get it to perform a rolling calculation where the [Beg] amount always equals the [End] amount from the prior [Prd].
I tried various calculations using SUMX and ALLEXCEPT, but I'm not getting this one right. I even tried designating the Row Identifier in the Table Behavior tab based on this but it's not working with that either.
Appreciate any suggestions!
I would suggest you to base your formula for [Beg] column on previous values of [Prd] column. Therefore
Beg=SUMX(
FILTER(
ALL(Table[Prd]),
Table[Prd] < EARLIER(Table[Prd])
),
Table[Prd]
) + 1
Explanation:
It sums up all the previous values for [Prd] column and adds 1 (if you take a look at the generated values, you'll see the pattern).
But the formula for [End] should also be fixed so you won't run into the same exception. So you'll have the following (this will sum values from current row for [Beg] and [Prd]):
End=SUMX(
FILTER(
ALL(Table[Beg], Table[Prd]),
Table[Prd]=EARLIER(Table[Prd])),Table[Beg]
) + Table[Prd]
Explanation:
In your case, avoiding to use CALCULATE and using instead just SUMX and EARLIER for [End] will help you to get rid of circular dependency.
Related
HI.
how can i come up with return value of "company name" (column H) at Column B IF any of the "PrefiX" (Column G) found at "con no" (Column A).
Sample of outcome needed as in column B.
Sample:
620011113 = DD
CN1234 = BB
thanks
=INDEX($H:$H,AGGREGATE(15,6,ROW($G$1:$G$7)/(--(FIND($G$1:$G$7,$A2)=1)*--(LEN($G$1:$G$7)>0)),1),1)
Breaking this down, the INDEX retrieves the Nth item from Column H (Company name). To find the value of N, we are using the AGGREGATE function
AGGREGATE is a weird function - it lets us use things like MAX or LARGE or SUM while ignoring any error values. In this case, we will be using it for SMALL (first argument, 15), while Ignoring Error Values (second argument, 6). We will want the very smallest value, so the fourth argument will be 1. (If we wanted the second smallest, it would be 2, and so on)
=INDEX($H:$H,AGGREGATE(15,6, <SOMETHING> ,1),1)
So, all we need now is a list of values to compare! To make things slightly simpler, I'll break that bit of the code out for you here:
ROW($G$1:$G$7) / (--(FIND($G$1:$G$7,$A2)=1) * --(LEN($G$1:$G$7)>0))
There are 3 parts to this. The first, ROW($G$1:$G$7)is the actual value we want to retrieve - these will be the Row Numbers for each Prefix that matches your value. On its own, however, it will be all the row numbers. Since we are skipping errors, we want any Rows that don't match the prefix to throw an error. The easiest way to do this is to Divide by Zero
At the start of --(FIND($G$1:$G$7,$A2)=1) and --(LEN($G$1:$G$7)>0) we have a double-negative. This is a quick way to convert True and False to 1 and 0. Only when both tests are True will we not divide by 0, as this table shows:
A | B | A*B
1 | 1 | 1
1 | 0 | 0
0 | 1 | 0
0 | 0 | 0
Starting with the second test first (it's easier), we have LEN($G$1:$G$7)>0 - basically "don't look at blank cells".
The other test (FIND($G$1:$G$7,$A2)=1) will search for the Prefix in the Con No, and return where it is found (or a #VALUE! error if it isn't). We then check "is this at position 1" - in other words, "Is this at the start of the Con No, rather than in the middle". We don't want to say Con No CNQ6060 is part of Company AA instead of Company BB by mistake!
So, if the Prefix is at the Start of the Con No, AND it isn't Blank (because there is an infinite amount of Nothing Before, After, and Between every number and letter), then we get it added to our list of Rows. We then take the smallest row (i.e. closest to the top - change AGGREGATE(15 to AGGREGATE(14 if you want the closest to the bottom!), and use that to get the Company Name
You could try the below formal:
=VLOOKUP(IF(LEFT(A3,1)="6",LEFT(A3,4),IF(LEFT(A3,1)="C",LEFT(A3,2),IF(LEFT(A3,1)="E",LEFT(A3,7)))),$G$3:$H$7,2,0)
Have in mind that you have to use ' before the cell value of column A & G in order to convert cell value into text get the correct out comes using VLOOKUP
Result:
I have the following Excel table:
Date | Value
===========+=======
24.02.2019 | 1350
25.02.2019 | 1120
26.02.2019 | 1200
|
|
|
===========+=======
DIFFERENCE | 80
The bottom total row (DIFFERENCE) should calculate the difference between value of last inserted record in table and value of previous record. When I tomorrow insert the new record for 27.02.2019 with value 1300, the bottom row should show difference 100 (1300-1200). There are undefined number of blank rows between last inserted row and bottom total row.
And here is another example
=INDIRECT("B"&COUNTA(INDIRECT("B1:B"&ROW()-1)))-INDIRECT("B"&COUNTA(INDIRECT("B1:B"&ROW()-1))-1)
I think that OFFSET and INDIRECT are not necessary here, you can simply use INDEX like this:
=INDEX($B$2:$B$10,COUNTA($B$2:$B$10))-INDEX($B$2:$B$10,COUNTA($B$2:$B$10)-1)
Note: OFFSET and INDIRECT are volatile functions, while INDEX is not. Volatile means that if anything changes anywhere in your workbook, than its value has to be recalculated. In case of non-volatile function, however, recalculation is initiated only if its parameters (in this case $B$2:$B$10) change. So, in general my solution is more efficient than the other two posted before.
Well, this works, quick and dirty...
=OFFSET(B1,LOOKUP(2,1/(B:B<>""),ROW(B:B))-1,,)-OFFSET(B1,LOOKUP(2,1/(B:B<>""),ROW(B:B))-2,,)
If you want the result in the same column, then you will have to control the range B:B...
Suppose I have the following data in a spreadsheet, where the first row contains the column headings and the first column contains the row index (for reference):
||A | B | C |
==||================
0 ||2 | 3 | Y |
--||----------------
1 ||2 | 4 | Y |
--||----------------
2 ||3 | 5 | N |
--||----------------
3 ||8 | 3 | Y |
--||----------------
How can I get the sum of all the values in column B for which b - a >= 1 && c == "Y", in Google Sheets and Excel?
So essentially, the sum should factor in only rows 0 and 1 in which case the result should be 7.
I know this sounds like a very specific question but I did not know how else to describe it other than by example. The answer should be applicable in other similar scenarios.
Thanks for the help.
[Edit] In response to people voting down due to lack of research, well, I've tried to use the sumif() function but I got stuck immediately on the condition part as I am not sure how to compare the current item in the aggregation with another cell. I also tried to use the sumifs() function which allows for multiple criteria, but also to no avail. As for my research, I searched on Google but could not find anything, possibly due to my inability to express the requirement in a manner suitable for a google query. Therefore, I have presented the above as a way of explaining my requirement by example.
I hope this helps.
I appreciate that this may not be possible to do with the simple built in formulas. If this is the case, please mention it as that would also be useful to know.
Thank you.
Excel: =SUMPRODUCT(((B:B-A:A)>=1)*(C:C="Y")*(B:B))
Untested, but let me know if it works. Next time, remember to add an example of code/formulas that you have already tried and what error you ran into.
Edit:
Tested it, here is a screenshot of it working with your example data (disregard the fact that my Excel is in spanish)
This works by intersecting both logical tests (that is, performing a logical AND): (B-A)>=1 AND C="Y". Here you can see the result of each logical test and then, finally, where it evaluates to TRUE it returns the value in column B; where it's FALSE, it returns 0. Finally, it sums the values in the result array.
Say I have two tables. attrsTable:
file | attribute | value
------------------------
A | xdim | 5
A | ydim | 6
B | xdim | 7
B | ydim | 3
B | zdim | 2
C | xdim | 1
C | ydim | 7
sizeTable:
file | size
-----------
A | 17
B | 23
C | 34
I have these tables related via the 'file' field. I want a PowerPivot measure within attrsTable, whose calculation uses size. For example, let's say I want xdim+ydim/size for each of A, B, C. The calculations would be:
A: (5+6)/17
B: (7+3)/23
C: (1+7)/34
I want the measure to be generic enough so I can use slicers later on to slice by file or attribute. How do I accomplish this?
I tried:
dimPerSize := CALCULATE([value]/SUM(sizeTable[size])) # Calculates 0
dimPerSize := CALCULATE([value]/SUM(RELATED(sizeTable[size]))) # Produces an error
Any idea what I'm doing wrong? I'm probably missing some fundamental concepts here of how to use DAX with relationships.
Hi Redstreet,
taking a step back from your solution and the one proposed by Jacob, I think it might be useful to create another table that would aggregate all the calculations (especially given you probably have more than 2 tables with file-specific attributes).
So I have created one more table that contains (only) unique file names, and thus the relationships could be visualized this way:
It's much simpler to add necessary measures (no need for calculated columns). I have actually tested 2 scenarios:
1) create simple SUM measures for both Attribute Value and File Size. Then divide those two measures and job done :-).
2) use SUMX functions to have a bit more universal solution. Then the final formula for DimPerSize calculation could look like this:
=DIVIDE(
SUMX(DISTINCT(fileTable[file]),[Sum of AttrValue]),
SUMX(DISTINCT(fileTable[file]),[Sum of FileSize]),
BLANK()
)
With [Sum of AttrValue] being:
=SUM(attrsTable[value])
And Sum of FileSize being:
=SUM(sizeTable[size])
This worked perfectly fine, even though SUMX in both cases goes over all instances of given file name. So for file B it also calculates with zdim (if there is a need to filter this out, then use simple calculate / filter combination). In case of file size, I am using SUMX as well, even though it's not really needed since the table contains only 1 record for each file name. If there would be 2 instances, then use SUMX or AVERAGEX depending on the desired outcome.
This is the link to my source file in Excel (2010).
Hope this helps.
You look to have the concept of relationships OK but you aren't on the right track in terms of CALCULATE() either in terms of the structure or the fact that you can't simply use 'naked' numerical columns, they need to be packaged in some way.
Your desired approach is correct in that once you get a simple version of the thing running, you will be able to slice and dice it over any of your related dimensions.
Best practice is probably to build this up using several measures:
[xdim] = CALCULATE(SUM('attrstable'[value]), 'attrstable'[attribute] = "xdim")
[ydim] = CALCULATE(SUM('attrstable'[value]), 'attrstable'[attribute] = "ydim")
[dimPerSize] = ([xdim] + [ydim]) / VALUES('sizeTable'[size])
But depending on exactly how your pivot is set up, this is likely to also throw an error because it will try and use the whole 'size' column in your totals. There are two main strategies for dealing with this:
Use an 'iterative' formula such as SUX() or AVERAGEX() to iterate individually over the 'file' field and then adds up or averages for the total e.g.
[ItdimPerSize] = AVERAGEX(VALUES('sizeTable'[file]), [dimPerSize])
Depending on the maths you want to use, you might find that produce a useful average that you need to use SUMX but devide by the number of cases i.e. COUNTROWS('sizeTable'[file]).
You might decide that the totals are irrelevant and simply introduce an error handling element that will make them blank e.g.
[NtdimPerSize] = IF(HASONEVALUE('sizeTable'[file]),[dimPerSize],BLANK())
NB, all of this assumes that when you are creating your pivot that you are 'dragging in' the file field from the 'sizetable'.
Program: Excel 2010
I have a large selection of data which I filter for various reasons, I have been able to use the following to count my sales when filtered, however I want to be able add a 2nd criteria to the mix.
New: count by value B11 and C12
(B11) = Store Name
(C12) = Product Name
=SUMPRODUCT(--($C$38:$C$1000=(B11)),SUBTOTAL(3,OFFSET($C$38,ROW($C$38:$C$1000)-ROW($C$38),0)))
I have tried variations of the following however I keep getting errors:
=SUMPRODUCT(--($C$38:$C$1000=(B11),SUBTOTAL(3,OFFSET($C$38,ROW($C$38:$C$1000)-ROW($C$38),0)),(--($C$38:$C$1000=(C12),SUBTOTAL(3,OFFSET($C$38,ROW($C$38:$C$1000)-ROW($C$38),0)))
|Prod |Store
---------------
|ABC |CDA
|DEF |XYZ
|GHI |TUV
|ABC |XYZ
Prod = ABC; Store = CDA; Result = 1 (not 2)
Please help :-)
I'm not very familiar with SUBTOTAL, but this seems to work fine:
=SUMPRODUCT(--($C$38:$C$1000=(B11)),--($B$38:$B$1000=(C12)),SUBTOTAL(3,OFFSET($C$38,ROW($C$38:$C$1000)-ROW($C$38),0)))
I just added --($B$38:$B$50=(C12)) neat the beginning between the two expressions in the SUMPRODUCT
Another option to simplify formulas is to introduce a helper column which indicates whether the row is visible or not, e.g. in Z38 copied down
=SUBTOTAL(3,B38)
Now for your count with 2 criteria you can use COUNTIFS like this
=COUNTIFS(C:C,B11,B:B,C12,Z:Z,1)