I have a dynamically created table with a number of columns, including a input text control.
I read records from the DB and populate this input field accordingly.
It gets populated correctly on the first page, but not for the other pages.
I am using Footable v3
I tried a bunch of things.
The script seems to go through all the records correctly, but the output is not visible page 2 onwards.
function populateNotes(tableId) {
var table = document.getElementById(tableId);
var allRows = FooTable.get(table).rows.all;
var rowItem, rw;
var notesTD, jNo;
// This loop goes through all records correctly
for (rw in allRows) {
rowItem = allRows[rw];
var jNo = rowItem.$el.find("td:nth-child(1)").text();
console.log("populateNotes: Row: ", jNo);
var notesTD = rowItem.$el.find("td:nth-child(12)").find('#kpi-notes');
if (notesTD.length !== 0) {
notesTD.val('' + getKpiNotes(jNo));
}
}
}
I expect to see the input field 'notesTD' containing the correct value, but this happens only on the first page.
Next page onwards, it is empty.
Appreciate any help or pointers.
Did you try using the footable events, I use to do this to manage modification of content or style. It also take less time because you only iterate in the 10 or 15 lines of the pages
For example you can use the afterpaging
"after.ft.paging": function (e, ft) {
var colarray = ft.columns.array; //array is just the records shown on the page
........
Related
This question already has answers here:
Return focus to spreadsheet
(3 answers)
Closed 2 years ago.
My current environment: Chrome, Win10, Thinkpad also FF, Win10, PC
When calling a function from a button on a sheet - the following script works, enabling a new row to be added after the lastRow with data.
But, when I type anything in my keyboard, the entered data isn't inputted into the cell.
The cell needs to be clicked before it accepts keyboard entries.
However, when the same function is run from the script editor the user does not have to click in the cell for keyboard entries to be accepted. This is the action that I require.
I have tried the same in a new Spreadsheet and using a different browser and hardware with same outcome.
Is this a bug in App Script? Is there a workaround?
Here's the script:
function addVenue() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Venues");
var column = ss.getRange('A:A');
var values = column.getValues();
//loop down until Venue name cell blank
var ct = 0;
while ( values[ct] && values[ct][0] != "" ) {
ct++;
}
ct++;
ss.getRange("A"+ct).activate();
}
Update:
I don't think your current code works since it doesn't add a new row after the last row with content. This is why I post this solution to answer this part of the question as it also offers a substantial improvement over the solution in your question. The following code has been tested and worked on google chrome (PC) and it is executed from the script editor.
The cell was activated and the user is able to directly enter data (regardless of its size) in that cell and he does not need to click on that cell:
Solution:
If you want to add a row after the last row with content of column A:
function addVenue() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Venues");
var filledRows = ss.getRange("A1:A").getDisplayValues().filter(String).length;
ss.insertRowsAfter(filledRows, 1);
ss.getRange(filledRows+1,1).activate()
}
Restrictions:
This method will only work if column A does not contain empty cells
in between the first and last row of content; as your solution makes
the same assumption.
References:
insertRowsAfter(afterPosition, nRows)
filter()
I am working on a project where I take multiple column/row inventory sheets and turn them into a multi-row/2-column format for order picking.
I have a switch for selecting the appropriate inventory sheet and a map() function that copies the imported information from the inventory DataRange().
However, not all the data is in consistent columns. What I would like to do is find an expression that maps the next column in if the column it was mapping has a zero or "" value.
I won't give you the full body of code unless you need it, but hopefully just the important parts.
This is what I have:
var source = SpreadsheetApp.openById("1xixIOWw2yGd1aX_2HeguZnt8G_UfiFOfG-W6Fk8OSTs"); //This sheet
var srcSht = SpreadsheetApp.getActive();
var sourceMenu = srcSht.getRange('A1');//This is the cell cotaining the dropdown
var menuTest = sourceMenu.getValue();
// Variable for the vars sheet. If it doesn't exist, create it
var varsTest = source.getSheetByName('vars');
if (!varsTest){source.insertSheet('vars');}
var importedA1 = varsTest.getDataRange().getA1Notation();
varsTest.clearContents();
var t1Imp = '=ImportRange("test1_Id", "Stock!A1:F11")';
var varsData = varsTest.getRange('A1');// This is the cell we fill with the importRange formula
varsData.setValue(t1Imp);
var imported = varsTest.getDataRange().getValues();
var newOrder = imported.map(function(item) {
if (item[4] !== NaN){return [[item[0]],[item[4]]];};
if (item[4] === NaN){return [[item[0]],[item[3]]];};}
var orderRange = source.getSheetByName('Sheet1').getRange(10,1,newOrder.length, newOrder[0].length);
orderRange.setValues(newOrder);
Logger.log("\t" + newOrder);
Logger.log(newOrder):
[(timestamp omitted)] items1,order,caramel,6,c&c,2,mint,3,PB,0,,,items2,,caramel,,strawberry,,mint,,PB,
It seems to be skipping the if statements, or I told it that I mean to test the index as NaN, which will obviously never be true.
I also tried replacing 'NaN' with 'undefined'. Same result. I tried finding the item[4].Values, but it gave me an error. I also tried the same logic using filter() instead of map() but it copied the entire data set.
I pull these values onto a new 'vars' sheet in the workbook (to minimize calls to the web service):
test1
reduce them to the first and last columns, then output:
test
The cells in the 'order' column for the second set of items in the 'test' sheet are blank. The values for that order column should be in item[3] of that array, but I can't get the script to identify that that the blank cells are blank.
I am new to Google Apps Script and JS, but I am watching a lot of tuts and learning by doing. If I find a solution, I will post it.
Thank you StackOverflow, I could not have learned as much as I have without this community!
I have a working function that does what I want. In short:
I had to create a duplicate of the order column in a new column, so that all the values would line up. It's not technically a JS answer, but was the simplest and follows good spreadsheet rules.
function rmZeroOrderPS(item){
var source = SpreadsheetApp.openById("<sheetId>"); //This sheet
var varsTest = source.getSheetByName('vars');
var imported = varsTest.getDataRange().getValues();
var i=-1;
while (i <= imported.length){
if(item[8]!= 0) {return [item[0],item[8]]};
i+=1;
};
After around two to three hours of digging across many sites, I cobbled together this functioning script to watch an "input" column on a sheet and, using onEdit(), whenever data is put into that column, move the data further down the sheet to the next available cell in that specific row.
function onEdit(e) {
var s = e.source.getActiveSheet();
var sheetName = 'Pricing Chart';
var colToWatch = 5;
var copyFrom = 5;
var nextEmptyCol = colToWatch + 22;
var emptyCellCheck = s.getRange(e.range.rowStart, nextEmptyCol,1,1);
if (s.getName() !== sheetName || e.range.columnStart !== colToWatch) return;
while (emptyCellCheck.isBlank() !== true){
nextEmptyCol++;
var emptyCellCheck = s.getRange(e.range.rowStart, nextEmptyCol,1,1);
}
if (emptyCellCheck.isBlank()){
s.getRange(e.range.rowStart, copyFrom,1,1)
.copyTo(s.getRange(e.range.rowStart, nextEmptyCol,1,1), {contentsOnly: true}),
s.getRange(e.range.rowStart, copyFrom,1,1).clear({contentsOnly: true});
}
}
Specific example:
Into cell E5, type "222". If AA5 is empty, it will copy "222" into AA5, and then clear E5. If AA5 is not empty, it will check AB5, then AC5, etc until it finds an empty cell. On my specific sheet, it then uses all the data from the row and displays various calculations (average, max, etc) so that those data are visible, but all the individual inputs are tucked away behind the scenes. It's been useful for keeping a large list of data on many different variables in a format that's easy to look at and easy to share with others.
Problem is... sometimes it will do as intended at first, find the next available cell, copy the data, and erase the original input cell (e.g. E5). But, sometimes, it will also erase the cell the data was copied TO (e.g. AB5). Roughly once or twice every ten iterations of the script.
So, I was wondering if anyone could have a look at my script and give me tips on optimizing it or just doing things better so the script runs correctly consistently.
I am having an application with functionality of showing tables for multiple stocks. If two stocks are present, two tables will be created dynamically as below.
Here two tables are present and I want to get the sum of %change in each year. ie sum of %change in 2015 from both tables like 2014=7.88+1.69, 2015=-11.24+6.44 etc. Please help me to do. I need a solution using javascript.
Link to Tables Image
Depending on how the tables are formatted, you could write a function to look at the <td> tags that belong to the %change column and then sum the values in it. The 5th <td> of row 2 and on will have the numerical value in it.
Set up a loop of all stock tables first..
var stocks = ["GE", "GOO"]; // stock codes, to use with table IDs
var num = stocks.length;
var years = {};
for(var loop = 0; loop < num; loop++){ // loop all of our stocks
var tableID = "table_"+stocks[loop]; // make sure this matches tableid structure
var table = document.getElementById(tableID); // get our table
var rowNums = table.rows.length; // number of rows in table
for(var rowLoop=1; rowNums: rowLoop++){ // skip first row (row 0)
var row = table.rows[rowLoop]; // get the row
var year = row.cells[0].innerHTML; // get text inside the cell
var change = rows.cells[5].innerHTML(); // get text inside the cell
change = change.replace("%", ""); // remove % sign
// Strip change percentage here
// Make sure it is proper number that can be added
if(!years.year){
years.year = change;
} else {
years.year += change; // do math to update year change amt
}
}
}
console.log(years);
I wrote this from my phone and it's 3:45am so I haven't had a chance to test it. Although I'm sure any errors could be easily fixed. This code and logic will do what you want. The only thing you have to do is actually remove the percentage signs and do some beta testing to ensure it works for you
You also need to make sure your tables have proper ID :)
SO really needs a code button for mobile... Spacebar 4 times on every line sucks
I'm pulling my hair out a little trying to write a conditional Google apps script for Google sheets. The sheet has 5 tabs. Basically, the sheet gets it's data from a google form. Clients fill the form out and it populates our "Master" tab of the sheet in question.
Here's where I'm hung up:
The form is used for teachers to refer students to specific administrators. Whoever is controlling the form needs to be able to assign a specific row of data to a specific administrator, which each have their own tab set up. They do this by selecting, from a drop down, which admin they want to assign the row to.
So, if row 2 is assigned to "Miranda," Certain data would get moved over to the "Miranda" tab. For the sake of argument lets say column D and E of that particular row would get moved over to column A of the "Miranda" tab.
Here's what I've come up with so far:
function importStudent() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var master_sheet = ss.getSheetByName("Master");
var miranda_sheet = ss.getSheetByName("Miranda");
var columnT = master_sheet.getRange("T1:T").getValues();
var columnD = master_sheet.getRange("D1:D").getValues();
var columnE = master_sheet.getRange("E1:E").getValues();
for(var i = 0; i <= columnT; i++) {
if (columnT[i][0] === "Miranda") {
var miranda_row = (miranda_sheet.getLastRow() + 1);
var active_row = SpreadsheetApp.setActiveRange(columnT[i].getRow());
var selectionFirst = columnD.setActiveRange(active_row:columnD);
var selectionLast = columnE.setActiveRange(active_row:columnE);
var fullName = selectionFirst + " " + selectionLast;
fullName.copyValuesToRange(miranda_sheet, 1, 1, miranda_row, miranda_row);
}
}
}
The below code is broken, and i'm looking for a little guidance in making it work. Right off, I know I have at least two issues: 1 there are too many variables, and 2 I'm not sure I can pass a variable as a parameter for the setActiveRange() class. So, my questions:
How can I clean this up? And what (class?) should I be using in order to make it functional?
PS - I still consider myself a novice when it comes to JavaScript. I have the knowledge, but the practical application is something I'm still learning :)
not sure if you need to use script to do what you are trying. Why not use a query formula?
For example:
=query(MasterData!:A:E,"SELECT D,E WHERE A = 'Miranda'",0)
There is some help on queries here. You can also query across spreadsheets. That is to say you could assign Miranda her own spreadsheet, which feeds from your master data.
Please share with me a sample spreadsheet data if you need more assistance.