Glide Big Tables API! Get your big table to your google sheet!

Hey guys, I used google apps script to figure out how to import your entire Glide Big Table.

Here are the two functions I used to make this happen:

//Variable to store all rows outside the row reader function

  var allRows = [];

//This function can read and return all the rows from any Glide Table

/**
 * Can read all the rows in any one glide table.
 * @param {String} app_id The designated ID to define each app built on Glide
 * @param {String} secret_code The 'Bearer' token provided by Glide allowing you to access their API
 * @param {String} table_name The name of the table assigned by Glide storing the subset of rows
 * @param {String} continuation The continuation token provided by a previous API call to help retrieve the next batch of data
 * @return {Object} Returns an array object full of json values, each json object will be a row in the table
 * @customfunction
 */
function Read_Rows_From_Any_Glide_Table(app_id,secret_code,table_name,continuation){

  console.log('Commenced '+arguments.callee.name); //This will display the start of the function in the console

  //Trying to catch errors

  try

        {

        //Defining the API endpoint URL
        
        var url = 'https://api.glideapp.io/api/function/queryTables';

        //Defining the headers so that Glide's server can authorize your API call

        var headers = 
        
            {
              'Content-Type': 'application/json', //Content type will always be application JSON

              'Authorization': 'Bearer '+secret_code, //The secret API provided to each unique user by Glide
            };

        //Defining the data payload to tell Glide's server where and how to query the data from

        var data = 
        
                    {
                      appID: app_id, //The authorised app ID provided by Glide within which the table is used

                      queries:
                                [
                                  {
                                    tableName: table_name, //The name of the table assigned by Glide storing the subset of rows

                                    startAt: continuation, //The continuation token provided by a previous API call to help retrieve the next batch of data
                                  }
                                ],
                    };

        //Defining the options to tune the API call to be read by Glide's server

        var options =
        
                      {
                        method: 'post',// All requests to Glide's servers are 'POST' request

                        headers: headers,// As defined above

                        payload: JSON.stringify(data),

                        muteHttpExceptions: true // Set as 'TRUE' to examine the full server response
                      };

        var response = UrlFetchApp.fetch(url, options);
        
        var response_parsed = JSON.parse(response.getContentText());

        //Pushing the rows from the first API call to the 'all_Rows' variable defined outside this function

        allRows = allRows.concat(response_parsed[0]['rows']);

        //Blocking the next console log command to generate a simpler log

        //console.log({'output':response_parsed,'row data length':response_parsed[0]['rows'].length, 'total data length': allRows.length});

        //Checking to see if a 'next' json has been provided

        if(response_parsed[0]['next'])
        
            {
              //Pass the 'next' value as is, without parsing

              console.log("Partial data fetched. Another call will be made."); //If there is a 'next', return more rows

              console.log('Terminated '+arguments.callee.name); //This will display the end of the function in the console

              Read_Rows_From_Any_Glide_Table(app_id,secret_code,table_name,response_parsed[0]['next']);

              console.log('Terminated '+arguments.callee.name); //This will display the end of the function in the console

              return {'status':'success','payload':allRows,'error':null}
            } 
        
          else
          
            {
              console.log("All data fetched"); //If there is no 'next', return all rows

              console.log('Terminated '+arguments.callee.name); //This will display the end of the function in the console

              return {'status':'success','payload':allRows,'error':null}
            }

        }

    catch(error)

      {
        console.log('Failed to run the function due to '+error);

        return {'status':'failure','payload':null,'error':error};
      }
}

//This function will parse data from a json format and return it in a format that will allow google sheets to read it

/**
 * Can transform a JSON dataset into a format readable by google sheets.
 * @param {Array} json_object_array The JSON dataset array provided from another function
 * @return {Object} Returns an array of all the json values, in a google sheets readable format
 * @customfunction
 */
function Parse_JSON_Dataset_To_Google_Sheets(json_object_array){

  console.log('Commencing '+arguments.callee.name); //This will display the start of the function in the console

  //Trying to catch errors

  try

    {

      //Retrieving the firstg json object to get the json keys

      var object_0 = json_object_array[0];

      //The keys are being obtained next to allow the mapping of all row values

      var object_0_keys = Object.keys(object_0);

      //Mapping each through all the rows to then map each row item by its JSON Key

      var mapper_1 = json_object_array.map(json_object => 
      
                      {
                        var row_array = []; //Creating a row array for the looper below to add elements for each cell in the row

                        //Looping through each key-value pair in the JSON object using the JSON keys

                        var looper_1 = object_0_keys.forEach(key => 
                        
                                        {
                                          //If the json array does not contain that key value pair, a blank value will be inserted

                                          var cell_item = json_object[key] || '';

                                          row_array.push(cell_item);
                                        });

                        //Adding the headers to the row array

                        row_array.unshift(object_0_keys);

                        return row_array;
                        
                      });

      //Returning the enitre mapped array

      console.log('Terminating '+arguments.callee.name); //This will display the end of the function in the console

      return mapper_1;
    }

  catch(error)

    {
      console.log('Failed to run this function due to '+error);

      console.log('Terminating '+arguments.callee.name); //This will display the end of the function in the console

      return null;
    }
}

function Test_1(){

  var glide_table_data_cities_towns = Read_Rows_From_Any_Glide_Table('YOUR_APP_ID','GLIDE_SECRET_CODE','GLIDE_TABLE_NAME');

  var glide_table_data_cities_towns_payload = glide_table_data_cities_towns['payload'];

  Parse_JSON_Dataset_To_Google_Sheets(glide_table_data_cities_towns_payload);

}
 

The last function, called ‘Test_1()’ is just a dummy function used to test the working version of the Glide Big Tables API call!

@Darren_Murphy
@Sean_Martin
@Robert_Petitto
@DarrenHumphries
@experts

Please review this when you guys have the time!

My use case for this would be as such:

  1. Using the data for analytics.

  2. Using this data to push to a normal glide table to avoid incurring the query costs.

  3. Using this data to create basic automations based on the analysed data to push back to Glide. (Currently will not be possible until Glide releases the Automations feature).

1 Like

@Alaap_Kanchwala This might be exactly what I’m looking for as I’m struggling to get gpt to understand the pagination of this api,

Could you possibly provide some instructions on how to use the script?

Many thanks!

Hi Michael! Welcome to Glide!

Here’s a quick screen recording of me demonstrating how to build showing how to read a glide big table using google apps script: Demo:How To Read Rows From A Glide Big Table Using Google Apps Script.mov - Google Drive

Here’s the spreadsheet i used to record the video: Big Tables API Testing Into Google Sheets - Google Sheets.

You can just head over to the apps script attached file of this sheet and explore the code.

@Michael_Stanger

I am also pasting the code block here just in case.

//This function can read and return all the rows from any Glide Table with the help of a recursive function

/**
 * Can read all the rows in any one glide table and uses the help of a recrusive function
 * @param {String} app_id The designated ID to define each app built on Glide
 * @param {String} secret_code The 'Bearer' token provided by Glide allowing you to access their API
 * @param {String} table_name The name of the table assigned by Glide storing the subset of rows
 * @return {Object} Returns an array object full of json values, each json object will be a row in the table
 * @customfunction
 */
function Read_Rows_From_Any_Glide_Table(app_id, secret_code, table_name){

    return Recursive_Fetch(app_id, secret_code, table_name);
}

/**
 * Can read all the rows in any one glide table and acts as a recursive function
 * @param {String} app_id The designated ID to define each app built on Glide
 * @param {String} secret_code The 'Bearer' token provided by Glide allowing you to access their API
 * @param {String} table_name The name of the table assigned by Glide storing the subset of rows
 * @param {String} continuation The continuation token provided by a previous API call to help retrieve the next batch of data
 * @return {Object} Returns an array object full of json values, each json object will be a row in the table
 * @customfunction
 */
function Recursive_Fetch(app_id, secret_code, table_name, continuation, all_rows){
  
    console.log('Commenced ' + arguments.callee.name);

    if (!all_rows){

        all_rows = [];
    }

    try
      
      {
          var url = 'https://api.glideapp.io/api/function/queryTables';

          var headers = {

                          'Content-Type': 'application/json',

                          'Authorization': 'Bearer ' + secret_code,

                        };

          var data =
          
                    {
                      appID: app_id,

                      queries:[
                          {
                              tableName: table_name,

                              startAt: continuation,
                          }
                      ],
                    };

          var options =
          
                        {
                            method: 'post',

                            headers: headers,

                            payload: JSON.stringify(data),

                            muteHttpExceptions: false
                        };

          var response = UrlFetchApp.fetch(url, options);

          var response_parsed = JSON.parse(response.getContentText());

          all_rows = all_rows.concat(response_parsed[0]['rows']);

          if (response_parsed[0]['next'])
          
            {
                console.log("Partial data fetched. Another call will be made.");

                return Recursive_Fetch(app_id, secret_code, table_name, response_parsed[0]['next'], all_rows);
            } 
          
          else
          
            {
                console.log("All data fetched");

                return { 'status': 'success', 'payload': all_rows, 'error': null }
            }
        } 
        
      catch (error){

        console.log('Failed to run the function due to ' + error);

        return { 'status': 'failure', 'payload': null, 'error': error };
        
        }
}

@Darren_Murphy @david @SantiagoPerez @Marcel_at_Glide

Please provide your input if you have a way to improve this answer!

Thank you!

Thank you!

I had to make a change to the script as the test_1 function worked flawlessly i couldnt call the Read_Rows_From_Glide_Table function from the sheet and it continuously gave me a parsing error.

I decided to adapt the test_1 function so it can be configured to only pull certain Collumn ID’s

You can also use the built in trigger option to run the script to further automate.

I could obviously be using the script completely wrong and waisted a whole bunch of time but i have attached the changes made.

// This function can read and return all the rows from any Glide Table with the help of a recursive function

/**
 * Can read all the rows in any one glide table and uses the help of a recursive function
 * @param {String} app_id The designated ID to define each app built on Glide
 * @param {String} secret_code The 'Bearer' token provided by Glide allowing you to access their API
 * @param {String} table_name The name of the table assigned by Glide storing the subset of rows
 * @return {Object} Returns an array object full of JSON values, each JSON object will be a row in the table
 * @customfunction
 */
function Read_Rows_From_Any_Glide_Table(app_id, secret_code, table_name) {
    return Recursive_Fetch(app_id, secret_code, table_name);
}

/**
 * Can read all the rows in any one glide table and acts as a recursive function
 * @param {String} app_id The designated ID to define each app built on Glide
 * @param {String} secret_code The 'Bearer' token provided by Glide allowing you to access their API
 * @param {String} table_name The name of the table assigned by Glide storing the subset of rows
 * @param {String} continuation The continuation token provided by a previous API call to help retrieve the next batch of data
 * @return {Object} Returns an array object full of JSON values, each JSON object will be a row in the table
 * @customfunction
 */
function Recursive_Fetch(app_id, secret_code, table_name, continuation, all_rows) {
    if (!all_rows) {
        all_rows = [];
    }

    try {
        var url = 'https://api.glideapp.io/api/function/queryTables';
        var headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + secret_code,
        };
        var data = {
            appID: app_id,
            queries: [
                {
                    tableName: table_name,
                    startAt: continuation,
                },
            ],
        };
        var options = {
            method: 'post',
            headers: headers,
            payload: JSON.stringify(data),
            muteHttpExceptions: false,
        };
        var response = UrlFetchApp.fetch(url, options);
        var response_parsed = JSON.parse(response.getContentText());
        all_rows = all_rows.concat(response_parsed[0]['rows']);
        if (response_parsed[0]['next']) {
            return Recursive_Fetch(app_id, secret_code, table_name, response_parsed[0]['next'], all_rows);
        } else {
            return { 'status': 'success', 'payload': all_rows, 'error': null };
        }
    } catch (error) {
        return { 'status': 'failure', 'payload': null, 'error': error };
    }
}

/**
 * Read data from Glide Table and write to a Google Sheet
 * @param {String} sheetName The name of the Google Sheet where data will be written
 * @customfunction
 */
function Read_Test_1(sheetName) {
    // Replae 'Big Tables API' with the name of the sheet you want to store the data or rename the sheet Big Tables API
    sheetName = sheetName || 'Big Tables API';

    // Defining the local spreadsheet
    var local_ss = SpreadsheetApp.getActive();
    
    // Defining the local sheets used to store the secret key as per the original script
    var big_tables_sheet = local_ss.getSheetByName(sheetName); // Use the provided sheetName
    var secret_key_sheet = local_ss.getSheetByName('Secret Key 🔑');
    
    // Obtaining the secret key from the sheet - I am only doing this to preserve the identity of my secret key
    var secret_key = secret_key_sheet.getRange('A2').getValue();

    // Calling the function to read the data in the glide table replace 'App_ID' and 'Table_name' with those found in glide
    // you can also store the secret_key in the script if you would prefer
    //PLEASE REMEMBER TO KEEP THE VARIABLES IN SINGLE QUOTES
    var read_glide_table_function = Read_Rows_From_Any_Glide_Table
        ('App_ID', secret_key, 'Table_name');
    
    // Extract the rows from the payload
    var rows_data = read_glide_table_function['payload'];
    
    // Check if rows_data is an array and not empty
    if (Array.isArray(rows_data) && rows_data.length > 0) {
        // Clear the existing data in the target sheet
        if (big_tables_sheet) {
            big_tables_sheet.clear();
        } else {
            console.log("Sheet not found. Existing data not cleared.");
        }
        
        // Create a 2D array to set the values in the Google Sheet
        var dataToWrite = rows_data.map(function(row) {
            return [
                row['$rowIndex'],
                row['$rowID'],
                row['p1Sdk'],
                row['xwr3O'],
                row['QquoA'],
                row['wvMaD'],
                row['nlcis'],
                row['D252v'],
                row['sVUi8'],
                row['UbYK9'],
               // Add more fields as needed
            ];
        });

        // Write the data to the selected sheet
        if (big_tables_sheet) {
            big_tables_sheet.getRange(1, 1, dataToWrite.length, dataToWrite[0].length).setValues(dataToWrite);
        } else {
            console.log("Sheet not found. Data not written.");
        }
    } else {
        console.log("No data to write to the sheet.");
    }
}

Hey Michael, the modifications look great!

You’re really good at understanding and writing apps script javascript!

I just wanted to know if you tested this out and it worked out well.

Please do let me know!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.