Appsheet Standard Naming Protocol

(En) AppSheet Naming Standard Protocol

Click "Show more" to expand the protocol: 

Show More

INTRO

Dear community, today I bring you a new compendium (shorter but concise). This isn't an update of the old version; it's a rework of what was the AppSheet Standard Protocol. These are firm foundations for robust and consistent work (whether you have previous experience or not).

This guide arises from the need to avoid chaos in AppSheet app development by establishing clear rules for organizing and naming elements. It's not a tutorial, but a standard to improve performance and efficiency in individual or team work.

This work has been cleaned up to offer you a simple experience. Without further ado, let's begin.

WHAT IS A STANDARD PROTOCOL?

Show More
A standard protocol is a set of rules that eliminates mental noise for developers, allowing them to focus on building instead of wasting time deciding on names. It's like a "language" chosen to proceed, based on experience. Without a standard, chaos reigns in teamwork and personal organization. Adopting it improves clarity, efficiency, and professionalism, boosting creativity by eliminating unnecessary distractions.

1. DATA

Show More

1.1. GOOGLE SHEETS AS DATABASES

Show More

When we use Google Sheets as our database in AppSheet, folders are automatically generated in our Google Drive directory, inside the 'appsheet/data' folder. These folders have a default name that matches the name of the created application, followed by a hyphen and a number that acts as the application's unique identifier → We will remove this number so the folder name matches the application name.

Additionally, in the AppSheet application settings, we must also adjust the name of the folder containing the databases by entering the same name it has in Google Drive. To do this, go to 'Settings' in the AppSheet editor and look for 'Default app folder'.

It's important to understand the difference between a spreadsheet (file) and a sheet (worksheet) in Google Sheets. The spreadsheet is the database file itself, while the sheets are the individual worksheets within the spreadsheet where our database tables are created.

If you choose to use Google Sheets, it's recommended that the worksheets have no blank columns or empty rows, and that continuous maintenance is performed by deleting any empty rows during the application's use. This is because deleting a record from AppSheet will leave entire empty rows in the tables of the worksheet used as the database. You can visit this post explaining how to create a script in Google Apps Script to automatically delete blank rows from your Google Sheets databases.

I personally created this one that I'm currently using. You can use mine or create your own, but in any case, be careful adding scripts you don't know to your databases:

Show More
function eliminarFilasVacias() {
  // Obtén la hoja activa
  var hoja = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
  // Obtén el rango de la columna A
  var rango = hoja.getRange("A:A");
  var valores = rango.getValues();
  
  // Variable para contar las filas vacías
  var filasVacias = 0;
  
  // Recorre las filas de abajo hacia arriba (para evitar problemas al eliminar filas)
  for (var i = valores.length - 1; i >= 0; i--) {
    if (valores[i][0] === "" && filasVacias < 1) {
      // Si hay una fila vacía, deja esta fila
      filasVacias++;
    } else if (valores[i][0] === "") {
      // Si la fila está vacía y ya hay una fila vacía, elimina la fila
      hoja.deleteRow(i + 1); // +1 porque las filas en Apps Script son 1-indexed
    }
  }
}

1.2. FILES FOR DATABASES

Show More

Google Sheets currently has a limit of 10 million cells per spreadsheet file. See the following link: Google Sheets Best Practices.

If we try to create all tables as sheets within a single spreadsheet file, we can affect performance and information organization.

In this protocol, it is recommended to use a separate spreadsheet file for each table. This way, each spreadsheet file will have its own 10 million cell limit, and each spreadsheet effectively becomes an independent database table with high capacity. This provides greater flexibility, improves performance, and facilitates data organization.

1.3. NAMING AND ORGANIZATION

Show More

All spreadsheet files for each application or section should be placed inside a container folder with the same name as the application or section (as created).

The Google Sheets file name, the worksheet name (inside the file), and the table name within AppSheet must match (all three must be the same).

This name must follow these rules:

  • Written in lowercase, snake_case format.

  • Plural and in English, regardless of the developer's language.

  • No special characters. May contain numbers, but must not start with them.

  • Must clearly express the table's purpose without ambiguity.

Example, if we create a table named categories, this doesn't tell us much, as they could be tax categories, item categories, etc. The name needs to be specific:

items_categories

items_families
items_types
items_instances


nutrients_categories
nutrients_families
nutrients_types

1.4 DATABASES (Structure/Naming Summary)

Show More

📌 Reglas:

  • snake_case, lowercase, singular (except for special cases detailed later) and in English, regardless of the developer's language.

  • Clear and descriptive purpose.

  • Preferably, a maximum of 27 characters to avoid long and unwieldy names.

Container folder name in Google Drive:

<app_name>_<app_section> (the section is optional).

Google Sheets file name:

<table_name>

Worksheet name (inside the Google Sheet file):

<table_name>

Table name (in AppSheet, matching the file/worksheet):

<table_name>

Slice names:

<table_name>_<descriptor>

I've requested a new feature for the editor: a checkbox that allows you to add a number so we can organize our tables in the editor (by index, not alphabetically) to separate the table names from their organization in the editor. You can vote for this request here.

1.5 ADDITIONAL RECOMMENDATIONS

Show More
  1. Format as Table: It is recommended to use the "Format as table" option in Google Sheets to be able to apply filters within the database view in Sheets.

  2. Protect Headers: It is recommended to use the "Protect range" function in Google Sheets to prevent accidental deletion or modification of table headers.

  3. Freeze the header row: This helps improve the visual organization of data in Sheets.

  4. Name Length: Although not mandatory, it's recommended that names have fewer than 27 characters to avoid complications when writing expressions and ensure names display correctly in the editor without wrapping onto multiple lines.

This will allow the data structure in Google Sheets to function with many features of a traditional database.

1.6 GENERAL FIELD NAMING

Show More

📌Rules:

  • snake_case, lowercase, singular (except for special cases detailed later) and in English, regardless of the developer's language.
  • Clear and descriptive purpose.
  • Preferably, a maximum of 20 characters to avoid long and unwieldy names.

Image of Example Table:

1.6.1. COMMON FIELDS

Show More
These are fields commonly repeated in many tables:
Field Name Purpose
Row ID If using AppSheet DataBase, this field is automatic and doesn't need to be created. It's the row id. Not visible by default in the database. Note that when migrating the application to another database, you must be very careful when using another field as the id. Although it copies without issues when migrating to Google Sheets, returning to the AppSheet database can generate conflicts with duplicate keys.

Editable If' unchecked by default
id

If using Google Sheets, mandatory field, primary key of the table, always named "id" in lowercase. You can use: UNIQUEID("UUID"), UNIQUEID("packedUUID"), UNIQUEID(). In specific cases, like tables with constant, read-only content, other values can be used in the id field, such as manually chosen values, as long as they are unique. 

Editable If' unchecked

_rowNumber Automatic: This field is automatically created in all tables, numbering the rows.
ia_<purpose> Optional: it's a virtual text-type field, empty (with a formula like: ""), used to anchor 'actions, usually inline'. There will be as many such fields as actions needed.
created_at Optional: This field stores the date and time in the database. Configure a YYYY-MM-DD hh:mm:ss format in Google Sheets.
DateTime, initial value NOW(), reset on edit.
user_id Optional: It's typically the email of the user logged into the application, so USEREMAIL() is used in the formula space, but it can be a reference to a user table.

1.6.2. FOREIGN KEY FIELDS

Show More
  • Ref:
    <singular_table/slice_name>_id
  • Enum base Ref:
    <singular_table/slice_name>_id
  • Enumlist base Ref:
    <singular_table/slice_name>_ids

Assuming special cases where we have two ref, enum base ref, or enumlist base ref fields coming from the same source table within the current table, we cannot name them the same as it would cause an error. We can solve this generically as follows:

The first ref field from a table can be named:

<singular_table/slice_name>_id

The second ref field from the same table can be named:

<singular_table/slice_name>_<aditional_descriptor>_id/s

1.6.3. INHERITED FIELDS

Show More

The most common case of an inherited field is a foreign key. As seen previously, they are named <singular_table/slice_name>_id

These fields inherited into other tables have a name in their source table; for inherited fields other than the 'id', the following convention will be used:

<singular_table/slice_name>_<field_name>, Thus, if a field is named “nature” in the “categories” table, in the “types” table it will be named “category_nature”, making it clear it's an inherited field from the “categories” table.

2. VIEWS

Show More

2.1. VIEWS - EDITOR'S RESULT

Here's the result, I'll explain it below:

2.2. VIEW TYPES IN APPSHEET (CODE)

Show More

In AppSheet, views function as the user interface. Currently, there are 11 view types (as of 2025), but it's anticipated that more will likely be added in the future. A highly requested example is the Gantt Chart view, which is apparently under study and development.

Below, I will detail the view type along with its naming code (in red) and the icon we will use for each ref view. (The views that are displayed directly to the user in the editor will have icons chosen by the developer; we are only referring to ref views.)


Table-Dependent

  • Calendar (cl): "calendar-alt" regular icon

  • Deck (dk): "list-alt" regular icon

  • Table (tb): "table" regular icon

  • Gallery (gl): "th-large" regular icon

  • Detail (dt): "indent" regular icon

  • Map (mp): "map-marker-alt" regular icon

  • Chart (ch): "chart-pie" regular icon

  • Form (fr): "edit" regular icon

  • Onboard (ob): "window-restore" regular icon

  • Card (cd): "portrait" icon

Table-Independent

  • Dashboard (db): "layer-group" icon

2.3. VIEW EDITOR STRUCTURE

Show More

The AppSheet editor organizes views into four sections:

  1. Primary Navigation

    • Contains the views for the app's main panel (not much to say here).

  2. Menu Navigation

    • Shows views accessible from the menu (not much to say here).

  3. System Generated

    • Views automatically created by AppSheet for each table. Using them directly is not recommended.

  4. Referenced Views

    • A disorganized area where all referenced views are stored (Reason for the view naming convention); see below.

2.4. REFERENCED VIEWS

Show More

 Similar to a bag of trash (because that's what I perceive), they have no organization whatsoever; everything is "thrown in the same bag". It's incredibly tedious to see the views there without even having sorting by table or view type. Anyway, because of this, I have modified the convention that will allow us to have a clean, organized, intuitive editor, and although a bit cryptic, the "app editor" is accessible to the work team who will know the convention, making it less "cryptic". Truthfully, the convention only serves to provide order until AppSheet implements native sorting for this section. By the way, you can vote for this idea by clicking the link to give it relevance. Once AppSheet organizes this section, this naming convention will automatically lose its effect, and we can enjoy native sorting without having to return to the legacy editor.

To solve this, I propose a naming convention that will allow for a clean, organized, and intuitive editor, at least until AppSheet implements a native organization system.

2.5. ORGANIZATION METHOD

Using the “source_prefix_generator” file

Show More

Our colleague @yasarcan proposed creating a file to document table names in the old protocol. I have taken his idea as inspiration and created a Google Sheets file called "source_prefix_generator".

This file will serve to:
✔ Generate standardized prefixes for naming views, actions, bots, and format rules.
✔ Keep a record of changes in the app's structures.
✔ Facilitate navigation within the editor.

This file contains the following fields:

 

table_sufix

slice_sufix

table/slice_name

action_bots_format_prefix

view_prefix

001

-

table_one

001

001_00

002

-

table_two

002

002_00

002

01

slice_of_table_two

-

002_01

  • The table_sufix field contains a number from 001 to 999 (three digits) and is the identifier for your tables. Each time a table is added to our database structure, we must register that table in the source_prefix_generator with its ID.

  • The slice_sufix field is a number from 01_99 and represents the slice identifier number. Each time we create a slice, we add it to the source_prefix_generator with its identifier.

  • table/slice_name is a field that stores the table/slice name exactly as it is in our application. The table/slice name can change, but the table_sufix and slice_sufix should never change.

  • action_bots_format_prefix is a field with an expression that takes only the table ID (it does not consider slices) since actions, bots, and format rules apply only to tables.

  • view_prefix is a field that generates a usable prefix for views, since these can be based on slices. Fields with an empty slice_sufix cell are tables, and their view_prefix will always have the table suffix and 00 as the slice suffix.

See the cases in the following example:

2.6. VIEW NAMING

Show More

Our colleague @Yahia_DAK suggested table sorting based on prefixes and view types; it was really interesting, so I decided to take his idea as inspiration for this new naming convention (though slightly modified). He starts with numbers, but I realized that starting view names with numbers in the editor while adding expressions doesn't automatically trigger the suggestion popup dialog. Whereas, if we start with letters, filtered suggestions automatically start appearing, which is more intuitive during development and increases typing speed. See it right here:

The first part of the name structure always has the same length and is displayed very orderly, to the point where it eventually goes unnoticed, while the purpose becomes more recognizable.

<view_type_code>_<view_prefix>_<view_purpose>

What is the advantage of using prefixes (even numeric ones within the view_prefix) instead of full names?

  • If the table name changes, the view name doesn't have to because the prefix is an ID, while the name can change.

  • Everything becomes much simpler to visualize.

  • Names are drastically shortened, which is more comfortable in the editor.

  • Allows quick detection of unused or duplicate views.

2.7. SPECIAL CASES: DASHBOARD

Show More

The only view type that doesn't follow the table-based naming format is the Dashboard view, as it can be composed of two or more tables.

For these cases, we use a representative name in lowercase, following this format:

db_<purpose>

📌 Rules:

  • snake_case, lowercase.

  • The purpose should be a clear and descriptive noun.

  • Preferably, a maximum of 30 characters to avoid long and unwieldy names.

2.9. DISPLAY NAMES

Show More
The name the user will see in the interface must be inserted within quotes in the Display Name field, as an expression, whether in views, actions, fields, etc.

3. FORMAT RULES

Show More

3.1. FORMAT RULE NAMING


f_<table_prefix>_<purpose>

Example: f_008_blank_children

Indicates a format rule applied to the table with prefix 008, to handle rows without children.

📌Rules:

  • snake_case, lowercase.

  • Maximum 23 characters.

  • The purpose should be clear and descriptive.

4. BEHAVIOR ACTIONS

Show More

4.1 SYSTEM-GENERATED ACTIONS

Show More

System-generated actions receive a default name. Some examples are:

  • Add

  • Delete

  • Edit

  • Compose Email (User ID)

  • View Ref (TABLE)

These names are consistent across all tables and should not be modified.

4.2. CUSTOM ACTIONS

Show More

For actions we create manually, we will use the "source_prefix_generator" file..

First, I'll show the result, then I'll explain:

actions.png

As you can see, the actions are already organized by table in the editor UI (in the case of the image above, organized under the “items_types” table), but the naming convention ensures the first part of the name always has the same length and provides a better visualization of the action's purpose.

Now, why is this convention necessary when they are already natively organized by table in the editor?

Because AppSheet doesn't allow us to use the same name for actions in different tables. If we created an action named “update” in one table and then another with the same name in another table, AppSheet would automatically rename it to “update 2”, which creates naming inconsistencies. Note that this problem doesn't occur with system-generated actions, since AppSheet gives them the same name in all tables (i.e., there's no Add 1, Add 2, Add n).

Therefore, until AppSheet allows manually created actions to share the same name if they are in different tables, this convention helps us maintain order and avoid inconsistencies in our apps.

I have created a topic for AppSheet to implement this improvement; you can vote here so this limitation disappears in the future. When this happens, our convention will no longer be necessary, and development will be simpler.

4.3. ACTION CODE(action_code)

Show More

There are four main sets of behavior actions in AppSheet:

ACTION

CODE

Application

a

Data

d

External

e

Grouped

g


This code convention (action_code) facilitates the organization and quick reference of actions in AppSheet, improving clarity and efficiency in application development.

Each set contains specific actions:

  • 7 Application Actions

  • 4 Data Actions

  • 5 External Actions

  • 1 Grouped Action

4.3.1. Application Actions (a)

Show More

Below are the actions of the "Application" set with their code and suggested icon for those with "hidden" condition.

  1. Copy this row and edit the copy(a1): "clone" icon

  2. Edit this row(a2):"edit" regular icon

  3. Export this view to a CSV file (not a row-level action)(a3)"fiie-csv" regular icon

  4. Go to another AppSheet app(a4)"rocket"-regular icon

  5. IGo to another view within this app (a5)"chevron-circle-right" black icon

  6. Import a CSV file for this view (not a row-level action) (a6)"fiie-csv" black icon

  7. Open a form to add a new row to this table (not a row-level action) (a7)"plus" regular icon

4.3.2. Data Actions (d)

Show More
Below are the actions of the "Application" set with their code and suggested icon for those with "hidden" condition.
  1. Add a new row to another table using values from this row(d1)"layer-plus" light icon

  2. Delete this row (d2)"trash-alt" solid icon

  3. Execute an action on a set of rows (d3)"table" light icon

  4. Set the values of some columns in this row (d4)"slider-h" regular icon

4.3.3. External Actions (e)

Show More
Below are the actions of the "Application" set with their code and suggested icon for those with "hidden" condition.
  1. Go to a website (e1)"browser" regular icon

  2. Open a file(e2)"folder-open" regular icon

  3. Start a phone call (e3)"phone" regular icon

  4. Start an SMS message → (e4)"envelope" regular icon 

  5. Start an email (e5):"comment-alt-lines" regular icon

4.3.4. Grouped Action (g)

Show More
Below are the actions of the "Application" set with their code and suggested icon for those with "hidden" condition.
  1. Execute a sequence of actions (g1)"list-ol" regular icon

4.4. NAMING FOR ACTIONS

Show More

<action_code>_<source_table_prefix>_<destination_table_prefix>_<action_purpose>

If the action is applied to a single table, both the source and target tables will use the same prefix.

📌 Rules:

  • snake_case, lowercase.

  • The purpose should be a clear and descriptive noun.

  • Preferably, maximum 30 characters to avoid long and unwieldy names.

5. BOTS  

Show More

5.1. NAMING CONVENTION FOR BOTS

Show More

bot_<table_prefix>_<purpose>

Example:bot_018_adder

Este bot pertenece a la tabla con prefijo 018 y su propósito es agregar filas.

📌Rules:

  • snake_case, lowercase.

  • The purpose should be a clear and descriptive noun.

  • Preferably, maximum 27 characters to avoid long and unwieldy names.

5.2. NAMING CONVENTION FOR EVENTS

Show More

Events in AppSheet are triggered when one of these situations occurs:


Event Type Code
App Event app
Scheduled Change (Time) sch
Chat Application cha
Database Trigger dbt
Form Submission frs

📌 Event name format:

event_<table_prefix>_<event_type_code>_<n_order_number>

Example: event_008_app_1

Indicates it's an event on table 008, of type app (application event), with order index 1.
If multiple similar events are created, the number is incremented (_2, _3, etc.) to avoid conflicts.

5.3. NAMING CONVENTION FOR PROCESSES

Show More

In the rest of the editor, we use a coded nomenclature, but in this case, we'll use an intuitive one. Processes are organized as a sequence of logical steps whose purpose is to solve a problem (i.e., an algorithm).
It's very interesting to see how processes look in a bot when their nomenclature is clear and understandable. Here's a visual example:

process.png

Bots execute processes in sequence, which can include:

  • Run a task

  • Run a data action

  • Branch on a condition

  • Wait

  • Call a process

  • Return value(s)

📌Rules:

  • snake_case, lowercase.

  • Short, clear, and descriptive purpose.

  • Preferably, maximum 21 characters to avoid long and unwieldy names.

Example: "generate_invoice"

Process name for a process that generates an invoice.

5.4. BOTS - ICONS

Show More

It is recommended to keep the default bot icon.

The bot's purpose defines its function, but the icon helps identify it visually in the editor.

This convention ensures order, clarity, and scalability in AppSheet application development.

(Es) Protocolo de Nomenclatura Estándar AppSheet

Haga clic en "Show more" para desplegar el protocolo: 

Show More

INTRO

Querida comunidad, hoy les traigo un nuevo compendio (más corto pero conciso). No se trata de una actualización de la antigua versión , se trata de una reelaboración de lo que fue el AppSheet Standard Protocol. Son cimientos firmes para un trabajo sólido y consistente (sea que tengas experiencia previa o no).

Este manual surge de la necesidad de evitar el caos en el desarrollo de apps con AppSheet, estableciendo reglas claras para la organización y nomenclatura de elementos. No es un tutorial, sino un estándar para mejorar el rendimiento y la eficiencia en el trabajo individual o en equipos.

Este trabajo se ha limpiado para ofrecerles una experiencia simple. Sin más, comencemos.

¿QUÉ ES UN PROTOCOLO ESTÁNDAR?

Show More
Un protocolo estándar es un conjunto de reglas que eliminan el ruido mental a los desarrolladores, permitiéndoles enfocarse en construir en lugar de perder tiempo decidiendo nombres. Es como un "idioma" que se elige para proceder, basado en la experiencia. Sin un estándar, el caos reina en el trabajo en equipo y la organización personal. Adoptarlo mejora la claridad, eficiencia y profesionalismo, potenciando la creatividad al eliminar distracciones innecesarias.

1. DATOS

Show More

1.1. GOOGLE SHEETS - BASES DE DATOS

Show More

Cuando usamos Google Sheets como nuestra base de datos en AppSheet, se generan automáticamente carpetas en nuestro directorio de Google Drive, dentro de la carpeta 'appsheet/data'. Estas carpetas tienen un nombre predeterminado que coincide con el nombre de la aplicación creada, seguido de un guion y un número que actúa como identificador único de la aplicación → Eliminaremos este número para que el nombre de la carpeta coincida con el nombre de la aplicación.

Además, en la configuración de la aplicación en AppSheet, también debemos ajustar el nombre de la carpeta que contiene las bases de datos, ingresando el mismo nombre que tiene en Google Drive. Para hacerlo, debemos ir a 'Settings' en el editor de AppSheet y buscar 'Default app folder'.

Es importante entender la diferencia entre una spreadsheet (archivo) y una sheet (hoja de cálculo) en Google Sheets. La spreadsheet es la base de datos en sí misma, mientras que las sheets son las hojas dentro de la spreadsheet donde se crean las tablas de nuestra base de datos.

Si optamos por usar Google Sheets, se recomienda que las hojas no tengan columnas en blanco ni filas vacías, y que se realice un mantenimiento continuo eliminando cualquier fila vacía durante el uso de la aplicación, ya que al eliminar un registro desde AppSheet, se dejarán filas completas vacías en las tablas de la hoja de cálculo usada como base de datos. Puedes visitar este post donde se explica cómo crear un script en Google Apps Script para eliminar automáticamente las filas en blanco de tus bases de datos en Google Sheets.

Yo personalmente he creado este que estoy usando actualmente. Puedes usar el mío o crear el tuyo, pero en cualquier caso ten cuidado con agregar scripts que no conozcas en tus bases de datos:

Show More
function eliminarFilasVacias() {
  // Obtén la hoja activa
  var hoja = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
  // Obtén el rango de la columna A
  var rango = hoja.getRange("A:A");
  var valores = rango.getValues();
  
  // Variable para contar las filas vacías
  var filasVacias = 0;
  
  // Recorre las filas de abajo hacia arriba (para evitar problemas al eliminar filas)
  for (var i = valores.length - 1; i >= 0; i--) {
    if (valores[i][0] === "" && filasVacias < 1) {
      // Si hay una fila vacía, deja esta fila
      filasVacias++;
    } else if (valores[i][0] === "") {
      // Si la fila está vacía y ya hay una fila vacía, elimina la fila
      hoja.deleteRow(i + 1); // +1 porque las filas en Apps Script son 1-indexed
    }
  }
}

1.2. ARCHIVOS PARA BASES DE DATOS

Show More

Google Sheets tiene un límite de 10 millones de celdas por hoja de cálculo actualmente. Consulta el siguiente enlace: Google Sheets Best Practices.

Si intentamos crear todas las tablas en hojas dentro de una única hoja de cálculo, podemos afectar el rendimiento y la organización de la información.

En este protocolo, se recomienda utilizar una hoja de cálculo separada para cada base de datos. De este modo, cada hoja tendrá su propio límite de 10 millones de celdas, y cada hoja de cálculo se convertirá en una base de datos independiente con alta capacidad. Esto proporciona mayor flexibilidad, mejora el rendimiento y facilita la organización de los datos.

1.3. NOMENCLATURA Y ORGANIZACIÓN

Show More

Todas las hojas de cálculo de cada aplicación o sección deben colocarse dentro de una carpeta contenedora con el mismo nombre que la aplicación o la sección (según se haya creado).

El nombre del archivo de Google Sheets, el nombre de la hoja de cálculo y el nombre de la tabla dentro de hoja de cálculo deben coincidir (los tres deben ser iguales).

Este nombre debe seguir estas reglas:

  • Escrito en minúsculas, en formato snake_case.

  • Plural y en inglés, independientemente del idioma del desarrollador.

  • Sin caracteres especiales. Puede contener números, pero no debe comenzar con ellos.

  • Debe expresar claramente el propósito de la tabla sin ambigüedades.

Ejemplo, si creamos una tabla llamada categories, esto no nos dice mucho, ya que podrían ser categorías de impuestos, categorías de artículos, etc. Es necesario que el nombre sea específico:

items_categories
items_families
items_types
items_instances

nutrients_categories
nutrients_families
nutrients_types

1.4 BASES DE DATOS

Show More

📌 Reglas:

  • snake_case, minúsculas, en singular (salvo casos especiales que se detallarán) y en inglés, independientemente del idioma del desarrollador.

  • Propósito claro y descriptivo.

  • Preferentemente, máximo 27 caracteres para evitar nombres largos y poco manejables.

Nombre de la carpeta contenedora de la base de datos en Google Drive:

<app_name>_<app_section> (la sección es opcional).

Nombre del archivo Google Sheets:

<table_name>

Nombre de la hoja de cálculo:

<table_name>

Nombre de la tabla dentro de la hoja de cálculo y en AppSheet:

<table_name>

Nombre de slices:

<table_name>_<descriptor>


He solicitado una funcionalidad nueva para el editor; un casillero que permita agregar un número para que podamos organizar nuestras tablas en el editor (por índice y no por orden alfabético a los fines de independizar el nombre de las tablas de su organización en el editor. Puedes votar esta solicitud aquí.

1.5 RECOMENDACIONES ADICIONALES 

Show More
  1. Convertir en tabla: Se recomienda utilizar la opción "Crear tabla" en Google Sheets para poder aplicar filtros dentro de la base de datos.

  2. Proteger encabezados: Se recomienda usar la función "Proteger rango" en Google Sheets para evitar la eliminación o modificación accidental de los encabezados de las tablas.

  3. Congelar la fila del encabezado: Esto ayuda a mejorar la organización visual de los datos.

  4. Longitud del nombre: Aunque no es obligatorio, es recomendable que el nombre tenga menos de 27 caracteres para evitar complicaciones al escribir expresiones y asegurar que los nombres se vean correctamente en el editor sin ocupar varias líneas.

Esto permitirá que la estructura de datos en Google Sheets funcione con muchas de las características de una base de datos tradicional.

1.6 NOMENCLATURA GENERAL DE CAMPOS

Show More

📌 Reglas:

  • snake_case, minúsculas, en singular (salvo casos especiales que se detallarán) y en inglés, independientemente del idioma del desarrollador.

  • Propósito claro y descriptivo.

  • Preferentemente, máximo 20 caracteres para evitar nombres largos y poco manejables.


Imagen de Tabla Ejemplo:

1.6.1. CAMPOS HABITUALES

Show More
Son campos que se repiten habitualmente en muchas tablas: 
Nombre de campo Propósito
Row ID Si usan AppSheet DataBase, este campo es automático y no necesita ser creado. Es el id de fila. No es visible de manera predeterminada en la base. Tenga en cuenta que cuando se migra la aplicación a otra base de datos debe tener sumo cuidado al usar otro campo como id. Aunque se copia sin problemas al migrar a Google Sheets, regresar a la base de datos de AppSheet puede generar conflictos con campos duplicados.

Editable If' destildado por defecto.
id

Si usan Google Sheets, campo obligatorio, clave principal de tabla, siempre se llama "id" en minúsculas. Puede usar: UNIQUEID("UUID"), UNIQUEID("packedUUID"), UNIQUEID(). 

En casos específicos, como tablas con contenido constante y de solo lectura, pueden usarse otros valores en el campo id, como valores elegidos manualmente siempre que no se repitan.

Editable If' destildado.

_rowNumber Automático: Este campo se crea automáticamente en todas las tablas, numerando las filas.
ia_<purpose> Opcional: es un campo virtual de tipo texto, vacío (con una fórmula como esta: ""), utilizado para señalar las 'acciones, generalmente en línea'. Habrá tantos campos como acciones se necesiten.
created_at Opcional: Este campo almacena la fecha y hora en la base de datos. Configurar en Google Sheet un formato YYYY-MM-DD hh:mm:ss.
DateTime, initial value NOW(), reset on edit.
user_id Opcional: Es típicamente el correo electrónico del usuario que inicia sesión en la aplicación, por lo que se utiliza USEREMAIL() en el espacio de fórmula, pero puede ser referencia a una tabla con usuarios.

1.6.2. CAMPOS FORÁNEOS

Show More
  • Ref:
    <singular_table/slice_name>_id
  • Enum base Ref:
    <singular_table/slice_name>_id
  • Enumlist base Ref:
    <singular_table/slice_name>_ids

Suponiendo casos especiales en los que tenemos dos campos ref, enum de base type ref o enumlist de base type ref, que provienen de una misma tabla, en la tabla actual, no podemos nombrarlos iguales ya que generaría error. Para ello podemos solucionarlo del siguiente modo genérico:

Al primer campo ref proveniente de una tabla podemos llamarlo:

<singular_table/slice_name>_id

Al segundo campo ref proveniente de una tabla podemos llamarlo

<singular_table/slice_name>_<aditional_descriptor>_id/s

1.6.3. CAMPOS HEREDADOS

Show More

El caso más común de campo heredado es una clave foránea. Como vimos anteriormente se nombran <singular_table/slice_name>_id

Estos campos que se heredan en otras tablas tienen un nombre en su tabla origen; para campos diferentes a id heredado se tomará la siguiente convención:

<singular_table/slice_name>_<field_name>, así, si un campo se llama “nature” en la tabla “categories”, en la tabla “types” se llamará “category_nature” dejando en claro que es un campo heredado de la tabla “categories”.

2. VISTAS

Show More

2.1. VISTAS - RESULTADO EDITOR

Les dejo el resultado, después se los explico:

2.2. TIPOS DE VISTAS EN APPSHEET (CÓDIGO)

Show More

En AppSheet, las vistas funcionan como la interfaz de usuario. Actualmente, existen 11 tipos de vistas (hasta 2025), pero es se ha adelantado que es probable que se agreguen más en el futuro. Un ejemplo muy solicitado es la vista Gantt Chart, que al parecer está en proceso de estudio y desarrollo.

A continuación detallaré junto al tipo de vista, su código para la nomenclatura (en rojo) y el ícono que usaremos para cada vista ref (las vistas que se muestran al usuario directamente en el editor tendrán íconos que el desarrollador elija; solo hablamos de las vistas ref):

Dependientes de una tabla

  • Calendar (cl) icono "calendar-alt" regular

  • Deck (dk) ícono "list-alt" regular

  • Table (tb) ícono "table" regular

  • Gallery (gl) ícono "th-large" regular

  • Detail (dt) ícono "indent" regular

  • Map (mp) ícono "map-marker-alt" regular

  • Chart (ch) ícono "chart-pie" regular

  • Form (fr) ícono "edit" regular

  • OnBoard (ob) ícono "window-restore" regular

  • Card (cd) ícono "portrait" regular

Independientes de una tabla

  • Dashboard (db) ícono "layer-group" regular

2.3. ESTRUCTURA DEL EDITOR DE VISTAS

Show More

El editor de AppSheet organiza las vistas en cuatro secciones:

  1. Primary Navigation

    • Contiene las vistas del panel principal de la app (no hay demasiado por opinar aquí).

  2. Menu Navigation

    • Muestra las vistas accesibles desde el menú (no hay demasiado por opinar aquí).

  3. System Generated

    • Son vistas creadas automáticamente por AppSheet para cada tabla. No se recomienda usarlas directamente.

  4. Referenced Views

    • Un área desorganizada donde se almacenan todas las vistas referenciadas (Razón de ser de la convención de nomenclatura de vistas); véase a continuación.

2.4. REFERENCED VIEWS

Show More

Similar a una bolsa con basura (porque eso es lo que percibo), no tienen organización alguna, está todo “tirado en la misma bolsa”. Resulta un enorme tedio ver las vistas allí sin si quiera disponer de un ordenamiento por tabla o por tipo de vista. En fin debido a esto es que he modificado la convención que nos va a permitir tener un editor limpio, ordenado, intuitivo y, aunque un poco críptico, el "app editor" es accesible al equipo de trabajo que conocerá la convención con lo cual no es tan "críptico" y, a decir verdad, la convención solo sirve para brindar un orden mientras AppSheet no genere un ordenamiento nativo para esta sección. Dicho sea de paso puedes votar esta idea haciendo clic en el enlace para que tome relevancia. Una vez que AppSheet organice esta sección, esta nomenclatura perderá automáticamente su efecto y podremos disfrutar de un ordenamiento nativo sin tener que volver al legacy editor.

Para solucionar esto, propongo una convención de nombres que permitirá un editor limpio, ordenado e intuitivo, al menos hasta que AppSheet implemente un sistema de organización nativo.

2.5. MÉTODO DE ORGANIZACIÓN

Uso del archivo “source_prefix_generator”

Show More

Nuestro compañero @yasarcan propuso la creación de un archivo para documentar nombres de tabla en el viejo protocolo. Yo he tomado su idea como idea fuerza y he creado un archivo de Google Sheets llamado "source_prefix_generator".

Este archivo servirá para:
✔ Generar prefijos estandarizados para nombrar vistas, acciones, bots y reglas de formatos.
✔ Llevar un registro de cambios en las estructuras de la app.
✔ Facilitar la navegación dentro del editor.

Este archivo contiene los siguientes campos:

 

table_sufix

slice_sufix

table/slice_name

action_bots_format_prefix

view_prefix

001

-

table_one

001

001_00

002

-

table_two

002

002_00

002

01

slice_of_table_two

-

002_01

El campo table_sufix, contiene un número del 001 al 999 (con tres dígitos) y es el identificador de sus tablas. Cada vez que se agrega una tabla a la estructura de nuestra base de datos, debemos darle de alta a dicha tabla en el source_prefix_generator con su id.  

El campo slice_sufix es un número del 01_99 y representa al número identificador del slice. Cada vez que creamos un slice lo agregamos al source_prefix_generator con su identificador.

table/slice_name es un campo que almacena el nombre de tabla tal cual está en nuestra aplicación. Puede cambiar el nombre de tabla pero el table_sufix y el slice_sufix no deben cambiar nunca. 

action_bots_format_prefix es un campo con una expresión que toma el id de tabla solamente en los casos de tabla (no tiene en cuenta slices) ya que las acciones, bots y reglas de formato se aplican a las tablas solamente.

view_prefix es un campo que genera un prefijo utilizable en vistas ya que estas sí pueden estar basadas en slices. Los campos que tienen vacío la celda slice_sufix son tablas y su view_prefix siempre tendrá el sufijo de tabla y 00 en el sufijo de slice. 

Véanse los casos en el siguiente ejemplo:

 

2.6. NOMENCLATURA DE VISTAS

Show More

Nuestro compañero @Yahia_DAK  sugirió un ordenamiento de tabla basado en prefijos y tipos de vista, realmente fue interesante así que decidí tomar su idea como idea fuerza para esta nueva nomenclatura (aunque un poco modificada). Él comienza con números pero me he dado cuenta que al comenzar con números en el editor mientras estamos agregando expresiones, el cuadro de diálogo no se genera automáticamente con el popup de sugerencias, en cambio si iniciamos con letras si, automáticmente comienzan a desplegarse sugerencias filtradas, lo cual es más intuitivo en el desarrollo y aumenta la velocidad de escritura. 

Véanlo aquí mismo:


La primera parte de la estructura del nombre tiene siempre la misma longitud y se visualiza de forma muy ordenada al punto que termina pasando desapercibida mientras el propósito se hace más reconocible.

<view_type_code>_<view_prefix>_<view_purpose>

¿Cuál es la ventaja de usar prefijos numéricos en lugar de nombres completos?

  • Si el nombre de tabla cambia, el nombre de vista no tiene porque hacerlo porque el prefijo es un id mientras que el nombre puede cambiar.
  • Se hace todo mucho más simple de visualizar.
  • Los nombres se acortan abruptamente, lo cual es más cómodo en el editor.
  • Permite detectar vistas inutilizadas o duplicadas, rápidamente.

2.7. CASOS ESPECIALES: DASHBOARD

Show More

El único tipo de vista que no sigue el formato de nombres basado en tablas es la vista Dashboard, ya que puede estar compuesta por dos o más tablas.

Para estos casos, usamos un nombre representativo en minúsculas, siguiendo este formato:

db_<purpose>

📌 Reglas:

  • snake_case, minúsculas.

  • El propósito debe ser un sustantivo claro y descriptivo.

  • Preferentemente, máximo 30 caracteres para evitar nombres largos y poco manejables.

2.8. NOMBRES VISIBLES (Display Names)

Show More
El nombre que verá el usuario en la interfaz debe ser insertado dentro de comillas en el campo Display Name, como una expresión, ya sea en vistas, acciones, campos, etc.

3. REGLAS DE FORMATO

Show More

3.1. NOMENCLATURA REGLAS DE FORMATO:


f_<table_prefix>_<purpose>

Ejemplo: f_008_blank_children

Indica que es una regla de formato aplicada a la tabla con prefijo 008, para manejar filas sin hijos.

📌 Reglas:

  • snake_case, minúsculas.

  • Máximo 23 caracteres.

  • El propósito debe ser claro y descriptivo.

4. ACCIONES DE COMPORTAMIENTO

Show More

4.1 ACCIONES GENERADAS POR EL SISTEMA 

Show More

Las acciones autogeneradas reciben un nombre por defecto. Algunos ejemplos son:

  • Add

  • Delete

  • Edit

  • Compose Email (User ID)

  • View Ref (TABLE)

Estos nombres son consistentes en todas las tablas y no deben ser modificados.

4.2. ACCIONES PERSONALIZADAS

Show More

Para las acciones que creamos manualmente, usaremos el archivo "source_prefix_generator".

Primero les muestro el resultado, seguidamente les explico:

actions.png

Como pueden ver, las acciones ya están organizadas por tabla, en el caso de la imagen anterior, organizadas bajo la tabla “items_types”, lo que garantiza que la primera parte del nombre tenga siempre la misma longitud y proporcione una mejor visualización del propósito de la acción.

Ahora, ¿por qué es necesaria esta convención estando ya organizada de forma nativa por tabla?

Porque AppSheet no nos permite usar el mismo nombre para acciones en tablas diferentes. Si creásemos una acción llamada “update” en una tabla y luego otra con el mismo nombre en otra tabla, AppSheet la renombrará automáticamente como “update 2”, lo que genera inconsistencias en la nomenclatura. Nótese que este problema no ocurre con las acciones generadas por el sistema, ya que AppSheet les da el mismo nombre en todas las tablas; es decir, no existe Add 1, Add2, Add n.

Por eso, hasta que AppSheet permita que las acciones creadas manualmente puedan compartir el mismo nombre si están en tablas distintas, esta convención nos ayuda a mantener el orden y evitar inconsistencias en nuestras apps.

He creado un tópico para que AppSheet implemente esta mejora, puedes votar aquí para que esta limitación desaparezca en el futuro. Cuando esto ocurra, nuestra convención dejará de ser necesaria y el desarrollo será más simple.

 4.3. CÓDIGO DE ACCIÓN (action_code)

Show More

Existen cuatro conjuntos principales de acciones de comportamiento en AppSheet:

ACCIONES

CÓDIGO

Application

a

Data

d

External

e

Grouped

g

Cada set contiene acciones específicas:

  • 7 Application Actions
  • 4 Data Actions
  • 5 External Actions
  • 1 Grouped Action

4.3.1. Acciones de Aplicación (a)

Show More
A continuación las acciónes del set "Aplicación" con su código y su ícono sugerido para aquellas con condición "oculta"
  1. Copiar esta fila y editarla → (a1): "clone" icon

  2. Editar esta fila → (a2): "edit" regular icon

  3. Exportar esta vista a un archivo CSV (no es una acción a nivel de fila)(a3): "fiie-csv" regular icon

  4. Ir a otra app de AppSheet → (a4): "rocket"-regular icon

  5. Ir a otra vista dentro de esta app → (a5): "chevron-circle-right" black icon

  6. Importar un archivo CSV para esta vista (no es una acción a nivel de fila)(a6): "fiie-csv" black icon

  7. Abrir un formulario para agregar una nueva fila a esta tabla (no es una acción a nivel de fila)(a7): "plus" regular icon

4.3.2. Acciones de Datos (d)

Show More

A continuación las acciónes del set "Aplicación" con su código y su ícono sugerido para aquellas con condición "oculta"
  1. Agregar una nueva fila a otra tabla usando valores de esta fila → (d1): "layer-plus" light icon

  2. Eliminar esta fila → (d2): "trash-alt" solid icon

  3. Ejecutar una acción en un conjunto de filas → (d3): "table" light icon

  4. Establecer valores en algunas columnas de esta fila → (d4): "slider-h" regular icon

4.3.3. Acciones Externas (e)

Show More
A continuación las acciónes del set "Aplicación" con su código y su ícono sugerido para aquellas con condición "oculta"
  1. Ir a un sitio web → (e1): "browser" regular icon

  2. Abrir un archivo → (e2): "folder-open" regular icon

  3. Iniciar una llamada telefónica → (e3): "phone" regular icon

  4. Iniciar un mensaje de texto → (e4): "envelope" regular icon 

  5. Iniciar un correo electrónico → (e5): "comment-alt-lines" regular icon

4.3.4. Acción Agrupada (g)

Show More

A continuación las acciónes del set "Aplicación" con su código y su ícono sugerido para aquellas con condición "oculta"

  1. Ejecutar una secuencia de acciones → (g1): "list-ol" regular icon

Esta convención de código (action_code) facilita la organización y referencia rápida de las acciones en AppSheet, mejorando la claridad y eficiencia en el desarrollo de aplicaciones.

4.4. NOMENCLATURA PARA ACCIONES

Show More

<action_code>_<source_table_prefix>_<destination_table_prefix>_<action_purpose

Si la acción se aplica en una sola tabla, tanto la tabla origen como la tabla destino usará el mismo prefijo.

📌 Reglas:

  • snake_case, minúsculas.

  • El propósito debe ser un sustantivo claro y descriptivo.

  • Preferentemente, máximo 30 caracteres para evitar nombres largos y poco manejables.

5. BOTS  

Show More

5.1. CONVENCIÓN DE NOMBRES PARA BOTS 

Show More

bot_<table_prefix>_<purpose>

Ejemplo:bot_018_adder

Este bot pertenece a la tabla con prefijo 018 y su propósito es agregar filas.

📌 Reglas:

  • snake_case, minúsculas.

  • El propósito debe ser un sustantivo claro y descriptivo.

  • Preferentemente, máximo 27 caracteres para evitar nombres largos y poco manejables.

5.2. CONVENCIÓN DE NOMBRES PARA EVENTOS

Show More

Los eventos en AppSheet se generan cuando ocurre alguna de estas situaciones:

 

Tipo de Evento Código
Evento en la aplicación app
Cambio programado (Tiempo) sch
Aplicación de Chat cha
Disparador en base de datos dbt
Envío de formulario frs

📌 Formato de nombre de eventos:

event_<table_prefix>_<event_type_code>_<n_order_number>

Ejemplo: event_008_app_1

Indica que es un evento en la tabla 008, de tipo app (evento en la aplicación), con un índice 1.
Si se crean múltiples eventos similares, se incrementa el número (_2, _3, etc.) para evitar conflictos.

5.3. CONVENCIÓN DE NOMBRES PARA PROCESOS

Show More

En el resto del editor usamos una nomenclatura codificada pero en este caso vamos a usar una nomenclatura intuitiva. Los procesos se ordenan como una secuencia de pasos lógicos ordenados cuya finalidad es resolver un problema (es decir, un algoritmo). 
Es muy interesante ver cómo se ven los procesos en un BOT cuando su nomenclatura es clara y entendible. Aquí les dejo un ejemplo visual:

process.png

Los bots ejecutan procesos en secuencia, que pueden incluir:

  • Ejecutar una tarea

  • Ejecutar una acción sobre los datos

  • Dividir la ejecución con una condición

  • Esperar

  • Llamar a un proceso

  • Devolver valores

📌 Reglas:

  • snake_case, minúsculas.

  • Propósito corto, claro y descriptivo.

  • Preferentemente, máximo 21 caracteres para evitar nombres largos y poco manejables.

  • Ejemplo: "generate_invoice"

Proceso que genera una factura.

5.4. BOTS - ÍCONOS

Show More
  • Se recomienda mantener el ícono del bot por defecto.

  • El propósito del bot define su función, pero el ícono ayuda a identificarlo visualmente en el editor.

Esta convención garantiza orden, claridad y escalabilidad en el desarrollo de aplicaciones en AppSheet.

 

26 97 6,442
97 REPLIES 97

Yes, but I don't recommend it, it's not better than this. Also, I haven't updated the book because I've had problems with Apple payments and I've decided to donate to the community in this post.

It's much appreciated. For the instructions, I'm studying one by one, great but I do wish if there's some more (example) photos... as English is not my mother language. 

I'm finishing developing an application and I'm planning an update to this protocol at the end of the month or early next month. If you follow this thread, you'll see the changes! Thank you very much for your support.

2025 APPSHEET WORK STANDARD NOMENCLATURE PROTOCOL UPDATE

Hello to everyone following this post. Recently, I’ve been reviewing the protocol, and as a result (in addition to having made some changes to my apps and achieved substantial improvements), I’ve also updated the protocol (marked in red).

Here is the result of the latest update as of 12/29/2024, which will be effective in 2025. You can choose to adopt it or not. I’d like to thank those who have participated and commented recently, as your input has helped me think outside the box. Thanks also to everyone in this community—I want to say that AppSheet is what it is because of you. Additionally, I’d like to share that I see a slight increase in Google’s interest in this wonderful tool (as reflected in Google Workspace).

Happy New Year to everyone! May 2025 be a year full of opportunities. Cheers!

Es un excelente aporte, abordas temas que ya son propios de un programador.

Soy ingeniero en sistemas y por ejemplo la forma de nombrar tablas es algo que aunque parezca poco importante, facilita mucho la comprensión de una base de datos. 

A mi parecer appsheet busca democratizar la creación de aplicaciones pero si de verdad uno quiere hacerlo de la mejor manera y cosas mas complejas si o si se va encontrar con cosas de programadores.

Algo que puedo añadir y que a un usuario nuevo le puede ayudar es tener conceptos básicos del modelo de bases de datos como los modelos de clases o modelos entidad-relación. Otro punto clave podría ser comentar el código de programación ya que eso puede facilitar mantenimiento y documentación. Ahora mismo estoy trabajando en una app para controlar un sistema administrativo de una empresa que vende emulsiones y asfaltos para carretera y hacerlo de la manera mas estandarizada me ha facilitado la vida. Incluso mi jefe subestima la parte de documentar la app pero como desarrollador te ayuda muchísimo y así te ves de más profesional entregando aplicación, que es el programa funcionando, manual técnico y manual de usuario. 

Podría recomendarte aprender temas básicos de metodologías de creación de software ya que eres un usuario más avanzado y si vas a programar para una empresa te va ayudar bastante.

 

De nuevo, excelente aporte.

@GUS123 veo en tu comentario nada más que buenas intenciones y por ello quiero agradecerte personalmente ya que para mí es un honor que una persona como tu, además ingeniero en sistema, haga tamaña valoración de este trabajo. Por supuesto que estoy más que de acuerdo en lo que dices. Yo soy arquitecto y la nomenclatura es muy importante para nosotros ya que la función de un estándar no es limitar sino simplificar el trabajo, haciendo las cosas más fáciles y automáticas para los usuarios. Quisiera agregar que no es un documento definitivo sino más bien algo vivo que se va amoldando a las actualizaciones de AppSheet y a la manera en que voy viendo más amena para trabajar. Yo mismo hago las pruebas y voy sugiriendo. Una vez al año (o dos) cambio el manual con mejoras. Imagino que llegará un momento en que los cambios serán mínimos. 

Quiero decir además que agregaré lo de la documentación ya que no solo sirve al usuario sino a nosotros mismos a la hora de retomar un proyecto dado que no siempre recordamos el "porqué" hemos hecho tal o cual cosa. También pienso en hacerlo en español para usuarios como tu y yo. 

Respecto a tu sugerencia " metodologías de creación de software " es muy valiosa. Yo ni siquiera sabía que existía eso. Voy a investigar para aprender. 

Respecto al manual técnico (e incluso un glosario dentro de la app) me parece un buen aporte (quizás mucho no tenga que ver con la nomenclatura que es el fin de esta publicación) pero la realidad es que un manual es (te diría) casi imprescindible. 

Nuevamente muchas gracias por tu valoración! Es lo que nos motiva a seguir, un abrazo 

Colleagues following this post,

In the coming hours, there will be an update to the Standard Protocol. What is currently in red will change to black, and today's updates will be written in red. Significant progress has been made regarding the nomenclature of actions, bots, and format rules.

I deeply appreciate your support and want to say that I am proud to give back to the community a part of what it has given me.


@Gustavo_Eduardo wrote:

It is important to understand the distinction between a spreadsheet and a spreadsheet in Google Sheets


A spreadsheet and a sheet I think ? 

 

Thanks for your clarification. I must have missed it in the translation. I'll correct it tomorrow.


@Gustavo_Eduardo wrote:

function eliminarFilasVacias() { // Obtén la hoja activa var hoja = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // Obtén el rango de la columna A var rango = hoja.getRange("A:A"); var valores = rango.getValues(); // Variable para contar las filas vacías var filasVacias = 0; // Recorre las filas de abajo hacia arriba (para evitar problemas al eliminar filas) for (var i = valores.length - 1; i >= 0; i--) { if (valores[i][0] === "" && filasVacias < 1) { // Si hay una fila vacía, deja esta fila filasVacias++; } else if (valores[i][0] === "") { // Si la fila está vacía y ya hay una fila vacía, elimina la fila hoja.deleteRow(i + 1); // +1 porque las filas en Apps Script son 1-indexed } } }


 

Hi Gustavo, about deleting blank rows, if we have 10 tables, it means creating 10 spreadsheet, it means 10 times of adding the scripts to the spreadsheet ? Thanks. 

The idea of creating a separate Google Sheet file for each table is to extend the cell limit. You could work with a single file, but I prefer to handle each one separately.

Regarding your question, unfortunately, yes. You have to create one for each sheet, but it’s just a matter of copying and pasting.

Hi


@Gustavo_Eduardo wrote:

E1_SUPPLIES_TUAD

Or for slices

E1_SUPPLIES_SUAD_actives

Note: It could also have any of the following suffixes depending on the permissions: U, A, D, AD, UA, UD, or RO, in addition to UAD.

 
1.png

 

 Hi Gustavo, in the example image, for table name, you write only "...._UAD" instead of "TUAD" ? 

Yes, thank you! The example image is old. It is TUAD and not UAD. I will correct it.

@kvngo94 Thank you very much, I have corrected your observations.

kvngo94_0-1737880021059.png

Hi @Gustavo_Eduardo are you leaving empty for the file/folder path section for image data type columns ? 

 

The truth is that I haven't worked on this case. That being said, I must confess it's something that has me uncertain.

What I have been doing for now is creating folders in the google drive directory in which their name is, for example, looking at your case, A01_COMPANY_images

For now, I'm leaving it blank. If you have a suggestion, it would obviously be very helpful to us! 

@Gustavo_Eduardo Hi Gustavo, 

What if you have too many tables and views, then what'll you do to split them into smaller apps to make syncing time better ? I'm having an app which have many tables and views, sync time is like 7-8s every time T.T

Hi @kvngo94 , how are you?

Synchronization is the time it takes to process all the requested information to display it to the user. The fewer tables and views, the less time it takes; however, it does not only depend on that (as far as I understand) but also on how you manage the data, data integrity/redundancy, and of course, the virtual columns and the amount of data stored in the databases.

More tables likely mean more relationships and, naturally, more "RefRows" (Related).

These columns are calculated every time you sync (and if you have additional ones, the synchronization time will increase).

One way I found to "avoid generating them" is to use an Enum with a base type of Ref instead of using "Ref", In cases where it is not strictly necessary. This calls a table but does not require a "Ref Row" to be created in the referenced table.

Another thing I’ve put into practice is going through the virtual columns one by one, renaming and saving them. If nothing is affected, it usually means they are not being used, so I delete all those virtual columns.

Then, I try to remove everything I don’t use (actions and bots). Also, although it seems hidden, format rules consume a lot of resources because the app has to process everything in the backend before displaying the information.

Now, regarding virtual columns, in terms of the number of tables (I use many tables, and each file is a separate database), I’ve found that when cloning my apps from SQL to Sheets, they were created as separate files. I found it more practical to manage it this way. However, having the data split across multiple files is not mandatory but optional—you can opt for a single file, which might be easier to manage.

Regarding views, you can create multiple views or just a few with restrictions based on user type (i.e., granting data access according to the user type).

Whenever possible, avoid virtual columns, and if you can, use field properties like "Valid If," "Show If," etc., as these reduce complexity during synchronization.

As a final tip, I’d recommend using the system-generated REF ROWS() columns in filters since you cannot delete them, and they are automatically created when a field is set as Ref. Instead of creating a new FILTER(), use these.

Apply security filters in the table settings, for example, [userid] = USEREMAIL(). This reduces the amount of data loaded per user during each sync.

Regarding synchronization, I am always studying it, but to be completely honest, I don’t know more than this. If you have any additional insights, it would be useful to share them—not necessarily in naming conventions but Democratic post to discuss best practices for application performance 

 

Hi Gustavo, 

Thank you for all the valuable knowledges, I'm going to practice them one by one. 
Now going through your instructions to rebuild my current app. Love it every time I can learn something new and make the current thing better.

It is always a pleasure for me to be able to help and give back to the community what I receive from it. Thank you! Have a great day. 

Hi @Gustavo_Eduardo ,
May I ask how you store the data of the [id] column ? 

1) Simple UNIQUEID() or with something sequential as 0000001-UNIQUEID ?

2) For example if a company has 2 brands, how you store the id of each brand ? 

2.1) Are you simply keeping it as same as how you do with company id : UNIQUEID() or 0000001-UNIQUEID ?

2.2) OR are you adding the company id before each brand id ? eg : company id-UNIQUEID() ? 

Thank you.

 

You can create any combination that's most convenient for you. The important thing is that the id column has unique elements that are managed as an "initial value" and not as a formula, because if you add it as a formula, it would be edited every time you open the row in the form. I also believe that Appsheet prevents using id with a formula.

With this in mind, use initial value with the "editable if" field unchecked, meaning it can't be edited.

 

Show More
Method Advantage Disadvantage
Editable_If = FALSE Ensures the field can never be edited This condition is always evaluated, even during form rendering and updates
Editable_If = ISBLANK([_THIS]) Allows editing only when the field is blank Seems helpful, but still causes unnecessary computation (why keep it editable at all?)
✔️ Uncheck “Editable” and only use Initial Value Cleaner, better performance, does exactly what you want No real downside

In databases, the initial values for empty fields are usually null, which is not the same as false. In Google Sheets, it's false, which is not the same as null. Therefore, if you use ISBLANK([_THIS]), it will work for databases but not for Google Sheets, and if you use false, it will work for Google Sheets but not for databases. Consequently, simply uncheck the 'editable if' option, and that's not only more elegant and cleaner, but it's also one less formula in your system, and what doesn't subtract adds up.

 

 

By default, for the id column, Appsheet uses UNIQUEID() in Google Sheet; in Appsheet databases, it uses UNIQUEID(packedUuid). Previously, I used UNIQUEID(“UUID”), but I read a comment and you said you used UNIQUEID(). I figured out the possible 8-digit combinations (16,796,163,257,856 different combinations), and I don't think I'll ever fill out the combinations myself or my users in the future, so I opted for your UNIQUEID() option.

The purpose of id is to make the value different for each row. If you feel comfortable adding a representative value for the company, you can do so, but remember not to use a combination of the ID with a variable value like a company name, since if the name changes, the ID will not change given the editable condition is disabled. In short, what you put inside your ID is up to the developer. For my part, I could tell you something, but I wouldn't want to limit it too much, and on the other hand, I don't see much point in adapting an ID per company, since UNIQUEID will always create a different ID.

You can also create a column called [code], for example, in which you can create combinations of representative numbers, but that has nothing to do with the row ID. Let me explain. I'm currently working with an inventory application. It has a three-level taxonomy. Level 1 is a natural, unrepeatable number from 1 to 999. Level 2 is a concatenation between the parent level 1 and the index of that row, for example, 001-003. Level three is the concatenation of the parent code of level three with the index of that row, for example, 001-003-005.
This ensures that each item has a unique, but internal, code. ids are for the software, not the user; you can extrapolate this to anything.

Thank you for the helpful advices !

I think I'm going to put it simply as UNIQUEID() !

I've corrected this recommendation because I found inconsistencies in scalability. Please see this comment @kvngo94

Thanks Gustavo, I've seen many great update from your posts and studying it, truly learning alot from you!

a hug friend thanks again

Hi @Gustavo_Eduardo
If your EvoWell needs to have a Product group module, could you advise how you're going to put the name, for ENGINEERING department for example : 


- Spreadsheet name: EvoWell_ENGENIEERING-1_PRODUCT GROUP or EvoWell_ENGENIEERING-1_PRODUCT_GROUP
- Sheet name: E1_PRODUCT GROUP or E1_PRODUCT_GROUP

- Column name : product group_name  or productGroup_name or product_group_name

The only thing I'm wondering is the "_" ^^. Thank you. 

I understand. What you're asking me is, how would I handle cases where the table name is composed of two words?

The quick answer is, “I use a simple name“


In principle (I'm cheating a bit) hehe. I consult the AI for the most appropriate name for a table containing certain records. I try to get a simple word. If I don't get one, my first decision would be to use the -, however I see that Google Sheets doesn't allow it because when I go to enter the table name it indicates that special characters cannot be used. That said, in all honesty, I would try to find a simple, non-compound name to avoid long table names that, being within the app, create a problem for me when writing expressions.
It's not the same to write:
SELECT(
              E1_PRODUCTS[id],

than 
SELECT(
               E1_PRODUCTS-GROUPS[id]

it's very long when we're indenting.
Finding the correct table name is practically a "name engineering"
In short, perhaps for your case I would use GPRODUCTS or simply PRODUCTS or if you want to make a taxonomy for example I would use:
CATEGORIES (Packaging)
FAMILIES (boxes)
TYPES (shoe box)

Thanks Gustavo, I've been struggling with naming but it's clear now !

💪🏻🙌

@Gustavo_Eduardo Hi Gustavo, 
Could you please advise how we should do with an image table ?

For now each spreadsheet (google sheet) contains a sheet only, for example E01_PRODUCTS

If you want to create a table to stores all the images of a product, in the above same spreadsheet, you will create one more sheet name E01_PRODUCTIMAGES ?

I wonder how you manage images and files in an app, create separate table for each sheet or create only table, for example, named En_IMAGES and then in this table there will be many Ref columns. 

Thank you.

 

Hello, @kvngo94 how are you? I hope you're doing well.

Yes, exactly, and there is a reason for it. The sheets are kept as separate elements because it makes it easier to migrate applications from a database to Google Sheets or vice versa when the sheets are individual files rather than combined into a single file. In fact, when you try to move from SQL to Google Sheets, the copies are naturally created as separate files. Because of this, and to maximize the space of each file, it is decided to use them separately (in my view, this is a good practice).

Regarding images, I haven't worked much with this, but at first glance, if there are many images and you need to add multiple columns to the product table to store them, then:

  • If the number of images is always the same and all are mandatory, you could probably add columns to the product table.
  • However, if products do not always have the same number of images, I would likely opt for a product images table (which also wouldn't limit me). In that table, I would add a new column of type Ref to the product so that each image is linked to its respective product (Is a part of). You could even upload them directly from the product form by displaying the Related column.

That said, one way or another, as far as I understand, we don't store images in tables but rather links pointing to the images.

In conclusion, I would choose to create a separate table for images and add a Ref is a part of field linking to the product.

As for its name, in my case, I might go with something like En_PRODPICS.

Thanks so much @Gustavo_Eduardo  !!! 

Hi 


@Gustavo_Eduardo wrote:

Therefore, when using a 'Ref' type field, it is advisable to name it the same as the referenced table, which will save time in editing. For example, if we are referencing the table 'E3_SUPPLIES_TUAD,' the 'Ref' type field should be named the same.


 

@Gustavo_Eduardo Regarding the above column naming, what if I want to ref to a slice, for example a slice for userid, could you kindly advise if I should name the column as E3_SUPPLIES_SUAD_userid ? Thank you. 

Yes, @kvngo94 that's exactly what I do and suggest. If the Ref column points to a slice, I name it as the slice. This way it's possible to add many ref columns of the same table but name them differently because they point to different slices.

I actually thought I had already added this. Thanks for suggesting it. I'll check back soon!!

Friends, I’ve been researching and studying the case of the "An" column, which is used to store inline actions within tables, for example. I changed it from real to virtual since it doesn't consume data during synchronization because:

  • It is not stored in the database.
  • Virtual columns exist only within the app at runtime.
  • They are neither sent nor received from the server, so they don’t generate sync traffic since their formula is "".
  • They don’t cause record changes.

If the column were real, any change in its value would trigger a database update, affecting synchronization.
But since it’s virtual, its value is calculated in the device's memory without affecting the database.

It only impacts local performance

The only impact is the calculation time on the device, but with "", the impact is practically zero.

In summary:

✔ Does not increase database size
✔ Does not generate sync traffic
✔ Is dynamically calculated on the device

So, if you only need the column to hold an action and its formula is "", there’s no issue in terms of performance or synchronization.

You'll see the update in red in the usual fields table.

I'm curious why you named the column to hold buttons "An" - why not Button_Holder?

I"m sure there's logic, I'm just curious.

Hello, dear Matt! @MultiTech  

1. I found it to be a very short name, which makes it simpler to write.

2. Because “A” is the initial of “action” which felt intuitive to me!

3. It stands out well from the rest of the column names.

Of course, it’s not mandatory I am just sharing what I do! Sending you a hug, Matt, and thank you for being such a valuable member of this community.

Top Labels in this Space