Matrix Grid Control - genexus-sd

I am trying to implement a Matrix Grid Control in my project. Trying to follow the instructions:
http://wiki.genexus.com/commwiki/servlet/hwiki?HowTo%3A+Using+Matrix+Grid+Control+for+Smart+Devices
I have already created an XAxis (rows), YAxis (columns) and data SDTs, set the properties and fill the data, but no matter what, I always end up with a "Application needs to close" message (Android).
Maybe I'm not doing things right, do you know where I can find a project source to use as a reference?
Thanks

I found a way of solving the error.
Columns and Headers are still being filled by a SDT (loaded in Start Event).
Replaced the data SDT by a layout var (&valueVar) inside the Matrix Control, being loaded in Load Event.
Event Grid1.Load
&xfrom = 1
&xto = 1
&yfrom = 1
&yto = 1
&valueVar = 'Value 1'
LOAD
&xfrom = 2
&xto = 2
&yfrom = 2
&yto = 2
&valueVar = 'Value 2'
LOAD
Endevent

Related

[Google Data Studio]: Can't create histogram as bin dimension is interpreted as metric

I like to make a histogram of some data that is saved in a nested BigQuery table. In a simplified manner the table can be created in the following way:
CREATE TEMP TABLE Sessions (
id int,
hits
ARRAY<
STRUCT<
pagename STRING>>
);
INSERT INTO Sessions (id, hits)
VALUES
( 1,[STRUCT('A'),STRUCT('A'),STRUCT('A')]),
( 2,[STRUCT('A')]),
( 3,[STRUCT('A'),STRUCT('A')]),
( 4,[STRUCT('A'),STRUCT('A')]),
( 5,[]),
( 6,[STRUCT('A')]),
( 7,[]),
( 8,[STRUCT('A')]),
( 9,[STRUCT('A')]),
(10,[STRUCT('A'),STRUCT('A')]);
and it looks like
id
hits.pagename
1
A
A
A
2
A
3
A
A
and so on for the other ids. My goal is to obtain a histogram showing the distribution of A-occurences per id in data studio. The report for the MWE can be seen here: link
So far I created a calculated field called pageviews that evaluates the wanted occurences for each session via SUM(IF(hits.pagename="A",1,0)). Looking at a table showing id and pageviews I get the expected result:
table showing the number of occurences of page A for each id
However, the output of the calculated field is a metric, which might cause trouble for the following. In the next step I wanted to follow the procedure presented in this post. Therefore, I created another field bin to assign my sessions to bins according to the homepageviews as:
CASE
WHEN pageviews = 0 OR pageviews = 1 THEN "bin 1"
WHEN pageviews = 2 OR pageviews = 3 THEN "bin 2"
END
According to this bin-defintion I hope to obtain a histogram having 6 counts in bin 1 and 4 counts in bin 2. Well, in this particular example it will actually have 4 counts in bin one as ids 5 and 7 had "null" entries, but never mind. This won't happen in my real world table.
As you can see in the next image showing the same table as above, but now with a bin-column, this assignment works as well - each id is assigned the correct bin, but now the output field is a metric of type text. Therefore, the bar-chart won't let me use it (it needs it as dimension).
Assignment of each id to a bin
Somewhere I read the workaround to create a selfjoined blend, which outputs metrics as dimension. This works only by name: my field is now a dimension and i can use it as such for the bar-chart, but the bar chart won't load and shows a configuration error of the data source, which can be seen in this picture:
bar-chart of id-count over bin. In the configuration of the chart one can see that "bin" is now a dimension. The chart won't plot, however, as it shows a data configuration error (sorry for the German version of data studio).

Merging Two Files Together and Retaining All Columns

I think this surely must be a simple thing to achieve, but I have tried various appends and merges and can't seem to get it right.
I have two files, one titled 'Previous' and one titled 'Current'. Both show near identical data, like so :
ID Status Date_Changed
1 Closed 10/11/21
2 Open 10/01/21
3 Closed 10/03/21
4 Pending 10/15/21
I'd like to merge both files together, but retain all columns so that it is structured as below. This will allow me to show tables of what has changed etc.
ID Previous.Status Current.Status Previous.Date_Changed Current.Date_Changed
1 Closed Open 10/11/21 10/15/21
2 Open Closed 10/01/21 10/15/21
3 Closed Pending 10/03/21 10/14/21
I am aware this is probably due to my own naivety with PowerBI. I have tried combining the data by connecting to the folder, but that seems to create a new dataset with the data stacked on top (ie with duplicate ID values). I tried using merge queries as new and joiningby ID, but that didn't seem to give me the right output either?
You can start from the Current table and merge in the previous table joining on ID and then expand the columns. Rename and reorder columns as desired.
Here's an example you can paste into the Advanced Editor:
let
CurrentSource = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUfIvSM0DUoYG+oam+kYGRoZKsTrRSkZAIeec/OLUFEw5Y6BQQGpeSmZeOlTSBCFpglMyFgA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID = _t, Status = _t, Date_Changed = _t]),
Current = Table.TransformColumnTypes(CurrentSource,{{"ID", Int64.Type}, {"Status", type text}, {"Date_Changed", type date}}),
PreviousSource = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUXLOyS9OTQEyDA30DQ31jQyMDJVidaKVjIBC/gWpeRAZAyQZYzRdBsYIOROgUEBqXkpmXjrUSFOoZCwA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID = _t, Status = _t, Date_Changed = _t]),
Previous = Table.TransformColumnTypes(PreviousSource,{{"ID", Int64.Type}, {"Status", type text}, {"Date_Changed", type date}}),
#"Merged Queries" = Table.NestedJoin(Current, {"ID"}, Previous, {"ID"}, "Previous", JoinKind.LeftOuter),
#"Expanded Previous" = Table.ExpandTableColumn(#"Merged Queries", "Previous", {"Status", "Date_Changed"}, {"Previous.Status", "Previous.Date_Changed"}),
#"Renamed Columns" = Table.RenameColumns(#"Expanded Previous",{{"Status", "Current.Status"}, {"Date_Changed", "Current.Date_Changed"}}),
#"Reordered Columns" = Table.ReorderColumns(#"Renamed Columns",{"ID", "Previous.Status", "Current.Status", "Previous.Date_Changed", "Current.Date_Changed"})
in
#"Reordered Columns"
Note: I've defined Previous within the query above so that it's self-contained. Ordinarily, it would be a separate query.
You can try the following steps:
create a new column called "Source Name" in each table with a constant value mentioning if the data if from "Previous" or "Current"
Then append both the table in Power Query. This will still stack both the tables on top of each other.
But now you can use the "Source Name" column to differentiate them in the Matric Visual. You can add a Matrix visual with
"Source Name" in the Column Field
"Date" & "Status" in values field
"ID" in Rows field
This is ideal because you get all the data in a tabular format which will help you in further calculations if necessary
You can check out an example screenshot below:

Google Docs Invoice template with dynamically items row from Google Sheets

I really need your help with this.
I have created an invoice template in Google Docs with databases flowed from Google sheets.
The problem is:
In the template (Google Docs), I only put a specific items line (eg 3 lines).
When the data is changed, such as the number of items lines are changing, how it's automatically gone through Google Docs if there are more than 3 items lines
Many thanks for your help.
Below is my script to get data from G-sheets to G-Docs template.
function Invoice() {
let copyFile = DriveApp.getFileById('id URL').makeCopy(),
copyID = copyFile.getId(),
copyDoc = DocumentApp.openById(copyID),
copyBody = copyDoc.getBody()
let activeSheet = SpreadsheetApp.getActiveSheet(),
numOfCol = activeSheet.getLastColumn(),
activeRowIndex = activeSheet.getActiveRange().getRowIndex(),
activeRow = activeSheet.getRange(activeRowIndex, 1, 1, numOfCol).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numOfCol).getValues(),
columnIndex = 0
for (; columnIndex < headerRow[0].length; columnIndex++){
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%', activeRow[0][columnIndex])
}
copyDoc.saveAndClose()
Here is screenshot of the files.
Data in G-sheet with the additional item (Item 4)
G-Docs template with specific 3 rows for 3 items lines
When I have 4 items, I must manually amend the G-Docs template. Is there any way to get its automatically.
#Duc I don't think it's possible to pass the new header as placeholder in the GDoc, it sounds like an endless loop.
Unless you pass it as List_ITEM, but I am pretty sure you will lose formatting.

Is there a way to use arrayformula with match/index in google script? Or at least get it to autofill the entire column? Scripts are an option

I have the following formula: =ArrayFormula(INDEX(Items!F2:F,MATCH(C2,Items!E2:E,0)))
I would like to extend it such that the entire C column runs the same formula for values. Please help. If a script is necessary to achieve this, I'd like to explore that option too.
Use Apps Script!
Sheet functions (formulae) work great (especially if you are a master like player0), but I find it much easier to work within Apps Script for anything much more complicated than a simple INDEX MATCH. If you are willing to learn some JavaScript, I highly recommend learning some.
Custom Functions
You can write custom sheet functions in Apps Script that you can call with the traditional =FUNCTION() from a cell.
The way it works is that you write a function in Apps Script that returns a two dimensional array corresponding to the area that it needs to fill.
For example, if wanted a function to fill a 2 x 2 block with 1, you would need to make your function return:
[[1,1],[1,1]]
Or you can write it like this:
[
[1, 1],
[1, 1]
]
Implementing Index Match
There are many ways you can implement it, here is an example.
The example spreadsheet has 2 tabs, "Ledger" and "Items".
The goal of the function that follows is to get the costs of the items from the "Items" tab.
function ledgerIndexMatch(){
// Initializing the location of data
let ss = SpreadsheetApp.getActive();
let ledger = ss.getSheetByName("Ledger");
let source = ss.getSheetByName("Items");
let ledgerRange = ledger.getDataRange();
let sourceRange = source.getDataRange();
// Getting the values into a 2D array
let ledgerValues = ledgerRange.getValues();
let sourceValues = sourceRange.getValues();
// Discarding the first row (headers)
ledgerValues.shift();
sourceValues.shift();
// Initializing the output array
let output = [];
// This is where the INDEX MATCH happens
// For each row in ledger
ledgerValues.forEach(ledgerRow => {
// Get the second column (index 1)
let item = ledgerRow[1];
// Initialize the column
let value = [];
// For each row in the source
sourceValues.some(sourceRow => {
// Check if the item is there
if (item == sourceRow[0]) {
// if so, add to value
value.push(sourceRow[1]);
// stop looking for values
return true
// if not matched, keep looking
} else return false
})
// Add the found value (or blank if not found)
// to the output array.
output.push(value);
})
return output;
}
Which can be used like this:
Whats nice about Apps Script is that you can customize it to your heart's content. In this example, the function automatically detects the height of the respective tables, so you don't need to fiddle around with ranges.
You might want to extend this function with arguments so that its more flexible. Or you could just have a few versions of it for different operations, if you don't have too many. Or refactor it... its up to you.
References
Apps Script
Custom Functions
Tutorials
SpreadsheetApp
use:
=ARRAYFORMULA(IFNA(VLOOKUP(C2:C, Items!E2:F, 2, 0)))

Dc crossfilter hide particular selection

Working on a grails application, wherein I am using dc-crossfilter to plot 5 bar graphs which are interconnected to each other.
Now, I want to do a simple thing here : In my first bar graph, there are 14 bars ( x number of departments and 1 "All" graph)
So the problem here is that the presence of "All" in the graph really messes up every other department's number as they are way too low (All is summation of all x number of departments) So each department number is so low that it's not even visible clearly.
But, it is very important to load the data for "All", as all the remaining 4 bar charts are filtered for "All" only.
So, is there any way how I can hide "All" in my first bar graph even though data is loaded? Is this even feasible?
There has to be some simple workaround to do this.
All approaches/suggestions are most welcome.
UPDATE :
Code:
This is the part where I define the groups and dimensions
var devValue = facts.dimension(function (d) {return d.c;});
var devValueGroupSum = devValue.group().reduceSum(function(d) { return +d.g;});
var mvValue = facts.dimension(function(d,i) {return d.b;});
var mvValueGroupSum = mvValue.group().reduceSum(function(d) {return +d.g;});
Now, where and how exactly do I define a fake group and prefilter the data. But will "ALL" be included in the actual dataset ( and not visualization part) even after prefiltering the data.
Code for fake group as in documentation :
var group = {
all:function () {
var cumulate = 0;
var g = [];
_group.all().forEach(function(d,i) {
cumulate += d.value;
g.push({key:d.key,value:cumulate})
});
return g;
}
};
I am really not able to understand the documentation as in how to implement this, can you help me in implementing this?
You can use a "fake group" to prefilter the data. Whenever the chart fetches the data it will go through your fake group, which then fetches the data from the real group and changes it.
The technique is described in the FAQ.

Resources