0

I need something similar to HLOOKUP in Google apps script. But rather than returning one value (as is the case with HLOOKUP), i need a range of values. I searched and saw some similar stuff but didn't get what i need. Basically i have data like in the image below.

My Data

If the value I am looking up is 102, then I need the range of values from F2:F6 (which are the names of participants in the program 102). Similarly, if the ProgramIDis 104, i need the range of values in the range H2:H5. Note that the number of participants varies in each program.

In reality, have over one hundred ProgramIDs or rows (and hence also those many columns with participant names; among these there is one appropriate column from where I need to the range of values). What is the best way to do this?

Appreciate any help. Thanks a lot!

TheMaster
  • 45,448
  • 6
  • 62
  • 85
user1327454
  • 145
  • 3
  • 16
  • Is your sample image the sample input situation? If my understanding is correct, can I ask you about the sample output situation you expect? – Tanaike Jan 24 '22 at 07:51
  • @Tanaike, Thanks for the reply!. Yes the image is my sample input situation. The output i need is the range with participant names (e.g. F2:F6). The values in this range are to be pasted on another Google sheet. I can manage that part. – user1327454 Jan 24 '22 at 07:54
  • Thank you for replying. From your replying, I proposed a sample script as an answer. Could you please confirm it? If I misundetrstood your question and that was not useful, I apologize. – Tanaike Jan 24 '22 at 08:30

1 Answers1

1

I believe your goal is as follows.

  • From the cells "E2:H", you want to retrieve the a1Notation of rows by searching the header value.
  • For example, when you use 102 as the header value using your sample Spreadsheet, you want to retrieve the a1Notation of F2:F6.
  • You want to achieve this using Google Apps Script.

In this case, how about the following sample script?

Sample script:

function myFunction() {
  // Ref: https://stackoverflow.com/a/21231012/7108653
  const columnToLetter = column => {
    let temp, letter = "";
    while (column > 0) {
      temp = (column - 1) % 26;
      letter = String.fromCharCode(temp + 65) + letter;
      column = (column - temp - 1) / 26;
    }
    return letter;
  };

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");
  const values = sheet.getRange("E1:H").getValues();
  const obj = values[0].map((_, c) => values.map(r => r[c])).reduce((o, [h, ...v], i) => {
    const rows = v.filter(String);
    const col = columnToLetter(i + 5);
    o[h] = `${col}2:${col}${rows.length + 1}`;
    return o;
  }, {});


  // When "102" is used as the header value, the A1Notation is returned.
  const searchHeader = "102";
  console.log(obj[searchHeader])
}

If you want to achieve this using a custom function, you can also the following script.

function SAMPLE(values, search) {
  // Ref: https://stackoverflow.com/a/21231012/7108653
  const columnToLetter = column => {
    let temp, letter = "";
    while (column > 0) {
      temp = (column - 1) % 26;
      letter = String.fromCharCode(temp + 65) + letter;
      column = (column - temp - 1) / 26;
    }
    return letter;
  };

  const obj = values[0].map((_, c) => values.map(r => r[c])).reduce((o, [h, ...v], i) => {
    const rows = v.filter(String);
    const col = columnToLetter(i + 5);
    o[h] = `${col}2:${col}${rows.length + 1}`;
    return o;
  }, {});
  return obj[search];
}
  • In this case, when =SAMPLE(E:H,102) is put to a cell using your sample Spreadsheet, you can retrieve F2:F6.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • Given that I'm understanding their question and assuming all of user1327454's data is in set positions, could the same output be achieved by finding the ID given a range --> let idCol = range.createTextFinder(ID).matchEntireCell(true).findNext().getColumn(); --> let names = sheet.getRange(1, idCol, sheet.getMaxRows(), 1).getValues() --> paste names wherever they want the data? Obviously this is missing a lot of code so I'm just wondering about whether or not the general concept would work – kanwoody Jan 24 '22 at 09:12
  • 1
    @kanwoody I thought that OP wanted to retrieve the A1Notation by searching the header value. If my understanding is correct, I think that TextFinder can also search the header column. But in your script, `let names = sheet.getRange(1, idCol, sheet.getMaxRows(), 1).getValues()` returns the values from the header row to the bottom of the sheet. In this case, unfortunately, A1Notation is not returned. – Tanaike Jan 24 '22 at 09:16
  • it seems that you & I are interpreting their question completely differently. In the instance of my understanding, if the user inputs '101' they receive ['101', 'Ann', 'Ben', 'Ken', 'Susy'] (per the image). So, with that, I was thinking they were looking to use the program id as a key to output the participant's names. Additionally, they noted that the number of names is arbitrary, so using the method I asked about (again, its missing a lot of code & comments have limited characters) OP could store the column in an array & filter out the blank cells using names.filter(Boolean) – kanwoody Jan 24 '22 at 09:41
  • Thanks for your time!. Yes, if the input is 102, the output must be "F2:F6". In A1Notation so yes- in the sample data in the picture, it is "F2:F6". However, in my real data, the columns where my participant names are in my data are from columns S to AS. I guess i have to change the line of code const col = columnToLetter(i + 5); ? – user1327454 Jan 24 '22 at 10:26
  • Also, the number of participants in each of the columns S to AS is anywhere between 3 to 40. – user1327454 Jan 24 '22 at 10:35
  • @user1327454 Thank you for replying. I deeply apologize for my poor English skill. Unfortunately, I couldn't notice that your actual situation was `my data are from columns S to AS`. I had thought that your sample Spreadsheet was "E1:H". I apologize for this. When you want to use `S1:AS`, please modify to `sheet.getRange("S1:AS").getValues()` and/or `=SAMPLE(S1:AS,102)` and test them again. – Tanaike Jan 24 '22 at 11:44