I have a script that copies a certain cell when a new form is submitted, (which contains a drop down list, on sheet "Validation") and pastes it into the first blank cell in column A on the sheet "Internal Recruitment Requests".
The code is not copying into the right cell.
Below is the current script, which doesn't work.
I am running it with onEdit at the moment for testing purposes.
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Validation');
var sheet2 = ss.getSheetByName('Internal Recruitment Requests');
var lastEmptyOnColumnA = sheet2.getRange("A1:A" + sheet2.getLastRow()).getValues().join(",").replace(/,,/g, '').split(",").length;
var DVcopyFrom = sheet1.getRange("A4");
var DVcopyTo = sheet2.getRange('A' + lastEmptyOnColumnA);
sheet1.getRange(DVcopyFrom).copyToRange(sheet2.getRange(DVcopyTo), {contentsOnly:false});
}
Bingo, all sorted. used the below script which was a tiny tweak on what you had given me. thanks for the help :)
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Validation');
var sheet2 = ss.getSheetByName('Internal Recruitment Requests');
var lastRowSheet2 = sheet2.getLastRow();
var cellRefLastRowSheet2 = "A1:A" + lastRowSheet2.toString();
var cellRefLastRowSheet2Empty = "A" + lastRowSheet2.toString();
var lastEmptyOnColumn_A_Sheet2 = sheet2.getRange(cellRefLastRowSheet2);
var DVcopyFromValue = sheet1.getRange("A4");
var contentOfLastCell = sheet2.getRange(cellRefLastRowSheet2Empty).getValue();
if (contentOfLastCell === "")
{
DVcopyFromValue.copyTo(sheet2.getRange(cellRefLastRowSheet2Empty));
}
}
Related
I have found so many scripts to copy values only from one spreadhseet to another. However, all of them is to copy the whole spreasheet.
I am very new with google script and cannot find a way to copy values only from specific tabs to another spreasheet adding these new tabs to it.
function temp() {
var sss = SpreadsheetApp.openById('XYZ'); // sss = source spreadsheet
//var ss = sss.getSheets()[4]; // ss = source sheet
var ss = sss.getSheets(); // ss = source sheet
var id=4; //default number
for(var i in ss)
{
var sheet = ss[i];
if(sheet.getName()== "ABC")
{ id=i;
break;
}
}
console.log(id);
ss=sss.getSheets()[id];
//Get full range of data
var SRange = ss.getDataRange();
//get A1 notation identifying the range
var A1Range = SRange.getA1Notation();
//get the data values in range
var SData = SRange.getValues();
SpreadsheetApp.flush();
var tss = SpreadsheetApp.getActiveSpreadsheet(); // tss = target spreadsheet
var ts = tss.getSheetByName('ABC'); // ts = target sheet
//set the target range to the values of the source data
ts.getRange(A1Range).setValues(SData);
}
Thanks a lot in advance.
Issue:
You can to copy the values from a specific set of sheets to a new spreadsheet.
I assume that you don't want to copy the sheet itself, but only the values from the source sheet.
Modifications:
Use filter to get an array of your desired sheets (based on sheet name).
If the target spreadsheet doesn't have a sheet with that name, create it with Spreadsheet.insertSheet.
Code sample:
function temp() {
var sheetNames = ["ABC", "DEF"]; // Change accordingly
var sss = SpreadsheetApp.openById('XYZ');
var sheetsToCopy = sss.getSheets().filter(s => sheetNames.includes(s.getSheetName()));
sheetsToCopy.forEach(ss => {
var sourceSheetName = ss.getSheetName();
var SRange = ss.getDataRange();
var A1Range = SRange.getA1Notation();
var SData = SRange.getValues();
var tss = SpreadsheetApp.getActiveSpreadsheet();
var ts = tss.getSheetByName(sourceSheetName);
if (!ts) ts = tss.insertSheet(sourceSheetName);
ts.getRange(A1Range).setValues(SData);
});
}
Copy these sheets to another spreadsheet
function copythese() {
const ss = SpreadsheetApp.getActive();
const these = ['Sheet0','Sheet1'];//Put your sheetnames here
const another = SpreadsheetApp.openById("another id");//put the other spreadsheet id here
ss.getSheets().filter(sh => ~these.indexOf(sh.getName())).forEach(sh => {
sh.copyTo(another);
});
}
Append These Values to another spreadsheet
function appendthesevalues() {
const ss = SpreadsheetApp.getActive();
const these = ['Sheet0','Sheet1'];
const another = SpreadsheetApp.openById("another id");
ss.getSheets().filter(sh => ~these.indexOf(sh.getName())).forEach(sh => {
let vs = sh.getDataRange().getValues();
let nsh = another.getSheetByName(sh.getName());
if(!nsh) {
nsh = another.insertSheet(sh.getName());
SpreadsheetApp.flush();
}
if(nsh) {
nsh.getRange(nsh.getLastRow() + 1, 1 ,vs.length, vs[0].length).setValues(vs);
}
});
}
Here is my coding. Help me out.
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").activate();
var lr = ss.getLastRow();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1,1).getValue();
//for (var i =2;i<=lr;i++){
var currentEmail = column(i,1);
var currentClass = column(i,3).getValues();
var currentName = ss.getRange(i,2).getValues();
var messageBody = templateText.replace("{name}",currentName).replace("{class}",currentClass);
var subjectLine = "Reminder:" + currentClass + " Upcoming Class";
MailApp.sendEmail(currentEmail,subjectLine,messageBody);
Issue:
There are many issues in your code, including undefined variables (e.g. column, i), but I think you want to do the following:
Send an email for each row in Sheet1, taking into account that:
recipient is in column A.
subject is based on the value of column C.
The message body is built by replacing the keywords {name} and {class} from a string template found in Template!A1 with the values of column B and C respectively.
Code snippet:
If the above is correct, you can do the following:
function yourFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Sheet1");
var firstRow = 2;
var numRows = sheet1.getLastRow() - firstRow + 1;
var templateText = ss.getSheetByName("Template").getRange(1,1).getValue();
var values = sheet1.getRange(firstRow,1,numRows,3).getValues(); // Retrieve data from all rows
values.forEach(row => { // Iterate through each row
var [currentEmail, currentName, currentClass] = row; // Get values from columns A-C
var messageBody = templateText.replace("{name}",currentName)
.replace("{class}",currentClass);
var subjectLine = "Reminder:" + currentClass + " Upcoming Class";
MailApp.sendEmail(currentEmail,subjectLine,messageBody);
});
}
Reference:
Tutorial: Sending emails from a Spreadsheet
Best Practices
I Have data in "Form responses 1". I want to move data from "Form responses 1" sheet to "Verified Form Response" Sheet. The condition is that entries which are marked as True in Column W should move, not all the entries.
The link of the sheet is:
https://docs.google.com/spreadsheets/d/1LUUEZ7sSjBy-WWL3TZt8l6sqtrEBn3dZ03iRDTY1bF0/edit?usp=sharing
The code I am using is:
function copyInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Form responses 1");
var pasteSheet = ss.getSheetByName("Sheet5SS");
var pasteSheet_size=pasteSheet.getRange('A2:A').getValues().filter(String).length;
var source_size=copySheet.getRange('A2:A').getValues().filter(String).length;
var source_range = copySheet.getRange(1,1,source_size,copySheet.getLastColumn());
var move_data = source_range.getValues().filter(row=>row[23]==true);
var source_data = source_range.getValues().filter(row=>row[23]==false);
pasteSheet.getRange(pasteSheet_size+1,1,move_data.length,move_data[0].length).setValues(move_data);
source_range.clearContent();
copySheet.getRange(1,1,source_data.length,source_data[0].length).setValues(source_data);
}
Explanation:
You are very close.
You need to start the range from the second row:
copySheet.getRange(2,1,source_size,copySheet.getLastColumn());
and the checkboxes are in column W, therefore in column number 22:
filter(row=>row[22]==true);
Solution:
function copyInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Form responses 1");
var pasteSheet = ss.getSheetByName("Verified Form Responses");
var pasteSheet_size=pasteSheet.getRange('A2:A').getValues().filter(String).length;
var source_size=copySheet.getRange('A2:A').getValues().filter(String).length;
var source_range = copySheet.getRange(2,1,source_size,copySheet.getLastColumn());
var move_data = source_range.getValues().filter(row=>row[22]==true);
var source_data = source_range.getValues().filter(row=>row[22]==false);
pasteSheet.getRange(pasteSheet_size+1,1,move_data.length,move_data[0].length).setValues(move_data);
source_range.clearContent();
copySheet.getRange(2,1,source_data.length,source_data[0].length).setValues(source_data);
}
I have a Google Spreadsheet with 3 different sheets that you can see here.
What I would like to do is per each person in the 'person' sheet, create a row of the person in the 'stacs' sheets that will be repeated as many times based of the number of 'meals' that we have in the 'meals' sheet. So, per each person, I want to create personA + meal1 in row #1, personA + meal2 in row #2, personA + meal3 in row #3, etc.
I figured it out how to do this repeating the same code over and over again. The code works but it's very inefficient. I guess that there has to be a way of doing the same repetition that I'm doing in a much cleaner and simpler way. I'm just learning how to you use some scripting to improve my spreadsheet so any help with this will be very welcome!
Some Caveats:
If you take a look at the spreadsheet, you will see that I'm using formulas in some cell to calculate the last row with value or the sizes of the ranges.
In the 'meals' tab I have defined a name range with the meals. I'm not very proud of this, because the list of the meal will grow so I wonder if there is a more dynamic way of dealing with this instead of adjusting the range every time I add a new meal.
Here is the code that you also find in the spreadsheet:
function copyValuesA() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("names");
var name = sheet.getRange("A2");
var sheetMeals = ss.getSheetByName("meals");
var rangeMeals = sheet.getRange("mealsNames");
var sheetstacs = ss.getSheetByName("stacs");
var lastRow = sheetstacs.getRange("B1").getValue();
var mealCount = sheetstacs.getRange("D1").getValue();
var lastRowMeals = sheetstacs.getRange("C1").getValue();
var rangeOrigname01 = sheetstacs.getRange("A" + lastRow + ":A" + mealCount);
var rangeOrigname02 = sheetstacs.getRange("A1");
name.copyTo(rangeOrigname01);
var rangeDestMeals01 = sheetstacs.getRange("B" + lastRowMeals);
rangeMeals.copyTo(rangeDestMeals01);
}
function copyValuesB() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("names");
var name = sheet.getRange("A3");
var sheetMeals = ss.getSheetByName("meals");
var rangeMeals = sheet.getRange("mealsNames");
var sheetstacs = ss.getSheetByName("stacs");
var lastRow = sheetstacs.getRange("B1").getValue();
var mealCount = sheetstacs.getRange("D1").getValue();
var lastRowMeals = sheetstacs.getRange("C1").getValue();
var rangeOrigname01 = sheetstacs.getRange("A" + lastRow + ":A" + mealCount);
var rangeOrigname02 = sheetstacs.getRange("A1");
name.copyTo(rangeOrigname01);
var rangeDestMeals01 = sheetstacs.getRange("B" + lastRowMeals);
rangeMeals.copyTo(rangeDestMeals01);
}
function copyValuesC() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("names");
var name = sheet.getRange("A4");
var sheetMeals = ss.getSheetByName("meals");
var rangeMeals = sheet.getRange("mealsNames");
var sheetstacs = ss.getSheetByName("stacs");
var lastRow = sheetstacs.getRange("B1").getValue();
var mealCount = sheetstacs.getRange("D1").getValue();
var lastRowMeals = sheetstacs.getRange("C1").getValue();
var rangeOrigname01 = sheetstacs.getRange("A" + lastRow + ":A" + mealCount);
var rangeOrigname02 = sheetstacs.getRange("A1");
name.copyTo(rangeOrigname01);
var rangeDestMeals01 = sheetstacs.getRange("B" + lastRowMeals);
rangeMeals.copyTo(rangeDestMeals01);
}
function copyValuesAll() {
copyValuesA();
copyValuesB();
copyValuesC();
}
If your interested in a dynamic formula to accomplish this:
in your stacs sheet in column A cell 2 put:
=TRANSPOSE(SPLIT(JOIN(";",ARRAYFORMULA(REPT(A2:A&";",COUNTA(meals!$A$2:$A)))),";"))
and in cell B2:
=TRANSPOSE(SPLIT(ARRAYFORMULA(REPT(JOIN(";",meals!$A$2:$A$8),COUNTA(names!A2:A))),";"))
doing this will automatically account for new values
This code gets values from different locations in my sheet and writes the combined data to another sheet.
Problem is, if the row is blank, the code copies a blank row into the receiving sheet. I would like to first check cell "B8", and if it is blank, skip this function and run the next function.
If cell "B8" has data in it (anything, but it will usually be a date), then I would like to run the function to copy the code to the new sheet.
Here is my code:
function submitButtonClick() {
//Begining of entry8 transfer start.
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
Logger.log('sheet.getName(): ' + sheet.getName());
if (sheet.getName() !== "TimeCardEntry") {return;};
var targetSheet = ss.getSheetByName("TimeSheetRecord");
var arrayOfData = [];
var weekBegining = sheet.getRange(4, 11).getValue();
var employName = sheet.getRange(4, 4).getValue();
var entry8 = sheet.getRange(8,2,1,9);
var entry8Data = entry8.getValues()[0];//Get inner array of the rows data
Logger.log('entry8Data: ' + entry8Data);
//Add weekBegining and employName values to the array
entry8Data.splice(0, 0, weekBegining, employName);
//Push row data into another, outer array. setValuies() needs a 2D array.
arrayOfData.push(entry8Data);
Logger.log(arrayOfData);
var lastRow = targetSheet.getLastRow();
Logger.log('lastRow: ' + lastRow);
targetSheet.getRange(lastRow+1, 1, 1, entry8Data.length).setValues(arrayOfData);
sheet.getRange('B8:M8').clearContent();
//End of entry8 transfer.
}
You could add some code in between these line:
var arrayOfData = [];
var weekBegining = sheet.getRange(4, 11).getValue();
Change to:
var arrayOfData = [];
var B8_Value = sheet.getRange(8, 2).getValue();
if (B8_Value === "") {return;};//If cell value is empty stop code here
var weekBegining = sheet.getRange(4, 11).getValue();