Find Index of Column(s) after it has been Moved - javascript

We are using DHTMLX Grid. Need some help, please.
I have a table and each columns (has filter/dropdown) are allocated an id eg. fac, date, sel, loc, tag ... etc
We have hard coded the index of columns to set and get the cookie elsewhere.
function doInitGrid(){
mygrid.setColumnIds("fac,date,sel,loc,tag"); //set ids
mygrid.attachEvent("onFilterStart",function(ind,data)
{
setCookie("Tray_fac_filter",mygrid.getFilterElement(0).value,365); //column index 0
setCookie("Tray_loc_filter",mygrid.getFilterElement(3).value,365);//column index 3
setCookie("Tray_tag_filter",mygrid.getFilterElement(4).value,365); //column index 4
mygrid.getFilterElement(0).value = getCookie("Tray_fac_filter")
mygrid.getFilterElement(3).value = getCookie("Tray_dep_filter")
mygrid.getFilterElement(4).value = getCookie("Tray_prg_filter")
});
}
But when the columns are moved, the problem arises as the index of the column changes yet it is set in setCookie /getCoookie
DHTMLX allows to get the index of the id using --
var colInd = grid.getColIndexById(id);
eg: var colInd = grid.getColIndexById(date); // outputs 1.
After moving the date column to the end -- fac, sel, loc, tag, date // it will output 4.
However, we have about 14 columns that can be moved/rearranged and I could use the
var colInd = grid.getColIndexById(id); 15 times
var facInd = grid.getColIndexById("fac");
var dateInd = grid.getColIndexById("date");
var selInd = grid.getColIndexById("sel");
var locInd = grid.getColIndexById("loc";
var tagInd = grid.getColIndexById("tag");
and put those variables in the set/get cookie. I was thinking if there was a better way.
To understand the code better, I have put the minimised version of the code in fiddle.
http://jsfiddle.net/19eggs/s5myW/2/

You've got the best answer I think. Do it in a loop and it's easier:
var cookie_prefix = "Fray_filter_";
var cookie_dur = 365;
var num_cols = dhx_grid.getColumnCount();
// filter vals to cookies
for (var col_idx=0; col_idx<num_cols; col_idx++) {
var filter = mygrid.getFilterElement(col_idx)
if (filter) { // not all columns may have a filter
var col_id = dhx_grid.getColumnId(col_idx);
var cookie_name = cookie_prefix+col_id;
setCookie(cookie_name, filter.value, cookie_dur);
}
}
// cookies to filter vals
for (var col_idx=0; col_idx<num_cols; col_idx++) {
var col_id = dhx_grid.getColumnId(col_idx);
var filter_val = getCookie(cookie_prefix+col_id);
var filter = mygrid.getFilterElement(col_idx)
filter.value = filter_val;
}

You can use dhtmlxgrid native event to assign the correct id everytime a column is moved.
The event is called onAfterCMove, you can check the documentation here. onAfterCMove Event
You would do something like:
mygrid.attachEvent('onAfterCMove',function(cInd,posInd){
//Your processing here to change the cookies; where cInd is the index of the column moved
//and posInd, is the position where it Was moved
}):

Related

How to create a for loop to loop through JSON.stringified values determining "paste tabs" for values

Update: I need to check if a unique value is already in the pasteTab's appropriate column. My code for that is --
for (a = 0; a<coldChainRange.length;a++){
var fillWeeks = coldChainRange[a][12]
**var rxNumbers = coldChainRange[a][0]**
var pasteTab = ss.getSheetByName(fillWeeks)
//var range = pasteTab.getRange('A2:P'+pasteTab.getLastRow()).getDisplayValues()
**var array = [];
array.push(rxNumbers)**
Logger.log(array)
//Logger.log(fillWeeks)
if(fillWeeks != "Need Days Supply"){
if (pasteTab !== null && **array.indexOf(pasteTab[a][0]==-1**)){
var patientInfo = ([coldChainRange[a][0],coldChainRange[a][1],coldChainRange[a][2],coldChainRange[a][3],coldChainRange[a][4],
coldChainRange[a][5],coldChainRange[a][6],coldChainRange[a][7],coldChainRange[a][8],coldChainRange[a][9],
coldChainRange[a][10],coldChainRange[a][11],coldChainRange[a][12],coldChainRange[a][13],coldChainRange[a][14]])
pasteTab.appendRow(patientInfo)
}
}
}
}
I need to have the info not be appended if a number is already in the column, however I think the loop is iterating the length of the "pasteTab" which is determined by a week number which is two characters long
How can I create a loop that will go read JSON.stringifed values?
I am trying to loop through cell values to determine where the information should be appended to. For example, if a cell had a value of "23" it would be appended to the 23 tab.
function sendToFillWeek() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var coldChainPasteSheet = ss.getSheetByName('from looker')
var coldChainRange = coldChainPasteSheet.getRange('A2:P' + coldChainPasteSheet.getLastRow()).getDisplayValues()
for (a = 0; a<coldChainRange.length;a++){
var fillWeeks = JSON.stringify(coldChainRange[a][12])
var pasteTab = ss.getSheetByName(fillWeeks)
Logger.log(pasteTab)
}}
This is my code so far for determining the appropriate sheet. The fillWeeks produces the values I need, however the pasteTab outputs all "null" values.
for(b=0; b<fillWeeks.length;b++){
(if fillWeeks !== "Need Day Supply" ){
var patientInfo = ([coldChainRange[a][0],coldChainRange[a][1],coldChainRange[a][2],coldChainRange[a][3],coldChainRange[a][4],
coldChainRange[a][5],coldChainRange[a][6],coldChainRange[a][7],coldChainRange[a][8],coldChainRange[a][9],
coldChainRange[a][10],coldChainRange[a][11],coldChainRange[a][12],coldChainRange[a][13],coldChainRange[a][14],
coldChainRange[a][15]])
pasteTab.appendRow(patientInfo)
}
}
}
}
Essentially, I would like the information to be appended the appropriate tabs.

Use Google Apps Script to loop through the whole column

I am trying to loop through the whole row in my google sheet and copy some of the data from one sheet to another. The list will get longer over time.
More specifically: If input in column B equals "blue", than copy the values from column A and C into another sheet.
Do this for all columns till the end of the column.
Link to my spreadsheet: https://docs.google.com/spreadsheets/d/1xnLygpuJnpDfnF6LdR41gN74gWy8mxhVnQJ7i3hv1NA/edit?usp=sharing
The loop stops when the colour does not equal blue. Why?
As you can see I used a for loop. Is that even the way to go?
Can I do anything about the speed of the code execution?
Any comments, hints or help are highly appreciated.
Regards!
You had the input sheet named "List" and I named the output sheet "Output". And here's the code.
function condCopy()
{
var s = SpreadsheetApp.getActiveSpreadsheet();
var sht = s.getSheetByName('List')
var drng = sht.getDataRange();
var rng = sht.getRange(2,1, drng.getLastRow()-1,drng.getLastColumn());
var rngA = rng.getValues();//Array of input values
var rngB = [];//Array where values that past the condition will go
var b = 0;//Output iterator
for(var i = 0; i < rngA.length; i++)
{
if(rngA[i][1] == 'blue')
{
rngB[b]=[];//Initial new array
rngB[b].push(rngA[i][0],rngA[i][2]);
b++;
}
}
var shtout = s.getSheetByName('Output');
var outrng = shtout.getRange(2,1,rngB.length,2);//Make the output range the same size as the output array
outrng.setValues(rngB);
}
You have 2 options. The first is to use the standard query() function from Google Sheets to get the values. The downside here is that it is only a reference of the values. So you cannot reorder them, etc. To use this, place this in cell A1 and it will pull the Headers and retrieve the values from column A and C:
=QUERY(A:C, "select A, C where B = 'blue'", 1)
For a Google Apps Script answer:
This will loop through your List sheet and for every row where column B is blue it will save the values in column A and C to column A and B of the new sheet:
function doIt(){
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet4");
var lastRow = activeSheet.getLastRow();
var lastCol = activeSheet.getLastColumn();
var targetValues = [];
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("List");
var lastSourceRow = sourceSheet.getLastRow();
var lastSourceCol = sourceSheet.getLastColumn();
var sourceRange = sourceSheet.getRange(1, 1, lastSourceRow, lastSourceCol);
var sourceData = sourceRange.getValues();
var activeRow = 0;
//Loop through every retrieved row from the Source
for (row in sourceData) {
//IF Column B in this row has 'blue', then work on it.
if (sourceData[row][1] === 'blue') {
//Save it ta a temporary variable
var tempvalue = [sourceData[row][0], sourceData[row][2]];
//then push that into the variables which holds all the new values to be returned
targetValues.push(tempvalue);
}
}
//Save the new range to the appropriate sheet starting at the last empty row
activeSheet.getRange(lastRow + 1, 1 , targetValues.length, 2).setValues(targetValues);
}
Of course, you could pass the value to test to the function by replacing 2 lines. The first, defining the function:
function doIt(testingvar){
to pass a variable called testingvar, and the test line to replace the hard coded test with the passed variable:
if (sourceData[row][1] === testingvar) {

Cant set the value of a cell within a row because it was converted to object or array with no methods

I am trying to write a function that will iterate over each row in a master spreadsheet and check the value of the 3rd column against every row in a second spreadsheet and compare it with the value in the 6th column, then change the value in the 4th column of the master spreadsheet based on the result. The script is a standalone script because its part of a larger project.
The problem is that when I try to set the value of the 4th column in the spreadsheet, I am getting an error that reads "Cannot find function setValue in object SENT". SENT is the value that is in that cell, and I do not understand how it became an object or how I would need to change to code to get at the value to change it. I checked this post about someone having a problem not being able to act on a date value, but I could not figure out how to take that feedback and apply it to this problem.
function eFormCheck() {
var masterSS = SpreadsheetApp.openById("mastersheet");
var masterSheet = masterSS.getSheets()[0];
var masterRange = masterSheet.getDataRange();
var masterData = masterRange.getValues();
var workersCompSent = "SENT";
var workersCompRec = "RECEIVED";
var workersCompSS = SpreadsheetApp.openById("formsheet");
var wcSheets = workersCompSS.getSheets()[0];
var wcRange = wcSheets.getDataRange();
var wcData = wcRange.getValues();
for (var i = 1; i < masterData.length; i++) {
var row = masterData[i];
var email = row[2];
var rowLog = row[3]; //on my spreadsheet this value is "SENT"
for (var j = 1; j < wcData.length; j++) {
var wcRow = wcData[j];
var wcEmail = wcRow[5];
if (email == wcEmail) {
rowLog.setValue(workersCompRec);//having an issue with the value of the third column being an object, but I don't understand how its an object
}
}
}
}
The setValue() method only works on the Range Class. You can't chain the setValue() method to a variable or a cell value. You must first define a range. There are 4 variations of the getRange() method. If you want to set a value in a single cell, then you must get a range that is a single cell. You may need to use your variable i in the getRange() method to get the row. If the column is always the same, then you can "hard code" the column value.
sheet.getRange(i, 4).setValue(workersCompRec);

Setting array values across row in Google Sheets

I have an array pulled from a Google Sheet column using the following code. How can I distribute these values across a row inside of a different sheet? Essentially, I would like the value at decisionPoint[1] to populate cell 'B2', decisionPoint[2] to populate cell 'C2', decisionPoint[3] to populate cell 'D2', and so on. Thanks in advance for any help!
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); // get the spreadsheet object
var decisionPointSheet = spreadsheet.getSheets()[2]; // set decision point sheet
var lastDecisionPoint = decisionPointSheet.getDataRange().getLastRow();
var decisionPoints = decisionPointSheet.getDataRange().getValues();
for ( var i = 1; i < lastDecisionPoint; i++){
Logger.log(decisionPoints[i][0]);
}
You may try that:
function transpose(){
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Requests"); // origin sheet
var out = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("output"); // destination sheet
var data = input.getDataRange().getValues();
data.shift(); // remove first row (apparently you are not taking the title)
var output = []; // better to create your object and then push it at once - it run faster
for(var i in data){ // I prefer that than the classical var i =1;i<numCol ....
if(i<10) output.push(data[i][0]);
}
out.getRange(4, 1,1,output.length).setValues([output]); // i you want to specify the row where it need to end
// out.appendRow(output); // or you can change for that just to appen a new row
}

Need to call back an array in Google Script

I am attempting to send an array through the callback and having no luck. Let me explain my intent and perhaps an expert out there can send me some ideas for how to solve this dilema.
I have creates a spreadsheet that collects data. I then have a UI script which pulls row data into a flex table for a user to process by clicking a checkbox. I created a separate flex table that contains the checkboxes which the user checks or leaves blank. In my script I need to send an array that contains the checkbox condition. Why? Because I also need the row # or array placement that I can push to the spreadsheet to send the correct updated status for the data.
The script only pulls data that needs action into the UI. Thus I may be acting on Rows 1,3,4,5,and 8 of the spreadsheet but on the UI flextable the row that correspond to the data are rows 1,2,3,4,5 thus the row assignments don't match. BUT if I use an array I can capture that the row pulled was 1,3,4,5,and 8 and then update the spreadsheet accordingly.
However, that is the problem when I try to callback my array labeled offset[inc] I cannot get it to work I get run errors of cannot find method addcallback and cannot get it to work.
Recommendations on how to send an array through the addcallback method or alternate recommendations would be appreciated.
Thanks,
Sean Nutzman
function doGet(e){
var app = UiApp.createApplication();
//Create Caption Panel
var captionPanel = app.createCaptionPanel('Detention Attendance').setWidth('350px').setHeight('75px').setStyleAttribute('fontWeight', 'bold').setStyleAttribute('fontSize', '24px');
//Add a widget to caption panel
captionPanel.add(app.createLabel("Please enter attendance for Detention by clicking the checkbox next to the student's name if they were present. Then click Sumbit."));
//add the caption panel to the application
app.add(captionPanel);
var panel = app.createHorizontalPanel();
var flexTable = app.createFlexTable().setStyleAttribute('border', '2px solid black')
.setStyleAttribute('borderCollapse','collapse')
.setBorderWidth(2)
.setCellSpacing(50)
.setCellPadding(6);
//Get Data from spreadsheet
var spreadsheetId = '0Aup0nXQ4K-pydFREb1FFcTFYX3lOenNQenR1Q01jQ1E'; //Change this to the Spreadsheet ID
var dataArray = getData(spreadsheetId);
var inc = 1;
//Load data into table cells
for (var row = 0; row<dataArray.length; row++) {
var booleanCheck = dataArray[row] [17];
var offset = new Array();
if (booleanCheck == "" || booleanCheck == "Date Served") {
if (row > 0) {
Logger.log("Row value = " + row);
var ticketDate = dataArray[row] [0];
var dateStamp = Utilities.formatDate(new Date(ticketDate), "America/Chicago", "MM/dd/yyyy");
dataArray[row] [0] = dateStamp;
var ticketDate2 = dataArray[row] [16];
var dateStamp2 = Utilities.formatDate(new Date(ticketDate2), "America/Chicago", "MM/dd/yyyy");
dataArray[row] [16] = dateStamp2;
flexTable.setText(row, 1, dataArray[row][2].toString());
flexTable.setText(row, 0, dataArray[row][0].toString());
flexTable.setText(row, 2, dataArray[row][16].toString());
offset[inc] = row; inc++;
Logger.log('Inc variable = ' + inc);
Logger.log('Offset = ' + offset[inc-1]);
} else {
Logger.log("Inside ELSE row is not > 0");
Logger.log("Row value here = " + row);
flexTable.setText(0, 1, "Student's Name").setStyleAttribute(0, 1, 'fontWeight', 'bold');
flexTable.setText(0, 0, "Date Assigned").setStyleAttribute(0, 0, 'fontWeight', 'bold');
flexTable.setText(0, 2, "Date Delinquent").setStyleAttribute(0, 2, 'fontWeight', 'bold');
}
}
}
Logger.log(offset);
panel.add(flexTable);
var check1 = app.createCheckBox().setName('ch1');
var check2 = app.createCheckBox().setName('ch2');
var check3 = app.createCheckBox().setName('ch3');
var check4 = app.createCheckBox().setName('ch4');
var check5 = app.createCheckBox().setName('ch5');
var check6 = app.createCheckBox().setName('ch6');
var check7 = app.createCheckBox().setName('ch7');
var check8 = app.createCheckBox().setName('ch8');
var check9 = app.createCheckBox().setName('ch9');
var submitButton = app.createButton("Submit");
var handler = app.createServerClickHandler('updateStatus');
handler.addCallbackElement(check1)
.addCallbackElement(check2)
.addCallbackElement(check3)
.addCallbackElement(check4)
.addCallbackElement(check5)
.addCallbackElement(check6)
.addCallbackElement(check7)
.addCallbackElement(check8)
.addCallbackElement(check9)
.addCallbackElement(offset);
submitButton.addClickHandler(handler);
handler.addCallbackElement(check1)
.addCallbackElement(check2)
.addCallbackElement(check3)
.addCallbackElement(check4)
.addCallbackElement(check5)
.addCallbackElement(check6)
.addCallbackElement(check7)
.addCallbackElement(check8)
.addCallbackElement(check9)
.addCallbackElement(offset);
var table = app.createGrid(11,1).setStyleAttribute('border', '2px solid black')
.setStyleAttribute('borderCollapse','collapse')
.setBorderWidth(2)
.setWidth('75px')
.setCellSpacing(5)
.setCellPadding(6);
table.setStyleAttributes({textAlign: "center"});
table.setStyleAttribute('fontWeight', 'bold').setText(0, 0, 'Attendance');
table.setWidget(1,0, (check1));
table.setWidget(2,0, (check2));
table.setWidget(3,0, (check3));
table.setWidget(4,0, (check4));
table.setWidget(5,0, (check5));
table.setWidget(6,0, (check6));
table.setWidget(7,0, (check7));
table.setWidget(8,0, (check8));
table.setWidget(9,0, (check9));
table.setWidget(10,0,(submitButton));
panel.add(table);
app.add(panel);
app.close();
return app;
}
What I usually do is to convert the array to a string and write it on the widget's tag.
Then I can retrieve it using e.parameter.widgetName_tag in the handler function. At this point I can split it to get back the array : e.parameter.widgetName_tag.split(',');
You'll have to be careful when choosing the join and split character since your data might contain a comma (which is the default separator in arrays)... I often use a | or any other 'uncommon' character (Ë,Í;∆) in combination with join('∆') and split('∆') so I'm sure I get the array back as it should.
Of course the widget must be included in the callBackElement but this is easily achieved by using the highest level parent UiApp element as callBackElement.
Last comment : try to use widget Ids that will simplify your life ... for example use Ids containing a number that corresponds to the array index ( chk0, chk1, chk2...) so that you can easily retrieve the numeric value to use in your handler function using something like this :
Number(e.parameter.source.replace(/[a-z]/ig,''))
which will give you a number that identifies which checkBox is the origin of the handler call so you can write :
var arrayElement = e.parameter.widgetName_tag.split(',')[Number(e.parameter.source.replace(/[a-z]/ig,''))];
var array = ['foo','poo'];
var arrayString = JSON.stringify(array);
At that point, just attach arrayString to a callback element and voila! Then in the handlerFunction, you access it out with e.parameter.arrayString and then parse it to return it back to an array like so:
var array = JSON.parse(e.parameter.arrayName);
//array = ['foo','poo']

Categories

Resources