Subtotals with ArrayFormula() - arrays

I've created a simple table and trying to split data with subtotals.
A indicates the subtotal lines.
B contains the rows number for previous subtotal. This is just extra field to simplify formulas.
C Contains some amounts.
D Contains subtotals of amounts between previous and current subtotal line.
The subtotal formula has the following view:
=ArrayFormula(
IF($A2:$A; MMULT(
($B2:$B < TRANSPOSE(ROW($A2:$A))) * (TRANSPOSE(ROW($A2:$A)) < ROW($A2:$A));
IF(ISNUMBER(C2:C); C2:C; 0)
); )
)
The problem is that the formula is extrimely slow. Is there a way to make it faster?
Example file:
https://docs.google.com/spreadsheets/d/1HPGeLZfar2s6pIQMVdQ8mIPzNdw2ESqKAwZfo4IicnA/edit?usp=sharing

You could also try this much simpler formula:
=ArrayFormula(
if(B3:B="","",
sumif(row(B3:B),"<="&row(B3:B),C3:C)-
sumif(row(B3:B),"<="&B3:B,C3:C)
)
)

Yes there is
The easier is to remove the blank rows below the data range.
One that might require maintenance, replace open reference like $A2:$A by closed references, i.e. $A2:$A100
One that incresase the formula complexity an volatility, put each open reference inside ARRAY_CONSTRAIN but it's easier to maintain in case that new data rows were added

use the "necessary" range:
=ARRAYFORMULA(IFERROR(IF(A2:A; MMULT((
INDIRECT("B2:B"&MAX(IF(B2:B="";; ROW(B2:B)))) < TRANSPOSE(ROW(
INDIRECT("A2:A"&MAX(IF(A2:A=TRUE; ROW(A2:A); )))))) * (TRANSPOSE(ROW(
INDIRECT("A2:A"&MAX(IF(A2:A=TRUE; ROW(A2:A); ))))) < ROW(
INDIRECT("A2:A"&MAX(IF(A2:A=TRUE; ROW(A2:A); ))))); IF(ISNUMBER(
INDIRECT("C2:C"&MAX(IF(C2:C="";; ROW(C2:C)+1))));
INDIRECT("C2:C"&MAX(IF(C2:C="";; ROW(C2:C)+1))); 0)); )))
this should be way faster...

Related

What is wrong with this expressions? =CountRows(ReportItems!Textbox58.Value = "Intervene"). I want to count each row which says Intervene

What is wrong with this expression? =CountRows(ReportItems!Textbox58.Value = "Intervene")
I want to count each row which says Intervene.
As Larnu has commented, you cannot use CountRows against the ReportItems collection.
Probably what you need to do is
Look at the expression in Textbox58 and see where it gets it's data from. In this exmaple let's say it comes from Fields!myFieldName.Value.
Now we need to count the rows where Fields!myFieldName.Value = "Intervene" but rather than using count, we can convert these matches to return 1 or 0 where the field is not "Intervene"
So the expression would look something like this
=SUM(IIF(Fields!myFieldName.Value = "Intervene", 1, 0))
This will sum the rows withing the current scope, so if this is contained in a row group for example, then it will only sum those rows in that row group.
If you need to count based on a a different scope (e.g. the entire dataset) then you can specify that in the SUM() function like this
=SUM(IIF(Fields!myFieldName.Value = "Intervene", 1, 0), "DataSet1")
Here we are summing across the entire dataset where the dataset name is DataSet1
Update based on OP comment
As your expression is
=SUM(IIF(Fields!Actual_Duration.Value >= 10, "Intervene", "No Intervention Needed"))
What we actually need to count is instances where Actual_Duration is >= 10.
So the final expression should be
=SUM(IIF(Fields!Actual_Duration.Value >= 10, 1, 0))

google sheet : How to vlookup by matching value in between max and min?

I have 2 sheets like this :
In that 2nd sheet, i want to lookup the id (S/M/L/XL) by checking if value is in between the Min value and Max value. So the goal is to have something like that 2nd sheet where in 'level' column, i need to put a formula so it will check the value is between what range so then it will retrieve the correct 'id' from 1st sheet.
the rule is if the value is >= minvalue and < max value
How can i do this ?
Thanks
use:
=INDEX(IF(A9:A="",,VLOOKUP(A9:A, {C2:C5, A2:A5}, 2, 1)))
Your first table, has overlapping values, so I suggest you think better about the rules you want to apply.
For example, 1, according your table can match both "S" and "M" , same for 3, which can be "M" or "L".
Once you have resolved that, you can use the QUERY function.
Example:
=QUERY($A$2:$D$5,
"select A,D where C<="&A2&" AND D >="&A2&" ORDER BY D DESC LIMIT 1 ")
Working solution can be found here:
https://docs.google.com/spreadsheets/d/1oLVwQqihT_df2y_ZQnfx7By77HnKSFz0bcbOzMuWqOM/edit?usp=sharing
Rather than have min and max columns, you could just use one column to list incremental values that determine the next size, and use vlookup() with a sort option of true - this avoids overlapping values:
=arrayformula({"level";if(A2:A<>"",VLOOKUP(A2:A,{Source!C:C,Source!A:A},2,1),)})

MATLAB Extract all rows between two variables with a threshold

I have a cell array called BodyData in MATLAB that has around 139 columns and 3500 odd rows of skeletal tracking data.
I need to extract all rows between two string values (these are timestamps when an event happened) that I have
e.g.
BodyData{}=
Column 1 2 3
'10:15:15.332' 'BASE05' ...
...
'10:17:33:230' 'BASE05' ...
The two timestamps should match a value in the array but might also be within a few ms of those in the array e.g.
TimeStamp1 = '10:15:15.560'
TimeStamp2 = '10:17:33.233'
I have several questions!
How can I return an array for all the data between the two string values plus or minus a small threshold of say .100ms?
Also can I also add another condition to say that all str values in column2 must also be the same, otherwise ignore? For example, only return the timestamps between A and B only if 'BASE02'
Many thanks,
The best approach to the first part of your problem is probably to change from strings to numeric date values. In Matlab this can be done quite painlessly with datenum.
For the second part you can just use logical indexing... this is were you put a condition (i.e. that second columns is BASE02) within the indexing expression.
A self-contained example:
% some example data:
BodyData = {'10:15:15.332', 'BASE05', 'foo';...
'10:15:16.332', 'BASE02', 'bar';...
'10:15:17.332', 'BASE05', 'foo';...
'10:15:18.332', 'BASE02', 'foo';...
'10:15:19.332', 'BASE05', 'bar'};
% create column vector of numeric times, and define start/end times
dateValues = datenum(BodyData(:, 1), 'HH:MM:SS.FFF');
startTime = datenum('10:15:16.100', 'HH:MM:SS.FFF');
endTime = datenum('10:15:18.500', 'HH:MM:SS.FFF');
% select data in range, and where second column is 'BASE02'
BodyData(dateValues > startTime & dateValues < endTime & strcmp(BodyData(:, 2), 'BASE02'), :)
Returns:
ans =
'10:15:16.332' 'BASE02' 'bar'
'10:15:18.332' 'BASE02' 'foo'
References: datenum manual page, matlab help page on logical indexing.

MDX Group & Count

I'm having the below MDX Query
WITH
MEMBER Measures.Improvement AS
[Measures].[School Evaluation]
-
(
[Measures].[School Evaluation]
,[Cycle].[Name].CurrentMember.PREVMEMBER
)
MEMBER Measures.PreviousEvaluation AS
(
[Measures].[School Evaluation]
,[Cycle].[Name].CurrentMember.PREVMEMBER
)
SELECT
Measures.Improvement ON COLUMNS,
Filter (
{ [Cycle].[Name].[Name].ALLMEMBERS }
* { [School].[Name En].[Name En].ALLMEMBERS }
, Measures.PreviousEvaluation > 0
AND
[Measures].[School Evaluation] > 0
)
ON ROWS
FROM [SchoolCube];
This code generates the below output
Now what I need is to count the occurrence of Improvement "-2,-1,0,..." across all the schools So I have something like this
How Can I achieve this?
Thanks,
You have to add another dimension "Improvement" that holds possible values for either a fixed range, e.g. -10..+10 or you build the range dynamically based on your data.
Add a second measure group to the cube based on that dimension table and create a measure "Improvement base", that sums the improvement value. This is a helper measure to simplify the following steps.
Now you can create a new calculated measure:
CREATE MEMBER CURRENTCUBE.[Measures].[Count Improvements] AS
SUM(IIF([Measures].[Improvement] = [Measures].[Improvement base], 1, 0));
Maybe you have to scope the All-member of the Improvement dimension to sum the children.

Sum of cost amount calculation

I have attached the screenshot. Most probably that the image itself will explain my logic. Let me paste the code I have used in the fields. Product Info1 field which hold Y & N.
RemainingCosu2=If(Invoice Line Items::Product Info1 = GetAsText ("N"); Sum(Cost Total) - Invoice Line Items::VendPaid_total;0)
RemainingCosu1=If(Vendor Status="Partly Paid"; RemainingCosu2; 0)
What should I do to fix this issue?. Please check the screenshot:
Filemaker has no SumIf() function. You need to create a calculation field in the LineItems table, along the lines of:
If ( Paid = "N" ; Cost )
then sum this field at the invoice level (and/or summarize it at the LineItems table itself), instead of the Cost field.
--
BTW, it is much more convenient to define Boolean (yes/no) fields as Number and use the values of 1 for True, 0 (or empty) for False. Then the calculation can be simply:
If ( not Paid ; Cost )

Resources