Copy Paste into formula as apps script - google-apps-script

I'm trying to run a google apps script which takes a series of importrange functions and puts them into an arrayformula query. I've successfully created a cell which actively accumulates the correct links for use in the importrange and puts it into a cell as a string. All I need the script to do is to copy that string and paste it as a formula in another cell. I can do this manually pretty easily, but I'd like to be able to set it up on a timer so it does it automatically on a certain time period.
As far as I've gotten is below and it doesn't work at all:
function Update Import Ranges() {
var spreadsheet = SpreadsheetApp.getActive();
var source = spreadsheet.getRange('B2').activate();
spreadsheet.getCurrentCell('B3').setFormula(???);
spreadsheet.getRange('B3').activate();
};

accumulates the correct links for use in the importrange and puts it into a cell as a string
The importrange() function only accepts two parameters: one for the spreadsheet to read from, and another to specify which range in the spreadsheet to return. To read from several spreadsheets and/or ranges with importrange(), you will have to create several formulas.
Alternatively, use an Apps Script function that mimics importrange() but supports multiple spreadsheets and ranges, such as the ImportMultipleRanges() function. You could call it like this:
function updateDataFromOtherSpreadsheets() {
var rangeToUpdate = "All Data!A2";
var sourceSpreadsheetKeysRange = "Config!B2:B5";
var sourceSpreadsheetDataRange = "Config!C2:C5";
var add_spreadsheet_name_prefix = false;
var add_sheet_name_prefix = false;
var ignore_blank_rows = true;
var ss = SpreadsheetApp.getActive();
var spreadsheet_keys = ss.getRange(sourceSpreadsheetKeysRange).getValues();
var range_strings = ss.getRange(sourceSpreadsheetDataRange).getValues();
var data = ImportMultipleRanges(spreadsheet_keys, range_strings, add_spreadsheet_name_prefix, add_sheet_name_prefix, ignore_blank_rows);
ss.getRange(rangeToUpdate).offset(0, 0, data.length, data[0].length).setValues(data);
}
To answer your question, you can fix the syntax errors and semantics in your function like this:
function updateImportrangeFormula() {
const sheet = SpreadsheetApp.getActiveSheet();
const ssId = sheet.getRange('B2').getValue();
const rangeA1 = sheet.getRange('C2').getValue();
const formula = '=importrange("' + ssId + '", "' + rangeA1 + '")';
sheet.getRange('B3').setFormula(formula);
}

Related

Google App Script Function: Return Drive Filename from File URL

I've searched extensively for an answer to this, but have not had much luck. I think it should be a fairly simple answer. Here's what I'm trying to do:
I have a list of (other) Google Sheets document URLs in a Google Sheet.
I'd like to have a simple function that loads the URL in each line and returns the file name.
To illustrate, if the URLs are in A2:A10, a user could input a custom function like =GetFileName(A2) and it would return the file name corresponding to the Google Sheet URL that is in A2.
Here's the code that I have thus far, but it's returning an error, " TypeError: SpreadsheetApp.openByURL is not a function (line 3)."
function getFileName(fileURL) {
var GetFile = SpreadsheetApp.openByURL(fileURL);
var GetName = GetFile.getName();
return GetName;
}
UPDATE *************
Here's the code that worked for me. Basically, it loops through the sheet with IDs to pull file names. Not the most efficient, but works for relatively short lists just fine.
function getFileName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// DocumentIDs are listed in the 'tool' sheet
var targetSheet = ss.getSheetByName("tool");
// Find the last row
var LastRow = targetSheet.getLastRow();
//Loop Begins
//Initializing variable assumes that the first valid Drive ID is in the 3rd row.
for(var i = 3; i < LastRow; i++) {
// Get the Document ID. This gets the Document ID
var LookupID = targetSheet.getRange(i,1).getValue();
// Get the Filename
var FileOpen = SpreadsheetApp.open(DriveApp.getFileById(LookupID));
var FileName = FileOpen.getName();
// Write the FileName in the second column
targetSheet.getRange(i,2).setValue(FileName);
Logger.log(i);
Logger.log(LookupID);
Logger.log(FileName);
}
}
Suggestion:
You can try this script together with using clickable image to act as a button for the function to run the script below:
function convertURLtoSheetName() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var cell = ss.getActiveCell().getValue();
var getSheetName = SpreadsheetApp.openByUrl(cell).getName();
var seturl = SpreadsheetApp.newRichTextValue().setText(getSheetName).setLinkUrl(cell).build();
ss.getActiveCell().setRichTextValue(seturl);
}
Here is how you assign a script function to an image:
Custom Functions Cannot open other spreadsheets (SpreadsheetApp.openById() or SpreadsheetApp.openByUrl()).
reference

Values from Ranges by named ranges to variables

I have many named ranges in Spreadsheet.
I need get values from areas by current row (e) and current column by namedranges and write it to variables. I write a lot of the same script
function sendEmailClerck(e){
var sheet = SpreadsheetApp.getActive().getSheetByName('Ответы на форму (1)');
var idRow = e.range.getRow();
var name = sheet.getRange(idRow, SpreadsheetApp.getActiveSpreadsheet().getRangeByName('ReqUser').getColumn()).getValue();
var cli = sheet.getRange(idRow, SpreadsheetApp.getActiveSpreadsheet().getRangeByName('ReqCLI').getColumn()).getValue();
var priority = sheet.getRange(idRow, SpreadsheetApp.getActiveSpreadsheet().getRangeByName('ReqPriority').getColumn()).getValue();
var date = sheet.getRange(idRow, SpreadsheetApp.getActiveSpreadsheet().getRangeByName('ReqDateStart').getColumn()).getValue();
var date2 = sheet.getRange(idRow, SpreadsheetApp.getActiveSpreadsheet().getRangeByName('ReqDateCloseU').getColumn()).getValue();
var tip = sheet.getRange(idRow, SpreadsheetApp.getActiveSpreadsheet().getRangeByName('ReqType').getColumn()).getValue();
var users = sheet.getRange(idRow, SpreadsheetApp.getActiveSpreadsheet().getRangeByName('ReqAddress').getColumn()).getValue();
I found one script in this site but I can't understand how can I use it here
function getRangeName(A1Notation) {
var rangeName = "";
//get all the name ranges of the sheet
var namedRanges = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getNamedRanges();
// loop on all the names range of the sheet
for(i=0;i<namedRanges.length;i++){
//if it's the same A1 Notation
if(namedRanges[i].getRange().getA1Notation() == A1Notation)
rangeName = namedRanges[i].getName();
}
//will return the name of the range or "" if there is no range
return rangeName;
}
I think that's it I need. I think I can write to variables the values by put the value in parameter and send it to one function and return it back. Can you help me this this?
Thank you for your help!
Try Array.map() to make this a bit more manageable, like this:
function sendEmailClerck(e) {
const sheet = SpreadsheetApp.getActive().getSheetByName('Ответы на форму (1)');
const rangeNames = [
'ReqUser',
'ReqCLI',
'ReqPriority',
'ReqDateStart',
'ReqDateCloseU',
'ReqType',
'ReqAddress',
];
const [name, cli, priority, date, date2, tip, users] = rangeNames.map(rangeName => {
const column = sheet.getRange(rangeName).getColumn();
return sheet.getRange(e.range.rowStart, column).getValue();
});
}
You may want to rethink the whole approach though. The code is very inefficient because it reads every cell one by one. You should probably use just one sheet.getDataRange().getValues() call and parse the data from the the 2d array it returns.
Some of the best resources for learning Google Apps Script include the Beginner's Guide, the New Apps Script Editor guide, the Fundamentals of Apps Script with Google Sheets codelab, the Extending Google Sheets page, javascript.info, Mozilla Developer Network and Apps Script at Stack Overflow.

Apps script copy multiple range from 1 sheet to another spreadsheet

I am trying to copy data from 1 spreadsheet to another, I have successfully implemented something i found online that works with a specific range
function cloneGoogleSheet() {
// source doc
var sss = SpreadsheetApp.openById("spreadsheetkey1");
// source sheet
var ss = sss.getSheetByName('_tab_name_source');
// Get full range of data
var SRange = ss.getRange(7,3,5,1);
// get A1 notation identifying the range
var A1Range = SRange.getA1Notation();
// get the data values in range
var SData = SRange.getValues();
// target spreadsheet
var tss = SpreadsheetApp.openById("spreadsheetkey2");
// target sheet
var ts = tss.getSheetByName('tab_name_destination');
// Clear the Google Sheet before copy
//ts.clear({contentsOnly: true});
// set the target range to the values of the source data
ts.getRange(A1Range).setValues(SData);
};
The above piece coding work perfectly however I need to copy 18 different ranges that i cant just merge into 1 range. I considered the option of using the above however "multiplying" it 18 times for each range that however seems like a very inelegant solution.
I found a working solution that works if it stays within the same spreadsheet since it uses copyto instead of get/set values. The values part works perfectly since it doesnt mess with merge cells formatting. I have been struggling past 2-3 hours in merging the below-working code with elements from the first code to make a working script.
function test () {
try {
var spread = SpreadsheetApp.openById("spreadsheetkey");
var sheet = spread.getSheetByName("tab_name_source");
var rlist = sheet.getRangeList(["c7:c11", "g7:g11", "k7:k11"]);
sheet = spread.getSheetByName("tab_name_destination");
for( var i=0; i<rlist.getRanges().length; i++ ) {
var r1 = rlist.getRanges()[i];
var r2 = sheet.getRange(r1.getA1Notation());
r1.copyto(r2);
}
}
catch(err) {
Logger.log(err);
}
}
I tried initially to adapt the 2nd piece of coding to using setvalues however i had not been able to succesfully implement the part of getvalues within the scope of this code. I figured once I got this piece of code working with get and set values instead of Copyto i would only need to add the spreadsheetid of the other spreadsheet to get the final result
Try this:
function myFunction() {
var sourceSS = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = sourceSS.getSheetByName("sheetname");
var targetSS = SpreadsheetApp.openById("spreadsheet id here");
var targetSheet = targetSS.getSheetByName("Sheet1");
var ranges = ["C7:C11", "G7:G11", "K7:K11"];
ranges.forEach(range => {
var data = sourceSheet.getRange(range).getValues();
targetSheet.getRange(range).setValues(data);
})
}
Source sheet:
Destination sheet:
References:
setValues()
getValues()

Google sheet + Apps script: faster then for loop

Hi I'm using this code to loop trough another google worksheet find in column 'B' the id number 'idNum' once the id number is found the script replaces the whole row with new data but it seem to be taking a long time before the following script get triggered is there a way to make it faster to loop though or to make the next script trigger faster.
here's my code Thanks
function editRow(){
var mainsheet = ('10_XEaQiR71----- Sheet ID ----uOhi9VVtk5FI')
var tsheet = SpreadsheetApp.openById(mainsheet).getSheetByName('Data')
var targetSheet1 = tsheet.getDataRange().getValues()
var sheet = SpreadsheetApp.getActive();
var sourceData = sheet.getSheetByName('Data Input').getRange('A2:IB2').getValues()[0];
var idNum = sheet.getSheetByName('Data Input').getRange ("B2").getValue();
var copyFrom = sheet.getSheetByName('Data Input').getRange('A2:IB2')
var data = copyFrom.getValues()
for(var i = 0; i<targetSheet1.length;i++){
if(targetSheet1[i][1] == idNum){
var row = i=i+1
tsheet.getRange('A'+row+':IB'+row).setValues(data);
break;
}
}
next script
}
I believe your goal as follows.
You want to reduce the process cost of your script in your question.
Issue and workaround:
In your script, the values are retrieved from getRange("B2") and getRange('A2:IB2'). In this case, I think that you can retrieve them from getRange('A2:IB2').
When you are using V8 runtime, the process cost of for loop is almost the same with others. Ref So in this case, I would like to propose to use TextFinder instead of the for loop. Because I thought that TextFinder is run in the internal server and by this, the search process might be able to be reduced a little. But I'm not sure about your actual situation. So I'm not sure whether this is the correct direction for achieving your issue. So, please test the following script.
When your script is modified, it becomes as follows.
Modified script:
function editRow() {
var mainsheet = '10_XEaQiR71----- Sheet ID ----uOhi9VVtk5FI';
var sheet = SpreadsheetApp.getActive();
var data = sheet.getSheetByName('Data Input').getRange('A2:IB2').getValues();
var idNum = data[0][1];
var tsheet = SpreadsheetApp.openById(mainsheet).getSheetByName('Data');
var row = tsheet.getRange("B1:B" + tsheet.getLastRow()).createTextFinder(idNum).findNext().getRow();
tsheet.getRange(row, 1, 1, data[0].length).setValues(data);
// next script
}
Reference:
Class TextFinder

Google Scripts - Can't Find Destination Sheet After Form Creation

My script creates a Google Form programmatically and sets the destination to the current Spreadsheet:
var sheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
var form = FormApp.create(acctName).setTitle(acctName).setDestination(FormApp.DestinationType.SPREADSHEET, sheetId);
// several form items added here
Next, I'd like to rename the destination Sheet and make a few formatting edits. When I do, however, the sheet doesn't seem to exist. For example, getSheets() does not contain the new Sheet! (And yes, ideally I'd like to open the sheet by ID; see function below which also doesn't work.)
var sheets = SpreadsheetApp.openById(form.getDestinationId()).getSheets();
SpreadsheetApp.setActiveSheet(sheets[0]);
The above code opens what I would consider index 1, not index 0, because the sheet isn't indexed. I even tried creating a few second delay (hoping that it was just a matter of time to allow the sync to happen between the client and server) but without any success.
I have also tried something like the following, as suggested elsewhere here on Stack Overflow, but the destination Sheet doesn't come up in getSheets() even when called through a separate function:
function getFormDestinationSheetId(form) {
var destinationId = form.getDestinationId();
if(destinationId) {
var spreadsheet = SpreadsheetApp.openById(destinationId);
spreadsheet.getSheets().forEach(
function(sheet) {
var sheetFormUrl = sheet.getFormUrl();
if(sheetFormUrl) {
var sheetForm = FormApp.openByUrl(sheetFormUrl);
if(sheetForm.getId() == form.getId()) {
return sheet.getSheetId();
}
}
}
);
}
return null;
}
I haven't been able to find anyone have a similar problem on the webs. Any advice would be appreciated. Thanks!
Welcome to Stack!
I assume your script is bound to a sheet? Depending on how you're calling the script you may not see the new sheets because of browser caching.
function myFunction() {
var sheet = SpreadsheetApp.getActive();
var sheetId = sheet.getId();
var form = FormApp.create('acctName').setTitle('acctName').setDestination(FormApp.DestinationType.SPREADSHEET, sheetId);
var ssSheets = sheet.getSheets();
var respSheet = ssSheets[0]
respSheet.getRange('A1').setBackground('RED');
respSheet.getRange('C1').setFormula('=COUNTA($C$2:$C)');
respSheet.setColumnWidth(2, 100);
SpreadsheetApp.flush();
}