I'm looking for some ideas of how to accomplish this as I am hitting a wall on it.
I have a table that displays data pulled from a MySQL db. The table goes in a sequence of a row of 13 cells with displayed data followed by a hidden row of one cell. The hidden row is toggled by clicking a link in cell index 1 of the previous row. Like so:
row 1 : click this cell to show row 2 : another cell : another cell : ad nauseum till we get to 13 :
row 2 which is hidden
row 3 : click this cell to show row 2 : another cell : another cell : ad nauseum till we get to 13 :
row 4 which is hidden
...
so using jquery I pulled all the rows, then set a test to determine if it was a displayed row or hidden row, if it was displayed then I put that row and the following one into an object and then placed that object into another object, like so:
//this function is for sorting the data in the table
$(".sort").click(function() {
//get what column we are sorting by
var sortBy = $(this).attr('sortBy');
//set the colnum to sort by
if (sortBy == "itemname") {
var sortCol = 1;
} else if (sortBy == "priority") {
var sortCol = 2;
} else if (sortBy == "livedate") {
var sortCol = 10;
} else if (sortBy == "status") {
var sortCol = 11;
} else if (sortBy == "designer") {
var sortCol = 12;
}
//get the table data
var tableData = getTableData("NO", "null", "YES", sortBy);
//get all the rows
var tableRowArray = $("#productTableBody tr");
//declare new table object
var tableObj = new Object;
var rowPackage = new Object;
//loop through tableRowArray and put rows into packages of two, the main row and the hidden row
for(var t=0; t<tableRowArray.length; t++) {
if($(tableRowArray[t]).children(":first").attr('class') == "colorCode") {
rowPackage[t] = $(tableRowArray[t]).children();
rowPackage[t+1] = $(tableRowArray[t+1]).children();
//dump rows into tableObj
tableObj[t] = rowPackage;
}
//clean out rowPackage
rowPackage = {};
}
var x=-2;
for(thisRow in tableObj) {
x = x+2;
var sortItem = $(tableObj[thisRow][x][sortCol]).html();
//ack! -->getting stumped here
}
});
I've also collected which column the user wants to sort by. I can then find the cell the user wants to sort by. I know I need to pull that info, put into an array and sort but I guess I am getting stumped on how to apply the sorted array back to my tableObj so I can rewrite the table body HTML...the reason I am getting stumped is that some of the data to be sorted will be identical, for example if sorting by designer the data could be this {"a", "b", "c", "c", "a", "a", ""a"}, which when sorted would be a, a, a, a, b, c, c, but since some are identical I can't go back and loop through the object and find the entry that matches the first item in my sorted array, 4 items will match it. So how do I determine which entry in the object matches up with the first a in the sorted list?
Thanks in advance.
That's a tough one, but I suppose there is hardly anything impossible in this life.
I would go like this (using Underscore library)
var packs = [];
// assuming you always have even number of tr's
$("#productTableBody tr:odd").each(function(i, tr){
packs.push( {main: tr, sub: tr.next()} );
// tr.next() will be :even, so it's not yet selected
// now detach rows from the table
// note the order - next() wont work otherwise
tr.next().remove();
tr.remove();
});
var sortedPacks = _(packs).sortBy(function(pack){
return $(pack.main).find('td:nth('+sortCol')').text();
});
// now in sortedPacks you have touples of rows sorted by "main" rows sortCol column
// and you would probably want to restore the table now
$.each(packs, function(i, pack){
$("#productTableBody").append(pack.main).append(pack.sub);
});
The code may not reflect your situation perfectly, but I suppose you should be able to get the main idea.
Not really to easy to get what you are asking for here, but this will at least enable you to get the data sorted.
Start by collecting your data into an array, eg data, each row can be represented by either an array or an object.
Now simply call
data.sort(function(a, b){
// select the two values from a and b depending on the column to sort by
a = a[colNr];
b = b[colNr];
return a == b ? 0 : a < b ? -1 : 1;
});
Now you can easily rebuild your table based on the sorted array.
If you during data-collection also added a reference to the row to the array/object, then you can now remove all rows from the table, loop over the data array, and add each node back to the table.
Related
I'm trying to accomplish somewhat of a database table editor that edits rows based on a Trans ID.
I've accomplished vlookups and return values with a vlookup similar script I have, but this time I need to return position and not value.
I need help on how to set this script flow up. I've drawn and wrote everything out on a picture, it was a lot easier to write out that way.
This is what I'm starting with and need some suggestions.
I want to return row position instead of value and repeat until hit first empty row as seen in example picture I attached.
function vlookup(sheet, column, index, value) {
var sheet = sheet
var lastRow= sheet.getLastRow();
var data=sheet.getRange(1,column,lastRow,column+index).getValues();
for(i=0;i<data.length;++i){
if (data[i][0]==value){
return data[i][index];
}
}
}
The row number is just the index of the array + 1 as arrays start at 0.
return i + 1;
Heres the script on how I accomplished the task.
function doit(){
var lastrow = gv.glr(gv.invhelper,"A") // global function getting last row of target/loop column
for (var i = 4; i < lastrow+1; i++){ //loop statement
// actions to repeat
var id = gv.invhelper.getRange("A"+i).getValue(); //get id from row
var duradj = gv.invhelper.getRange("D"+i).getValue(); //get billing adjustment from row
var dbidrow = gv.dblkup(id); // global function to lookup id and find row position in other ss
var invstat = gv.dbtimetest.getRange("G"+dbidrow).setValue('TRUE'); // set invoiced status
var billadjust = gv.dbtimetest.getRange("M"+dbidrow).setValue(duradj); // set billing adjustment
}
}
I'm trying to come up with a function that will split data stored in a cell into multiple rows based on a delimiter (in this case, "\n"). I found a really good solution here:
https://webapps.stackexchange.com/questions/60861/google-sheets-split-multi-line-cell-into-new-rows-duplicate-surrounding-row-e
However, this solution only allows you to split up ONE column into multiple rows; I need to split up multiple columns.
Here is an example of some data I have now:
Here is an example of what I would like the final product to look like:
I know I can get this result by using =TRANSPOSE(SPLIT(cell,CHAR(10))) and then copying down the other cells, but I have a lot of data so I'd really prefer to automate this like in the above link. Any help you can give me is appreciated. Thank you!
Restructure rows to accomodate multiple items in a single cell
function restructureRows() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet2');
const shsr=2;//data start row
const rg=sh.getDataRange();//this includes one header row
const dlm='\n';//cell delimiter
let vs=rg.getValues();//this includes header row
let hA=vs.shift();//this put the header row in hA
var ttl={};//converts array indices to column names
var a=0;//added row counter
hA.forEach(function(h,i){ttl[i]=h;});
//vs nolonger contains header row
for(var i=0;i<vs.length;i++) {
var robj={max:1,maxidx:''};
for(var j=0;j<vs[i].length;j++) {
var temp=vs[i][j].toString();
//if data contain line feed then that row will be expanded
if(vs[i][j].toString().indexOf(dlm)!=-1) {
let t=vs[i][j].toString().split(dlm);//split cell on dlm
robj[ttl[j]]=[];//row expansion object
t.forEach(function(e,k){
robj[ttl[j]].push(e);//push expanded cell data into obj property arrays
});
if(robj[ttl[j]].length>robj.max) {
robj.max=robj[ttl[j]].length;//keeping record of the max number of delimited terms
robj.maxidx=j;//never actually used this yet
}
}else{
robj[ttl[j]]=[];
robj[ttl[j]].push(vs[i][j]);//if no dlm the just same the one term
}
}
if(robj.max>1) {
for(var k=0;k<vs[i].length;k++) {
const l=robj[ttl[k]].length;
if(l>1 && l<robj.max) {
for(let m=l;m<robj.max;m++) {
robj[ttl[k]].push(undefined);//This section fills in the cells that had multiple dlms with undefined so that all columns have the same amount of terms in their array
}
}else if(l==1) {
for(let m=1;m<robj.max;m++) {
robj[ttl[k]].push(vs[i][k]);//this section fills in the cells that have no dlms with the same value for all rows
}
}
}
sh.insertRows(i+shsr+1+a, robj.max-1);//insert addtional row
var oA=[];
for(var r=0;r<robj.max;r++) {
oA[r]=[];
for(var k=0;k<vs[i].length;k++) {
oA[r].push(robj[ttl[k]][r]);//This section loads data into the ouput array in preparation for a single setvalues() to load all new rows at one time.
}
}
sh.getRange(i+shsr+a,1,oA.length,oA[0].length).setValues(oA);//load data
a+=robj.max-1;//increment added row counter
}
}
}
Animation:
I need some help determining how i can compare 4 columns of one row with 4 columns of another row.
To explain, I have two tables, which both have four columns: State, Area, City & Location.
PINPOINT table - this table has a unique combination of values
FEED table - this table has a recurring combination of values, as well as the KEY value from the PINPOINT Table.
What i want is a code that says
"If a row from column CL in the FEED sheet contains the Key Value from column K in the PINPOINT sheet,
...but columns CN to CQ that FEED sheet row doesn't have the same values as column A-D in the PINPOINT table...
update column CN to CQ the FEED sheet with the same combination of values as A-D in the PINPOINT table."
I pasted the latest code i have below, as well as the images. Admittedly, this code is a mess I just started learning code, so I'm happy to rewrite this if someone proposes a solution.
In any case, any insight into how i should write this will be quite helpful.
var Data = SpreadsheetApp.getActiveSpreadsheet(); // DATA spreadsheet
var PinpointDataSheet = Data.getSheetByName("The Pinpoints") // DATA "Pinpoint" sheet
var PinpointAllValues = PinpointDataSheet.getRange(2, 1, PinpointDataSheet.getLastRow()-1,PinpointDataSheet.getLastColumn()).getValues();
var FeedDataSheet = Data.getSheetByName("The Feed_Raw") // DATA "Feed" sheet
var FeedAllValues = FeedDataSheet.getRange(2, 1, FeedDataSheet.getLastRow()-1,FeedDataSheet.getLastColumn()).getValues();
var PinpointStateObj = {}; // Object for "Locale" values
var PinpointAreaObj = {}; // Object for "Locale" values
var PinpointCityObj = {}; // Object for "Locale" values
var PinpointSpotObj = {}; // Object for "Locale" values
for(var P = PinpointAllValues.length-1;P>=0;P--) // put Pinpoint values in array..
{
PinpointStateObj[PinpointAllValues[P][0]] = PinpointAllValues[P][10];
PinpointAreaObj[PinpointAllValues[P][1]] = PinpointAllValues[P][10];
PinpointCityObj[PinpointAllValues[P][2]] = PinpointAllValues[P][10];
PinpointSpotObj[PinpointAllValues[P][3]] = PinpointAllValues[P][10];
}
for(var F = FeedAllValues.length-1;F>=0;F--) // for each row in the "Feed" sheet...
{
var Feed_GeotagKey = FeedAllValues[F][90]; // Pinpoint Key values in Feed sheet
{
// If Pinpoint array dont match feed values
if ((PinpointStateObj[Feed_GeotagKey] != FeedAllValues[F][95]) || (PinpointAreaObj[Feed_GeotagKey] != FeedAllValues[F][96])
|| (PinpointCityObj[Feed_GeotagKey] != FeedAllValues[F][97]) || (PinpointSpotObj[Feed_GeotagKey] != FeedAllValues[F][97]))
{
FeedAllValues[F][95] = PinpointAllValues[P][0]; // ...Change FYI Category Name in FYI Topic Sheet
FeedAllValues[F][96] = PinpointAllValues[P][1];
FeedAllValues[F][97] = PinpointAllValues[P][2];
FeedAllValues[F][98] = PinpointAllValues[P][3];
}
}
}
Geotag Sheet - unique values "Dark column"
Feed Sheet - recurring values - "Highlighted column"
I'm attempting to transpose my script from gathering an array from a column to gathering an array from a row instead. Unfortunately, during the process, I've managed to garble it up pretty well. I can get the right column, but can't seem to get the right row.
if(activeCell.getColumn() == 2 && activeCell.getRow() > 1){
activeCell.offset(0, 1).clearContent().clearDataValidations();
var item = itemDVss.getRange(activeCell.getRow(),activeCell.getColumn(),itemss.getLastColumn()).getValues();
var itemIndex = item[0].indexOf(activeCell.getValue()) + 2;
if(itemIndex != 0){
var itemValidationRange = itemDVss.getRange(itemIndex,3,itemDVss.getLastColumn());
var itemValidationRule = SpreadsheetApp.newDataValidation().requireValueInRange(itemValidationRange).build();
activeCell.offset(0, 1).setDataValidation(itemValidationRule);
}
}
The script should locate the active cell in the "Estimate" sheet and return the corresponding values from the "Items" sheet (offset by +1 column). So when in cell Estimate!B11, the script should return the row array from Items!C11 to the last column.
Estimate Master Sheet
dynamicDropDowns.gs row 34
Nothing is "easy" when you're just beginning to learn it. At any rate, I got it working by changing
var itemValidationRange = itemDVss.getRange(itemIndex,3,itemDVss.getLastColumn());
to
var itemValidationRange = itemDVss.getRange(activeCell.getRow(),3,1,itemDVss.getLastColumn());
May not be the best method, but it works!
I want to get all the rows of JQGrid in a javascript variable in a certain order.
I was able to get the data of all rows by :
var rowData = $("#gridId").jqGrid("getRowData");
But I want the rows to appear in the same order as that I entered in the grid.
I am trying to create a table and get its column details through the grid. So I require the order of the columns to remain the same. Any suggestions?
You can explicitly push the jqgrid rowdata to an array and then convert that to json string.
To do that you may use a function like the one given below to iterate through the jqgrid rows:(From Oleg's answer)
var gridData= {};
var $grid = jQuery("#gridId"), rows = $grid[0].rows, cRows = rows.length,
iRow, rowId, row, cellsOfRow;
for (iRow = 0; iRow < cRows; iRow++) {
row = rows[iRow];
if ($(row).hasClass("jqgrow")) {
cellsOfRow = row.cells;
// row represent the row with cellsOfRow.length cells.
// So one can use for loop with iCol between 0 and cellsOfRow.length
// cellsOfRow[iCol] represent the cell with the index iCol
// and $(cellsOfRow[iCol]).text() - the text of the cell
}
}
Inside the loop you can push the celldata to an array.
gridData['column_index1'] = $(cellsOfRow[0]).text();
gridData['column_index2'] = $(cellsOfRow[1]).text();
.............................................
Finally convert gridData to json string using
var result = JSON.stringify(gridData) ;