i'm just struggling through the following situation -
there's a datasource added to a grid in axapta 2009, filtered by a querybuildrange.
i want to mark a specific dataset by x++ via
datasource_DS.findrecord( specificRecord )
this works as intended, removing the filter, but not having the filter active!
a workaround to remove the filter and add everything ( filtered! )to a temporary table first is not what i want.
i can't imagine there's no way to achieve this task?!
thanks in advance!
edit:
datasources on form:
- ProdRouteJob ( JoinSource: ProdTable, LinkType: InnerJoin )
- ProdTable
only datasets containing a specified ProdStatus should be displayed in the grid.
This is done by the mentioned Range, e.g.:
prodStatusRange = prodTable_ds.query().dataSourceTable( tablenum( ProdTable )).addRange( fieldnum( ProdTable, ProdStatus ));
prodStatusRange.value( "(( ProdStatus == 0) || ( ProdStatus == 1 ))" );
selecting a specified dataset is done by, e.g.:
ProdRouteJob currentProdRouteJob;
;
currentProdRouteJob = ProdRouteJob::findJobId( "JOB_12345" );
info ( currentProdRouteJob.JobId );
prodRouteJob_DS.findRecord( currentProdRouteJob );
the info-function shows the correct JobId.
if i remove the filter, findRecord() selects the dataset, if not - not.
adding the DS.research( true ); does not change this behaviour.
You objective is to redraw the grid and to retain any filtering.
In AX 2009 it is easy:
datasource_DS.research(true);
In AX 4.0 and previous you can research and then refind:
specificRecord = datasource.data();
datasource_DS.research();
datasource_DS.findRecord(specificRecord)
This can sometimes be slow if there are many records in the grid.
Related
This question is a slightly varied version of this one...
Now I'm using Measures instead of Calculated columns and the date is static instead of having it based on a dropdown list.
Here's the Power BI test .pbix file:
https://drive.google.com/open?id=1OG7keqhdvDUDYkFQFMHyxcpi9Zi6Pn3d
This printscreen describes what I'm trying to accomplish:
Basically the date in P6 Update table is used as a cut date and will be fixed\static. It's imported from an Excel sheet where the user can customize it however they want.
Here's what should happen when a matching row in Test data table is found for P6 Update date:
column Earned Daily - must have its value summed with the next row if there's one;
column Earned Cum - must grab the next row's value;
all the previous rows should remain intact, that is, their values won't change;
all subsequent rows must have their values assigned 0.
So for example:
If P6 Update is 1-May-2018, this is the expected result:
1-May 7,498 52,106
2-May 0 0
If P6 Update is 30-Apr-2018, this is the expected result:
30-Apr 13,173 50,699
1-May 0 0
2-May 0 0
If P6 Update is 29-Apr-2018, this is the expected result:
29-Apr 11,906 44,608
30-Apr 0 0
1-May 0 0
2-May 0 0
and so on...
Hope this makes sense.
This is easier in Excel, but trying to do this in Power BI is making me go nuts.
I will ignore previously asked related questions and start from scratch.
First, create a measure:
Current Earn =
CALCULATE (
SUM( 'Test data'[Value]),
'Test data'[Act Rem] = "Actual Units",
'Test data'[Type] = "Current"
)
This measure will be used in other measures, to save you from typing all these conditions ("Actual Units" and "Current") again and again. It's a great practice to re-use measures in other measures - saves work, makes code cleaner and easier to refactor.
Create another measure:
Cut Date = SELECTEDVALUE('P6 Update'[Date])
We will use this measure whenever we need a cut off date. Please note that it does not have to be hard-coded - if P6 table contains a list of dates, you can create a pull-down slicer from the dates, and can choose the cut-off date dynamically. The formula will work properly.
Create third measure:
Next Earn =
VAR Cut_Date = [Cut Date]
VAR Current_Date = MAX ( 'Test data'[Date] )
VAR Next_Date = Current_Date + 1
VAR Current_Earn = [Current Earn]
VAR Next_Earn = CALCULATE ( [Current Earn], 'Test data'[Date] = Next_Date )
RETURN
SWITCH (
TRUE,
Current_Date < Cut_Date, Current_Earn,
Current_Date = Cut_Date, Current_Earn + Next_Earn,
BLANK ()
)
I am not sure if "Next Earn" is a good name for it, hopefully you will find a more intuitive name. The way it works: we save all necessary inputs into variables, and then use SWITCH function to define the results. Hopefully it's self-explanatory. (Note: if you need 0 above Cut Date, replace BLANK() with 0).
Finally, we define a measure for cumulative earn. It does not require any special logic, because previous measure takes care of it properly:
Cum Earn =
VAR Current_Date = MAX('Test data'[Date])
RETURN
CALCULATE(
[Next Earn],
FILTER(ALL('Test data'[Date]), 'Test data'[Date] <= Current_Date))
Result:
I've got a form done in x++ (formBuild) and I managed to display different grids in different tabs. However, when I do a right-click record info on any of the grids other than the first one, the details are that of the first grid. Eg. The second row of grid 2 when I do a record info is actually the second row of grid 1.
One thing is all the grids are actually using the same table, just having different query ranges for each.
Any way to fix this?
Added code snippets
Making the grid:
for (counter = 0; counter < locations.lastIndex(); counter++)
{
formBuildDatasource = form.addDataSource(tableStr(SomeTable));
formBuildTabPageControl = formBuildTabControl.addControl(FormControlType::TabPage, locations.value(counter+1));
formBuildTabPageControl.caption(locations.value(counter+1));
formBuildGridControl = formBuildTabPageControl.addControl(FormControlType::Grid, locations.value(counter+1));
formBuildGridControl.allowEdit(0);
formBuildGridControl.dataSource(formBuildDatasource);
formBuildGridControl.height(500,-1);
formBuildGridControl.width(550,-1);
formBuildGridControl.addDataField(formBuildDatasource.id(), fieldNum(SomeTable, MachineId));
formBuildGridControl.addDataField(formBuildDatasource.id(), fieldNum(SomeTable, MachineStatus));
}
Adding the query:
for (counter = 0; counter < locations.lastIndex(); counter++)
{
fds = formRun.dataSource(counter+1);
qbds = fds.query().dataSourceNo(1);
qbr = Qbds.addRange(fieldnum(SomeTable, MachineLocation));
qbr.value(locations.value(counter+1));
}
This answer to your prior question applies here as well:
Adding view/temporary table records to Form Grid
You will have to use more than one datasource (using the same table). Remember to change the datasource attribute of the grids to match the correct one. My guess would be that they currently all reference the same datasource.
Can you make a query + view of the table, and have that as the 'child' entity?
I don't know why you can't have the same table referenced twice in the same form data sources, however. Ensure that the link between the tables are defined correctly, and you have no confusion with the datasource names that you use for them.
You actually need to set the datasource on the grid object using the id() method on the FormDataSource object, not just the full object.
Change from:
formBuildGridControl.dataSource(formBuildDatasource);
to:
formBuildGridControl.dataSource(formBuildDatasource.id());
How do I sum different fields? I want to sum all of the information for material(1) ...so I want to add 5+4+6+300 but I am unsure how. Like is there another way besides just doing material(1).May + material(1).June etc....
material(1).May= 5;
material(1).June=4;
material(1).July=6;
material(1).price=300;
material(2).May=10;
material(2).price=550;
material(3).May=90;
You can use structfun for this:
result = sum( structfun(#(x)x, material(1)) );
The inner portion (structfun(#(x)x, material(1))) runs a function each individual field in the structure, and returns the results in an array. By using the identity function (#(x)x) we just get the values. sum of course does the obvious thing.
A slightly longer way to do this is to access each field in a loop. For example:
fNames = fieldnames(material(1));
accumulatedValue = 0;
for ix = 1:length(fNames)
accumulatedValue = accumulatedValue + material(1).(fNames{ix});
end
result = accumulatedValue
For some users this will be easier to read, although for expert users the first will be easier to read. The result and (approximate) performance are the same.
I think Pursuit's answer is very good, but here is an alternative off the top of my head:
sum( cell2mat( struct2cell( material(1) )));
I have a spreadsheet with three sheets. Two are called 2012 and 2011 and have a bunch of similar data. The last sheet does comparisons between the data.
To be able to choose year, I'm using a cell (D1) where I can I can write either 2011 or 2012. The formulas then use the INDIRECT function to include this cell as part of the reference.
INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!F:F")
This is not a pretty solution and makes the formula quite long and complex.
=IFERROR(SUM(FILTER( INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!M:M") ; (INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!B:B")=$A4)+(INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!B:B")=$A5)+(INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!B:B")=$A6)+(INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!B:B")=$A7)+(INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!B:B")=$A8); MONTH(INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!D:D"))=$B$1 ; INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!F:F")=D$3));0)
Is there a better way of doing this?
I've tried to create a separate spreadsheet for the calculations sheet and importing (IMPORTRANGE) the data from the two sheets together on one sheet with VMERGE (custom function from the script gallery) but there is quite a lot of of data in these two sheets and the import takes a long time. Any changes (like changing year) also take a long time to recalculate.
Database functions tend to be cleaner when doing this kind of thing.
https://support.google.com/docs/bin/static.py?hl=en&topic=25273&page=table.cs&tab=1368827
Database functions take a while to learn, but they are powerful.
Or
You could put INDIRECT(CHAR(39)&$D$1&CHAR(39)&"!B:B") in a cell on its own.
I think that you have two years of information where the schema is identical (column C has the same type of information on both sheets). Also, I'm assuming that column B tracks the year.
If so, consider holding all of your information on one sheet and and use the spreadsheet function "QUERY" to create views.
For instance, this formula returns all the cells between A1:E from a sheet named "DataSheet" where the values in column B = 2010.
=QUERY(DataSheet!A1:E; "SELECT * WHERE B = 2010";1)
Sometimes there is a really good reason to have the data stored on two sheets. If so, use one of the vMerge functions in the script gallery to assemble a working sheet. Then create views and reports from the working sheet.
function VMerge() {
var maxw=l=0;
var minw=Number.MAX_VALUE;
var al=arguments.length ;
for( i=0 ; i<al ; i++){
if( arguments[i].constructor == Array )l =arguments[i][0].length ;
else if (arguments[i].length!=0) l = 1 ; // literal values count as array with a width of one cell, empty cells are ignored!
maxw=l>maxw?l:maxw;
minw=l<minw?l:minw;
}
if( maxw==minw) { /* when largest width equals smallest width all are equal */
var s = new Array();
for( i=0 ; i<al ; i++){
if( arguments[i].constructor == Array ) s = s.concat( arguments[i].slice() )
else if (arguments[i].length!=0) s = s.concat( [[arguments[i]]] )
}
if ( s.length == 0 ) return null ; else return s //s
}
else return "#N/A: All data ranges must be of equal width!"
}
Hope this helps.
I have a schema of Row Keys 1-n. In each row there are a variable number of supercolumns with a TimeUUID 'name'. Im hoping to be able to query this data by a time range.
Two issues have come up:
in KeyRange -> the values that I put in for 'start_key' and 'end_key' are getting misunderstood (for lack of a better term) by Thrift. Experimenting with different groups of values Im not seeing what I expect and often get back something completely unexpected.
Example: my row keys are running from 1-1000 with lots of random gaps. I put start_key = 50 and end_key = 20 .. and I get back rows with keys ranging from 99 to 414.
Example: I have a known row with key = 13. Putting this value into start_key and end_key gives me no results.
Second issue: even when I do get results the 'columns' portion of the 'keyslice' is always empty. I have checked via cassandra-cli and I know there is data.
Im using Perl as follows:
my $slice_range = new Cassandra::SliceRange();
$slice_range->{ start } = create_UUID( UUID::Tiny::UUID_TIME, "2010-12-24 00:00:00" );
$slice_range->{ finish } = create_UUID( UUID::Tiny::UUID_TIME, "2011-12-25 00:00:00" );
my $slice_predicate = new Cassandra::SlicePredicate();
$slice_predicate->{ slice_range } = $slice_range;
my $key_range = new Cassandra::KeyRange();
$key_range->{ start_key } = 13;
$key_range->{ end_key } = 13;
my $result = $client->get_range_slices( $column_parent, $slice_predicate, $key_range, $consistency_level );
print Dumper( $result );
Clearly Im misunderstanding some basic precept.
EDIT: It turns out that the Perl library Im using is not properly documented. The UUID creation was not working as advertised. I opened it up, fixed it, and now its all going a bit more as I was expecting. I can slice my supercolumns by date/time range. Still working on getting the key range portion to work.
http://wiki.apache.org/cassandra/FAQ#range_rp covers why you're not seeing what you expect with key ranges.
You need to specify a SlicePredicate that contains the actual range of what you're trying to select. The default of no column_names and no slice_range will result in the empty columns list that you see.