Convert url to clickable hyperlink [duplicate] - javascript

This question already has an answer here:
How to create a hyperlink in Google Sheets
(1 answer)
Closed 2 months ago.
I'm using the Discogs API to export my Wantlist to Google Sheets
Is there a way to add the HTML to make the release-url (resource_url) clickable in the output?
function logTheData (url){
var sheet = SpreadsheetApp.getActiveSheet();
var url ='https://api.discogs.com/users/bartvanbelle/wants?per_page=100';
var response = UrlFetchApp.fetch(url); // get feed
var json = response.getContentText(); //
var data = JSON.parse(response);
var counter = 100;
for (var i = 0; i< counter; i++) {
var stats = [];
// var instance_id = data.wants[i].instance_id;
//if (typeof data.wants[i].basic_information.formats[0].descriptions[0] !== "undefined"){
// var description = data.wants[i].basic_information.formats[0].descriptions[0]
// };
// stats.push(instance_id);//works a
stats.push(data.wants[i].basic_information.title); //works a
stats.push(data.wants[i].basic_information.formats[0].name);
// stats.push(description); //stringify array?
stats.push(String(data.wants[i].basic_information.formats[0].descriptions));
stats.push(data.wants[i].basic_information.labels[0].name); //works c
stats.push(data.wants[i].basic_information.labels[0].catno); // work d
stats.push(data.wants[i].basic_information.year); //l
stats.push(data.wants[i].basic_information.artists[0].name); //works j
stats.push(data.wants[i].basic_information.id); // m
stats.push(data.wants[i].basic_information.resource_url); // m
Logger.log(stats);
SpreadsheetApp.getActiveSpreadsheet().appendRow(stats);
}
var pages = data.pagination.pages;
for (var a = 1; a < pages; a++){
var next = data.pagination.urls.next;
var response = UrlFetchApp.fetch(next); // get feed
var json = response.getContentText(); //
var data = JSON.parse(response);
var counter = 100;
for (var i = 0; i< counter; i++) {
var stats = [];
stats.push(data.wants[i].basic_information.title); //works a
stats.push(data.wants[i].basic_information.formats[0].name);
stats.push(String(data.wants[i].basic_information.formats[0].descriptions));
stats.push(data.wants[i].basic_information.labels[0].name); //works c
stats.push(data.wants[i].basic_information.labels[0].catno); // work d
stats.push(data.wants[i].basic_information.year); //l
// stats.push(description); //stringify array?
stats.push(data.wants[i].basic_information.artists[0].name); //works j
stats.push(data.wants[i].basic_information.id); // m
stats.push(data.wants[i].basic_information.resource_url); // m
Logger.log(stats);
SpreadsheetApp.getActiveSpreadsheet().appendRow(stats);
}
}
}
The resource URL is also formatted as http://api.discogs.com/.... Is there a way to convert that to http://www.discogs.com?

Maybe try something like:
stats.push('=HYPERLINK(data.wants[i].basic_information.resource_url,data.wants[i].basic_information.resource_url')
In general what works is to
get the cell
set the value
set the formula (HYPERLINK(...))
setShowHyperlink(true) on the cell.
Hope this helps.
You might aswell checkout this answer: https://stackoverflow.com/a/37488194/1698461

I think you need to wrap data.wants[i].basic_information.resource_url into html tag
like this :
stats.push(
'link'
);
so full code ll be :
function logTheData (url){
var sheet = SpreadsheetApp.getActiveSheet();
var url ='https://api.discogs.com/users/**********/wants?per_page=100';
var response = UrlFetchApp.fetch(url); // get feed
var json = response.getContentText(); //
var data = JSON.parse(response);
var counter = 100;
for (var i = 0; i< counter; i++) {
var stats = [];
stats.push(data.wants[i].basic_information.title); //works a
stats.push(data.wants[i].basic_information.formats[0].name);
stats.push(String(data.wants[i].basic_information.formats[0].descriptions));
stats.push(data.wants[i].basic_information.labels[0].name); //works c
stats.push(data.wants[i].basic_information.labels[0].catno); // work d
stats.push(data.wants[i].basic_information.year); //l
stats.push(data.wants[i].basic_information.artists[0].name); //works j
stats.push(data.wants[i].basic_information.id); // m
stats.push(data.wants[i].basic_information.resource_url); // m
Logger.log(stats);
SpreadsheetApp.getActiveSpreadsheet().appendRow(stats);
}
var pages = data.pagination.pages;
for (var a = 1; a < pages; a++){
var next = data.pagination.urls.next;
var response = UrlFetchApp.fetch(next); // get feed
var json = response.getContentText(); //
var data = JSON.parse(response);
var counter = 100;
for (var i = 0; i< counter; i++) {
var stats = [];
stats.push(data.wants[i].basic_information.title);
stats.push(data.wants[i].basic_information.formats[0].name);
stats.push(String(data.wants[i].basic_information.formats[0].descriptions));
stats.push(data.wants[i].basic_information.labels[0].name);
stats.push(data.wants[i].basic_information.labels[0].catno);
stats.push(data.wants[i].basic_information.year);
stats.push(data.wants[i].basic_information.artists[0].name);
stats.push(data.wants[i].basic_information.id);
stats.push( 'link');
Logger.log(stats);
SpreadsheetApp.getActiveSpreadsheet().appendRow(stats);
}
}
}

Related

Var not being used in object.var

function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('data');
var data = sheet.getDataRange().getValues();
var range = sheet.getRange("A1:L" + data.length);
range.sort(1);
const people = {};
for(var i = 0; i < data.length; i++) {
var name = data[i][0] + data[i][1];
console.log(i);
if (!people.name) {people.name = {rows: [i]};} else {people.name.rows.push(i)}
}
Logger.log(people);
}
What should I be doing differently? At the end, it logs {name={rows=[0.0, 1.0, 2.0, ...]}} instead of having an object for each name...?
In the sheet there's just a first name and last name on columns A and B, for around 80 rows.
Use the bracket syntax if you want to use dynamic names for properties: https://riptutorial.com/javascript/example/2321/dynamic---variable-property-names
In your case:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('data');
var data = sheet.getDataRange().getValues();
var range = sheet.getRange("A1:L" + data.length);
range.sort(1);
const people = {};
for(var i = 0; i < data.length; i++) {
var name = data[i][0] + data[i][1];
console.log(i);
if (!people[name]) {people[name] = {rows: [i]};} else {people[name].rows.push(i)}
}
Logger.log(people);
}

How can I extract Information in a Google Sheet from a xlsx gmail attachment via google apps script [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
I want to extract the content from an xlsx gmail attachment via google apps script. And then put the information into a Google Sheet. It's working fine for CSV files, but I don't get the content of a xlsx file.
Unlike csv files, xlsx file data cannot be directly inserted into a spreadsheet
What you can do instead:
Save the attachment on your disc in its original mimeType
Convert it to a Google Sheets document with e.g. Drive.Files.copy
Delete the excel file from your disc
Sample:
function GmailToDrive() {
var threads = GmailApp.getInboxThreads();
var message = threads[0].getMessages()[0];
var attachment = message.getAttachments()[0];
var blob = attachment.getAs(attachment.getContentType());
blob.setName(attachment.getName())
var excel = DriveApp.createFile(blob);
Drive.Files.copy({mimeType: MimeType.GOOGLE_SHEETS}, excel.getId());
excel.setTrashed(true)
}
Note that Drive is an advances service that needs to be enabled beforehand.
You can extract data directly from MS Excel files stored in Google Drive or in Gmail attachment without any upload or conversion to Google Spreadsheet. πŸŽ‰πŸΎπŸ₯³
Since xlsx workbooks are zipped XML files you can unzip the xlsx blob, process the XML files and extract data needed like this.
/**
* Parsing MS Excel files and returns values in JSON format.
*
* #param {BlobSource} blob the blob from MS Excel file
* #param {String[]} requiredSheets the array of required sheet names (if omitted returns all)
* #return {Object} Object of sheet names and values (2D arrays)
*/
function parseMSExcelBlob(blob, requiredSheets){
var col_cache = {};
var forbidden_chars = {
"<": "<",
">": ">",
"&": "&",
"&apos;": "'",
""": '"'
};
blob.setContentType("application/zip");
var parts = Utilities.unzip(blob);
var relationships = {};
for( var part of parts ){
var part_name = part.getName();
if( part_name === "xl/_rels/workbook.xml.rels" ){
var txt = part.getDataAsString();
var rels = breakUpString(txt, '<Relationship ', '/>');
for( var i = 0; i < rels.length; i++ ){
var rId = breakUpString(rels[i], 'Id="', '"')[0];
var path = breakUpString(rels[i], 'Target="', '"')[0];
relationships[rId] = "xl/" + path;
}
}
}
var worksheets = {};
for( var part of parts ){
var part_name = part.getName();
if( part_name === "xl/workbook.xml" ){
var txt = part.getDataAsString();
var sheets = breakUpString(txt, '<sheet ', '/>');
for( var i = 0; i < sheets.length; i++ ){
var sh_name = breakUpString(sheets[i], 'name="', '"')[0];
sh_name = decodeForbiddenChars(sh_name);
var rId = breakUpString(sheets[i], 'r:id="', '"')[0];
var path = relationships[rId];
if( path.includes("worksheets") ){
worksheets[path] = sh_name;
}
}
}
}
requiredSheets = Array.isArray(requiredSheets) && requiredSheets.length && requiredSheets || [];
var worksheets_needed = [];
for( var path in worksheets ){
if( !requiredSheets.length || requiredSheets.includes(worksheets[path]) ){
worksheets_needed.push(path);
}
}
if( !worksheets_needed.length ) return {"Error": "Requested worksheets not found"};
var sharedStrings = [];
for( var part of parts ){
var part_name = part.getName();
if( part_name === "xl/sharedStrings.xml" ){
var txt = part.getDataAsString();
txt = txt.replace(/ xml:space="preserve"/g, "");
sharedStrings = breakUpString(txt, '<t>', '</t>');
for( var i = 0; i < sharedStrings.length; i++ ){
sharedStrings[i] = decodeForbiddenChars(sharedStrings[i]);
}
}
}
var result = {};
for( var part of parts ){
var part_name = part.getName();
if( worksheets_needed.includes(part_name) ){
var txt = part.getDataAsString();
var cells = breakUpString(txt, '<c ', '</c>');
var tbl = [[]];
for( var i = 0; i < cells.length; i++ ){
var r = breakUpString(cells[i], 'r="', '"')[0];
var t = breakUpString(cells[i], 't="', '"')[0];
if( t === "inlineStr" ){
var data = breakUpString(cells[i].replace(/ xml:space="preserve"/g, ""), '<t>', '</t>')[0];
data = decodeForbiddenChars(data);
}else if( t === "s" ){
var v = breakUpString(cells[i], '<v>', '</v>')[0];
var data = sharedStrings[v];
}else{
var v = breakUpString(cells[i], '<v>', '</v>')[0];
var data = Number(v);
}
var row = r.replace(/[A-Z]/g, "") - 1;
var col = colNum(r.replace(/[0-9]/g, "")) - 1;
if( tbl[row] ){
tbl[row][col] = data;
}else{
tbl[row] = [];
tbl[row][col] = data;
}
}
var sh_name = worksheets[part_name];
result[sh_name] = squareTbl(tbl);
}
}
function decodeForbiddenChars(txt){
for( var char in forbidden_chars ){
var regex = new RegExp(char,"g");
txt = txt.replace(regex, forbidden_chars[char]);
}
return txt;
}
function breakUpString(str, start_patern, end_patern){
var arr = [], raw = str.split(start_patern), i = 1, len = raw.length;
while( i < len ){ arr[i - 1] = raw[i].split(end_patern, 1)[0]; i++ };
return arr;
}
function colNum(char){
if( col_cache[char] ) return col_cache[char];
var alph = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", i, j, result = 0;
for( i = 0, j = char.length - 1; i < char.length; i++, j-- ){
result += Math.pow(alph.length, j) * (alph.indexOf(char[i]) + 1);
}
col_cache[char] = result;
return result;
}
function squareTbl(arr){
var tbl = [];
var x_max = 0;
var y_max = arr.length;
for( var y = 0; y < y_max; y++ ){
arr[y] = arr[y] || [];
if( arr[y].length > x_max ){ x_max = arr[y].length };
}
for( var y = 0; y < y_max; y++ ){
var row = [];
for( var x = 0; x < x_max; x++ ){
row.push(arr[y][x] || arr[y][x] === 0 ? arr[y][x] : "");
}
tbl.push(row);
}
return tbl.length ? tbl : [[]];
}
return result;
}
Using the function parseMSExcelBlob(blob, requiredSheets) you can put the data in a gsheet.
function getDataFromGmail(){
var threads = GmailApp.getInboxThreads();
var message = threads[0].getMessages()[0];
var attachment = message.getAttachments()[0];
var blob = attachment.copyBlob();
// if second parameter is not provided all sheets will be parsed
var data = parseMSExcelBlob(blob, ["Funny corgi names"]);
// here we have the data in 2D array
var tbl = data["Funny corgi names"];
// putting data into the sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("Corgi names");
sh.clearContents();
sh.getRange(1, 1, tbl.length, tbl[0].length).setValues(tbl);
}
Also find it in this GitHub repo.

How to set data from an array to another array to improve performance

I'm currently developing a sheet that shows results from a set of data based on some filters but the data loads to slowly when getting the results, I've tried to follow the Best Practices from Google Documentacion with no luck, how can I set an array for the data to load faster?
Below is the code commented with what I've already tried
function realizarBusqueda() {
var inicio = SpreadsheetApp.getActive().getSheetByName("INICIO");
var aux_tags = SpreadsheetApp.getActive().getSheetByName("Aux_Tags");
var data = SpreadsheetApp.getActive().getSheetByName("Data");
var data_lc = data.getLastColumn();
var data_lr = data.getLastRow();
var searchRange = data.getRange(2,1, data_lr, data_lc);
var inicio_lc = inicio.getLastColumn();
inicio.getRange("A8:L1000").clearContent();
inicio.getRange("A8:L1000").clearFormat();
var countRows = inicio.getMaxRows();
inicio.deleteRows(20, (20-countRows)*-1);
if (inicio.getRange("B4").isBlank()) {
inicio.getRange("A8:L1000").clearContent();
inicio.getRange("A8:L1000").clearFormat();
var countRows = inicio.getMaxRows();
inicio.deleteRows(20, (20-countRows)*-1);
SpreadsheetApp.flush();
}
else if ((inicio.getRange("B4").getValue() != "" &&
inicio.getRange("C4").getValue() === "")) {
//filtrado 1
var arrayDatos = searchRange.getValues();
var inicio_fr = 8;
//var row = new Array(11);
for (var j = 2; j <= data_lr; j++) {
//row[j] = new Array(data_lr);
if (aux_tags.getRange("P2").getValue() === arrayDatos[j-2][4]) {
var inicio_fc = 1;
for (var i = 0; i < arrayDatos[j-2].length; i++) {
//row[j][i] = arrayDatos[j-2][i];
var row = arrayDatos[j-2][i];
inicio.getRange(inicio_fr, inicio_fc).setValue(row);
inicio_fc++;
}
inicio_fr++;
}
//inicio.getRange("A8").setValues(row);
}
}
I expect the output to load lots faster, currently what I've tried is commented, the code as-is is working but too slow
I just wanted to update this subject because I figured out myself, see attached the new code with the use of new 2D arrays
...
//filtrado 1
var arrayDatos = searchRange.getValues();
var inicio_fr = 8;
var rows = [];
var row = [];
for (var j = 2; j <= data_lr; j++) {
if (aux_tags.getRange("P2").getValue() === arrayDatos[j-2][4]) {
var inicio_fc = 1;
for (var i = 0; i < arrayDatos[j-2].length; i++) {
row.push(arrayDatos[j-2][i]);
if (i == 11) {
rows.push(row);
row = [];
}
}
}
}
inicio.getRange(8, 1, rows.length, rows[0].length).setValues(rows);
}
Now instead of writing on row at a time, I just write the whole array at once

How can I parse an URL's HTML and insert data to a Google Sheet using Google Script?

I'm completely new to Google Apps Script and JavaScript.
I just wanted to:
Read column A and do an URL request.
Parse the URL's HTML to get the title and num count.
Write the title into column B and the num count into column C.
Here's my code:
function getHtml()
{
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var url_range = sheet.getRange('A1:A').getValue();
var response = UrlFetchApp.fetch(url);
var content = response.getContentText("UTF-8");
var title = new Array();
var num_count = new Array();
for (var i = 1; i < data.length; i++) {
title = content.match(/<title>(.*?)<\/title>/);
num_count = content.match(/<span class="num_count">(.*?)<\/span>/);
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("sheet1");
for (var i = 1; i < data.length; i++) {
sheet1.getRange(i,2).setValue(title[i]);
sheet1.getRange(i,3).setValue(num_count[i]);
}
}
But I only get the below result:
Please tell me what I should improve.
Assuming that your scraping works I think this is pretty close to what you require.
function getHtml()
{
var ss=SpreadsheetApp.getActive();
var sheet=ss.getActiveSheet();
var range=sheet.getRange(1,1,sheet.getLastRow(),3);
var data=range.getValues();
for(var i=0;i<data.length;i++){
var response = UrlFetchApp.fetch(data[i][0]);
var content = response.getContentText("UTF-8");
data[i][1]=content.match(/<title>(.*?)<\/title>/);
data[i][2]=content.match(/<span class="num_count">(.*?)<\/span>/);
}
rg.setValues(data);
}

Google script - parse HTML from Website Forum - and Write Data to Sheet

I'm getting HTML from a forum url, and parsing the post count of the user from their profile page. I don't know how to write the parsed number into the Google spreadsheet.
It should go account by account in column B till last row and update the column A with count.
The script doesn't give me any errors, but it doesn't set the retrieved value into the spreadsheet.
function msg(message){
Browser.msgBox(message);
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Update")
.addItem('Update Table', 'updatePosts')
.addToUi();
}
function getPostCount(profileUrl){
var html = UrlFetchApp.fetch(profileUrl).getContentText();
var sliced = html.slice(0,html.search('Posts Per Day'));
sliced = sliced.slice(sliced.search('<dt>Total Posts</dt>'),sliced.length);
postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
return postCount;
}
function updatePosts(){
if(arguments[0]===false){
showAlert = false;
} else {
showAlert=true;
}
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var accountSheet = spreadSheet.getSheetByName("account-stats");
var statsLastCol = statsSheet.getLastColumn();
var accountCount = accountSheet.getLastRow();
var newValue = 0;
var oldValue = 0;
var totalNewPosts = 0;
for (var i=2; i<=accountCount; i++){
newValue = parseInt(getPostCount(accountSheet.getRange(i, 9).getValue()));
oldValue = parseInt(accountSheet.getRange(i, 7).getValue());
totalNewPosts = totalNewPosts + newValue - oldValue;
accountSheet.getRange(i, 7).setValue(newValue);
statsSheet.getRange(i,statsLastCol).setValue(newValue-todaysValue);
}
if(showAlert==false){
return 0;
}
msg(totalNewPosts+" new post found!");
}
function valinar(needle, haystack){
haystack = haystack[0];
for (var i in haystack){
if(haystack[i]==needle){
return true;
}
}
return false;
}
The is the first time I'm doing something like this and working from an example from other site.
I have one more question. In function getPostCount I send the function profileurl. Where do I declare that ?
Here is how you get the URL out of the spreadsheet:
function getPostCount(profileUrl){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var thisSheet = ss.getSheetByName("List1");
var getNumberOfRows = thisSheet.getLastRow();
var urlProfile = "";
var sliced = "";
var A_Column = "";
var arrayIndex = 0;
var rngA2Bx = thisSheet.getRange(2, 2, getNumberOfRows, 1).getValues();
for (var i = 2; i < getNumberOfRows + 1; i++) { //Start getting urls from row 2
//Logger.log('count i: ' + i);
arrayIndex = i-2;
urlProfile = rngA2Bx[arrayIndex][0];
//Logger.log('urlProfile: ' + urlProfile);
var html = UrlFetchApp.fetch(urlProfile).getContentText();
sliced = html.slice(0,html.search('Posts Per Day'));
var postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
sliced = sliced.slice(sliced.search('<dt>Total Posts</dt>'),sliced.length);
postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
Logger.log('postCount: ' + postCount);
A_Column = thisSheet.getRange(i, 1);
A_Column.setValue(postCount);
};
}
You're missing var in front of one of your variables:
postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
That won't work. Need to put var in front. var postCount = ....
In this function:
function updatePosts(){
if(arguments[0]===false){
showAlert = false;
} else {
showAlert=true;
}
There is no array named arguments anywhere in your code. Where is arguments defined and how is it getting any values put into it?

Categories