Google Script for deleting blank or unused columns - google-apps-script

I have searched and searched but can't find anything that works. I am trying to eliminate any empty columns that remain in the spreadsheet when creating a Google Form. It would be helpful because I have a formula for the sum of a string comparison in the sheet, but I don't want it to include comparisons of empty cells. (i.e. I compare the entries in from H:X in every individual row to H2:X2 and have it count how many are the same.) I know I could adjust the formula, but I am looking to build a template for fellow colleagues so they don't have to worry about altering anything. If I could get the empty columns at the end to disappear automatically, I could just change the sum formula to extend all the way to column CZ (just to be sure it goes far enough), without it calculating blanks in its comparison.
Any help would be great! Thanks!

i use these scripts in the script editor of my google sheets for cleaning them up. stumbled across them somewhere... perhaps they will help.
//Remove All Empty Columns in the Entire Workbook
function removeEmptyColumns() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var s in allsheets){
var sheet=allsheets[s]
var maxColumns = sheet.getMaxColumns();
var lastColumn = sheet.getLastColumn();
if (maxColumns-lastColumn != 0){
sheet.deleteColumns(lastColumn+1, maxColumns-lastColumn);
}
}
}
//Remove All Empty Rows in the Entire Workbook
function removeEmptyRows() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var s in allsheets){
var sheet=allsheets[s]
var maxRows = sheet.getMaxRows();
var lastRow = sheet.getLastRow();
if (maxRows-lastRow != 0){
sheet.deleteRows(lastRow+1, maxRows-lastRow);
}
}
}

This is something you will have to get used to when using Google forms. Data is never really erased if you physically delete rows/columns, they will just reappear at some unknown time in the future. It's a pretty buggy and unreliable setup.
My advice is to keep your formulas and data completely separate. You do this by copying the form responses to another sheet (using code or otherwise). That sheet allows you to control the data being fed (or NOT fed) to the rest of your system. I would also go 1 step further and use formulas like
ImportRange(SheetSource!A:A)
in a 3rd sheet to allow you to control the order of the columns. From there you can add your formulas to act on the data being fed through in relative safety.
However, I had a situation not long ago, where the form and the sheet randomly lost their linkage, and it was not possible to restore it. I stayed up until 6am trying to fix the issue, however if I did not have the data copied to the separate sheet (as described above) the catastrophe would have been complete.
Luckily this appeared to have been a random glitch, because everything went back to normal at about 10am, but put simply, your data is not truly safe with Google Forms.

Using Arrayformula is better suited for this though it does the same thing.
Example:
=ARRAYFORMULA('Form Responses'!A1:EA)
Importrange has a noticeable (and annoying) delay as this what you would use if you wanted to reference sheets from other spreadsheet files. Arrayformula references sheets within the same file, no delays.

Related

Efficiently making Cell Notes from another Cell

I'm making a Google Sheet for a TTRPG I play with some friends and I'm trying to find the best way to make automated cell notes. I found a solution here that works and modified it to match my sheet but I'm VERY new to Google Scripts and am sure I'm doing things inefficiently.
Right now the solution is:
function onEdit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Copy of Digital');
var range = sheet.getRange("R31:T59");
range.clearNote();
for (var x=1;x<30;x++) {
range.getCell(x, 1).setNote(range.getCell(x, 3).getValue());
}
}
This is a workable solution for my needs but I always want to take things farther than just "workable" :). I know a small amount of C# but JavaScript is entirely new to me. The issues I see with my current implementation and possible areas of improvement are:
Because of formatting requirements on another section of the sheet, every other row where I am running this solution will ALWAYS be empty, but the solution is going to check the empty rows for notes every time. Is there a way for me to have the solution skip every second row? Can I specify exact cells rather than a range (and does JavaScript use absolute references like sheet formulas)?
Can I specify multiple ranges within the sheet for this solution to act on? Is it as simple as defining a second range?
Is it possible to restrict the onEdit(e) function's activation to only fire when specific ranges are edited? I'm generating a list of "Talents" that need the script to run whenever a player changes their gear through a validation list but to my understanding (and testing) onEdit(e) is going to run when any cell is modified (which will lead to numerous unneccessary script activations).
If I have multiple copies of the same tab active in the same sheet is it possible for multiple players to be using their own version of the sheet at the same time? (I think this must require the removal/modification of the getSheetByName line, but I'm only 2 days into trying to learn this!)
Huge apology for having so many questions! Any and all help is deeply appreciated!
Visual of the sheet for formatting reference
Try it this way:
function onEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() == "Copy of Digital") {
var range = sheet.getRange("R31:T59");
let notes = sheet.getRange("T31:T59").getDisplayValues()
range.clearNote();
sh.getRange(31,18,notes.length,notes[0].length).setNotes(notes);
}
}

How to check if user has clicked on the link in google sheet using google apps script?

I have been working on providing an google sheets interface for non technical members in my team, where they can see a sheet of info on some members, and one of those fields is a link to accessing that resource on an internal portal. The sheet looks as shown in the image attached.
This is an example sheet of the same type
This sheet will be accessible to these non technical team, who are going to have a look at this sheet, and if they want to work on a certain case, they will click on the link. What I want to ensure is that, when they get redirected to this url, I want to ensure that that particular row gets deleted from the sheet.
My initial problem is that I dont know what trigger should be used for making such a program. The one that seems most likely is a doGet(event) found here
The second one is how to do i catch an event like this and associate it to a particular cell.
A secondary solution could be that of an onClick(event) which would really make things simpler here, but that is not a "simple Trigger"
Note:- The good thing is that each resource is going to be unique
I could really use some ideas, i have drafted a little bit of a pseudo code here for the same, but it seems very hacks, and not computationally feasible:-
function doGet(event){
// code to delete a certain row when they visit the portal
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (s.getName = "clicker_checker" && check which url redirected){
check which row and cell matches with the redirections url, and delete that.
}
}
Since you are using a spreadsheet, the most suitable trigger for you would be an onSelectionChange one.
This trigger will allow you to detect when a selection has been made in this spreadsheet- more particularly in the cell wanted.
Therefore, you can use a script similar to this:
function onSelectionChange(e) {
var range = e.range;
var sheet = range.getSheet();
var col = range.getColumn(); //if needed
var row = range.getRow(); //if needed
if (sheet.getName() = "clickeer_checker" && other_condition) {
// instructions here
}
}
Reference
Apps Script Triggers.

Is there a way to determine when a spreadsheet is done calculating?

I've a spreadsheet with a lot of imports and formulas based on the imports. Sometimes it takes a long time to update -- there is now a progress bar in the upper right that pops ups the message "calculating formulas" when you hover over it. It there a programmatic way to detect when the sheet is done recalculating?
I'd like to popup a box (toast?) saying the sheet is busy and then disappear the box when the sheet is done recalculating.
Not really.
Volatile functions like Importrange are the enemies of spreadsheet stability. Sometimes they get stuck recalculating and never finish; that is for nor particular reason as creating a copy usually creates a version that finishes calculating (eventually).
If you work with many importrange formulas and formulas based on them it is generally advisable to replace the import formula by a scheduled import via script.
This seems to work so far:
SourceWB = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/185XVLyN4fFLds8Z7JIgkL6mGl1CC82maBmmVAhYP71g/");
SourceRange = SourceWB.getRangeByName("CoreElementExport");
SouceValues = SourceRange.getValues();
var sourceRows = SourceRange.getNumRows();
var sourceColumns = SourceRange.getNumColumns();
DestWB = SpreadsheetApp.getActive();
DestSheet = DestWB.getSheetByName("TaxonomyImport");
DestSheet.getDataRange().offset(0, 0, sourceRows, sourceColumns).setValues(SouceValues);
something after, just trying to use this very complicated input tech...

How to dumpValues & Data of a full column in google sheet via google script, in one operation?

I've been handling a big set of Data with automated scripts in google drive.
These script constantly update some cells in a column through different sheets.
Now here is the problem: Reading and writing in google scripts is super long. So I tried to get the column via getValues, dump it in a an array, do my researches and my mods there and write the whole array back to the sheet.
However, this erases the formulas that might have been in the column (getValues would then return the result of the formula). Using getFormulas wouldnt give back the values. I could write and read formulas and values, but that would add operations when I'm trying to save time.
How come google doesn't provide a way to directly dump a String content of each cell? Any work around?
A.
Well, I could find any google specified answer, but I developed a merge function and it's actually fast enough, if anyone needs it :
function dumpColumn(sheet, index){
var range = sheet.getRange(1, index, sheet.getLastRow(), 1);
var arrV = range.getValues();
var arrF = range.getFormulas();
for(i = 0; i<arrF.length; i++){
if(arrF[i][0] != "")
arrV[i][0] =arrF[i][0];
}
return arrV;
}

Spreadsheet stops working after creating a new sheet using a script and deleting exceeding col/rows

Every time I create a new sheet using a script, my Spreadsheet stops working after a while and I have to kill the browser tab.
The problem happens after I correctly create the new sheet and I use the following two statements to delete the exceeding columns and rows.
ss.deleteColumns(firstCol, colNb);
ss.deleteRows(firstRow, rowNb);
I have tried commenting the above and the Spreadsheet doesn't stop.
Do you have any idea, please?
Thanks,
Without knowing how you are declaring your variables, it is hard to say. Generally I use ss for the spreadsheet that contains the individual sheets, and sheet for a particular sheet I am working on. If this is the case for you, it appears you may be trying to do an action that is limited to individual sheets on the spreadsheet container.
var ss = SpreadsheetApp.getActiveSpreadsheet(),
sheet
;
sheet = ss.getActiveSheet();
Additionally, it may be best to test whether your sheet has the additional columns and rows you are trying to remove.
if (sheet.getMaxColumns() > lastCol) {
sheet.deleteColumns(lastCol +1, sheet.getMaxColumns() -lastCol);
}
if (sheet.getMaxRows() > lastRow) {
sheet.deleteRows(lastRow +1, sheet.getMaxRows() -lastRow);
}