Every value on a wallboard comes from a formula. A formula is a single expression over the live data of the contact center, for example
Conversations.Count(State = "Waiting")
— the number of waiting conversations. Which data exists is described in Data for formulas; ready-made formulas are listed under Examples. The performance indicators use the same language, with slightly different data, see below.
What a formula must return
| Where | Result |
|---|---|
| Label, digital display, table column | any value |
| Gauge, state indicator | a number |
| Row formula of a table or chart | yes/no |
| Series of a chart | a number or time span |
Basic rules
- A formula is one expression — without statements, variables or comments.
- Upper and lower case do not matter for names:
conversations.count()is the same asConversations.Count(). When comparing texts, however, case does matter:SkillName = "support"does not find the skill “Support”. - You can use any number of spaces and line breaks between the parts.
- You append fields and methods with a period:
Conversations.First().Agent.Name,Name.StartsWith("A"). - List queries need parentheses, even without content:
Agents.Count(). - Quotation marks are the straight
"— typographic ones such as “ ” cause a syntax error.
Values
| Notation | Meaning | Example |
|---|---|---|
| whole number | number | 42 |
| number with a decimal point | decimal number | 2.5 |
text in double quotation marks; a " in the text is doubled |
text | "Support" |
true, false |
yes, no | IsLogin = true |
null |
empty | Agent = null |
Now |
the current server time, in UTC | Now - StartTime |
TimeSpan(hours, minutes, seconds), TimeSpan.FromMinutes(5), TimeSpan.Zero |
time span | QueuedTimeSpan > TimeSpan(0,2,0) |
DateTime(year, month, day), DateTime.MinValue |
point in time | ChangeTime = DateTime.MinValue |
| the internal name of a state or type in quotation marks | state, type | State = "Waiting" |
You compare states and types using their internal names, see States and types; here, upper and lower case do not matter, and an unknown name is an error.
You convert with the .NET type names, for example Int32(x) or
Double(Agents.Count()), and with Convert.ToInt32(…) or
Convert.ToString(…); the language does not know short names such as int
or double. For calculations, all functions of Math are available —
Math.Round(x), Math.Round(x, 1), Math.Max(a, b), Math.Abs(x) — plus
the methods of the values themselves: Name.ToUpper(), Subject.Length,
QueuedTimeSpan.TotalSeconds, StartTime.ToLocalTime().
Operators
Ordered by precedence, the strongest first:
| Operators | Meaning |
|---|---|
. [ ] |
field, method, index |
-x, not x or !x |
sign; negation of yes/no |
*, /, % or mod |
multiplication and division. Whole numbers are divided as integers: 7 / 2 results in 3, 7 / 2.0 results in 3.5. |
+, -, & |
addition and subtraction, also with time spans and points in time: Now - StartTime results in a time span. & concatenates texts. |
= or ==, <> or !=, <, >, <=, >= |
comparison |
and or && |
and |
or or || |
or |
condition ? value1 : value2 |
condition, see below |
Parentheses ( ) change the order.
If & concatenates a state, a time span or a point in time with text, the
value appears untranslated: states with their internal names, time spans with
fractions of a second, points in time in UTC. So format it yourself, for
example
"Longest wait: " & Conversations.Max(QueuedTimeSpan).ToString("mm\:ss").
List queries
Every list — conversations, agents, skills … — supports these queries:
| Query | Returns | For an empty list | Example |
|---|---|---|---|
Count() |
the number | 0 | Agents.Count() |
Count(condition) |
the number of entries for which the condition holds | 0 | Conversations.Count(State = "Waiting") |
Where(condition) |
the entries for which the condition holds | empty | InboundCalls.Where(SkillName = "Support").Count() |
First(), First(condition) |
the first (matching) entry | empty | Agents.First(IsLogin).Name |
Min(field), Max(field) |
the smallest or largest value | 0 or 00:00:00 | Conversations.Max(QueuedTimeSpan) |
Sum(field) |
the sum | 0 or 00:00:00 | ACDs.Sum(WaitingCalls) |
Average(field) |
the average | 0 or 00:00:00 | Conversations.Average(QueuedTimeSpan) |
- Inside the parentheses, the fields of the individual entry apply: in
Agents.Count(IsLogin),IsLoginis the field of each agent. You refer to the entry itself asit. - Queries can be chained:
Conversations.Where(ConversationType = "InboundCall").Max(QueuedTimeSpan). - If the condition cannot be evaluated for an entry — for example
Skill.Namefor a conversation without a skill — the entry counts as not matching. - You check whether there is at least one entry with
Conversations.Count(State = "Waiting") > 0.
Conditions
iif(condition, value1, value2) and condition ? value1 : value2 return
value1 if the condition holds, otherwise value2. Both values must be of
the same type:
iif(Wrapup, WrapupTimeSpan, TimeSpan.Zero)
Agents.Count(IsLogin) = 0 ? "nobody" : "staffed"
Row and it
In table columns, row formulas and chart series, the current row
is available as Row. You can also name its fields without Row: in an
agent table, Name and Row.Name are the same.
Within a list query, it denotes the entry of the list; the row remains
accessible via Row. In a skill table, each row thus counts its own waiting
conversations:
Conversations.Count(Skill.Id = Row.Id and State = "Waiting")
If a field of the row has the same name as a list — agents, for example, have
the fields Skills and Languages — the name alone refers to the list. You
reach the field with Row.Skills or, in a query, with it.Skills.
Time and time zones
Nowand all points in time that the server supplies —StartTime,LoginTime,RaiseTime— are in UTC.- Time spans such as
Now - StartTimeorQueuedTimeSpando not depend on this. - A label whose formula returns a point in time shows it in the local
time of the computer. In tables and in texts you build yourself, you
convert:
StartTime.ToLocalTime(),Now.ToLocalTime().ToString("HH:mm").
Error messages
The designer checks every formula as you type; if it contains errors, the field changes color and the message appears below it, often with the position “(at index n)”. The most common ones:
| Message | Cause |
|---|---|
| Unknown identifier '…' | The name is misspelled, or the list does not exist. |
| No property or field '…' exists in type '…' | The field does not exist for this entry, see Data for formulas. |
| Operator '…' incompatible with operand types '…' and '…' | The values do not go together, for example a number and a time span. |
| Expression of type '…' expected | The result has the wrong type — a gauge does not get a number, a row formula does not get yes/no. |
| Ambiguous invocation of method '…' in type '…' | The arguments match several versions of a function. |
| Syntax error | for example a single | or typographic quotation marks |
| Unterminated string literal | A " is missing. |
| Character literal must contain exactly one character | A text is in single instead of double quotation marks. |
| Expression expected | The formula is empty, or something is missing after an operator. |
On the wallboard, a label with an erroneous formula shows the formula itself.
If an error only occurs during calculation — for example First().Name on an
empty list — the element shows an empty value: 0, empty text, 00:00:00 or
“No”.
Differences from performance indicators
| Wallboard | Performance indicator | |
|---|---|---|
| Calculated | in the Wallboard program, every second | on the server |
| Filters | the filters of the display element | none |
Agents |
all configured agents that match the filter — Agents.Count(IsLogin) counts the logged-in ones |
only the logged-in agents |
ACDs |
with metrics such as Open and WaitingCalls |
only the settings of the distribution rules |
Alarms |
the active alarms | empty |
Configuration, TimeStamps, ConversationStates, ConversationTypes, Bins |
available | not available |