3

I have a Google Sheet with Google Drive documents names in each cells. So each cells contain a Google Drive documents name. Together, the various cells form an array.

I'm trying to retrieve hyperlinks of these Google Drive documents based on the name in each Google Sheet cell, and set these hyperlink in each cell (by replacing documents name in each cell). To be noted that the Google Drive documents are not in the same Google Drive folders.

I managed to modify an existing code so that it works in my context; however, it only works for 1-column array. When I try to extend the range to several columns, all hyperlinks return "undefine" url (even for the first column that was previously working).

Google array example

See below my code. Any help would be much appreciated. Thanks a lot.

function getFile() {

const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet1 = ss.getSheetByName('Sheet1');

var lastRow = sheet1.getLastRow();

var range = sheet1.getRange(2,1,lastRow - 1,4);
var names = range.getValues();

var nameUrl ={};

for (let i in names) {

var files = DriveApp.getFilesByName(names[i]);

while (files.hasNext()) {
 var file = files.next();
 var fullName = file.getName();
 var url = file.getUrl();
 nameUrl[fullName] = url;
 }
 }

var links = names.map(function(e) {
  return [
    '=HYPERLINK("' + nameUrl[e] + '","' + e + '")'
      ];
});
range.setValues(links);
}
Marios
  • 26,333
  • 8
  • 32
  • 52
AlexCT
  • 35
  • 4
  • `links` is a 2D array of 1 column. If you want to paste data to multiple columns, then you need to adjust `links` to make it like: `[a,b]` instead of `[a]` where `a` is `'=HYPERLINK("' + nameUrl[e] + '","' + e + '")'`. Also `names` is a 2D array, you can't iterate element wise a 2D array with only one iteration (`i`). – Marios Apr 14 '21 at 08:44
  • Thanks Mario for your quick answer. You're right, and I have actually already tried defining links as a 4-column array as below: var links = names.map(function(e) { return [ '=HYPERLINK("' + nameUrl[e[0]] + '","' + e[0] + '")', '=HYPERLINK("' + nameUrl[e[1]] + '","' + e[1] + '")', '=HYPERLINK("' + nameUrl[e[2]] + '","' + e[2] + '")', '=HYPERLINK("' + nameUrl[e[3]] + '","' + e[3] + '")' ]; }); However it still does not work. My guess is that the problem lies with my nameUrl object, but I'm not sure. – AlexCT Apr 14 '21 at 08:49

2 Answers2

2

Explanation:

  • You are very close but your code is working for 2D arrays of one column and you need to redesign your code to work with 2D arrays with multiple columns as well.

I use a double map approach to iterate for every cell and by doing that you don't need to create the object nameUrl which also slows your code.

Solution:

function getFile() {   
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet1 = ss.getSheetByName('Sheet1');
  const lastRow = sheet1.getLastRow();
  const range = sheet1.getRange(2,1,lastRow - 1,4);
  const names = range.getValues();
  const data = names.map(r=>r.map(c=>{
    let files = DriveApp.getFilesByName(c);
    while (files.hasNext()) {
      var file = files.next();
      var url = file.getUrl();
      return c!=''?'=HYPERLINK("' + url + '","' + c + '")':'';
    }}));
  range.setValues(data);
}
Marios
  • 26,333
  • 8
  • 32
  • 52
  • 1
    Brilliant, it works perfectly. Many thanks Mario ! Will need to learn and understand what you did as I already spent hours on this... Thanks again for your help! – AlexCT Apr 14 '21 at 09:05
  • 1
    @AlexCT happy coding :) you will get there! – Marios Apr 14 '21 at 09:06
0

Try the script below. It finds the folder you want and lists the contents by file, name, and URL:

// replace your-folder below with the folder for which you want a listing
function listFolderContents() {
  var foldername = 'your-folder';
  var folderlisting = 'listing of folder ' + foldername;
  
  var folders = DriveApp.getFoldersByName(foldername)
  var folder = folders.next();
  var contents = folder.getFiles();
  
  var ss = SpreadsheetApp.create(folderlisting);
  var sheet = ss.getActiveSheet();
  sheet.appendRow( ['name', 'link'] );
  
  var file;
  var name;
  var link;
  var row;
  while(contents.hasNext()) {
    file = contents.next();
    name = file.getName();
    link = file.getUrl();
    sheet.appendRow( [name, link] );     
  }  
};

You can change the location of the file listing to whatever sheet you want by switching

var ss = SpreadsheetApp.create(folderlisting);

to

var ss = SpreadsheetApp.openById('SHEET_ID').getSheetByName('SHEET_NAME');.

Don't forget to change SHEET_NAME and SHEET_ID to the ones that match your spreadsheet.

Daniel H.
  • 621
  • 4
  • 20
  • The goal of the OP is to create hyperlinks in the sheet based on the urls. As you can see his code already finds the `urls`. Also, he doesn't need to construct an array of names and links. As he explained, he wants to construct hyperlinks for each cell. Last but not least, this in a loop `sheet.appendRow( [name, link] )` is not very efficient. It is a good practice to store the data to an array and then set the data to the sheet. Right now you are calling `sheet.appendRow` multiple times. – Marios Apr 14 '21 at 09:13
  • I'm not a particularly advanced programmer. I just thought that This could help the OP. – Daniel H. Apr 14 '21 at 10:35