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,465
97 REPLIES 97

Friends, some time ago I posted this in AppSheet Q&A, but I realized it's better to publish it in this section, especially for those who are interested in changing the workflow. This is how I work (it's not definitive, but it helps me a lot when it comes to organizing elements in the apps). I hope it helps, especially for those who are new members of the community.

Thanks @Gustavo_Eduardo  Can I get a simple sample database from you? I'm just getting into Appsheet and really like the way you define the data

This is an example table so you understand the concept. I have corrected the label field in the protocol. Now all tables, in the label field, have the name label.

 

ID S_CONCEPTS_TUAD E_expenseComment E_expenseMonth E_expenseAmount label E_expenseSpendDate E_expenseEffector E_expenseStatus date userID
79236FC5-27D5-47D6-A500-866E1AFBE608
145EA17A-E128-4BE1-9C40-1F70EB314DAB
  May

$189,99

 

 

2/5/2024   Juan false 2/5/2024 18:45:06 xxx@mail.com
32396F56-5BFF-4675-8D13-307EC49F23C4
5EEF9506-FB96-417C-9C4A-C12E534ACC77
  May $170,00 21/5/2024   Maria false 2/5/2024 18:45:22 xxx@mail.com
552388A1-F580-4D02-991D-AFD96CF1B924
FABE9650-2CF9-40F3-BAA0-3B3A1A118300
  May $1.770,00 24/5/2024   Juan false 2/5/2024 18:45:32 xxx@mail.com
  •  

Thank you so much! This is truly a perfect starting point for data management. I'm so fortunate to have come across your post

Thank you very much for such high praise. This document is constantly evolving, so it is not static but rather depends on user interest. Each query about it will be answered, and if I see that a correction is necessary, I will make it.

I am grateful that you keep updating this post as AppSheet keeps involving.
Do you have plan that talk a little bit about UI, for instance, tips on arranging forms, customizing views, or styling system-generated views to create a better visually appealing app ?

Hi @hhoanganh !

I hope you're doing great, and happy 2025!

Thank you for your kind words and interest. This post is specifically about nomenclature (not UX/UI), but to answer your question: absolutely yes.

UX/UI is a topic I find very interesting. As a user and the administrator of my own applications, I constantly work on improving this often overlooked aspect of AppSheet. In fact, I’ve been exploring how HTML and CSS can be introduced into AppSheet in certain ways, which I believe could be a game changer for enhancing visual design and user experience.

That said, I’m not a know-it-all (I learn a lot from this community), but I’d love to share some of the things I’ve been able to achieve.

Regarding AppSheet's native views, such as forms, detail views, and others, I do have some methods and tips to share. However, I plan to cover that in a new post to keep this one focused on nomenclature and separate it from UX/UI discussions.

Thank you again for your interest! I’m looking forward to continuing to exchange ideas and learn together.

Best regards,
Gustavo

Hi Gustavo, 

Excellent post. Could you advise the formula logic of this ID column ? 

kvngo94_0-1733274614065.png

 

@Gustavo_Eduardo Hi Gustavo, could you advise the above ? Thank you!

Gustavo, what a formidable initiative. Congratulations!

Hi @Gustavo_Eduardo,
I appreciate your content. I think this is a good standard for systematically maintaining apps.

 

From the above, I understood that it creates an F column, which is a virtual column with the formula CONTEXT("ViewType") = "Form".

How can we use this column? I don't really understand how this column is used. I would appreciate it if you could explain with an example.

 

Thank you.

 

Sure, here is an explanation. It has been said that it is better to create as few virtual columns as possible, because a virtual column is a real-time calculation within the application. However, I do not completely agree with that statement because it does not allow us to focus on the reality of the problem.

The problem is real-time calculations, not the virtual column itself. Moreover, if they are list calculations, this worsens the synchronization and loading speed. However, when you write expressions in the Show If or Valid If properties of each field, those properties behave like virtual columns because they are real-time calculations. What I have thought and tried during my time as an AppSheet user and having understood basic programming concepts, is to treat these virtual columns as "objects" to give it a comprehensible name. These objects are "reusable". So, when I have to make a calculation that is repeated several times in the applications, such as a CONTEXT("ViewType") = "Form" expression, and I need to use it multiple times within the properties, I create a virtual column that contains this expression in the table where I need it. Then, in the "Show If" property, instead of placing CONTEXT("ViewType") = "Form", I place the name of the virtual column [F]. Suppose there are many columns that you do not want to show in the form; you only need to place the name of the virtual column [F], and AppSheet does not have to recalculate it, it simply reads what is inside the virtual column that has been calculated once. Does the concept make sense?

To implement the functionality of displaying columns sequentially in an AppSheet application without overloading the system with repetitive calculations, you can use an efficient approach by reusing calculations through virtual columns. Here is a detailed explanation of how to achieve this:

Problem
You have 10 columns (Column 1, Column 2, ..., Column 10) that you want to display sequentially in a form, such that each column is shown only after the previous column has been completed and validated. If you copy and paste the same expression into the "Show If" property of each column, the system will perform the same calculation multiple times, which can slow down the application as the number of columns increases.

Solution
Instead of duplicating the calculation in each column, create virtual columns to store the result of the "Show If" conditions for each column. Then, reuse these results in the subsequent columns.

Steps to Follow

1. Create Virtual Columns for Show If Conditions:
- Create 10 virtual columns (one for each column you want to display sequentially).
- These virtual columns will evaluate whether the corresponding column should be shown.

2. Define Conditions in the Virtual Columns:
- Define the "Show If" condition in the first virtual column.
- For the following virtual columns, use the result of the previous virtual column.

For example, let's say you have a table called `Form` with columns `[Column_1]`, `[Column_2]`, ..., `[Column_10]` and virtual columns `[ShowIf|Column1]`, `[ShowIf|Column2]`, ..., `[ShowIf|Column10]`:


[ShowIf|Column1] (Virtual Column):
- Formula: ISNOTBLANK([Column_1])

[ShowIf|Column2] (Virtual Column):
- Formula: AND([ShowIf|Column1], ISNOTBLANK([Column_2]))

[ShowIf|Column3] (Virtual Column):
- Formula: AND([ShowIf|Column2], ISNOTBLANK([Column_3]))

...

[ShowIf|Column10] (Virtual Column):
- Formula: AND([ShowIf|Column9], ISNOTBLANK([Column_10]))
```

3. Use the Virtual Columns in the Show If Properties:
- Now, in the "Show If" property of each column, instead of duplicating the logic, simply reference the corresponding virtual column.

[Column_1]:
- Show If: TRUE (always shown)

[Column_2]:
- Show If: [ShowIf|Column1]

[Column_3]:
- Show If: [ShowIf|Column2]

...

[Column_10]:
- Show If: [ShowIf|Column9]

Benefits of This Approach
- Reuse of Calculations: Calculate once and reuse the result, reducing computational load.
- Easy Maintenance: Conditions are managed in one place (the virtual columns), making it easier to modify and maintain visibility rules.

 

 

Thanks for your reply. In fact, I cannot evaluate the consideration of limitations in the use of virtual columns.

BTW, I have got to know how to use the F virtual column. Thank you again.

 

I have one more question. From what I understand, the function of the "ShowIf|Field" column and the "F" column is basically the same.

Is the "ShowIf|Field" column created when we want to use it only in a specific column, and the "F" column when we want to use it in multiple columns?

@leinharte regarding your question, I must say that I have also wondered what to do. In my obsession with maintaining integrity and clarity (I can’t say clean code because we don’t use code, but it would be something like clean code), I have decided on my own to evaluate the case. If I use a calculation that repeats at least once, I create a virtual column and reference it. If, on the other hand, the calculation is done only once, it is not necessary to create a virtual column; in fact, in many cases, it is better to do it directly in the property field. Nevertheless, as I mentioned, my applications load very quickly due to the correct use of virtual columns.

In conclusion, my suggestion is that if you have only one column with the calculation, do it directly in the ShowIf|Field property. But if you have two or more columns needing the same show-if condition, for example, CONTEXT("ViewType") <> "Form", then create a virtual column named [NF], put the expression inside it, and then in the [ShowIf|Field] of the column you want to hide, use [NF] instead of CONTEXT("ViewType") <> "Form". This will make AppSheet avoid recalculating and instead use the value already computed in your virtual column [NF]. Hence, if you have 10 columns that you don't want to show in a form, this approach will be useful.

Imagine that you also want to create a FILTER() or a SELECT(). You can’t imagine the potential of creating a virtual column with such a SELECT() and then referencing that calculation as many times as needed in other expressions, without doing the calculation 2, 3, 4, or even countless times.

 

Your ideas are fresh and expand my view of AppSheet.

Currently, I am a hobbyist AppSheet developer, and I am very discouraged by the inefficiency due to lack of systematicity in the process of continuously improving the app.

Your ideas bring vitality to my app development.

Thank you.

Thank you very much! Don't get discouraged! This is the way! If you notice something that is inefficient in this protocol, I will check it and change it! Remember that it is not mine; it is rather an idea for everyone and must be functional! Thank you for your comments.

Have you tried using tables in Google Sheets? I'm really pleased with the update to Google's spreadsheets. In fact, I've started working with tables instead of databases created as simple elements. While it's necessary to be careful with data sorting in certain cases, I think it's a great feature. Soon, if I don't see any issues with using tables, I will modify the protocol to encourage their use.

Good post,  but stressful in the eyes.  May I request you uodate your post and divide them into paragraphs?  Each sections are appearing as of the whole post is one long paragraph.

Of course, I take your constructive criticism. I will try to structure this in a Q&A format to make it more enjoyable for us (including for myself).

Thank you! I haven't had a chance to delve into this too much yet, but I already know it's going to be helpful. When I first planned the structure for my apps, they were very straightforward and simple. But, unsurprisingly, when the ERM-charts hit reality, they ballooned into 7-million table monstrosities. And it's gotten steadily harder to maintain consistency in names etc.

So, again, thank you!

But please, that's what we're here for, to support each other in everything! Cheers to that, I'm here as a partner to share what I know and learn from all of your experiences. Thank you very much for your comment.

Hi,

"Standard Nomenclature Protocol" provides a "standard" for me, who has no professional experience in app development, to develop and maintain apps with "AppSheet", so it provides safety in my work.

I am making an app based on Google Sheets. Usually, apps have a number of tables, and according to "Standard Nomenclature Protocol", each table has its own "Google Sheet file" which has one sheet. As I frequently check "Google Sheet files" while creating and maintaining apps, I hesitate to choose the method of creating a number of "Google Sheet files". Could you explain the advantages of this method?

Thank you.

Hello, although the standard is something that is continuously being modified, and currently, in my approach, I use one sheet per section (if it's a system-type app) or one sheet for the entire app with all the tables if it's a small app, the purpose of using one sheet per table is to increase the storage capacity of the databases, since the cell limit per sheet in Google Sheets is reached more slowly when the table is exclusive to the sheet.

I don't remember exactly how many cells you can use per sheet as a maximum, but if you have all the tables in one and the app experiences heavy usage, the limit will likely be reached more quickly. I acknowledge that it's not very convenient, but it is beneficial in terms of space. Anyway, I recommend using whatever part of the protocol works best for you.

Thank you for your inquiry! Have an excellent day.

I want to let you know that I have corrected the name for the label field and the name for the dashboard type views in the post. I will be updating it as I can, in order to make your work in AppSheet easier.

Hi, @Gustavo_Eduardo 

Instead of creating F, NF, T, NT, D, ND, HD, HB virtual columns in all tables, I tried to create a separate table and use it, but it didn't work.

Here's what I did:
I created a table with only one row with virtual columns, like this:

leinharte_1-1732369920822.png

And I set the SHOW? like this:

leinharte_2-1732369984911.png

 

The result didn't work as I wanted.

Can't this be an alternative?

You deserve a response, and this post deserves a reformulation.

I am making exhaustive changes to this protocol because I have achieved substantial improvements in synchronization in the past few days due to some adjustments I’ve implemented.

Here are the changes I’ve made:

  • Column Naming: I’ve revised the column naming conventions.
  • Slices, Views, Actions, Bots, etc.: I’m testing shorter naming conventions, reducing text length.
  • Database Table Names: I’ve made changes to table names in the database.
  • Virtual Columns: I’ve revised my approach to virtual columns, now using as few as possible. I no longer use these columns to calculate “Show If.” Instead, I’m testing adding boolean-type columns in the database that mirror the “Show If” columns. This allows me to save on virtual columns while (being boolean) they don’t consume too many resources in the database and are easy to maintain. While AppSheet doesn’t yet support reusable objects, this seems to me to be the best option.

Regarding the possibility of creating a separate table with a single column (or object) containing the expression and pointing to it to retrieve the result, I’ve also tested this, and it doesn’t work. From what I understand, AppSheet interprets that it needs to verify the condition of the other table at the same time it verifies the condition in the current table. For an update I plan to release in early 2025, I recommend writing the expression CONTEXT("ViewType") = "..." directly in the “Show If,” as it evaluates only when needed and not during each synchronization.

As for the other “Show If” expressions, I’m getting better results by creating a column in the database with the expression I want in the “Show If” and then referencing it in the “Show If” (but in a real column, not a virtual one). This is a new practice for me—just about a week old—but it has significantly reduced synchronization time.

Since I’ve been renaming elements, I’ve also taken the opportunity to review everything and have discovered unnecessary columns, unused virtual columns, unused views, and unused actions. Purging every so often is always helpful (but I recommend cloning your app first to make changes in the cloned version).

Unofficially, here’s how I’m naming the database tables:

For example:

In a system app where the section is "Sales," I use the prefix S for "Sales", followed by a number to organize the tables in the AppSheet editor, then an underscore, and finally the table name. In the database, it’s just that (e.g., D1_TEAM). In the AppSheet editor, the table pulls data from D1_TEAM in the database, but the editor shows it as D1_TEAM_UAD (without the T for "table") if the table allows Update-Add-Delete actions.

For SLICES:

I’m testing names like TEAM_RO_purpose, implying it’s a slice of the table but without the D1 prefix (since it’s a slice of the same table).

For Columns:

I’ve simplified the naming conventions. For example:

  • Previously, I named them S_salesTotalPice
  • Now, I’ve opted to drop the S_ prefix and name the column sales_totalPrize

I’m also working on naming conventions for views and will share the details as soon as the work is complete.

Thank you for your reply and continuous reformulation.

Thank you. These are actually applications of my own experiences that are enriched by your comments and we all contribute together. Please visit this post as well. Democratic post to discuss best practices for application performance 

Hi, @Gustavo_Eduardo

A big thank you for this precious protocol and for the great effort you have devoted to its development.

For the naming of the tables I suggest that the number located after the prefix is ​​on two digits to allow an ordered classification in the editor and precisely when we have more than 9 tables. (D01_TEAM instead of D1_TEAM ).
on the other hand for the slices, it is better to specify it by an S Before RO, this is useful to differentiate between a view based on a table and a view that is based on a slice of this table.

First of all, thank you for your kind words.

Yes, that's exactly what I'm handling now, and it's part of the promise to edit this protocol. Thank you very much for contributing because it's not about what I want but about the combined experiences of all the users here. I'll keep it in mind for editing! I'll let you know about it.

Regarding the nomenclature of Slices, I used to use the letter "S," but I discovered that if I name the tables like E01_COMPONENTS_UAD (for example) and name the Slices without the "E01," it's enough to know that it's a slice without adding the "S." For instance, if I see COMPONENTS_RO_supplies, I know it's a slice because it doesn't have the initial "E01." On the other hand, if I see E01_COMPONENTS_RO (which could be a case), when I see "E01," I know it's a table.

As for the nomenclature E01, let's go a bit further. If your data structure has 10 tables in the same area, you might use two digits, but if you have 100 or more tables, you could use up to three digits. This part is flexible and depends on the number of tables you use in the same area or app. You can choose the number of digits, and what you're suggesting is perfectly fine.

Likewise, please be patient with me as I need to run some tests before making modifications, since many people use it and every change affects their work. The topic of the views you mentioned is extremely important, and believe me, this initial approach is not the absolute truth and is subject to change. Once again, I appreciate your input and promise to work on it. This channel remains open for suggestions.

Regarding the number of tables that an application (which is well-designed) can contain, the number cannot exceed about twenty tables, while naming with two numeric digits can go up to 100 tables.

From my personal experience, I have adopted the following method:

  • For tables:

• Each Appsheet table corresponds to a Google Sheets spreadsheet.
• The Appsheet table has the same name as the Google Sheets spreadsheet, except that it's in plural form.
• File naming starts with two numeric digits followed by an underscore and the name.
• The main tables of the application are placed at the beginning of the list.
• Auxiliary or reference tables come after.
• Tables that have similar roles have the same first digit, for example:

00_Users
01_Clients
10_Requests
11_Receipts
20_Consultations
30_Interveners
40_Navigations
41_Roles
42_Business_Supports
43_Directions
44_Professions

This way, we can do without the first letter that refers to the file name since the table name and the file name are the same, and on the other hand, to remove ambiguity if files start with similar letters.

  • For slices:

• The slice always refers to the table on which it is based.
• Its name is obtained by inserting "_S" after the first two digits of the table name, and at the end of the name, a description of the slice is added. For example:

00_S_Users_AdminFilter
00_S_Users_ManagerFilter
00_S_Users_GraphPreparation

Note that a table can have multiple slices.

  • For views:

• They are based either on tables or on slices.
• Naming is done in the same way, i.e., insertion of the capital letter V (View) followed by two lowercase letters that refer to the type of view.
• The description of the view is optional.

Examples of views based on tables:
00_Vcl_Users_planning (calendar view)
00_Vdk_Users (Deck view)
Examples of views based on slices:
00_Vtb_S_Users_Admin_Filter (Table view)
00_Vgl_S_Users_Admin_Filter (Gallery view)
View types:
• calendar view >> Vcl
• Deck view >> Vdk
• Table view >> Vtb
• Gallery view>> VVgl
• Detail View >> Vdt
• Map View >> Vmp
• Chart View >> Vch
• Dashboard View >> Vdb
• Form View >> Vfr
• Onboarding View >> Vob
• Card View >> Vcr

For all of the above, the two digits always refer to the table and allow for a coherent and visually significant classification.

 

It's a good way, no doubt! Regarding the letter, I've come to terms with it since it works for my system apps (which have areas and I prefer to assign said areas with letters and their order with numbers)

Regarding the views, I'm looking at a way to reduce the length of the name since I saw it as too long (your approach is valid) I'm going to try to see what I can come up with but it will be similar to what you say.

Thanks for the contribution @Yahia_DAK 

Hello @Yahia_DAK,

I am seriously considering changing the table and slice naming protocol to your suggestion (i.e., using two numbers instead of a letter and a number, or a letter and two numbers).

Basically, I am facing a situation that many of you have probably experienced: the need to add tables later on.

I had structured the application with names that followed an order and could be easily found alphabetically in the editor. However, for example, in an app I am currently developing, I found myself forced to add nutritional information tables as child tables of already existing ones, which would be more conveniently placed elsewhere in the editor.

By using a naming convention similar to yours (although I would personally prefer to keep a letter at the beginning), I could achieve a more intuitive organization. For example, if I needed to add a child table to E3_TYPES_TUAD, such as E12_TYPESINFON1_TUAD, this new table would end up lower in the natural order. However, if I rename E3_TYPES_TUAD as E31_TYPES_TUAD and E32_TYPESINFON1_TUAD, the child table would be placed right next to it, without any issues. This way, all tables under E3 would be grouped together in one place.

The next update of the naming protocol will follow this structure. Before anything else, I wanted to thank you for your input—it has been extremely helpful, as I remembered this comment while working.

Best regards!

I added a link to the database section that takes you to a publication where it explains how to erase blank queues.

Hi Gustavo, 

Could you also advise how you organize the images and files in your app ? create a table to keep images/files of all other tables or create teach images/files for each table ? 

Hello! @kvngo94  Thanks for writing. Before the end of the year (if possible) or early next year, I will edit the protocol as I am finding more practical ways of naming things and, in addition, discovering advantages in maintenance through renaming (uncovering useless actions, virtual columns that no longer work, etc.).

Regarding your question: I currently work with Google Sheets and store images and files in my app's directory. It's true that I haven't published anything about this and haven't developed this aspect in the protocol either, but I’ll get to work on it since it's a very important point (at least) in development.

The only thing I’ve done so far is create a folder for each table (with the same name as the table) and place the corresponding files for each one inside. Initially, it seemed the most intuitive approach, but thank you very much for asking. I promise that in the revised version of the protocol, you will not only see improvements but also see this point included.

Hi Gustavo, thank you so much for reply. I'm truly looking forward to you updates !

I made a small "update," you'll notice it because it's in red. Scroll to see it; it's at the beginning. While AppSheet has been down, I've taken advantage of the time. I'll keep making progress as I find time.

"if you have purchased this book, you will likely see continuous improvements as it will be updated".....

@Gustavo_Eduardo Is there a book on sale ? 

Top Labels in this Space