0

I have this a table that looks like this:

enter image description here

I want to create one line per year instead of one column per year, in a way it looks like this:

enter image description here

You can get the sample data in this google sheets.

I think it would be something using query or maybe even making a custom function, however I can't figure out how to do it (or to at least get close). Any suggestions?

aabujamra
  • 4,494
  • 13
  • 51
  • 101
  • pivot table.... – Cooper Jun 05 '20 at 15:34
  • I can't really see it happening with pivot table. Anyway, I need it in a formula since it will happen repeatedly with different datasets. – aabujamra Jun 05 '20 at 18:38
  • 1
    I didn't mean that you use a pivot table from the spreadsheet. I just meant this is a pivot table kind of problem. So do it with objects and in this case with objects of arrays. Keep a list of all of the array objects created and use that to create your final output.. – Cooper Jun 05 '20 at 20:33

1 Answers1

2

I believe your goal as follows.

  • You want to achieve the conversion of the table as shown in the images in your question using the built-in functions or the custom function.

For this, how about this answer? In this answer, I would like to propose to use the custom function. Each sample script retrieves the source values from the cells A2:H6. Please be careful this.

Pattern 1:

In this pattern, the values are put to the Spreadsheet using the custom function. Please copy and paste the following script to the script editor of the Spreadsheet. In this case, please put the custom function to a cell like =myFunction1().

Sample script:

function myFunction1() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const values = sheet.getRange("A2:H6").getValues();
  const headers = values.shift().splice(2);
  const res = values.reduce((ar, r) => {
    let temp = r.splice(0, 2);
    for (let i = 0; i < headers.length; i += 2) {
      let h = temp;
      ar.push(h.concat(headers[i].split("Revenues")[1].trim(), r.splice(0, 2)));
    }
    return ar;
  }, []);
  res.unshift(["Company", "Company code", "Year", "Revenues", "Costs"]);
  return res;
}

Pattern 2:

Please copy and paste the following script to the script editor of the Spreadsheet. When I saw your sample Spreadsheet, the columns of "Revenues" and "Costs" in the converted table have the cell coordinates of the original table. So in this pattern, the goal of your sample Spreadsheet is replicated. But, the custom function cannot directly put the formula. So in this pattern, this script is not used as the custom function. So in order to test this, please run this with the script editor.

Sample script:

function myFunction2() {
  // 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.getActiveSheet();
  const values = sheet.getRange("A2:H6").getValues();
  const headers = values.shift().splice(2);
  const res = values.reduce((ar, r, i) => {
    let temp = r.splice(0, 2);
    for (let j = 0; j < headers.length; j += 2) {
      let h = temp;
      const formulas = [`=${columnToLetter(j + 3)}${i + 3}`, `=${columnToLetter(j + 4)}${i + 3}`];
      ar.push(h.concat(headers[j].split("Revenues")[1].trim(), formulas));
    }
    return ar;
  }, []);
  res.unshift(["Company", "Company code", "Year", "Revenues", "Costs"]);
  sheet.getRange(23, 1, res.length, res[0].length).setValues(res);
}
  • In this script, when you run the function of myFunction2 with the script editor, the result values are put from the cell "A23".

Note:

  • If you don't want to put the header row, please remove res.unshift(["Company", "Company code", "Year", "Revenues", "Costs"]);.
  • Please use these script with V8.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • Great answer @Tanaike, thanks. I'm trying to make it work here :) I'm trying the first pattern and I have two questions: (a) In case my Revenues column is a bit different, like "Revenues in 2019", does the code mantain? (b) If I have more columns like "Expenses in 2019", "Expenses in 2017", "Profit in 2018", "Profit in 2019", etc I should add them in the unshift line right? – aabujamra Jun 09 '20 at 11:13
  • 1
    @abutremutante Thank you for replying. I would like to answer for your additional 2 questions. A1. My answer is for your question. Please be careful this. Because I obtained the information from only your question. So when `Revenues 2019` is changed to `Revenues in 2019`, the values for `Year` becomes like `in 2019`. But no error occurs. In this case, please modify `split("Revenues")[1].trim()` to `split("Revenues in")[1].trim()`. – Tanaike Jun 09 '20 at 11:33
  • 1
    @abutremutante A2. In this case, I think that the situation is different from your question. So it is required to think of the solution as the different situation from your this question. I deeply apologize that I cannot propose the script for using at various situations. This is due to my poor skill. I would like to study more. By the way, if my answer didn't resolve your this question, I apologize. – Tanaike Jun 09 '20 at 11:33