Struggling to Create a Simple Copy/Paste Script - google-apps-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!)

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

Force Calculation script of Cell Range in Google Sheet

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

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

How to write an onOpen triggered script without using Activate() methods

Good morning,
I am having an issue with a piece of script which will open the spreadsheet at the first available row after a data table. I am fairly new to this, but as I understand it from research, the onOpen trigger will not work for scripts featuring Activate() methods (which I assume are things like getActiveRange() and setActiveRange() etc.).
I'd really like for this to work, but I can only do it currently by placing a button at the top of the sheet which the user has to click to run the script. I'm at a loss as to how to write in a different way, and have spent ages googling but only get things which don't help me much at all. My code is as below, any help you can give in writing it without using Activate() methods would be very much appreciated. Thanks, MB
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange("A2");
var rowCount = range.getValue() + 3;
var newRange = ss.getRange("A" + rowCount);
SpreadsheetApp.setActiveRange(newRange); };
The value on line 4 refers to a value in a cell which is counting the number of rows in the dataset (I had issues trying to count this using script because there are other columns in the dataset which throw functions like getLastRow()).
As mentioned in issue 3928 there is no way (as of now, september 2014) to set a selection on a cell/range/sheet from a triggered function.
This issue was closed as "wont fix" but recently reopened - probably because a lot of people were very disappointed (to use a polite word) - so I suggest you star this issue to increase its visibility and its priority.
In the mean time I'm afraid there is not much we can do except continue to use old version spreadsheet in which this works without problem.
About what you said about counting the last row in a single column, this has been the subject of one of the most popular thread on this forum, look at the suggested solutions there (and also in other similar threads).

How can I return the range of an edited cell using an onEdit event?

This seems like it should be easy as pie, but I can't seem to get any of my little test implementations to work. The ultimate goal is to create a function that runs only when cells in a certain range are edited. To accomplish this, I am creating a function that runs on every edit but starts by checking to see if the range of the edited cell is within a certain range, and only executing the rest of the code if this is true, and otherwise, it just ends immediately.
The first step in doing this, it seems to me, is to find out how to return the range of the edited cell. I've tried various tests.
Here is the current version, which I test by editing the spreadsheet:
function onEdit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var eRange = e.range;
var message = eRange.getA1Notation();
ss.toast(message);
}
(output: toast does not appear/nothing happens)
I had about 10 other versions posted here, but I realized it was not helpful.
I've managed to return [object Object] and [undefined] in my toast message, so I know I'm not making some silly error with my toast function.
Doesn't e.range return a range? Is that where I go wrong? If it returns a range, shouldn't I be able to use any of the methods in range, just as if I'd used something like "ss.getRange("A1").someMethod()"? Or is there some difference that I don't understand?
Okay, I realize I've asked a couple of different questions here-- I'm just trying to give a clearer picture of my thought process in case it helps you to correct me where I'm wrong. The simple question is this: what sort of command or method can I use to return the range of an edited cell?
I'm so sorry to ask such a basic question. I'm really afraid that someone will enter the right combination of search terms and the answer will be right on the top of the results... but I just can't seem to find it on my own, so here I am. I've tried lots of snippets of code from both StackOverflow and the old Google Groups support forum, as well as lots of my own attempts. I see people have asked lots of similar questions regarding my ultimate goal here-- only running the onEdit function if cells in a certain range are edited-- but the answers are all more complex and seem tailored to each individual situation, and they don't fit mine. I'm certain the answer is out there, but I've been searching for three straight evenings now and found many similar questions asked, and just can't seem to get my own implementation of those suggestions to work. Thanks for being patient with me, and thank you so much for any answers you can offer!
here is the code taken (and slightly modified) from the doc :
function onEdit(event){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = event.source.getActiveSheet();
var r = event.source.getActiveRange();
r.setComment("Last modified: " + (new Date())+' by '+Session.getActiveUser());
ss.toast('Last cell modified = '+r.getA1Notation()+' by '+Session.getActiveUser());
}