1

I have a piece of code I use to import data to several sheets, and it is working fine. But I am trying to also modify all data from a specific column to turn it into an HTML button. The goal is to turn www.mylink.com to Button

Here is the code I use to import data (fetch data, filter it and put it in sheets into a folder)

function myfunction() {
  var keywords = ["valuetoremove1", "valuetoremove2"]; //  filter the column "C".

  // Retrieve CSV data.
  var csvUrl = "https://myurl";
  var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
  var csvData = Utilities.parseCsv(csvContent, ";");

  // Retrieve Spreadsheet and put the CSV data.
  var root = DriveApp.getFoldersByName("Folder1");
  while (root.hasNext()) {
    var folder = root.next();
    var files = folder.getFiles();
    while (files.hasNext()) {
      var spreadsheet = SpreadsheetApp.open(files.next());
      var name = spreadsheet.getName().toUpperCase();
      var values = csvData.reduce((ar, r) => {
        if (!keywords.some(e => r[2].toUpperCase().includes(e.toUpperCase())) && r.join("").toUpperCase().includes(name)) {
          ar.push(r);
        }
        return ar;
      }, []);
      if (values.length == 0) continue;
      var sheet = spreadsheet.getSheets()[0];
      sheet.clearContents().getRange(2, 1, values.length, values[0].length).setValues(values);

I have tried a code to change the link cells in a single page and it works, but not combined with my 1st code, it crashes because there are too much data. Here is what I tried :

// Modify column E
var dataRange = spreadsheet.getDataRange().getValues();
  var colData = [];

  for (var i = 1; i < dataRange.length; i++) {
    colData.push(dataRange[i][0]);
  }
  for (var i = 0; i < colData.length; i++) {

    // Get column E
    var comments_cell = spreadsheet.getDataRange().getCell(i + 2, 5).getValue();

        // Append
          spreadsheet.getDataRange().getCell(i + 2, 5).setValue('<a href="' + comments_cell + '" target="_blank"><button type="button">Button</button></a>');
    }

Here is my complete revised script :

function myfunction() {
  var keywords = ["removedata1", "removedata2"]; //  filter the column "C".
  var csvUrl = "https://myurl";
  var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
  var csvData = Utilities.parseCsv(csvContent, ";");
  var root = DriveApp.getFoldersByName("Myfolder");
  while (root.hasNext()) {
    var folder = root.next();
    var files = folder.getFiles();
    while (files.hasNext()) {
      var spreadsheet = SpreadsheetApp.open(files.next());
      var name = spreadsheet.getName().toUpperCase();
      var values = csvData.reduce((ar, r) => {
        if (!keywords.some(e => r[2].toUpperCase().includes(e.toUpperCase())) && r.join("").toUpperCase().includes(name)) {
          ar.push(r);
        }
        return ar;
      }, []);
      if (values.length == 0) continue;
      var sheet = spreadsheet.getSheets()[0];
      var v = [["Column1", "Column2", "Column3", "Column", "Column5"], ...values.map(r => {
        r[4] = `<a href="${r[4]}" target="_blank"><button type="button">Voir l'offre</button></a>`;
        return r;
      })];
      sheet.clearContents().getRange(1, 1, v.length, v[0].length).setValues(v);
    }
  }
}
Antoine
  • 63
  • 6
  • Previous similar topic https://stackoverflow.com/questions/72582826/make-appen-fonction-work-faster-in-google-google-sheet has been closed by @TheMaster ... but I have already answered. It could be fair to give a feed-back. – Mike Steelson Jun 13 '22 at 13:46
  • Can you clarify what is the end goal you are trying to achieve? – Kessy Jun 13 '22 at 14:32
  • @MikeSteelson thank you for your answer. I have opened a new topic after some tests with new clarification. Could you specify what file you would need to check ? I could create a file for you. It is just sample data in 5 colums – Antoine Jun 13 '22 at 16:26
  • 1
    Tanaike has already answered, with a great colde, as usual. Take it, I will not be able to do better. My code posted in the previous topic was quite the same but written in a more conventional way. – Mike Steelson Jun 13 '22 at 17:04

1 Answers1

1

In your script, getValue() and setValue() are used in the loop. In this case, the process cost will become high. In your script, how about the following modification?

From:

// Modify column E
var dataRange = spreadsheet.getDataRange().getValues();
  var colData = [];

  for (var i = 1; i < dataRange.length; i++) {
    colData.push(dataRange[i][0]);
  }
  for (var i = 0; i < colData.length; i++) {

    // Get column E
    var comments_cell = spreadsheet.getDataRange().getCell(i + 2, 5).getValue();

        // Append
          spreadsheet.getDataRange().getCell(i + 2, 5).setValue('<a href="' + comments_cell + '" target="_blank"><button type="button">Button</button></a>');
    }

To:

// var spreadsheet = SpreadsheetApp.getActiveSheet(); // In order to use this in your script, please remove this line.
var [, ...dataRange] = spreadsheet.getDataRange().getValues();
var values = dataRange.map(r => [`<a href="${r[4]}" target="_blank"><button type="button">Button</button></a>`]);
spreadsheet.getRange(2, 5, values.length).setValues(values);
  • When this script is run, an array for putting to the sheet is created and put the array to the sheet. By this, the process cost of the script can be reduced.

References:

Added:

I thought that when I saw your added script, it is required to modify for reducing the process cost. So, how about the following modification?

Modified script:

function myfunction() {
  var keywords = ["valuetoremove1", "valuetoremove2"]; //  filter the column "C".
  var csvUrl = "https://myurl";
  var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
  var csvData = Utilities.parseCsv(csvContent, ";");
  var root = DriveApp.getFoldersByName("Myfoldername");
  while (root.hasNext()) {
    var folder = root.next();
    var files = folder.getFiles();
    while (files.hasNext()) {
      var spreadsheet = SpreadsheetApp.open(files.next());
      var name = spreadsheet.getName().toUpperCase();
      var values = csvData.reduce((ar, r) => {
        if (!keywords.some(e => r[2].toUpperCase().includes(e.toUpperCase())) && r.join("").toUpperCase().includes(name)) {
          ar.push(r);
        }
        return ar;
      }, []);
      if (values.length == 0) continue;
      var sheet = spreadsheet.getSheets()[0];

      var v = [["Column1", "Column2", "Column3", "Column", "Column5"], ...values.map(([...r]) => {
        r[4] = `<a href="${r[4]}" target="_blank"><button type="button">Voir l'offre</button></a>`;
        return r;
      })];

      // Or, if the above modification was not useful, please test the following script instead of it.
      // var v = [["Column1", "Column2", "Column3", "Column", "Column5"], ...values.map(r => {
      //   const temp = r.slice();
      //   temp[4] = `<a href="${temp[4]}" target="_blank"><button type="button">Voir l'offre</button></a>`;
      //   return temp;
      // })];

      sheet.clearContents().getRange(1, 1, v.length, v[0].length).setValues(v);
    }
  }
}
  • About your reply of It means that one time the data is imported correctly but the E column is not being turned into a button and if I run the script again the E column is being turned into a button., when I tested this script, the values of column "E" has the values like <a href="###" target="_blank"><button type="button">Voir l'offre</button></a>.
    • By the way, when I saw your reply of It means that one time the data is imported correctly but the E column is not being turned into a button and if I run the script again the E column is being turned into a button. again, I thought that you might have wanted to put a button by creating HTML to a cell. If my understanding is correct, that cannot be achieved, because of the current specification. So, in this modification, I put the hyperlink to the column "E"?
    • If you want to put the value like <a href="###" target="_blank"><button type="button">Voir l'offre</button></a> to the column "E", please modify r[4] = `=HYPERLINK("${r[4]}","Voir l'offre")`; to r[4] = `<a href="${r[4]}" target="_blank"><button type="button">Voir l'offre</button></a>`;.
Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • Thank you for your help @Tanaike, I have tried this code but I get the following error "TypeError: Cannot read property 'getDataRange' of null" – Antoine Jun 13 '22 at 16:08
  • @Antoine Thank you for replying. I apologize for the inconvenience. About `I have tried this code but I get the following error "TypeError: Cannot read property 'getDataRange' of null"`, I noticed that I forgot to remove `var spreadsheet = SpreadsheetApp.getActiveSheet();`. So, please remove it and test it again. – Tanaike Jun 13 '22 at 23:27
  • Thank you again @Tanaike for this. I have tried it and this gave me a new error for the last line of the code which is "Exception: The parameters (String,number,number) don't match the method signature for SpreadsheetApp.Spreadsheet.getRange.". I have tried to change it to something like this `sheet.getRange(2, 5, values.length, values[0].length).setValues(values)` but when I run the script once it works, when I run it again it does not. intriguing – Antoine Jun 14 '22 at 06:27
  • @Antoine Thank you for replying. I apologize for the inconvenience. From your reply, in this case, it is required to know your current script. Because in my proposed script, such the error of `The parameters (String,number,number) don't match the method signature for SpreadsheetApp.Spreadsheet.getRange` doesn't occur. In this case, I think that it is required to correctly know your current script. So, can you add your current script for correctly replicating your current issue in your question? By this, I would like to confirm it. – Tanaike Jun 14 '22 at 06:29
  • Of course @Tanaike, I have added the full script in my 1st message. If I run the script it works fine and the E column is being changed. But if I run it again the E column is not being formated. – Antoine Jun 14 '22 at 06:55
  • @Antoine Thank you for replying. From your reply, your showing script cannot replicate `"Exception: The parameters (String,number,number) don't match the method signature for SpreadsheetApp.Spreadsheet.getRange."`? It seems that the error was different. So, I'm confused now. This is due to my poor English skill. I apologize for this. So, can I ask you about the detail of your current issue? – Tanaike Jun 14 '22 at 06:57
  • @Antoine By the way, about `I have added the full script in my 1st message. If I run the script it works fine and the E column is being changed. But if I run it again the E column is not being formated.`, in your showing script, by `sheet.clearContents().getRange(2, 1, values.length, values[0].length).setValues(values);`, the sheet is cleared and the new value is put. By this, the same Spreadsheet is overwritten. At this time, the column "E" is reconstructed. So, I cannot understand `But if I run it again the E column is not being formated.`. Can I ask you about the detail of it? – Tanaike Jun 14 '22 at 07:06
  • I am sorry @Tanaike this is absolutely my fault I mixed up two informations while I was testing. Please disregard the error I sent, I am not getting it now. The script seems to be working fine but only 1 over two times (one time the E column is being formatted, the other time it is not). It means that one time the data is imported correctly but the E column is not being turned into a button and if I run the script again the E column is being turned into a button. – Antoine Jun 14 '22 at 07:11
  • @Antoine Thank you for replying. I have to apologize for my poor English skill. Unfortunately, I cannot understand `It means that one time the data is imported correctly but the E column is not being turned into a button and if I run the script again the E column is being turned into a button.`. Can I ask you about the detail of your actual goal? – Tanaike Jun 14 '22 at 07:15
  • @Antoine For example, in order to test your issue, can you provide your sample CSV data? – Tanaike Jun 14 '22 at 07:16
  • I have just created a sample file for the test @Tanaike , you can use the following URL to fetch it in the script https://incensy.com/sample-data.csv . Thank you – Antoine Jun 14 '22 at 07:31
  • @Antoine About `It means that one time the data is imported correctly but the E column is not being turned into a button and if I run the script again the E column is being turned into a button.`, do you want to put the button by HTML to a cell? If my understanding is correct, that cannot be achieved. This is the current specification. I apologize for this. If you want to click the link, how about putting the hyperlink? So, I added one more modified script. Could you please confirm it? If that was not useful, I apologize. – Tanaike Jun 14 '22 at 07:40
  • Thank you for this @Tanaike ! We are almost there, your code is way better than what I had before, I am very thankful for it. The only issue I have is that to code seems to take what already exist in the E column and add the code. So after a few run E column looks like this "" target="_blank">". It should always take what is in the data feed instead of what is existing in the sheet. Do you think I should clear the column 1st or is there another way? – Antoine Jun 14 '22 at 08:56
  • For information I have used `` instead of `=HYPERLINK("${r[4]}","Voir l'offre")` – Antoine Jun 14 '22 at 08:56
  • @Antoine Thank you for replying. About your reply, in my added script, the values are always retrieved from the CSV data and the sheet is always cleared. So, I think that the situation of your reply doesn't occur. So, I'm worried that you might be testing a different script. So, in order to correctly replicate your situation, can you provide your whole script including the sample CSV data for correctly replicating your issue? By this, I would like to confirm it. – Tanaike Jun 14 '22 at 08:59
  • @Antoine Now, when I tested my proposed script using ``r[4] = ``;``, the cell value of column "E" is like `` even when the script is running several times. Unfortunately, I cannot replicate `" target="_blank">`. This is due to my poor skill. I deeply apologize for this. – Tanaike Jun 14 '22 at 09:03
  • Thank you for testing again @Tanaike , I have changed the revised script in my first message so you can see what I am trying. Sorry if I did not use your script correctly – Antoine Jun 14 '22 at 09:06
  • @Antoine Thank you for replying and adding your current script. When I tested your showing script, the cell value of column "E" is like `` even when the script is running several times. Unfortunately, I cannot replicate `" target="_blank">`. So, can I ask you about the detailed flow for correctly replicating your current issue? – Tanaike Jun 14 '22 at 09:07
  • @Antoine For example, your Google Apps Script project has multiple script files and those script files include the same function names of `myfunction()`? When it's yes, please modify the function name of your showing script to other name and test it again. Because my sample script doesn't use the existing values on Spreadsheet. By this, your showing issue cannot occur. – Tanaike Jun 14 '22 at 09:09
  • I have changed the name function to something unique but the problem is the same. @Tanaike What could I tell you about the flow to help ? – Antoine Jun 14 '22 at 09:23
  • @Antoine Thank you for replying. Unfortunately, I cannot replicate your situation of `a href="" target="_blank">`. When I tested your showing script and your provided sample CSV data, the script works. So, can you provide the detailed flow for correctly replicating your issue? By this, I would like to confirm it. – Tanaike Jun 14 '22 at 09:25
  • @Antoine For example, in order to completely repliate your current situation of `a href="" target="_blank">`, can you provide the sample Spreadsheet and the sample CSV data? – Tanaike Jun 14 '22 at 09:26
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/245588/discussion-between-antoine-and-tanaike). – Antoine Jun 14 '22 at 09:28
  • Thank you for your patience with this problem @Tanaike , I did not want to take too much of your time so I made several tests based on the information you gave and I think I found the issue. In my folder I have sheets with names close to each other like "Sheet 1" "Sheet 1 plus" and this is what seems to cause the issue. I have tested this in a new folder with only two sheets in it. Is there a way to fix this ? Without having to change sheets names – Antoine Jun 15 '22 at 06:28
  • @Antoine Thank you for replying. About `In my folder I have sheets with names close to each other like "Sheet 1" "Sheet 1 plus" and this is what seems to cause the issue. I have tested this in a new folder with only two sheets in it.`, what is `"Sheet 1" "Sheet 1 plus"`? Is that the Spreadsheet title? Or, the sheet names in a Spreadsheet? – Tanaike Jun 15 '22 at 06:39
  • Sorry @Tanaike , this is the Spreadsheet title, not the sheet. This is my mistake – Antoine Jun 15 '22 at 06:41
  • @Antoine Thank you for replying. In your situation, the Spreadsheets of "Sheet1" and "Sheet 1 plus" are existing in the folder of `DriveApp.getFoldersByName("Myfolder")`. Is my understanding correct? – Tanaike Jun 15 '22 at 06:42
  • Yes exactly @Tanaike , and I can not change these names unfortunately since they are important – Antoine Jun 15 '22 at 06:44
  • @Antoine Thank you for replying. In that case, when your provided CSV data `https://incensy.com/sample-data.csv` is used, the values are not put to those Spreadsheet by `if (values.length == 0) continue;`. So, unfortunately, I cannot understand your situation. But, I would like to suport you. So, can you provide the detaled flow for correctly replicating your current issue of `" target="_blank">`? – Tanaike Jun 15 '22 at 06:46
  • I have updated this sample data for a small test @Tanaike. You can use this sample data and create a folder named "testfolder" which includes a spreadsheet called "iPhone 8" and another called "iPhone 8 plus". This should show you the error after a few runs – Antoine Jun 15 '22 at 06:51
  • @Antoine Thank you for replying. Where can I see your new sample CSV data? – Tanaike Jun 15 '22 at 06:52
  • This is the same URL as before, I have changed the values in it : https://incensy.com/sample-data.csv . Thank you @Tanaike – Antoine Jun 15 '22 at 06:53
  • @Antoine Thank you for replying. From your provided CSV data, finary, I could understand your current issue. As the result, my script was required to be modified. I apologize for this. So, updated my answer. Could you please confirm it? If that was not useful, I apologize again. – Tanaike Jun 15 '22 at 07:15
  • I have tested with both sample and all data and it works perfectly ! I cannot thank you enough @Tanaike for your help. It is very kind of you to help me through all of this until the end, I am very grateful – Antoine Jun 15 '22 at 07:32