My code is a simple form with 3 input fields. Once the user fills them all in and presses the button it will add a row to the table with the input data aswell as an index number. Like this:
https://imgur.com/g5ToOpF
im trying to give each row in a table an index number that is correct with the amount of rows inserted. This works but now I want it to update the index number when I remove one of the rows from the table.
The following function is triggered when the customer fills in an input field with the desired index number that they want to delete and then press a button.
function removeRow() {
let tabel = document.getElementById("tabel");
let rows = tabel.getElementsByTagName("tr");
let indexNumber = document.getElementById("indexnumber").value;
Object.entries(rows).forEach(([key]) => {
if(key === indexNumber) {
tabel.deleteRow(indexNumber);
}
})
}
This works and deletes the row that the customer whats but it doesn't update the index numbers for the other rows. So when I delete row 5. My table will look like this.
https://imgur.com/Zz3sBSI
I figure I have to loop through all of the rows and set the index to the correct number again. Can anyone help me out :) ?
For the full code check:
https://codepen.io/Botert/pen/bJLLWL
grtz,
Botert
To answer your question, try adding the following snippet in your removeRow() function:
for (var i=1; i<rows.length; i++) {
var dataRow = rows[i].children[3];
dataRow.textContent = i;
}
Fiddle here: https://jsfiddle.net/ufszamv4/
It's outside of the scope of the question, but consider taking a different approach to the problem. Try placing your rows in an object that has its properties removed. The goal is to simply delete a row without having to update the rest of the data.
Related
I am working on a google sheets template that will have some roster maintenance built in. When rosters are updated on the main "roster" tab, I would like for all the other tabs in the sheet to check student ID #s against the updated roster tab. In the code, an example sheet is "anet" sheets the sheets. I am using indexOf and a for loop to check each value in the "anet" sheet against the IDs in the "roster" sheet. If an ID# has been removed from the "roster" sheet, I would like that row to be deleted in the "anet" sheet.
When I run the script right now, some of the rows are deleted, but not all of them. The list of IDs begins in A3 on the "roster" tab, and the other list begins in A15 on the "anet" tab. Can someone help me understand why it is deleting some of the rows returning an indexOf of -1, but not all of the rows I need deleted?
function withdrawnStudent (){
let lastRowTyler = roster.getLastRow();
let tylerData = roster.getRange(3,1,lastRowTyler,1).getValues();
let tylerArray = tylerData.map(function(r){ return r[0]});
let anetLastRow = anet.getLastRow();
let anetLastColumn = anet.getLastColumn();
let anetData = anet.getRange(15,1,anetLastRow,anetLastColumn).getValues();
let anetIDArray = anetData.map(function(r){ return r[0]});'''
for (let index = 14; index < 200; index++){
if(tylerArray.indexOf(anetIDArray[index][0]) === -1){
anet.deleteRow(index +14);
Logger.log(tylerArray.indexOf(anetIDArray[index][0]))
Here is a link to an example spreadsheet. In the "roster" tab, it lists 4th grade student IDS. In the "anet" tab, all rows with a number should be deleted because these are 5th grade IDs. However, not all rows are getting deleted, only some.
https://docs.google.com/spreadsheets/d/1vDse6X6gs3bkgnlBfgo-vzERkAMud3rUDC6j8fEkcrk/edit#gid=447751616
So when the document changes, set up a trigger to fire your script, and your script will loop through all the available IDs in the first sheet and save them to an array. Then in your second sheet, you will loop through the IDs, and if it is not in the array, then delete the row. We want to make sure that we run the loop backward because if we delete rows and keep moving down, the chart will be skipping rows here and there since the table has shifted upwards.
Here's what I was able to come up with:
function withdrawStudent() {
//Get Student IDs From Roster Spreadsheet
var rosterSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Roster");
var dataRangeOnRosterSheet = rosterSheet.getDataRange();
//Returns a nested Array of all values in the 3rd row, 1st column, all the rows to the end, only one column
//I added the flat() to make it into a one-dimenstional array
var studentIDs = rosterSheet.getRange(3, 1, dataRangeOnRosterSheet.getLastRow() - 1, 1).getValues().flat();
Logger.log(JSON.stringify(studentIDs)); //If you want to see what the data looks like
//Now loop through each student ID in the second sheet, and if it doesn't exist in our first array then delete the row
var ANetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ANet");
var dataRangeOnANetSheet = ANetSheet.getDataRange();
var lastRow = dataRangeOnANetSheet.getLastRow();
var firstRow = 15;
//Reverse the for loop to work bottom-up because row deletion shifts the chart
for (var i = lastRow; i >= firstRow; i--) {
var currentStudentID = ANetSheet.getRange(i, 1, 1, 1).getValue(); //Get Student ID of current row
//If the currentStudentID is not found in our list of student IDs, remove it
if (!studentIDs.includes(currentStudentID)) {
//Remove the row
ANetSheet.deleteRow(i);
}
}
}
How to set up your trigger so that it runs your function every time a user edits the chart:
Disclaimer: I made a copy of your document so I could test my code and make sure it works, but I'm deleting it now. Hope you are fine with that!
I would like to be able to achieve this on my google sheet.
Requirements.
IF Column B is not equal to the word " Pending ". Delete that row
IF the row gets updated and the content on Column B for that row gets updated AND IS NOT EQUAL to the wor " Pending". Delete that row as well.
So I would like to achieve auto row delete for existing and future updates on the sheet.
Thank you!
Just change the name of the sheet in the getSheetByName method to whatever you want. Deleting rows goes a lot easier if you start from the bottom. This function will do the deleting. The remaining issue is what's going to initiate the process. Perhaps a timed trigger?
function delIfBPending()
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('delIfPending');//Change this name as needed
var rng=sht.getDataRange();
var rngA=rng.getValues();
for(var i=rngA.length-1;i>-1;i--)//this limit is dependent upon whether or not you have a header row.
{
if(rngA[i][1]=='Pending')
{
sht.deleteRow(i+1);
}
}
}
What I'm looking for is an individual column searching function (exactly as this datatables spreadsheet example) for the Handsontable spreadsheet plugin.
What's already existing and has been developed by the Handsontable team is :
Multiple filtering Excel-like (but included in the PRO version) - Cons for my case are that it's not free, and it doesn't quite fit well what I'm looking for.
Highlighting the cell(s) or row(s) based on an user input - The Con is that I need to only display the relevant row(s)
Is there such thing as displaying only the relevant row(s) based on multiple inputs from an user with Handsontable ?
Based on the solution of this blog, I managed to code a solution.
See this JS fiddle that answers all my requirements.
The main function I was looking for is this one :
// The function push every row satisfying all the input values into an array that is loaded
function filter() {
var row, r_len, col, c_len;
var data = myData; // Keeping the integrity of the original data
var array = [];
var match = true;
for (row = 0, r_len = data.length; row < r_len; row++) {
for(col = 0, c_len = searchFields.length; col < c_len; col++) {
if(('' + data[row][col]).toLowerCase().indexOf(searchFields[col]) > -1);
else match=false;
}
if(match) array.push(data[row]);
match = true;
}
hot.loadData(array);
}
What I did is keeping synchronized a table of Strings with the input fields (searchFields), compare the data of each row between inputs and their corresponding column, and push into an array the relevant row(s) to finally display the resulting array. This function is called for any change in the input fields which result in a live table filtering.
Note that I tried my solution for ~10k rows and their isn't any performance issue with Chrome, Firefox and IE.
Also note that I managed to find a solution to keep synchronized the current displayed table with the original data when editing the values, but this is IMO out of the scope of this question. Please let me know in the comment if you're interested about this.
I want to check whether the newly added row appear in first page or not. One way of doing it is get the index, but I wonder why it doesn't work, the index for me is not accurate at all.
function add_row(name, time_taken, attempts) {
var t = $('#dashboard').DataTable();
var node = '';
node = t.row.add([
'',
name,
time_taken,
attempts
]).draw().node();
$(node).attr('id', concatSpaces(name)).hide().fadeIn('slow');
var index = t.row('#' + concatSpaces(name)).index() // doesn't work
any thought? stuck for 2 hours long!
API method row().index() returns internal index which doesn't mean row position in the table based on current sorting column and method.
You need to use the code below instead to locate index of the row based on current sorting column and method:
var index = table.$('tr').index(node);
See this jsFiddle for code and demonstration.
I'm using the latest SlickGrid, with dataView.
I subscribe to the onActiveCellChanged event to react to a user selecting a row, and get the cell contents of the first column with:
grid.onActiveCellChanged.subscribe(function(e, args)
{
var cell = args.cell;
var row = args.row;
vat cell_contents = data[row][grid.getColumns()[0].field];
This works perfectly until I filter the table. Then args.row doesn't match the row in the data table.
How can I map the filtered row number (given in the event), to the actual row of the data that I want to read?
i.e. A filtered grid could yield one row of data, but could actually be row ten of the actual data table. I need to be able to read the data in the visible row selected.
After numerous attempts, I finally managed to do this. For anyone else that comes looking, what I did was:
grid.onActiveCellChanged.subscribe(function(e, args)
{
var cell = args.cell;
var row = args.row;
var row_data = dataView.getItem(row); // Read from dataView not the grid data
var cell_contents = row_data['id'];
This solution compensates for re-ordered columns as well as filtered rows.