Multiple tabbed grids but record info only referencing to the grid in the first tab - forms

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());

Related

Remove formula from column with python

I am trying to remove the formula from a column in a existing sheet with python.
I tryed to set my formula to None using the column object (column.formula = None)
It does not work and my column object remains unchanged. Anyone have inputs to solve this issue ? Thank you !
This took me a bit to figure out, but seems like I've found a solution. Turns out that this is a 2-step process:
Update the column object to remove the formula (by setting column.formula to an empty string).
For each row in the sheet, update the cell within that column to remove the formula (set cell.value to an empty string and cell.formula to None).
Completing the STEP 1 will remove the formula from the column object -- but that cell in each row will still contain the formula. That's why STEP 2 is needed -- STEP 2 will remove the formula from the individual cell in each row.
Here's some example code in Python that does what I've described. (Be sure to update the id values to correspond to your sheet.)
STEP 1: Remove formula from the Column
column_spec = smartsheet.models.Column({
'formula': ''
})
# Update column
sheetId = 3932034054809476
columnId = 4793116511233924
result = smartsheet_client.Sheets.update_column(sheetId, columnId, column_spec)
STEP 2: Remove the formula from that cell in each row
Note: This sample code updates only one specific row -- in your case, you'll need to update every row in the sheet. Just build a row object for each row in the sheet (like shown below), then call smartsheet_client.Sheets.update_rows once, passing in the array of row objects that you've built corresponding to all rows in the sheet. By doing things this way, you're only calling the API once, which is the most efficient way of doing things.
# Build new cell value
new_cell = smartsheet.models.Cell()
new_cell.column_id = 4793116511233924
new_cell.value = ''
new_cell.formula = None
# Build the row to update
row_to_update = smartsheet.models.Row()
row_to_update.id = 5225480965908356
row_to_update.cells.append(new_cell)
# Update row
sheetId = 3932034054809476
result = smartsheet_client.Sheets.update_rows(sheetId, [row_to_update])

how to get a parentNode's index i using d3.js

Using d3.js, were I after (say) some value x of a parent node, I'd use:
d3.select(this.parentNode).datum().x
What I'd like, though, is the data (ie datum's) index. Suggestions?
Thanks!
The index of an element is only well-defined within a collection. When you're selecting just a single element, there's no collection and the notion of an index is not really defined. You could, for example, create a number of g elements and then apply different operations to different (overlapping) subsets. Any individual g element would have several indices, depending on the subset you consider.
In order to do what you're trying to achieve, you would have to keep a reference to the specific selection that you want to use. Having this and something that identifies the element, you can then do something like this.
var value = d3.select(this.parentNode).datum().x;
var index = -1;
selection.each(function(d, i) { if(d.x == value) index = i; });
This relies on having an attribute that uniquely identifies the element.
If you have only one selection, you could simply save the index as another data attribute and access it later.
var gs = d3.selectAll("g").data(data).append("g")
.each(function(d, i) { d.index = i; });
var something = gs.append(...);
something.each(function() {
d3.select(this.parentNode).datum().index;
});

Using cell value as reference to sheet in formulas

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.

How to quickly add many columns to GWT DataGrid

I am currently trying to create a DataGrid that can take an entity with a list of values as a row. Each value in the list is in its own column in the DataGrid. The entities' lists of values may have different sizes, so the DataGrid will have a variable number of columns. I have noticed that when I try to create the DataGrid and loop over the process of adding each of the column to the DataGrid, the time it takes to add the columns does not grow linearly.
Here is the code I was using to test the quickness of adding the columns
DataGrid<String> table = new DataGrid<String>();
table.setPageSize(25);
int NUM_COLUMNS = 40;
for (int i = 0; i < NUM_COLUMNS; i++) {
GWT.log("Adding column "+i);
TextColumn<String> nameColumn = new TextColumn<String>() {
public String getValue(String object) {
return object;
}
};
table.addColumn(nameColumn, "Column " + i);
table.setColumnWidth(nameColumn, 100, Unit.PX);
}
ArrayList<String> data = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
data.add("row "+i);
}
table.setRowCount(data.size(), true);
table.setRowData(0, data);
table.setWidth("100");
This took about 48 seconds, give or take 1 second, every time I ran it. It seems that loading less than 10 columns were fairly quickly, but as the number of columns grew, the time it took to load it grew exponentially.
Is there another way to add columns to the DataGrid that would be quicker? Thanks in advance.
One question you might want to ask yourself is if there's a better way to do it. A table with 40 columns (IMO) seems inefficient. In general, you're going to have significant performance loss when loading more than ~15 columns in a DataGrid, and FlexTable isn't any better.
I've worked with DataGrid quite a bit and haven't seen any of the behavior you're talking about, though in my case they typically only have 10 or fewer columns with several thousand rows. (Data is of course paged and not being jammed in all at once.)
One thing I've noticed does speed it up is pre-rendering. Are you adding the table to the DOM prior to adding all these columns, or are you adding them all first? Lots of time can be spent waiting for the DOM to update. If you're adding it to the page after rendering everything, you're probably looking at the best speed you'll get, since there's no built-in function for adding multiple columns simultaneously.

How can I reverse the row order for an ADO.NET DataTable?

I have a DataTable that I have obtained by deserializing a JSON message. I do not know ahead of time what the column names will be so I cannot use DataView.Sort on a specific column. I would simply like to reverse the order of the rows. Here is what I tried:
var reversedTable = new DataTable();
for (var row = originalTable.Rows.Count - 1; row >= 0; row--)
reversedTable.Rows.Add(response.Messages.Rows[row]);
but this throws "System.ArgumentException: This row already belongs to another table." How can I accomplish this seemingly simple task? Thanks in advance,
Frank
ANSWER:
var reversed = original.Clone();
for (var row = original.Rows.Count - 1; row >= 0; row--)
reversed.ImportRow(original.Rows[row]);
I've seen that error message before.....
You're not allowed to directly add a row from one table to another. First you have to clone the table, then you can go through and call ImportRow() for each of the rows.
Check out geekzilla for a decent example.
I hope that helps!