How to hyperlink an array of text using URLs in the sheet? - google-apps-script

In my Spreadsheet I have a column of data with book titles, and a column data with of URLS in it, about 5000 rows. I would like to use appscript to make a new column of data with those same titles hyperlinked using the URLS in the other column.
I'm trying to do this with arrays and the map function but I'm not sure how to use the map function so that the titles become hyperlinked. I'm very new at this so need a bit of help. Here's what I'm doing so far, the "????" in the MakeURL function is placeholder for the fix. Any suggestions?
Thank you for helping!
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet=ss.getActiveSheet();
function mainfunction() {
//Get both non-contiguous values into separate arrays.
var titles = activeSheet.getRange('E:E').getValues();
var theURLS = activeSheet.getRange('Q:Q').getValues();
//Put both values into a single unified array
var unified=[];
for (var i=0;i<titles.length;i++){
unified.push(titles[i],theURLS[i])
}
//Run a transformation on the values of the unified array and output it into newTitles array
var newtitles = unified.map(makeURL);
//write the new hyperlinked titles into a range(column).
activeSheet.getRange('Z:Z').setValues(newtitles);
};
function makeURL(row){ return ?????; };

I believe your goal as follows.
You want to retrieve the values from the columns "E" and "Q".
The columns "E" and "Q" are the title and the hyperlink, respectively.
You want to create the hyperlink value using the title and hyperlink, and want to put the values to the column "Z".
You want to achieve this using Google Apps Script.
In this case, I would like to propose to use RichTextValues. When this is reflected to your script, please modify as follows.
Modified script:
When you run the function of the modified mainfunction, the hyperlink values created from the columns "E" and "Q" are put to the column "Z".
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
function mainfunction() {
//Get both non-contiguous values into separate arrays.
var lastRow = activeSheet.getLastRow();
var titles = activeSheet.getRange('E1:E' + lastRow).getValues();
var theURLS = activeSheet.getRange('Q1:Q' + lastRow).getValues();
var richTextValues = titles.map(([e], i) => [SpreadsheetApp.newRichTextValue().setText(e).setLinkUrl(theURLS[i][0]).build()]);
activeSheet.getRange('Z1:Z' + richTextValues.length).setRichTextValues(richTextValues);
}
Note:
If you will achieve your goal using the built-in formula, I thought that you can also use the following formula. In this case, please put it to the cell "Z1".
=ARRAYFORMULA(HYPERLINK(Q:Q,E:E))
If you want to put the formulas using Google Apps Script, I thought that you can also use the following script.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
function mainfunction() {
//Get both non-contiguous values into separate arrays.
var lastRow = activeSheet.getLastRow();
var titles = activeSheet.getRange('E1:E' + lastRow).getValues();
var theURLS = activeSheet.getRange('Q1:Q' + lastRow).getValues();
var formulas = titles.map(([e], i) => [`HYPERLINK("${theURLS[i][0]}","${e}")`]);
activeSheet.getRange('Z1:Z' + formulas.length).setFormulas(formulas);
}
References:
Class RichTextValueBuilder
setRichTextValues(values)

Related

Google table script: filter by value, copy and paste individual columns, not the entire range

Good health to all! In this case, the row contains 136 columns, we filter by the 8th column, then we need to copy and paste into another file, for example, columns 134-136. I set the range var rng = sht.getRange(3,134,10000,3), I thought it would be similar to the FILTER() function, but no - the script works only if the range contains a column by which we filter... There was also a decision to insert all 136 columns and delete unnecessary 133, but this is generally, as it seems to me, inhumane.
Can you tell me what needs to be changed in the existing code so that you can copy and paste a filtered range that does not contain the column that is being filtered?
How can the script be modified so that it can be filtered by two or more columns?
Here I found a piece of code that filters the Google table by value and inserts the selected rows into the specified sheet.
I would be grateful for a tip on the optimal solutions for each issue
function CopyPaste()
{//the quantity is written
const SOURCE1 = SpreadsheetApp.openById("Here is the Google table ID");
const sht = SOURCE1.getSheetByName("Sales");
var ss = SpreadsheetApp.getActive();
var sheet2 = ss.getSheetByName("Monitor"); //settings sheet
var diap = sheet2.getRange("A1").getValue(); //value for the filter
var rng = sht.getRange(3,1,10000,136);// filtered range
var PasteSht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet 3');// sheet for inserting data in the current workbook
var rngA = rng.getValues();//this is where a fragment of someone else's code came from (I didn't rename variables)
var yesesA = []
for(var i=0;i<rngA.length;i++)
{
if(rngA[i][7]==diap)
{
yesesA.push(rngA[i])
}
}
var yesesRng = PasteSht.getRange(3, 1, yesesA.length, yesesA[0].length);
yesesRng.setValues(yesesA);
}
Try this
Code.gs
function CopyPaste() { //the quantity is written
const SOURCE1 = SpreadsheetApp.openById("Here is the Google table ID");
const sht = SOURCE1.getSheetByName("Sales");
var ss = SpreadsheetApp.getActive();
var sheet2 = ss.getSheetByName("Monitor"); //settings sheet
var diap = sheet2.getRange("A1").getValue(); //value for the filter
var rng = sht.getDataRange(); // filtered range
var PasteSht = ss.getSheetByName('Sheet 3');// sheet for inserting data in the current workbook
var rngA = rng.getValues();//this is where a fragment of someone else's code came from (I didn't rename variables)
var yesesA = rngA.filter( row => row[7] === diap ); // filter out all rows including diap
ysesA = yesesA.map( row => row.slice(132,136) ); // Array.slice(from,to(not including)) columns 133-136
var yesesRng = PasteSht.getRange(3, 1, yesesA.length, yesesA[0].length);
yesesRng.setValues(yesesA);
}
Reference
Array.filter()
Array.map()
Arrow function expression

Add custom formulas to Google sheets using Apps script

I'm trying to calculate to cells but not working. This is my code :
function total() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
var cell = sheet.getRange("A3");
var calculate = cell.setFormula("=SUM(A1+A2)");
return calculate
}
My cell is A1 AND A2 I want to put result in cell A3 by add "=total()".
not working but if run from script it work.
I want to put =total() in cell A3 and work without see my formula in sheet.
I wand to send copy of my sheet to people and he can read and edit it.
I don't need people to see my formulas.
or any another way to hide my formulas from people
You need to calculate the result in the script:
function total() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
var values = sheet.getRange("A1:A2").getValues();
var value = values[0][0] + values[1][0];
return value;
}
Alternatively, you can
Calculate normally with formulas in another spreadsheet
Use IMPORTRANGE to import the data from that spreadsheet such that only values but not formulas are display in the cells
However, he cannot make changes to the range directly.
He need to first copy and paste by values.
Your custom formula is returning the return value of the function Range.setFormula(formula), which is a Range. And you want a number. For this you need the values of both cells "A1"and "A2".
Furthermore, if you are using this custom formula to set a value in cell "A3" and not a formula then you can just have the custom formula return the value.
Example:
function total() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
var values = sheet.getRange("A1:A2").getValues();
var value = values[0][0] + values[1][0];
return value;
}

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()

How to copy cell value to another sheet base on criteria (Apps Script)

I'm trying to write some Apps Script to pull only the email addresses which match from an array of companies into another sheet for processing. This should also remove the #company.com extension and leave me with just the username.
So on Sheet 1:
In Column E, we have the Company names under Header: "Company"
In Column D, we have the Email Addresses under Header: "Emails"
On Sheet 2:
In Column A, we need the Username result under Header: "Username"
Currently the below script which should have 2 results, comes back with:
this
Any help with this would be immensely appreciated as I'm losing my mind.
Thank you!
function pullUsernames() {
//Get Sheet1
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
//Set Values for Search
var valuesToWatch = ['Company1','Company2'];
var range = sheet.getRange(2,5,sheet.getLastRow()-1).getValues();
var emails = sheet.getRange(2,4,lr-1).getValues();
//For Loop to match values, etc.
for(var i=0; i < range.length; i++){
if(valuesToWatch.indexOf(range[i][0])){;
var targetSS = SpreadsheetApp.openById("1hpIIgkXMgrlOfYqfS4A3ro8BFQB02dAy5G40Y7vUI2c").getSheetByName("Sheet2");
var targetRange = targetSS.getRange(i+1,1,targetSS.getLastRow(),1);
var usernames = String(emails[i][0]).replace("#company.com", "")
targetRange.setValue(usernames[i][0]);
} //if
} //for
} //Function
There were a bunch of issues in your code and I decided to optimize them. Feel free to modify the code if needed.
Issues:
Both range and emails can be fetched together instead of separate
Brought targetSS outside the loop since it is only static based on your issue
I don't quite get your getRange, I assume you want to append the usernames on the last row? If so, then use appendRow instead.
Since I didn't use the array index now, I used includes instead to check if the data is in valuesToWatch.
Your email string manipulation is quite hard coded so I replaced it with a better solution, removing anything but the characters before #.
Code:
function pullUsernames() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
// update your targetSS, made it under same ss for easier testing
var targetSS = ss.getSheetByName("Sheet2");
// set values for search
var valuesToWatch = ['Company1', 'Company2'];
// get email and company columns in one go
var data = sheet.getRange(2, 4, sheet.getLastRow() - 1, 2).getValues();
// each row of data contains email and company formatted as [email, company].
data.forEach(function ([email, company]){
if(valuesToWatch.includes(company))
// remove anything from # onwards from email and append at last row
targetSS.appendRow([email.substring(0, email.lastIndexOf("#"))]);
});
}
Sample Data:
Sample Output:

Copy a complete list on one spreadsheet to append on the bottom of another spreadsheet

In Google Spreadsheet I would like to take only the values from a complete list on one spreadsheet and append it to the bottom of a list on another spreadsheet. My trouble is that using the the copyValuesToRange() function errors the following:
Target sheet and source range must be on the same spreadsheet.
Here's my current code:
function transferList() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("0ABCD");
var target_sheet = target.getSheetByName("RFPData");
var sheet = source.getSheetByName("RFP List");
var sheet_last_row = sheet.getLastRow() + 1;
var source_range = sheet.getRange("A2:I"+sheet_last_row);
var sWidth=source_range.getWidth() + 1;
var sHeight=source_range.getHeight() + 1;
var last_row=target_sheet.getLastRow();
source_range.copyValuesToRange(target_sheet , 1, sWidth,
last_row + 1, last_row + sHeight );
}
Any idea how I can get this to work?
As you've found, copyValuesToRange() is a Range method that affects a Sheet Object that is in the same Spreadsheet Object as the Range. There isn't an atomic method that will copy a range of values to another Spreadsheet, but there are a number of ways you could do it.
Here's one way.
From the source sheet, get all the data in one operation, by selecting the complete range of data using getDataRange() and then grabbing all values into a javascript array with getValues().
To ignore the first row of headers, use the javascript array method splice().
Locate your destination, which is on the target sheet, starting after the last row of data that's currently there, using getLastRow().
Write the source data (without the headers) to the destination sheet starting at the next row, using setValues().
Script:
function transferList() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("RFP List");
var sourceData = sourceSheet.getDataRange().getValues();
sourceData.splice(0,1); // Remove header
var targetSS = SpreadsheetApp.openById("0ABCD").getSheetByName("RFPData");
var targetRangeTop = targetSS.getLastRow(); // Get # rows currently in target
targetSS.getRange(targetRangeTop+1,1,sourceData.length,sourceData[0].length).setValues(sourceData);
}
For some historic dashboard I created by importing and appending data, I use an add-on called Sheetgo. Save me programing time and help me with traceability issues.