Skip to content

Data types

Every variable and every activity result has a data type. 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
stringText"Hello world", "INV-001"
int / longWhole number42, -7
double / decimalNumber with decimals (the decimal separator is the dot). Use decimal for money3.14, 1250.50m
booleanLogical value: true or falsetrue, false
DateTimeDate and timeresult of now(), today()
TimeSpanA durationnow() - start
objectAny value—

The type selector in the variables panel groups them (Primitive, Collection, Data, Security, Session…) and has a search box. Composite type… builds types such as List<int> or Dictionary<string,string>.

On a text you can call these methods (besides the built-in functions such as upper, trim…):

MemberReturnsDescription
.LengthintNumber of characters
.ToUpper()stringUppercase
.ToLower()stringLowercase
.Trim() / .TrimStart() / .TrimEnd()stringRemoves spaces
.Contains(value)boolDoes it contain the substring?
.StartsWith(value) / .EndsWith(value)boolDoes it start / end with?
.Replace(old, new)stringReplaces occurrences
.Split(separator)string[]Splits into parts
.Substring(start) / .Substring(start, length)stringExtracts a portion
.IndexOf(value)intPosition of the first occurrence (-1 if not found)
.PadLeft(width, char) / .PadRight(width, char)stringPads up to a width
name.ToUpper()
code.Substring(0, 3) // first 3 characters
email.Split("@")[1] // email domain
MemberReturnsDescription
.Year .Month .DayintDate parts
.Hour .Minute .Second .MillisecondintTime parts
.DayOfWeekDayOfWeekDay of the week
.DayOfYearintDay of the year (1–366)
.DateDateTimeDate only (00:00:00)
.ToString(format)stringFormats it. E.g.: "yyyy-MM-dd", "dd/MM/yyyy HH:mm"
.AddDays(n) .AddHours(n) .AddMinutes(n)DateTimeAdds time (n can be negative)
.AddMonths(n) .AddYears(n)DateTimeAdds months / years
.Subtract(otherDate)TimeSpanDifference between two dates
today().AddDays(-7) // a week ago
now().ToString("yyyy-MM-dd_HH-mm") // useful for naming files
dueDate.Subtract(today()).Days // days left

They group several values. Indexes start at 0.

A sequence of elements. It is declared with its element type, for example List<string>. It is created with the Create List activity, with new List<string>(), with the newList() or arr(…) functions, or as the result of functions such as split.

MemberReturnsDescription
.CountintNumber of elements
.Add(item)—Adds an element at the end
.Remove(item) / .RemoveAt(index)—Removes an element
.Clear()—Empties the list
.Contains(item)boolIs the element there?
.IndexOf(item)intPosition of the element
.First() / .FirstOrDefault()elementFirst one (FirstOrDefault returns null if empty)
.Last()elementLast one
.Any() / .All(cond)boolIs there any / do all match?
.Where(cond)IEnumerableFilters (LINQ — end with .ToList())
.Select(proj)IEnumerableTransforms (LINQ — end with .ToList())
.OrderBy(key)IEnumerableSorts (LINQ)
.ToList() / .ToArray()List / arrayMaterializes the result
products.Count
products.Where(p => p > 100).ToList()
names.Contains("Ana")

Associates a text key with a value. The most common one is Dictionary<string,object>. It is created with Create Dictionary, with newDict() or with new Dictionary<string, object>().

MemberReturnsDescription
.CountintNumber of keys
.Keys / .ValuescollectionAll keys / values
.ContainsKey(key)boolDoes the key exist?
.Add(key, value)—Adds a pair
.Remove(key)boolRemoves a key
.GetValueOrDefault(key)valueValue, or null if it doesn’t exist
config["timeout"] // access by key
config.ContainsKey("proxy")
config.GetValueOrDefault("language")

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.

MemberReturnsDescription
.RowsDataRowCollectionThe rows
.Rows.CountintNumber of rows
.ColumnsDataColumnCollectionThe columns
.Columns.CountintNumber of columns
.AsEnumerable()IEnumerable<DataRow>To use LINQ on the rows
.Select(filter)DataRow[]Filters with an SQL-like expression (e.g. "Total > 1000")
.NewRow()DataRowCreates an empty row with the same structure
.Clone()DataTableCopies the structure without rows
.Copy()DataTableCopies structure and rows

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

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

row["Customer"] // raw value (may be DBNull)
str(row["Customer"]) // safe text (recommended)
num(row["Total"]) // safe number
MemberReturnsDescription
row["column"]objectCell value
.TableDataTableThe table it belongs to
.ItemArrayobject[]All cells as an array
.IsNull("column")boolIs the cell empty?

When a parameter accepts a list, dictionary or table that you write yourself, 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.

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 pass that session to the other activities of the same package, and at the end you close it. It’s the same pattern across the platform: open → use → close.

TypeOpened byClosed byPurpose
ZoanPageSessionOpen Browser / Attach BrowserClose Browser / Close PageThe browser and its page (Chrome/Edge)
ZoanExcelSessionExcel Open / Excel CreateExcel CloseExcel workbook
ZoanWordSessionWord Open / Word CreateWord CloseWord document
ZoanDbSessionDB ConnectDB CloseDatabase connection
ZoanSftpSessionSFTP ConnectSFTP CloseSFTP server
ZoanGoogleSheetsSessionGoogleSheets OpenGoogleSheets CloseGoogle spreadsheet
ZoanOutlookSession(Outlook activities)—Outlook session
ZoanDesktopSessionOpen App / Win AttachWin CloseWindows desktop application
// Typical pattern: the output of "open" feeds the next activities
// Open Browser → Save result in: page
// Get Text → page: page → Save result in: title
// Close Browser → session: page

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

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

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

Result of the email reading activities (Outlook, IMAP, POP3).

PropertyTypeDescription
.IdstringUnique identifier (use it to move/delete/get attachments)
.SubjectstringSubject
.FromstringSender
.To / .Cc / .Bccstring[]Recipients
.BodystringBody (plain text or HTML depending on IsHtml)
.IsHtmlbooleanIs the body HTML?
.SentAtDateTimeSent/received date
.IsReadbooleanHas it been read?
.AttachmentsZoanAttachment[]Attachments (if requested)
email.Subject
email.From
count(email.Attachments) > 0
PropertyTypeDescription
.NamestringFile name
.ContentTypestringMIME type (e.g. application/pdf)
.Contentbyte[]Binary content

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

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

It is the object the errorVariable of Try / Catch receives when something in the Try lane fails.

PropertyTypeDescription
.MessagestringError message
.TypestringException type (e.g. "HttpRequestException", "TimeoutException"); use it to tell errors apart
.SourcestringSource of the exception
.StackTracestringStack trace
error.Message
error.Type == "TimeoutException" // branch on the error type

To show the error in a log or an email, use error.Message.

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

toNumber(row["Total"]) // text → number
toInt(quantityText) // text → integer
toString(counter) // number → text
parseDouble(replace(amount, ",", ".")) // "1234,56" with a decimal comma → number

See the full list in Expressions › Type conversion.