How can I iterate through multiple rows in JavaScript?

Feeling stuck, the simple yet dreaded for loop has become my nemesis and I could really use some guidance. Currently, I have a Google sheet with 3 rows (excluding headers) and 8 columns. As users input data via a web app, the number of rows will dynamically increase. My goal is to extract this data from the sheet and utilize it to send targeted emails to specific services within our organization.

I only require 6 out of the 8 available columns of data. However, I'm struggling with iterating through all the columns and rows effectively. Despite trying a basic for loop, a nested for loop, and a forEach function, none have yielded the expected output.

Below is my most recent code snippet:

function serviceSelector() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Response');
  var row = sheet.getLastRow();
  var range = sheet.getDataRange();
  var data = range.getValues();
  var holderArray = [];
  for(i = 0; i < data.length; i++){
     holderArray.push(
       data[1][0],
       data[1][1],
       data[1][2],
       data[1][4],
       data[1][5],
       data[1][6]);
  }
 Logger.log(holderArray);


//  switch(holderArray[1]){
//    case 'Volunteering':
//      MailApp.sendEmail('<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ef8e818b969f8e9a839c9b8a998a819caf88828e8683c18c8082">[email protected]</a>', 'Message ID# ' +holderArray[2], 'You have receive the following message regarding Volunteering: \n\n'+holderArray[3]); 
//      break;  
//    case 'Home Help Service':
//      MailApp.sendEmail('<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8beae5eff2fbeafee7f8ffeefdeee5f8cbece6eae2e7a5e8e4e6">[email protected]</a>', 'Message ID# ' +holderArray[2], 'You have receive the following message regarding the Home Help Service: \n\n'+holderArray [3]); 
//      break;
//  }
} 

I have commented out the switch statement in order to address the issue related to obtaining the correct data.

Based on the fantastic advice given thus far, I have updated my code as shown below:

function serviceSelector() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Response');
  var row = sheet.getLastRow();
  var range = sheet.getRange(2,1, sheet.getLastRow() -1,8);
  var data = range.getValues();
  var holderArray = [];
  for(i in data[0]){
    for(j in data[i]){
      holderArray.push(data[j])
    }
  }

  Logger.log(holderArray);

The resulting log output is displayed below:

[20-03-26 12:35:22:136 GMT] [[Andy, Stevens, [email protected], Wed Mar 25 2020 16:43:38 GMT+0000 (Greenwich Mean Time), k87k4rp4, Home Help Service, Hello World, [email protected]], [...truncated text...]

To see the complete code, including the switch statement where the problem lies, please refer below:

function serviceSelector() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Response');
  var row = sheet.getLastRow();
  var range = sheet.getRange(2,1, sheet.getLastRow() -1,8);
  var data = range.getValues();
  var cols = range.getNumColumns();
  var rows = range.getNumRows();
  var holderArray = [];
  for (var i = 0; i < rows; i++){
    for (var j = 0; j < cols; j++) {
       holderArray.push(data[i][j]);
    }
  }
  Logger.log(holderArray);
  Logger.log(holderArray);
  switch(holderArray[5]){
    case 'Volunteering':
      MailApp.sendEmail(holderArray[2], 'Message ID# ' +holderArray[4], 'You have receive the following message regarding Volunteering: \n\n'+holderArray [6]); 
      break;  
    case 'Home Help Service':
      MailApp.sendEmail(holderArray[2], 'Message ID# ' +holderArray[4], 'You have receive the following message regarding the Home Help Service: \n\n'+holderArray [6]); 
      break;
  }
}

Answer №1

Explanation

The data variable provided is in the form of a two-dimensional array, requiring the use of two for loops to traverse it effectively. To account for varying row and column numbers within the data, it is recommended to define variables representing the number of rows and columns. This allows for one loop to iterate through the rows, while another handles the columns. Each iteration involves accessing the specific element using the notation data[i][j].

Snippet

 var cols = range.getNumColumns();
 var rows = range.getNumRows();
 var holderArray = [];
 for (var i = 0; i < rows; i++) 
    for (var j = 0; j < cols; j++) 
       holderArray.push(data[i][j]);

If only 6 columns are required, simply replace the cols variable with 6.

Reference

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to implement a gradual decrease in padding as the viewport resizes using JavaScript

My goal is to create a responsive design where the padding-left of my box gradually decreases as the website width changes. I want the decrease in padding to stop once it reaches 0. For instance, if the screen size changes by 1px, then the padding-left sh ...

JQuery UI Autocomplete: Results, Ctrl + A and Delete

I am currently designing a form that allows users to add members to a project. Only members with existing profiles in the system can be added. The form includes an input field for the member's name and a select box for their position, which is initial ...

Dealing with child elements in isomorphic React applications: a comprehensive guide

Looking at my server code, here is how it appears: var data = { scripts: scripts, children:[<Comp1 />, <Comp2 />, <Comp3 />] }; // keeping smaller for easier example than reality var markup = ''; markup += '<scrip ...

Is it possible to expand the Angular Material Data Table Header Row to align with the width of the row content?

Issue with Angular Material Data Table Layout Link to relevant feature request on GitHub On this StackBlitz demo, the issue of rows bleeding through the header when scrolling to the right and the row lines not expanding past viewport width is evident. Ho ...

Steps to send a table to PHP and store it as a text file

I have this program for a form data entry. It includes text boxes to input values, and upon clicking 'Submit', the input values should be displayed below while resetting the text box for another set of inputs. The issue I am facing is with the sa ...

5 Bootstrap Popovers with Custom HTML Contents

I am having trouble separating the content of the bootstrap5 popover from the HTML attributes, unlike other components where it is achievable. var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')) var ...

The Bootstrap Navbar is causing the navigation bar to span across two lines

I'm having an issue with my navbar taking up two lines on desktop resolution, but fitting perfectly on mobile. I've spent hours going through the code with no success. Any help would be greatly appreciated. The HTML code is provided below. <! ...

What is the best way to enhance a tool-tip with images or legends?

Currently, I have implemented a tool-tip feature which works for a text box. However, the issue is that users are unaware of the presence of the tool-tip for the text box until they hover over it. My question is, how can I make it more obvious to users t ...

What is the reason for the checkboxes in vuejs not being rendered with the checked attribute set

When working on an edit form, I encountered a situation where I had multiple options to choose from. These options were fetched via ajax using axios and assigned to the variable permisos in the component. Later, these options are rendered through a v-for l ...

Rendering child components in Vue.js with access to parent data

I have a main component in Vue.js with the following structure: <template> <ul class="list-group"> <li class="list-group-item" v-for="item in items"> <div class="row"> <div class="col-md-6"> ...

Discovering items within an array using Vue.js or JavaScript

I have an array of elements in Vue.js where I need to manipulate some data. For example, I have a select dropdown that displays company information with corresponding tags. These tags are at one sub level and are combined into one before being stored in th ...

Guide on transferring numerous files (50k+) from a folder to AWS S3 using node.js

Currently, my Node.js API on a Windows machine is generating numerous XML files that are later sent to an S3 bucket. The quantity of files sometimes surpasses 50k. For the uploading process, I am utilizing the aws-sdk package. Essentially, I iterate throu ...

When using Javascript to append content to the body, it may not be displayed as HTML on

My current project involves creating an HTML document through JavaScript templates. In the code snippet below, I have a const button which serves as my template. By using the replace method, I am able to update the content within the button template from c ...

Do not reload the page after a successful ajax request

I'm using an Ajax section to submit data in Laravel. I want the page to not reload if the submission is successful, but to reload if there's an error. Currently, when there is an error, the page reloads correctly. However, I'm facing an issu ...

how to toggle visibility of bootstrap accordion panel using jQuery

I have a bootstrap accordion that I want to customize. Specifically, I only want to enable a panel under specific conditions. The idea is for the second panel to be collapsible only when the first panel is valid. <div class="panel-group" id="accordion" ...

Leveraging reframe.js to enhance the functionality of HTML5 video playback

I'm struggling with using the reframe.js plugin on a page that includes HTML5 embedded video. When I try to use my own video file from the same folder, it doesn't work as expected. While everything seems to be working in terms of the page loadin ...

Enable/Disable Text Editing Based on Vue Js Input

I’m working on a way to make certain parts of a string in an input editable or non-editable (readonly) depending on the context in Vue.js. For instance: I have this text: My Name is $John Doe$ Now, I want my Vue.js code to scan the string and allow edi ...

Having trouble generating a bin executable for my npm package

Referencing: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bin I am attempting to generate a "binary" for my npm package. The structure of my package.json is as follows: { "name": "@internal/my-exe", "version": "0.0.0", "type": "commo ...

"Rest API is not activating JavaScript on Android devices, whereas it functions correctly in web browsers

<?php $conn = mysqli_connect('localhost','eyukti_home_roc','4nYntQuCjPYR','eyukti_home_roc'); $user_id = $_GET['user_id']; $sql = mysqli_query($conn,"SELECT * FROM `vehicle_type` WHER ...

React Select feature fails to show suggestions after asynchronous debounced call

I am currently utilizing react-select to load results from an API while debouncing queries using lodash.debounce: import React, {useState} from 'react'; import AsyncSelect from 'react-select/lib/Async'; import debounce from 'lodas ...