title: Datatable not populating if 2d data is created manually from array var instead of range.getDisplayValues() in Google Apps Script
body: <p>I am creating a Google Apps Script which takes the data from Google Sheets and renders it to jquery datatable.</p>
  <p>CASE 1: (ifUsingSheetAsDB = TRUE) I am able to fetch and render the data successfully by filtering required data to a short Google sheet's table (short table) in a separate sheet from a large table (big table) using Google sheet's Filter formula and then reading that filtered table in my .gs file. This case in the code is wrapped with &quot;ifUsingSheetAsDB&quot;</p>
  <p>My final data coming from .gs file to datatable is (in this case)</p>
  <pre><code>function userClickedCheck(name, code) {
    
    var ret = validator(name, code);  //name-code checker
    var range = wsTest.getRange(&quot;A2:A&quot;).getValues();  //short table is generated in the sheet Test here
    
    if(gInDebug || gAppDebug)
    {
      Logger.log(&quot;ret&quot; + ret);  //checking validation
    }
    
    if(ret == 1)  //success
    {
      if(ifUsingSheetAsDB)  //reading &quot;short table&quot; from G Sheet
      {
        var rangelen = range.length;
    
        //Logger.log(range.getDisplayValues());
      
        var lastRow = getLastRowSpecial(range);  //custom function which finds the last filled row
  
        range = wsTest.getRange(&quot;A2:L&quot; + (lastRow + 1));  //last filled row is the table length
        range = range.getDisplayValues();  //GSheet API returns string[][]
      }   
      else
      {
        //TODO without sheet as DB////////////////////////
  
        range = garySelectedRange;  //declared as let garySelectedRange = [];
        //TODO without sheet as DB end ////////////////////////
      }
    }
    else
    {
      range = [[]];
    }
  
    
    if(gAppDebug || gInDebug)
    {
      Logger.log(&quot;length of range &quot; + range.length);  //Apps Script Point 1
      Logger.log(range);  //Apps Script Point 2
    }
    return range;
  }
  </code></pre>
  <p>The range is captured in the datatable js as below:</p>
  <pre><code>function checkFinished(rangeValues)
  {
    if ( ! table.data().any() ) 
    {
      //alert( 'Empty table' );
    }
    else
    {
      table
      .clear()
      .draw();
    }
  
    //var len2D = rangeValues.length;
  
    //alert(&quot;Reached inside SubmitFinished &quot; + len2D);
    //TODO debug
    console.log(&quot;printing rangeValues &quot; + rangeValues.length)  //console debug
    console.table(rangeValues);  //console debug
    //TODO debug end
  
    table.rows.add( rangeValues )
      .draw();
  }
  </code></pre>
  <p>This is working real good. No issues here. I have read about range.getDisplayValues(); which returns string[][] according to <a href="https://developers.google.com/apps-script/reference/spreadsheet/range" rel="nofollow noreferrer">https://developers.google.com/apps-script/reference/spreadsheet/range</a></p>
  <p>Case 2: (ifUsingSheetAsDB = FALSE) Now I want to replace the data fetch and instead of using G Sheet's integrated Filter functions in the sheet, I am processing the whole &quot;big table&quot; by fetching data to .gs file and using my custom Filter:</p>
  <pre><code>function filterAndCreate(name)
  {
    var inneri = 0;
    var innerj = 0;
    for (var i in garyRangePO)  
    {
      if(garyRangePO[i][1] == name)
      {
        garySelectedRange.push(
          [
          garyRangePO[i][0] + &quot;/2122&quot;,
          garyRangePO[i][5],
          garyRangePO[i][6],
          garyRangePO[i][7],
          garyRangePO[i][8],
          garyRangePO[i][9],
          garyRangePO[i][10],
          garyRangePO[i][11],
          garyRangePO[i][12],
          garyRangePO[i][14],
          garyRangePO[i][13],
          garyRangePO[i][20]
          ]
          );
      }
    }
  
    if(gInDebug || gAppDebug)
    {
      Logger.log(garySelectedRange);   
    }
  }
  </code></pre>
  <p>.js side it's the same function.</p>
  <p>where garyRangePO is &quot;big table&quot; and garySelectedRange is &quot;short table&quot; and declared as
  let garyRangePO = [];
  let garySelectedRange = [];
  in global scope.</p>
  <p>If I debug this in Apps Script, my debug points when success gives me something like this:
  CASE 1:
  <a href="https://i.stack.imgur.com/uKfFi.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/uKfFi.png" alt="enter image description here" /></a></p>
  <p>CASE 2:
  <a href="https://i.stack.imgur.com/zTUFD.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/zTUFD.png" alt="enter image description here" /></a></p>
  <p>Everything looks great till now from return value perspective too.
  For both the cases Apps Script debugger is showing type as
  <a href="https://i.stack.imgur.com/a6QxG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/a6QxG.png" alt="enter image description here" /></a></p>
  <p>However, when I actually run my code...
  Case 1 console log (where data is properly populated to datatable and works like a charm):
  <a href="https://i.stack.imgur.com/CtK0Y.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/CtK0Y.png" alt="enter image description here" /></a></p>
  <p>Case 2 console log:
  <a href="https://i.stack.imgur.com/mqXgk.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/mqXgk.png" alt="enter image description here" /></a></p>
  <p>Now here I need help please.
  I am new to js and webapp and all. So please pardon me in advance.
  Thank you.</p>