Automatically Copy Data Between Google Sheets - google-apps-script

I am looking for some help automating copying data between google sheets.
I have a sheet called "Current Data". This sheet has data in columns A-F(with headers).
Column A contains usernames. Columns B-F will have formulas which pulls data from Instagram.com using
=VALUE(REGEXEXTRACT(IMPORTXML(
I got the formulas from this website:
https://www.benlcollins.com/spreadsheets/import-social-media-statistics/
There is another sheet called "Historical Data". This sheet contains the same columns as "Current Data" (A-F, with headers).
This sheet contains all data from the "Current Data" sheet, pasted daily.
My Current Process:
Open Sheet Navigate to "Current Data" sheet, copy values from A2-FXXX
Navigate to "Historical Data" sheet, scroll to next blank row, paste
data.
I am looking to automate this and have it occur daily.
I am using this script to automatically update my IMPORTXML function. This works great.
Periodically refresh IMPORTXML() spreadsheet function
I am copying the values from the Current Data sheet to the Historical
Data sheet, using this script.
copy and paste with google spreadsheet script.
This script also works, but it is only copying the first line of data to the destination. The script is also wiping the data from the Current Data sheet.
I removed the "source.clear ();" from the code, but the
data still gets wiped.
I also tried using this script, as some people mentioned users needed to use appendRow instead of copyTo. Still no luck with this code:
function moveValuesOnlyy() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange("CurrentData!A2:F100");
var destSheet = ss.getSheetByName("HistoricalData");
destSheet.appendRow(source.getValues());
}
In the end I am looking for the script to:
Find and copy the data range from the "Current Data" sheet, starting with A2.
Find next empty row on "Historical Data" sheet.
Paste as values.
Any help would be greatly appreciated, thank you!

Try this:
function copyPaste() {
var ss=SpreadsheetApp.getActive();
var srcsh=ss.getSheetByName('CurrentData');
var dessh=ss.getSheetByName('HistoricalData');
var srcrg=srcsh.getRange('A2:F100');
var data=srcrg.getValues();
var desrg=dessh.getRange(dessh.getLastRow() + 1,1,99,6);
desrg.setValues(data);
}

Related

How to have a reference to a sheet bound to the name instead of the sheet

I'm making a spreadsheet to format the responses of a google form. However, this form will be given every week; ideally, I would like to import the form responses into this spreadsheet, have the formatted data sheet now use this new responses sheet instead of the older one, without having to update the formulae in the data sheet. But if I try to do this by renaming the new data sheet to what the old one was called, it keeps the old sheet reference and updates its name in all the formulae.
I haven't found any solutions from a few google searches. Is there an easy way to get around this?
EDIT: here is an example spreadsheet. Ideally, I want the data in 'Formatting Sheet' to be retrieved from 'New Sheet' instead of old sheet. However, I don't want to have to change all of the formulae in 'Formatting Sheet' to reflect this, as this will be a transition I do regularly. Unfortunately renaming the sheets preserves the reference.
You want to use the values at the sheet Formatting Sheet by replacing the values in the sheet Old Sheet with new values in the sheet New Sheet.
In your current issue, even when the sheet name is changed, the values cannot be updated.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
In your case, even when the sheet name is changed, the sheet ID is not changed. By this, the formula uses old values. I think that the reason of your issue is this. In this answer, in order to achieve your goal, Google Apps Script is used.
Flow:
The flow of the sample script is as follows.
Retrieve the sheet object of New Sheet and Old Sheet, which are the source sheet and destination sheet, respectively.
Backup Old Sheet.
In you don't want to backup it, please remove destinationSheet.copyTo(ss).setName(destinationSheet.getName() + "_backup_" + new Date().toISOString());.
Copy the values from New Sheet to Old Sheet. By this, the values are replaced. And at Formatting Sheet, the new values are used.
Sample script:
Please copy and paste the following sample script to the script editor of your shared Spreadsheet. And run myFunction().
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("New Sheet");
var destinationSheet = ss.getSheetByName("Old Sheet");
// Backup "Old Sheet".
destinationSheet.copyTo(ss).setName(destinationSheet.getName() + "_backup_" + new Date().toISOString());
// Put values from "New Sheet" to "Old Sheet"
sourceSheet.getDataRange().copyTo(destinationSheet.getRange(1, 1));
}
When you run the script of myFunction(), you can see the result calculated by new values at the sheet of Formatting Sheet.
References:
copyTo() in Class Sheet
copyTo() in Class Range

Apps Script: how do you copy values from specific columns to a different spreadsheet via a time trigger, button press or sheet update?

I need to copy the values of multiple ranges of data from my main spreadsheet into another spreadsheet and then copy a different range of data back to the main spreadsheet.
Here are my example spreadsheets:
The main spreadsheet (two sheets: 1 - A sheet of pasted values alongside columns of user comments. 2 - A sheet with a button that runs the Apps Script)
The live data spreadsheet (pulls and formats the required data from other sheets).
Previously, I’ve used .copyTo() to copy the values of data and paste them elsewhere on the same spreadsheet. However, this method can’t be used to copy data to a different spreadsheet. Copying data from multiple ranges is also causing me issues. Here is my code:
function RefreshSheetData() {
// 1a. Run the script when a button is pressed (Main Spreadsheet - ‘Update report button!A3’)
// 1b. Run the script at a certain time (every Monday at 10 AM)
// 1c. Run the script when data in a sheet is replaced with new data via a formula – NOT POSSIBLE.
// 2. Copy email address and user comments (Main Spreadsheet - Editable report - J3:J & AM3:AR)
// 3. Clear the “Updated user comments” sheet below the header row (Live data Spreadsheet - Updated user comments - A2:G)
// 4. Paste the values (Live data Spreadsheet - Updated user comments - A2:G)
// 5. Clear the “Editable report” below the header rows (Main Spreadsheet - Editable report – B3:AR)
// 6. Copy the Live sheet (which should now include the most recent user comments via array vlookup) (Live data Spreadsheet - live data – A3:AQ)
// 7. Paste the values (Main Spreadsheet - Editable report - B3:AR)
// 8. Add the (United Kingdom) time and date (Main Spreadsheet - Update report button - A10)
// 9. Add the time and date (Live data Spreadsheet - Updated user comments - J1)
ScriptApp.newTrigger('RefreshSheetData')
.timeBased()
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.atHour(10)
.create();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var startSheet = ss.getSheetByName('Editable report');
var sourceRange = startSheet.getRangeList(['J3:J', 'AM3:AR']);
var sourceValues = sourceRange.getValues();
var target = SpreadsheetApp.openById('1OHQHefYvE4vZZPr8jgziy_L3-UBf1WSoKzMWQ8LUz6w');
var targetSheet = target.getSheetByName('Updated user comments');
var clearTargetRange = targetSheet.getRange('A2:G').clearContent();
var targetRange = targetSheet.getRange('A2').setValues(sourceValues);
var liveTargetSheet = target.getSheetByName('Live data');
var liveSourceRange = liveTargetSheet.getRange('A3:AQ').getValues();
var clearMainRange = startSheet.getRange('B3:AR').clearContent();
var startRange = startSheet.getRange('B3').setValues(liveSourceRange);
SpreadsheetApp.getActive().getRange('A10').setValue(new Date());
targetSheet.getRange('J1').setValue(new Date())
}
Any tips would be appreciated. Thank you.
Part of my question was how to trigger a script when a formula output changes. That’s not possible. Neither .onEdit or .onChange triggers work as they only respond to user actions. They won't run when the value of an IMPORTRANGE or alternative formula changes.
Here some suggestions referring to each of the steps mentioned in your Apps Script file
1b. To run the script at a certain time: please use the installable trigger "Time driven"
1c. To run the script when data in the sheet is updated: please use the onEdit trigger
1d. You can combine all triggers by simply adding as many, as required.
To copy and paste data, you just need the methods getValues() and setValues(), which you were using already, the important thing is that you chose the "to copy" range correctly.
You can clear a range with clear()
See 3.
You can copy a sheet with copyTo(), however keep in mind that if using this method, your data in the copied sheet will automatically be updated if there is a change in the original sheet. If you want the values to remain static, you have to copy and paste them with copyValues() and setValues().
See 2. and 5.
See here how to get and format the date in Apps Script
Assign the date to a variable and use setValue()
I encourage you to try and build the script based on those steps
yourself, the Apps Script documentation provides you good reference
and guidance, how to do so. If you encounter specific problems during
one of the steps which you cannot solve with the documentation, feel
free to ask!

Trigger a script when a formula changes a cell value

I'm using a Google script then sends out an email when a certain column in a Google sheet is changed. The information in the cell is either inputted manually, or completes using a formula based on information in other cells.
The script works fine when information is manually entered, but not when the formula runs. I've read up on it and realise that a formula calculation doesn't count as an edit, so how do I get the script to run?
It's currently set up to trigger from the spreadsheet when there's an edit.
Below is the part of my script that covers the column/cell in question.
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
if(sheet.getActiveRange().getColumn() == 12)
There's a lot more included in the script so I haven't copied everything onto here. Many thanks in advance.
There is no trigger that can run when a formula changes.
Try figure out, what conditions is your formula depends on:
if it is another cell, entered manually, then use those cell to trigger it's changes with onEdit
if the formula imports data from external source, use random or time functions, you'd better use onTime trigger.
if the formula uses importrange then go to the range you import and see the original range, return to step 1 → 2...

How to make a copy of a Google spreadsheet with formulas, not only values?

I have a master Google Sheet with formulas. The user enters some details and the script then makes a copy of the sheet using the copy method:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var tmpSS = ss.copy(bookID + "-" + title);
When I open the new spreadsheet, there are only values in the cells, the formulas have not been copied over. How do I copy over the formulas as well?
Try using this :
var sheetId = SpreadsheetApp.getActiveSpreadsheet().getSheetId();
DriveApp.getFileById(sheetId).makeCopy("SheetName");
As mentioned here: GAS-copyto, the method copyTo on sheet should make a copy of the sheet with values and formulae. So maybe you could write a loop to create copies of all sheets of a given spreadsheet, using this.
As per the documentation you can use .getFormulas() and .setFormulas() to copy over formulas. You can copy to any sheet or spreadsheet you have access to.

Google Spreadsheets with Form Vinculated copy

I'm trying to copy a spreadsheet with the responses of a form thought drive API.
https://developers.google.com/drive/v2/reference/files/copy
All files from my drive are working fine but only this spreadsheet that persist my form answers that create a duplicate form instead of only copying the spreadsheet itself.
You can try to reproduce the problem using the given Id. After copying you will notice that both spread sheet and form will be copied. This should not be a problem if I could erase the form but in the response of the copy procedure I don't get any advice about the form that is being copied together.
File id: 0Aqq-9JjR-lUydHRKVEJ2SThGMjJlVjVqczkyWlVCWUE
Please, help me. I'm desperate.
If you are only trying to copy the spreadsheet of the form, try this:
var fromSheet = ***whatever***;//this is the sheet attached to your form
var toSheet = ***whatever***;//this will be the sheet that you are copying to
var range = **whatever***;//this is the range you are copying over. If you are using dynamic ranges (ie varying number of rows), you may want to **getDataRange()** and **getLastRow** to build a more flexible range
function myCopyCat(){
myValues = fromSheet.getRange(range).getValues();//'copies' all of your data within range from fromSheet to an array
toSheet.getRange(range).setValues(myValues);//'pastes' all of your data into cells on toSheet
}