Force Calculation script of Cell Range in Google Sheet - google-apps-script

For some reason the formula isn't working when the data from importrange is being updated. What I have to do is to go to cells and pressing F2+enter to refresh and ya it works like that I tried creating a macro and it also works but I want it to be simplified.
I come up with this kind of script that doesn't really work because i don't have time to learn for and dig deeper for scripting
function CellRefesher() {
var spreadsheet = SpreadsheetApp.getActive();
var range = spreadsheet.getRange("A1:O52");
range = SpreadsheetApp.flush();
};
so What I'm trying to do is I want to do something like force calculation for the cell range of A1 to O52 and base of google document(just base on my understanding)
this "SpreadsheetApp.flush();" will do something similar that's why I do this "range = SpreadsheetApp.flush();"
This might be like a spoon feeding but please do help me. I want to learn but don't just have much time yet. Thank you

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);
}
}

Struggling to Create a Simple Copy/Paste Script

I've been trying to learn on my own by watching YouTube videos and reading forums, but I'm still struggling and...I'm a little embarrassed because it seems so simple. I'm hoping any answers/suggestion from you will help me in the future.
I have two sheets "Bishop" and "Log". I want to copy two specific cells (K11 and K12) from "Bishop", which are vertically aligned, and paste them horizontally in the sheet "Log" at C4 and D4, respectively, without any formatting or formulas being copied over.
Each time I press a button (I've already made and attached a script to) I want it to paste in those two cells, and then move down to the next empty row (so C4,D4 to C5,D5, C6,D6...and so on).
I never intended on getting someone to finish my script for me, but I'm getting confused by the examples I've found in my research. Here's my script so far (after deleting many dysfunctional versions)
function Logger(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var bishop = ss.getSheetByName('Bishop');
var log = ss.getSheetByName('Log');
}
I tried to copy and modify code examples from YouTube videos and articles, but I think my by modifying them I'm just making a mess.
Thank you for any help or suggestions.
Dustin
EDIT
After some tinkering and reading some more, I now have a pretty nifty script that copies data in to where I want it! However, my next goal is to learn how to move down one row each time I run the script, so it creates an actual list, or log. "InputData" and "PasteRange" are named ranges on my source sheet and destination sheet, respectively. Here's my code so far:
function Logger(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var bishop = ss.getSheetByName('Bishop');
var log = ss.getSheetByName('Log');
ss.getRange("InputData").copyTo(log.getRange("PasteRange"),SpreadsheetApp.CopyPasteType.PASTE_VALUES,true);
}
So far your script has gotten to the point of creating 2 variables that reference the Bishop and Log sheets.
Next, you'll need to select the specific ranges in those sheets. To get a range in a sheet, use the getRange method, which has a few variations on what inputs it takes. For example:
var range1 = sheet.getRange("A1");
Once you have references to the ranges, you can use the getValue or getValues method to extract the values inside a range, and then use the setValue or setValues method to overwrite new data into an existing range. For example:
var myValues = range1.getValues();
range2.setValues(myValues);
If you haven't seen this page before, take a look; it's probably the most helpful single webpage for writing sheet scripts.
(Also, I won't write the code for you; Stackoverflow is about specific questions and answers, not about figuratively doing your homework, though the lines are blurry at times. But feel free to keep asking questions!)

Google Sheets script that runs based on the face value of a cell while ignoring formulas

I made a Google Sheet to check every media that plays on a certain channel on TV using a lot of workaround formulas within the cells themselves. A part of this sheet is a column (G) that tells me whether or not the specific episode/media/whatever is currently playing, has played in the past or will be played later today/at a later date using a "NOW" function. Next to that column there is another (F) where the user is able to write a "V", and in the case the show is playing but the user hasn't checked it yet, it writes "Check Me" See Example.
I wanted to create a button that will automatically change that "Check Me" into a "V" but the problem is that "Check Me" is based on a simple formula written throughout column F (=IF(G5="Playing","Check Me","")), so when I tried to run a script I found here on StackOverflow:
function Test() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("F5:F700");
range.setValues(range.getValues().map(function(row) {
return [row[0].replace(/Check Me/, "V")];
}));
}
(Can't remember the exact thread I got it from and it's been two days since I found it with lots of similar searches in my history, so I apologize for not crediting)
together with its intended use, it also straight up deleted all the rest of the formulas from the column, probably due to the formula itself containing "Check Me" but I might be mistaken.
To be honest, before this week I barely ever worked with either Google Sheets, much less JavaScript or even coding in general, so I'm pretty much restrained to changing values and very minor modifications in scripts I find online.
The only idea I had as to how to solve it is to add an "if IsBlank" but regarding face value of the cell only rather than its contents, but I don't know how to do it or whether it is even possible in the first place. At the very least, google shows no results on the subject. Is there a way to add that function? or perhaps a different method altogether to make that button work? (it's a drawing I will assign a script to)
Because you're using a map function to update the range, you'll need to get the formulas using getFormulas() in addition to the display values using either getValues() or getDisplayValues(). Using only the display values, as you're currently doing, will cause you to lose the formulas when you update the sheet. Conversely, using only the formulas would cause you to lose all of the display values that don't have a formula, so you'll need both. Try this and see if does what you want:
function Test() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("F5:F700");
// Get all cell formulas and display values
var formulas = range.getFormulas();
var values = range.getValues();
range.setValues(formulas.map(function(row, index) {
var formula = row[0];
var value = values[index][0];
// Check only the display value
if (value == "Check Me") {
return ["V"];
} else {
// Return formula if it exists, else return value
return [formula || value];
}
}));
}

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...

Script in Google Apps Script that copies values in a range to another sheet

I am working on a tool that will allow my company to track its financial investments.
I need to create a simple data entry form for users to input transaction data, which will then populate a master sheet which is the basis for the analyses the tool does. I cannot do this via Google Forms because the data entry form uses a lot of conditional formatting based on other data in the sheet.
I have uploaded a very simplified sheet to illustrate what I need: this
What I am looking for is a script that, upon clicking Submit in the Data Entry sheet, copies the values (NOT the formulas) in B12:E12 to the first empty row (in this case, row 8) in the "Master Table" sheet. Ideally, clicking "Submit" will also clear the data entry fields in C4:C7 in the "Data Entry" sheet.
I have looked through various forums for a solution but have not found anything that does exactly that. I am sorry to say I am a complete newbie at Google Apps Script, therefore I could not write my own code to share, which I am aware is customary when asking a question here.
If anyone could point me in the right direction regardless, it would be much appreciated. I am currently trying to learn JavaScript and Google Apps Script using online resources, but for this specific project, it would take too long for me to reach a level where I could help myself.
Thank you very much, GEOWill!
Your answer solved my problem and thanks to your comments, I was able to understand exactly what your code does. I changed the code only to remove the Menu (but thank you very much for showing me how that is done anyway) - I tied the function to a Submit button inserted as a drawing. I also added some code to clear the contents of the entry range after clicking the button (this was suggested by someone else).
The final code that I used is:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var entry_sheet = ss.getSheetByName("Data Entry");
var master_sheet = ss.getSheetByName("Master Table");
function mySubmit() {
var entry_range = entry_sheet.getRange("B12:E12")
var val = entry_sheet.getRange("B12:E12").getDisplayValues().reduce(function (a, b) {
return a.concat(b);
});
Logger.log(val);
master_sheet.appendRow(val);
entry_sheet.getRange("C4:C7").clearContent()
}
I hope this helps others with a similar problem! Love how supportive this community is. Thanks for helping out.
I would begin by using a menu function to run your code in (rather than a cell button). You could use a cell button, but I believe you need to insert an image and assign a javascript function to that image anyways.
Basically, you begin by going to tools, script editor. Create an onOpen function and create a trigger that runs the onOpen() function each time the spreadsheet is opened. Inside the onOpen() function, we create a menu into which a physical menu item (a kind of button) exists (called 'Submit'). Finally, we associate a function to this button (I called it mySubmit()).
Inside of the mySubmit() function is where most of the functionality you are looking for exists. At this point, it is just a matter of copying from one range of cells and pasting them to another range of cells. For this, you'll notice that I had to setup a few variables ahead of time (ss, entry_sheet, master_sheet, entry_range, and master_row).
One last thing, you may want to protect the Master table sheet because if someone accidentally edits a cell beyond the last one edited, the input row would be copied to that row (due to how the getLastRow() function operates).
Hope this helps!
var ss = SpreadsheetApp.getActiveSpreadsheet();
var entry_sheet = ss.getSheetByName("Data Entry");
var master_sheet = ss.getSheetByName("Master Table");
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('MyMenu')
.addItem('Submit', 'mySubmit')
.addToUi();
}
function mySubmit() {
var entry_range = entry_sheet.getRange("B12:E12");
var master_row = (master_sheet.getLastRow() + 1);
entry_range.copyValuesToRange(master_sheet, 1, 3, master_row, master_row);
}