'Copy data from one spreadsheet file to another
I have a Google spreadsheet that I use to track my open crypto trades. The information consists of 4 columns. ("Coin", "Date", "Time" and "Price"). This information is not available to the public. When trades are closed I complete the next 3 columns ("Date", "Time" and "Price") and copy all 7 columns across to a different spreadsheet that is available to the public. There are other columns in this public spreadsheet that contain formulae that calculate trade profit and loss, weekly summary and monthly summary.
I have written the following code in Google Apps Script and attached it to a button on one of the spreadsheets to automate this task. I need all users to be able to run the code by clicking the button. Currently there are 4 users. My code does all of this automatically except, because I open a new spreadsheet part way through the script, none of the values collected before that point are available to be inserted into the target spreadsheet.Any help would be greatly appreciated.
function updatePublicSheet(){
var coinBought;
var dateBought;
var timeBought;
var priceBought;
var dateSold;
var timeSold;
var priceSold;
var lrIndex;
var sss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1cBGpD0nUqCGtQqq78svw4fxA4ZgwBqV2yzIbgY1tY2o/edit#gid=1107419239");
var sSheet = sss.getSheetByName('SS Open Trades');
var sRng = sSheet.getRange("F3:H").getValues();
// Find last entry in columns F, G or H in the Open Trades sheet
for (var i = sRng.length-1;i>=0;i--){
var lrIndex = i;
if (!sRng[i].every(function(c){return c == "";})){
break;
}
}
// Logger.log("Last row is %s", lrIndex + 3);
// Check that the closed information has been added to all columns
// index 6 = 6th column = F = dateSold
// index 7 = 7th column = G = timeSold
// index 8 = 8th column = H = priceSold
if ((sSheet.getRange((lrIndex + 3),6).getValue().length) == 0 ||
(sSheet.getRange((lrIndex + 3),7).getValue().length) == 0 ||
(sSheet.getRange((lrIndex + 3),8).getValue().length) == 0){
//Logger.log("Trade close information is not complete");
return;
}
// If there is a complete closed entry, copy the values to the variables
if (lrIndex > 0)
{
coinBought = sSheet.getRange((lrIndex + 3),2).getValue();
dateBought = sSheet.getRange((lrIndex + 3),3).getValue();
timeBought = sSheet.getRange((lrIndex + 3),4).getValue();
priceBought = sSheet.getRange((lrIndex + 3),5).getValue();
dateSold = sSheet.getRange((lrIndex + 3),6).getValue();
timeSold = sSheet.getRange((lrIndex + 3),7).getValue();
priceSold = sSheet.getRange((lrIndex + 3),8).getValue();
//Logger.log(coinBought);
}
var tss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1umkTCr95FZUrZzv0e_ZDD9QZYiiYuH1fJohPYQzNE9Q/edit#gid=1644116137");
var tSheet = tss.getSheetByName('Trade Tracker');
var tRng = tSheet.getRange("A3:H").getValues();
// Create a new row at Row 4 on the Trades Tracker Sheet
tSheet.insertRows(5, 1);//shift all rows down by one from row 5
// Copy values from row 4 to row 5, including the formulae
var tRange = tSheet.getRange(4, 1, 1, 26);
tRange.copyTo(tSheet.getRange(5, 1, 1, 26), {contentsOnly:false});
// Populate row 4, first 7 table columns, from the variables
//Logger.log(coinBought);
tSheet.getRange(4,2).setValue(coinBought);
tSheet.getRange(4,3).setValue(dateBought);
tSheet.getRange(4,4).setValue(timeBought);
tSheet.getRange(4,5).setValue(priceBought);
tSheet.getRange(4,6).setValue(dateSold);
tSheet.getRange(4,7).setValue(timeSold);
tSheet.getRange(4,8).setValue(priceSold);
// Sort the sheet by date/time closed
// Find last entry in Trade Tracker sheet
for (var i = tRng.length-1;i>=0;i--){
var lrIndex = i;
if (!tRng[i].every(function(c){return c == "";})){
break;
}
}
Logger.log("Last row is %s", lrIndex + 4);
var tRange = tSheet.getRange(4, 2, lrIndex + 4, 11)
tRange.sort([{column: 6, ascending: false}, {column: 7, ascending: false}]);
// On the source sheet, delete the row just copied and add another blank row
// Success message
}
Solution 1:[1]
Issue:
The script should run under an account that has access to the source spreadsheet. Therefore, executing this via button will not work, since the function will always execute under the user who clicked the button, and that, as I understood, might not have access to the non-public spreadsheet.
Solution:
Therefore, you should execute it a different way. I'd suggest the following:
- With an account that has access to the source spreadsheet, install an
onEdittrigger, either manually, by following these steps, or programmatically, by copying this function to your editor and executing it once:
function installOnEdit() {
var sss SpreadsheetApp.openByUrl("TARGET_SPREADSHEET_URL");
ScriptApp.newTrigger("updatePublicSheet")
.forSpreadsheet(sss)
.onEdit()
.create();
}
- Add a checkbox to a cell in the target spreadsheet.
- Modify your function so that it only updates a spreadsheet if the checkbox cell is edited. You can use the event object for this:
function updatePublicSheet(){
var range = e.range;
var sheet = range.getSheet();
var sheetName = "CHECKBOX_SHEET"; // Name of the sheet where the checkbox is found, change accordingly
var checkboxNotation = "A1"; // Notation of the checkbox cell, change accordingly
if (sheet.getName() === sheetName && range.getA1Notation() === checkboxNotation) {
// YOUR OLD CODE
range.uncheck();
}
}
Once you do that, every time the checkbox is clicked by anyone, the taget spreadsheet is updated.
Note:
- Using
getValueandsetValueto get or set values to multiple cells is not recommended. You can use getValues and setValues to grab and modify many cell values at once, minimizing the amount of calls to the Sheets service you make. See Best practices.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
