Skip to content

Data types

Each variable and each activity result has a type of data. The type determines what you can do with that value: a text can be converted to uppercase, a number can be added, a table can be traversed row by row. Knowing the type of your variables is key to writing correct expressions.

They are the simplest values: a text, a number, a yes/no.

TypeDescriptionExamples
stringTexto"Hola mundo", "FAC-001"
numberWhole number or decimal (the decimal separator is the period)42, 3.14, -7
booleanLogical value: true or falsetrue, false
DateTimeFecha y horaresultado de now(), today()

On a text you can call these methods (in addition to the built-in functions like upper, trim…):

MiembroReturnsDescription
.LengthintCantidad de caracteres
.ToUpper()stringUppercase
.ToLower()stringLowercase
.Trim() / .TrimStart() / .TrimEnd()stringQuita espacios
.Contains(valor)boolDoes it contain sub-text?
.StartsWith(valor) / .EndsWith(valor)boolDoes it start/end with?
.Replace(viejo, nuevo)stringReemplaza ocurrencias
.Split(separador)string[]Divide en partes
.Substring(inicio) / .Substring(inicio, largo)stringExtract a portion
.IndexOf(valor)intPosition of first appearance (-1 if not present)
.PadLeft(ancho, car) / .PadRight(ancho, car)stringFills to a width
= nombre.ToUpper()
= codigo.Substring(0, 3) // primeros 3 caracteres
= correo.Split("@")[1] // dominio del correo
MiembroReturnsDescription
.Year .Month .DayintDate components
.Hour .Minute .Second .MillisecondintComponents of time
.DayOfWeekDayOfWeekday of the week
.DayOfYearintDay of the year (1–366)
.DateDateTimeOnly the date (00:00:00)
.ToString(formato)stringDa formato. Ej: "yyyy-MM-dd", "dd/MM/yyyy HH:mm"
.AddDays(n) .AddHours(n) .AddMinutes(n)DateTimeSuma tiempo (n puede ser negativo)
.AddMonths(n) .AddYears(n)DateTimeAdd months/years
.Subtract(otraFecha)TimeSpanDiferencia entre dos fechas
= today().AddDays(-7) // hace una semana
= now().ToString("yyyy-MM-dd_HH-mm") // útil para nombrar archivos
= fechaVencimiento.Subtract(today()).Days // días que faltan

They group several values. The indices start at 0.

A sequence of elements. It is created with the List Create activity, with the newList() function, or as a result of activities such as split or Page Extract Table.

MiembroReturnsDescription
.CountintNumber of elements
.Add(item)Add an element to the end
.Remove(item) / .RemoveAt(indice)Remove an element
.Clear()Empty the list
.Contains(item)boolIs the element there?
.IndexOf(item)intElement position
.First() / .FirstOrDefault()elementoFirst (FirstOrDefault returns null if empty)
.Last()elementoLast
.Any() / .All(cond)boolAre there any/do they all meet?
.Where(cond)IEnumerableFilter (LINQ — end with .ToList())
.Select(proy)IEnumerableTransform (LINQ — end with .ToList())
.OrderBy(clave)IEnumerableOrdena (LINQ)
.ToList() / .ToArray()List / arrayMaterialize the result
= productos.Count
= productos.Where(p => p > 100).ToList()
= nombres.Contains("Ana")

Associates a text key with a value. It is created with Dict Create or newDict().

MiembroReturnsDescription
.CountintNumber of keys
.Keys / .ValuescollectionAll keys/values
.ContainsKey(clave)boolDoes the key exist?
.Add(clave, valor)Add a couple
.Remove(clave)boolRemove a key
.GetValueOrDefault(clave)valueValue or null if it does not exist
= config["timeout"] // acceso por clave
= config.ContainsKey("proxy")
= config.GetValueOrDefault("idioma")

A table with named columns, like an Excel sheet. It is the common format shared by Excel, CSV, databases and Google Sheets: what you read from one source you can write to another without converting.

MiembroReturnsDescription
.RowsDataRowCollectionThe rows
.Rows.CountintNumber of rows
.ColumnsDataColumnCollectionThe columns
.Columns.CountintNumber of columns
.AsEnumerable()IEnumerable<DataRow>To use LINQ on rows
.Select(filtro)DataRow[]Filter with a SQL expression (ex. "Total > 1000")
.NewRow()DataRowCreate an empty row with the same structure
.Clone()DataTableCopy the structure without rows
.Copy()DataTableCopy structure and rows

Convenient functions for tables: rowCount(dt), colCount(dt), firstRow(dt), asRows(dt), selectRows(dt, cond) (see Expressions).

Each element of a For Each on a DataTable is a DataRow. You access its cells by column name with square brackets:

= fila["Cliente"] // valor crudo (puede ser DBNull)
= str(row["Cliente"]) // texto seguro (recomendado)
= num(fila["Total"]) // número seguro
MiembroReturnsDescription
fila["columna"]objectcell value
.TableDataTableTable to which it belongs
.ItemArrayobject[]All cells as array
.IsNull("columna")boolIs the cell empty?

When a parameter accepts a literal list, dictionary or table, the Properties panel shows an Edit button with a visual editor, so you don’t have to write the structure by hand. The same applies to filter conditions and row values.

All of the Designer’s visual editors are explained in Parameter editors.

Some activities open a resource (a browser, an Excel workbook, a database connection) and return a session that represents that open resource. You move that session to the other activities in the same package, and at the end you close it. It’s the same pattern across the platform: open → use → close.

TypeOpensClosesPurpose
ZoanBrowserSessionOpen Browser / Browser AttachBrowser CloseWeb browser (Chrome/Edge)
ZoanPageSessionBrowser Open / Browser New PagePage CloseA specific browser tab/page
ZoanExcelSessionExcel Open / Excel CreateExcel CloseLibro de Excel
ZoanWordSessionWord Open / Word CreateWord CloseWord document
ZoanDbSessionDB ConnectDB CloseDatabase connection
ZoanSftpSessionSFTP ConnectSFTP CloseServidor SFTP
ZoanGoogleSheetsSessionGoogleSheets OpenGoogleSheets CloseGoogle Spreadsheet
ZoanOutlookSession(Outlook activities)Outlook session
ZoanDesktopSessionOpen App / Win AttachWin CloseWindows desktop application
// Patrón típico: la salida de "abrir" alimenta a las siguientes actividades
// Open Browser → output: page
// Page Navigate → page: = page
// Page Get Text → page: = page → output: titulo
// Browser Close → browser: = page

Other activities return an object with structured data that you do read for its properties.

Result of HTTP activities (GET, POST, PUT, PATCH, DELETE).

PropertyTypeDescription
.StatusCodenumberHTTP code (200, 404, 500…)
.Okbooleantrue if the code is 2xx
.BodyobjectResponse body. If it is JSON, it is automatically deserialized
.HeadersDictionaryResponse headers
= respuesta.Ok
= respuesta.StatusCode == 200
= respuesta.Body["token"] // si el body es JSON
= respuesta.Headers["Content-Type"]

Result of mail reading activities (Outlook, IMAP, POP3).

PropertyTypeDescription
.IdstringUnique identifier (use in move/delete/attachments)
.SubjectstringAsunto
.FromstringRemitente
.To / .Cc / .Bccstring[]Destinatarios
.BodystringBody (plain text or HTML according to IsHtml)
.IsHtmlbooleanIs the body HTML?
.SentAtDateTimeSend/receive date
.IsReadbooleanIs it read?
.AttachmentsZoanAttachment[]Attachments (if requested to include them)
= correo.Subject
= correo.From
= count(correo.Attachments) > 0
PropertyTypeDescription
.Namestringfile name
.ContentTypestringMIME type (e.g. application/pdf)
.Contentbyte[]Contenido binario

Result of consuming a Zoan Cloud queue (Queue package).

PropertyTypeDescription
.IdstringItem identifier
.QueueIdstringQueue to which it belongs
.Referencestring?Business reference (e.g. invoice number)
.Prioritystringlow / normal / high
.Statusstringnew / inProgress / success / failed
.SpecificContentDictionaryItem data (the fields you entered when queuing it)
.OutputDictionary?Result, once processed
.AttemptsintNumber of attempts
.CreatedAtstringCreation date
= item.Reference
= item.SpecificContent["nit"]

The object the errorVariable of Try / Catch receives when something in the try fails.

PropertyTypeDescription
.MessagestringError message
.TypestringException type (e.g. "HttpRequestException", "TimeoutException"); use it to distinguish errors
.SourcestringException source
.StackTracestringStack trace
= error.Message
= error.Type == "TimeoutException" // branch on the error type

Treating it as text uses the message (= "Error: " + error), so reading it as a string still works.

When a value arrives as text but you need a number (or the other way around), convert it explicitly:

= toNumber(fila["Total"]) // texto → número
= toInt(cantidadTexto) // texto → entero
= toString(contador) // número → texto
= parseDouble(replace(monto, ",", ".")) // "1.234,56" con coma decimal → número

See the complete list in Expressions › Type Conversion.