Tips for Emphasizing a Row in a Table Using a Specific Value

Currently, I am engaged in creating an educational YouTube tutorial that delves into Google App Script and Google Sheets.

I have been attempting various methods to highlight a row containing the word "ABSENT", but all my endeavors have proven to be unsuccessful.

If anyone could offer guidance on how to modify the code successfully, it would be greatly appreciated.

Important: A newer version of the code has been released for improved comprehension.

CODE.JS

function doGet(e) {
  
  return HtmlService.createTemplateFromFile("Index").evaluate()
  .setTitle("WebApp: Search By Password")
  .addMetaTag('viewport', 'width=device-width, initial-scale=1')
  .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}


/* PROCESS FORM */
function processForm(formObject){ 
  var concat = formObject.searchtext+formObject.searchtext2;
  var result = "";
  if(concat){//Execute if form passes search text
      result = search(concat);
  }
  return result;
}

//SEARCH FOR MATCHED CONTENTS ;
function search(searchtext){
  var spreadsheetId   = '1bahNEJIweyuvmocYbSR8Nc_IA_HP3qdO7tCKU6w'; //** CHANGE !!!!
  var sheetName = "Data";
  var range = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName).getDataRange();
  var data = range.getDisplayValues();
  var ar = [];
  
  data.forEach(function(f) {
    if (~[f[8]].indexOf(searchtext)) {
      ar.push([ f[2],f[3],f[4],f[5],f[6],f[7] ]);
    }
  });
                                           
  return ar;
};

INDEX.HMLT

<!DOCTYPE html>
<html>
    <head>
        <base target="_self">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
       
   <style>
   
   /* h5 {background: red;} */
   
   </style>

        
    </head>
    <body>
        <div class="container">
            <br>
            <div class="row">
              <div class="col">
            
                  <!-- ## SEARCH FORM ------------------------------------------------ -->
                  <center><form id="search-form" onsubmit="handleFormSubmit(this)">
                    <div class="form-group mb-2">
                      <h5 for="searchtext">Work Log Records</h5>
                    </div><p>
                    <div class="form-group mx-sm-3 mb-3">
                      <input type="email" class="form-control col-sm-6" id="searchtext" name="searchtext" placeholder="Email" required><br>
                  
                      <input type="text" class="form-control col-sm-6" id="searchtext2" name="searchtext2" placeholder="Employee ID" required>
                    </div><p>
                    <button type="submit" class="btn btn-primary mb-2">Generate
                      <span id="resp-spinner5" class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span> 
                    </button>
                    
                    
                 
                  </form></center>
                  <!-- ## SEARCH FORM ~ END ------------------------------------------- -->
              
              </div>    
            </div>
            <div class="row">
              <div class="col">
            
                <!-- ## TABLE OF SEARCH RESULTS ------------------------------------------------ -->
                <div id="search-results" class="table table-responsive ">
                  <!-- The Data Table is inserted here by JavaScript -->
                </div>
                <!-- ## TABLE OF SEARCH RESULTS ~ END ------------------------------------------------ -->
                  
              </div>
            </div>
        </div>
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s" crossorigin="anonymous"></script>



        <!--##JAVASCRIPT FUNCTIONS ---------------------------------------------------- -->
        <script>
          //PREVENT FORMS FROM SUBMITTING / PREVENT DEFAULT BEHAVIOUR
          function preventFormSubmit() {
            var forms = document.querySelectorAll('form');
            for (var i = 0; i < forms.length; i++) {
              forms[i].addEventListener('submit', function(event) {
              event.preventDefault();
              });
            }
          }
          window.addEventListener("load", preventFormSubmit, true);
             
          
          
          //HANDLE FORM SUBMISSION
          function handleFormSubmit(formObject) {
           if(document.getElementById('searchtext').value == "" || document.getElementById('searchtext2').value == ""){
              alert("Fill in Email and Employee ID");
           }else{
             document.getElementById('resp-spinner5').classList.remove("d-none");
        
            google.script.run.withSuccessHandler(createTable).processForm(formObject);
            document.getElementById("search-form").reset();
           };
          };
        
          //CREATE THE DATA TABLE
          
          function createTable(dataArray) {
             document.getElementById('resp-spinner5').classList.add("d-none");
   
            if(dataArray && dataArray !== undefined && dataArray.length != 0){
              var result = "<table class='table table-sm table-dark table-hover' id='dtable' style='font-size:0.8em'>"+
                           "<thead style='white-space: nowrap'>"+
                             "<tr >"+                               //Change table headings to match with the Google Sheet
                              
                              "<th scope='col'>EMPLOYEE</th>"+
                              "<th scope='col'>DATE</th>"+
                              "<th scope='col'>IN TIME</th>"+
                              "<th scope='col'>OUT TIME</th>"+
                              "<th scope='col'>HOURS</th>"+
                              "<th scope='col'>STATUS</th>"+
                            "</tr>"+
                          "</thead>";
              for(var i=0; i<dataArray.length; i++) {
                  result += "<tr>";
                  for(var j=0; j<dataArray[i].length; j++){
                      result += "<td>"+dataArray[i][j]+"</td>";
                  }
                  result += "</tr>";
              }
              result += "</table>";
              var div = document.getElementById('search-results');
              div.innerHTML = result;
            }else{
              var div = document.getElementById('search-results');
              //div.empty()
              div.innerHTML = "Data not found!";
            }
          }
        </script>
        <!--##JAVASCRIPT FUNCTIONS ~ END ---------------------------------------------------- -->    
    
    </body>
</html>

Answer №1

It seems like the value inside dataArray[i][j] might be where the word "Absent" could be located.

If this is the case, you are essentially checking if one string ("Absent") exists within another string (dataArray[i][j])

This is where the use of the search() method comes in handy. https://www.w3schools.com/jsref/jsref_search.asp

The following code snippet can help achieve this:

if (dataArray[i][j].search("ABSENT") > -1){
  /*change color to red or any other desired action*/
}

Answer №2

It appears that the provided code is unrelated to Google Spreadsheet and instead seems to be JavaScript code designed to create an HTML table for a web browser.

However, how exactly will this HTML table be transferred to Google Spreadsheet? Will it be done manually through copy and paste?

These tasks may prove to be quite different:

-- Changing the cell colors in the original HTML table (though these colors may not carry over when pasted into Google Spreadsheet via clipboard).

-- Changing the cell colors in a Google Spreadsheet table (but first, the table needs to be transferred there somehow, right?).

Answer №3

It is my understanding of your objective.

  • You aim to change the background color of a row when it contains the value ABSENT.

In this scenario, have you considered checking if each row includes the value ABSENT? By incorporating this into your script, it would look like this:

From:

for(var i=0; i<dataArray.length; i++) {
    result += "<tr>";
    for(var j=0; j<dataArray[i].length; j++){
        result += "<td>"+dataArray[i][j]+"</td>";
    }
    result += "</tr>";
}

To:

for(var i=0; i<dataArray.length; i++) {
  result += dataArray[i].some(c => c.toUpperCase() == "ABSENT") ? '<tr style="background-color:red;">' : "<tr>";
  for(var j=0; j<dataArray[i].length; j++){
    result += "<td>"+dataArray[i][j]+"</td>";
  }
  result += "</tr>";
}
  • In this case, rows with the value ABSENT will have a red background color. Feel free to adjust the script if you wish to change the color.

Note:

  • If you prefer to set the background color only for specific cells rather than the entire row, you can make the following adjustments:

      for(var i=0; i<dataArray.length; i++) {
        result += "<tr>";
        for(var j=0; j<dataArray[i].length; j++){
          result += (dataArray[i][j].toUpperCase() == "ABSENT" ? '<td style="background-color:red;">' : "<td>") +dataArray[i][j]+"</td>";
        }
        result += "</tr>";
      }
    

Added:

Based on your last comment,

@Tanaike I apologize for the confusion earlier. After placing your code correctly, the login and table are displaying properly, but the row highlighting isn't working. Here's the code you provided: 'for(var i=0; i<dataArray.length; i++) { result += dataArray[i].some(c => c.toUpperCase() == "Leave") ? '' : ""; for(var j=0; j<dataArray[i].length; j++){ result += ""+dataArray[i][j]+""; }'

It appears that you are testing the script using the value Leave. However, in your initial query, the value specified was ABSENT. If you intend to switch to using Leave, you can modify the script as follows, considering that toUpperCase() converts characters to uppercase:

From:

for(var i=0; i<dataArray.length; i++) {
    result += "<tr>";
    for(var j=0; j<dataArray[i].length; j++){
        result += "<td>"+dataArray[i][j]+"</td>";
    }
    result += "</tr>";
}

To:

for(var i=0; i<dataArray.length; i++) {
  result += dataArray[i].some(c => c == "Leave") ? '<tr style="background-color:red;">' : "<tr>";
  for(var j=0; j<dataArray[i].length; j++){
    result += "<td>"+dataArray[i][j]+"</td>";
  }
  result += "</tr>";
}

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

The error message "Cannot construct apickli.Apickli" is indicating a Type Error

Encountering this issue : TypeError: apickli.Apickli is not a constructor every time I attempt to execute Sendpostrequest.js again in the following step of a scenario. In A.js, the initial call to Sendpostrequest works without any problems. However, ...

Persist user input even after reloading the page

In order to enhance the user experience, I would like to implement a feature where the data entered by the user is preserved even if they refresh, reload, or close the page. This includes retaining the selections made in the select elements. Additionally, ...

Is jQuery still recommended for adding animations in VueJS?

In my component's methods object, I currently have the following code snippet: startImageAnimation() { $('.splash-image').fadeIn(1400, () => { setTimeout(function() { $('.splash-image').fadeOut(1400, () ...

Implementing HTML page authentication with Identity ADFS URL through JavaScript

I have a basic HTML page that displays customer reports using a JavaScript function. The JavaScript makes an ajax call to retrieve the reports from a backend Spring REST API. In the Spring REST API, I have set up an endpoint "/api/saml" for authentication ...

Customize your popover content with Bootstrap settings

I've been on a quest to dynamically update the content of a Bootstrap popover using JavaScript, but unfortunately, the methods I've tried so far haven't worked out as expected : <!--object with the popover--> <input id="popoverlist ...

Displaying random divs and subsequently animating them downwards using JavaScript

I am in the process of creating a random appearing div that then falls down. Here is the code I have so far: $(document).ready(function(){ $('#test').animate({top: 80 + '%'},900); }); <div id="test" style="background:#98bf21;heigh ...

What is the best way to send user input text to a Vue method using v-on:change?

I am trying to pass the input value from my HTML to a Vue method called checkExist(). I need to get this value within the checkExist() method. Can anyone provide advice on how I can achieve this? I am new to Vue and could use some guidance. HTML: <inp ...

Display the Material UI Switch in an active state even when the "checked" value is set to false

While using Material UI Switches with Formik, I've encountered an issue. When I toggle the switch to 'enable,' it automatically sets the value in Formik to "true," and when I toggle it to 'disable,' it sets the value in Formik to " ...

d3.json is unable to parse a value of 'Infinity

My goal is to retrieve data from an SQLite database and convert it into JSON format for use with d3.js in order to create a graph. I have successfully obtained this data in JSON format using the following URL: http://localhost:8085/SQLQuery/?date1=2019-03 ...

Load charts.js synchronously into a div using XMLHttpRequest

At the moment, there is a menu displayed on the left side of the page. When you click on the navigation links, the page content loads using the code snippet below: if (this.id == "view-charts") { $("#rightContainer").load("view-charts.php"); $(thi ...

Stop the background from scrolling and prevent auto-jumping to the top on mobile devices

When users click on the hamburger icon in the top right of our mobile site, I want the drop-down menu to appear and be scrollable without the background scrolling. I tried using JavaScript to set the body to fixed when the menu icon is clicked, but this ca ...

Auto-complete feature not populating the input field in Google Chrome

Within my register form, I have various INPUT tags present. One of these INPUTs has the name email. <input type=text name=email id=email> When filling out this form in Chrome, I encounter a peculiar behavior. Upon clicking on the email input field ...

The UI Bootstrap Datepicker requires a second click in order to update the month

I am currently using the UI Bootstrap Datepicker component. An issue arises when I try to select the next month - the datepicker itself updates correctly, but the displayed month name does not change (refer to picture 1 and 2). Interestingly, after select ...

Javascript 'break' statement is always executed

It seems like I'm overlooking a very basic concept here. Why isn't my code reaching the else statement? The issue might be related to the break statement. It's likely something simple that I am missing. Code Snippet: <button onclick="yo ...

"Adding an Image to Another Image in HTML or JavaScript: A Step-by-Step

Hello there! I'm currently working on creating a status bar where I can add an image after another image. Let me explain my idea clearly. So, I have two images in GIF format: one is white and 10x10px, and the other one is black and also 10x10px. On ...

Encountered an error while web crawling in JavaScript: Error - Connection timeout

I encountered an error while following a tutorial on web crawling using JavaScript. When I execute the script, I receive the following errors: Visiting page https://arstechnica.com/ testcrawl ...

Leveraging an external TypeScript library in a TypeScript internal module

Imagine you find yourself in a situation where you need to utilize a typescript/node library within an internal module that is spanned across multiple .ts files. ApiRepositoryHelper.ts import * as requestPromise from "request-promise"; module ApiHelp ...

The utilization of useState can potentially trigger an endless loop

Currently, I am in the process of developing a web application using Next.js and Tailwind CSS. My goal is to pass a set of data between methods by utilizing useState. However, I have encountered an issue where the application loads indefinitely with excess ...

What is the best way to retrieve localstorage information within the getStaticProps function in next.js?

Having trouble retrieving local storage data with the following code. localData = { id: localStorage.getItem("id"), token: localStorage.getItem("token"), }; This snippet is housed within a function called getStaticProps ...

Cloud Foundry deployment faces startup issues

I attempted to deploy my Node.js application on Bluemix, but encountered a failure. After executing cf logs IssueTracker --recent, I came across the following error: 2018-12-10T16:50:24.38+0000 [APP/PROC/WEB/0] ERR module.js:549 2018-12-10T16:50:24 ...