2

I am using 2 sheets, rawData and processedData.

rawData looks like this:

Title Options
Title1 Option1, Option2, Option3, Option4
Title2 Option1, Option2, Option3, Option4, Option5
Title3 Option1, Option2, Option3

processedData should look like this:

Title Options
Title1 Option1
Title1 Option2
Title1 Option3
Title1 Option4
Title2 Option1
Title2 Option2
Title2 Option3
Title2 Option4
Title2 Option5
Title3 Option1
Title3 Option2
Title3 Option3

In Google Sheets, I would use the formula =TRANSPOSE(SPLIT(rawData!B2,",",TRUE,TRUE)) to get the options for the first title in the format I need.

I'm trying to create a Google Apps Script that could take each row of rawData and convert it to the format shown in processedData.

function formatData() {
  // File
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // Get rawData sheet
  var rawData = ss.getSheetByName('rawData');

  // Get processedData sheet
  var processedData = ss.getSheetByName('processedData');

  // Get range that contains titles, get its values
  var titlesRange = rawData.getRange('A2:A');
  var titlesRangeValues = titlesRange.getValues();

  // Get range that contains options, get its values
  var optionsRange = rawData.getRange('B2:B');
  var optionsRangeValues = optionsRange.getValues();

  // Get number of rows in rawData sheet
  var titlesCount = GSheetsUtils.getRowsData(rawData);

  // Get last row in processedData sheet
  var lastRow = processedData.getLastRow();

  // Copy each title to processedData and format the options
  for (var i = 0; i<titlesCount.length; i++) {
    processedData.getRange(lastRow + 1,1).setValue(titlesRangeValues[i][0]);
    processedData.getRange(lastRow + 1,2).setValue(optionsRangeValues[i][0]);
    lastRow++;
  }
}

Executing this code will populate processedData like so:

Title Options
Title1 Option1, Option2, Option3, Option4
Title2 Option1, Option2, Option3, Option4, Option5
Title3 Option1, Option2, Option3

How can I get the script to split and transpose the options but write the same title for each option?

Thank you in advance.

PS: The code is likely not efficient and I assume it lacks any best practices, it's my first time using Google Apps Script so if anyone has any pointers I would appreciate it. I have been looking through Google's documentation but I need to sleep on it.

Rubén
  • 34,714
  • 9
  • 70
  • 166
kamen1111
  • 175
  • 10

1 Answers1

3

One way to solve this is to

  1. Split the options values
  2. and then build an output array with two columns and 13 (in this example) rows

Best practices suggest minimising calls to the sheet.

So the following variation of your script does all of the above:

function formatData() {

  // File
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // Get rawData sheet
  var rawData = ss.getSheetByName('rawData');

  // Input data
  var data = rawData.getRange("A2:B").getValues(); // Gets titles and options in a single call to the sheet

  // Initialise an array that will hold the output
  var outputArray = [];

  // Name a variable to hold the data from each set of options
  var options;

  // Start looping through the data
  for (var row = 0; row < data.length; row++) {

    // Split the options into an array: "Option1, Option2, Option3" ---> [Option1, Option2, Option3]
    options = data[row][1].split(", ");

    // Loop through the array of split options and place each of them in a new row
    for (var element = 0; element < options.length; element++) {

      outputArray.push([data[row][0], // Place the title in a new row
                        options[element]]); // Place one option in the 2nd column of the row

    } // Options loop ends here

  } // Data loop ends here

  // Get processedData sheet
  var processedData = ss.getSheetByName('processedData');

  // Get last row in processedData sheet
  var lastRow = processedData.getLastRow();

  // Post the outputArray to the sheet in a single call
  processedData.getRange(lastRow + 1, 1, outputArray.length, outputArray[0].length).setValues(outputArray);
}
ADW
  • 4,177
  • 1
  • 14
  • 22
  • Thank you for your help, it was exactly what I needed. – kamen1111 Aug 19 '19 at 14:41
  • If I only wanted the title printed once instead of it printing for each option, how would I go about that? I figure I need to move it outside the options loop, but then the first .push() uses one row to print the title and the second .push() goes to the next row(s) to print the options. – kamen1111 Aug 19 '19 at 17:41