Funktions- und Sprachreferenz

NX, the Ninox query language, is a powerful programming language which allows you to quickly extend Ninox databases with calculations and trigger actions.

While Ninox provides a visual function editor as described in the online manual, it also sports a text-mode for entering more complex expressions. This manual covers the text mode.

Here’s an example database
covering most of the topics of the tutorial:

Tutorial

Basic Arithmetics

NX provides arithmetic operations comparable to most other programming languages:

1 + 2 = 3
3 - 2 = 1
2 * 3 = 6
10 / 5 = 2

Arithmetic operations respect the typical operator precedence:

1 + 2 * 3 = 1 + (2 * 3) = 7

Expressions may be enclosed in parentheses:

 (1 + 2) * 3 = 9

Note, that NX will automatically remove insignificant parentheses, i. e. if you enter 1 + (2 * 3) it will store this expression as 1 + 2 * 3.

String Operations

A string, i. e. a sequence of characters, may be entered enclosed in double-quotes:

"Hello World!"
"This is a string."

Strings may be concatenated using the + operator:

"Hello World!" + " " + "This is a string." 
                            -- "Hello World! This is a String."

Strings may also be concatenated with other values:

"Hi " + 42 = "Hi 42"
2 + " fast " + 4 + " U"      -- "2 fast 4 U"

To enclose a double-quote within a string, it has to be escaped as “”:

"Hi, my name is ""Sally""!"

Working with Fields

Most NX functions operate in the context of a specific record. NX gives you access to all fields of that record. Consider a table Customer consisting of fields First NameLast NameStreetZIPCity. To generate the full address line, you may enter:

Street + ", " + ZIP + " " + City

Some field names may contain special characters like spaces, dots, colons and so on. Also they may collide with a reserved keyword of NX, like ifthenelse. To work around this, field names can be enclosed in single quotes:

'First Name' + " " + 'Last Name'

If a field name contains a single quote, this has to be escapes as ”:

'Last year''s total revenue'

Note, that NX is agnostic to field name changes. That is, if you’ve entered an expression referring to a field and you change that field’s name afterwards it will not have an impact to the expression. This is due to the fact that NX internally stores the expression with a reference to the field’s ID (which cannot me modified). Actually, if you open the function editor again, it will reflect the field’s new name.

Working with Table References

NX expressions can navigate along table references as well. Table references are always one-to-may relationships, e.g. one Customer may have many Invoices — where the table reference is defined as from Invoice to Customer (Invoice => Customer).

To display the Customer’s name in an Invoice, you’d write:

Customer.Name
Customer.'First Name' + " " + Customer.'Last Name'

Expressions may even jump along multiple hops, consider the case where a Customer has a reference to a Company. You could then display the Company’s in the Invoice as well:

Customer.Company.Name

Vice-versa, it’s also possible to get Invoice information for a Customer. Remember, that a Customer may have multiple Invoice’s. Thus, an expression referring to the Customer’s invoices will return multiple values. In order to display those values, some kind of aggregation has to be applied. The most common one is to sum up values:

sum(Invoice.Amount)

But there are other aggregations as well:

avg(Invoice.Amount)     -- the average, ignoring empty fields
cnt(Invoice.Amount)     -- the count of non-empty fields
min(Invoice.Amount)     -- the minimum value, 
                           ignoring empty fields
max(Invoice.Amount)     -- the maximum value, 
                           ignoring empty fields
first(Invoice.Amount)   -- the first value, according to 
                           Ninox' internal sorting
last(Invoice.Amount)    -- the first value, according to 
                           Ninox' internal sorting
concat(Invoice.Amount)  -- lists all values, separated by ", "

Logical Expressions

Logical expressions check if something is the case or not. Most often you’ll need them to create specific filter rules or to make decisions within a calculation. A logical expression either returns true or false. The most common form of a logical expression is a comparison of two values, like:

Amount > 100      -- greater than
Amount < 100      -- less than Amount >= 100     -- greater than or equal to
Amount <= 100     -- less than or equal to
Amount = 100      -- equal
Amount != 100     -- not equal

Logical expressions may be combined by andornot.

Age > 12 and Age < 18
Status = 1 or Status = 2 or Status = 3
not (Status = 4 or Status = 5)
Status != 4 and Status != 5

Note, the operator precedence is not > and > or.

Making Decisions

In the previous chapter you've learned about logical expressions. The result of such an expression may be used in a an if / then / else expression:

if Age < 18 then "Child" else "Grown-up"
if Age < 18 then
  if Age < 13  then 
    "Child"
  else 
    "Teenager"
else 
  "Grown-up"

Please note, that the then and else part have to return values of the same type — see chapter "Understanding Types".

Filtering Values

In the chapter "Working with Table References" you've already learned how to access multiple values from a table referring the current one — like sum(Invoice.Amount). With logical expressions, these results may also be filtered. A filter expression has to be enclosed in braces:

sum(Invoice[Status = 2].Amount)

This will only sum up the Invoice Amounts of Invoices with Status = 2.

Calling Functions

NX provides a range of built-in functions allowing you to transform values. A function call has the form:

function ( argument1, argument2, … )

Some examples:

age(Birthdate) -- The current age of a person with given Birthdate in years
cos(5) -- Cosinus of 5

Using Variables

Sometimes it can be useful to store the result of a intermediate calculation and do further calculations based on that result. Consider the case where you want to check the age of a person like:

if age(Birthdate) > 18 then "Grown-up"
else if age(Birthdate) > 12 then "Teenager"
else "Child"

Since age(Birthday) is used multiple times, things may be simplified with a variable which stores the result of the age calculation:

let a := age(Birthdate);
if a > 18 then "Grown-up" else if a > 12 then "Teenager" else "Child"

A variable is declared with a let statement:

let variable := expression;

Any expression following that let statement can make use of that variable.

Modifying Data

Some expressions in NX may also modify data. Up to the current release 1.5 of Ninox, this is only allowed for trigger expressions (field option Trigger after update). While further enhancements are planned, modifying data is currently restricted to change the value of record fields.

As an example, consider a table Article with a field Price (number) and another table Invoice Item with fields Article (reference to table Article) and Price (number). After assigning the Article, Ninox shall copy the Article's Price to the Invoice Item's Price. This can be achieved with a Trigger after update on Article containing following expression:

Price := Article.Price

It is also possible, to update multiple fields, using a semicolon:

Price := Article.Price;
Description := Article.'Article No' + " " + Article.Name

Create Records

With the create statement it's possible to create new records for a table. The following example creates a new record for the table Person and stores a reference to that record in the variable p. It then assigns a Name to the newly created Person.

let p := create Person;
p.Name := "Sarah Conner"

Select Records

Typically, formulas will access data from related tables like descibed above ("Working with Table References"). However, using the select statement there's also a way to access data from an unrelated tables.

select Person

Will look up all Person records, this statement returns an array of record references.

select Person where ZIP="10000"

This statement selects only the Persons with the given ZIP value 10000.

Selecting records is useful in many situations, one common case is to calculate the next Invoice ID.

'Invoice ID' := 
    max((select Invoices).'Invoice ID') + 1

Delete Records

With the "delete" command, it's possible to remove one or more records. Be careful in combination with select, because this may affect a wide range of records with a single call. Some examples:

delete first(select Person where 'First Name' like "Hans")

This will look up the first record from the Person table where the name contains "Hans" and remove it.

delete select Person where 'First Name' like "Hans"

This will look up the all records from the Person table where the name contains "Hans" and remove all matching records.

delete select Person

Will remove any record in the person table.

delete Customer

When issued on an invoice record, this will remove the customer that is linked to the current invoice.

delete Invoices

When issued on a customer record, this will remove all invoices which are linked to the current customer.

Loops

The for statement can be used to loop over arrays of values - e.g. the result of a select.

for p in (select Person)
    p.Haircolor := "red"

This exmple would lookup all Person records (select Person). For each record (stored in the variable p) it would then change the Person's Haircolor to red.

Function Reference

Type Conversion

number(value)

Tries to interpret the given value as a number.

  • If value stems from a choice field, this will be the choice's internal id. Use number(text(choice)) to get a numeric representation of the choice's text.
  • If value is a date, time or timestamp, this will be the the number of milliseconds between midnight of January 1, 1970 and the specified date.
  • If value is an appointment, it is treated like the appointment's begin date.
number("10") => 10
number(5) => 5
number(now()) => 1440681777046

text(value)

Converts any value to a string representation possibly reflecting the format option of its field settings. If there's no value, the result will be the empty string: "".

text("Hello") => "Hello"
text(2.34) => "2.34"
text(MyCurrencyField) => "1,234.56 $"
text(today()) => "08/27/2015"

Mathematical Functions

round(x) -- Rounds a number to the nearest integer.
round(x, digits) -- Rounds a number with the given amount of digits.
E.g. round(1.234, 2) = 1.23

floor(x) -- Rounds a number DOWNWARDS to the nearest integer.

ceil(x) -- Rounds a number UPWARDS to the nearest integer.

sqrt(x) -- The square root of x.

sqr(x) -- The square of x: x2

sign(x) -- The signum of x:

sign(-2.5) => -1
sign(2.5) => 1
sign(0) => 1

abs(x) -- The absolute value of x: abs(-5) = abs(5) = 5

sin(x) -- Sinus of x (in radians).

cos(x) -- Cosinus of x (in radians).

tan(x) -- Tangens of x (in radians).

asin(x) -- Arcus sinus of x (in radians).

acos(x) -- Arcus cosinus of x (in radians).

atan(x) -- Arcus tangens of x (in radians).

atan2(x) -- Arcus tangens of x (in radians), squared.

random() -- A random number between 0 (incl.) and 1 (excl.)

pow(x, y) -- x to the power of y: xy

exp(x) -- 10 to the power of x: 10x

log(x) -- Logarithm of x to the base of 10.

log(x, y) -- Logarithm of x to the base of y.

ln(x) -- Natural logarithm of x.

Text Functions

length(string) -- Returns the string's length (the number of characters).

trim(string) -- Removes leading and trailing white-space of string.

lower(string) -- Converts a string to lower case .

upper(s) -- Converts a string to upper case.

lpad(string, length, padding)

If string's length is smaller than the given length, the missing space is filled up with the given padding at the start of the string.

rpad(string, length, padding)

If string's length is smaller than the given length, the missing space is filled up with the given padding at the end of the string.

substring(string, start, end) -- Extracts a part of the string. Start and end are zero-based.

substr("Hello World!", 0, 5) => "Hello"
substr("Hello World!", 6, 10) => "World"

substr(string, start, length) -- Extracts a part of the string. Start is zero-based.

substring("Hello World!", 0, 5) => "Hello"
substring("Hello World!", 6, 5) => "World"

contains(string, match) -- Checks if string contains the given match string by exact comparison.

contains("Hello World!", "World") => true
contains("Hello World!", "world") => false

index(string, match) -- Finds the start index of the given match string within string.

index("Hello World!", "World") => 6
index("Hello World!", "world") => -1 (not found)

replace(string, find, replace) -- Replaces any occurance of find with replace.

replace("Hello World", "l", "X") => "HeXXo WorXd"

replacex(string, pattern, flags, replace) -- Replaces occurances of pattern in string with replace. Pattern is a regular expression string, flags is also a string specifying how the match takes place. Replace is a string, optionally using argument expressions. This call is compatible to JavaScript's
string.replace(new RegExp(pattern, flags), replace)
Learn more at: Javascript RegExp.

replacex("Hello World", "l", "g", "X") => "HeXXo WorXd"

Date Functions

date(year, month, day) -- Returns a date value, e.g. date(2016, 9, 27).

date(number) -- Converts a number to a date value. The number represents the number of milliseconds since the UNIX epoch ( 00:00:00 UTC on 1 January 1970).
date(datetime)
 -- Converts a date+time value to a date value (leaving out the time value).

year(date) -- Full year of the given date.
year(datetime) -- Full year of the given date+time value.
year(appointment) -- Full year of the start date of the given appointment.

month(date) -- Month of the given date (1 = January, … 12 = December).
month(datetime) -- Month of the given date+time value.
month(appointment) -- Month of the start date of the given appointment.

monthName(number) -- Name of the given month number, e.g. monthName(1) = "January".
monthIndex(text) -- Number of the given month name, e.g. monthIndex("January") = 1.

day(date) -- Day of month of the given date (between 1 and 31).
day(datetime) -- Day of month of the given date+time value.
day(appointment) -- Day of month of the start date of the given appointment

weekday(date) -- Weekday of the given date (0 = Sunday, 1 = Monday, … 6 = Saturday)
weekday(datetime) -- Weekday of the given date+time value
weekday(appointment) -- Weekday of the start date of the given appointment

weekdayName(number) -- Name of the given weekday number, e.g. weekdayName(0) = "Sunday"
weekdayIndex(text) -- Number value of the given weekday name, e.g. weekdayIndex("Sunday") =0

today() -- The current date (without time).

now() -- The current timestamp.

age(date) -- Number of full year's between now and the given date (e.g. a person's age).

format(date, format)
format(datetime, format)
format(appointment, format)
Formats a date as a string. The format expression is a string which may contain following tokens (example for 9th of August 2015, 01:02:03 am):

Token    Description              Example
YY       two digit year           15
YYYY     four digit year          2015
M        one or two digit month   8
MM       two digit month          08
MMM      abbreviated month name   Aug
MMMM     full month name          August
D        one digit day            9
DD       two digit day            09
Do       day ordinal              9th
dd       day name short           Sat
ddd      day name short           Sat.
dddd     day name full            Saturday
h        one digit hour           1
hh       tow digit hour           01
m        one digit minute         2
mm       two digit minute         02
s        one digit second         3
ss       two digit second         03
a        am or pm                 am

yearmonth(date)
yearmonth(datetime)
yearmonth(appointment)

Year and month of a date as a string, e.g. "2015/08". Useful for grouping records per month.

yearquater(date)
yearquater(datetime)
yearquater(appointment)
Year and quarter of a date as a string, e.g. "2015/03". Useful for grouping records per quarter.

yearweek(date)
yearweek(datetime)
yearweek(appointment)
Year and week of year of a date as a string, e.g. "2015/32". Useful for grouping records per calendar week.

week(date)
week(datetime)
week(appointment)
Calendar week of a date as a number.

start(appointment) -- Start timestamp of an appointment.

endof(appointment) -- End timestamp of an appointment.

duration(appointment) -- Duration of an appointment in milliseconds.

days(start, end) -- Number of days between two dates.

workdays(start, end) -- Number of working days between two dates. This function does consider any Monday to Friday to be working days, it does not respect holidays.

time(number) -- converts a number value (milliseconds) to a time value.

time(hours, minutes)
time(hours, minutes, seconds)
time(hours, minutes, seconds, millis)
Returns a time value with given hours, minutes, seconds and milliseconds.

datetime(year, month, day)
datetime(year, month, day, hour)
datetime(year, month, day, hour, minute)
datetime(year, month, day, hour, minute, second)
datetime(year, month, day, hour, minute, second, millis)
Returns a date+time value with given year, month, date, hour, minute, second and millisecond.

datetime(date) -- converts a date value to a date+time value, time is set to 00:00.
datetime(date, time) -- converts a date and a time value to a date+time value.
datetime(number) -- converts a number value to a date+time value, the number value represents the number of milliseconds since the UNIX epoch.

timeinterval(number) -- converts a number (milliseconds) to a timeinterval value.
timeinterval(time) -- converts a time value to a timeinterval value.

Color Functions

color(text) -- converts a text to a color value, e.g. color("red"), color("#f00"), color("ff0000"), color("rgb(255,0,0)"). color accepts any valid HTML/CSS color identifier.

color(red, green, blue) -- creates a color value from rgb-components. red, green and blue a numbers between 0 and 255.

color(red, green, blue, alpha) -- creates a color value from rgb- and alpha-components. red, green and blue a numbers between 0 and 255, alpha is between 0 and 1.

color(choice) -- returns the color of a choice value.

Icon Functions

icon(name) -- returns an icon, e.g. icon("warn")
icon(choice) -- returns the icon of a choice value

A full list of all icons and its corresponding names can be found here:

iconset.ninox

Location Functions

longitude(Location) -- the longitude value of a location field

latitude(Location) -- the latitude value of a location field

location(title, latitude, longitude) -- creates a location value with given title (text), latitude (number) and longitude (number).

User Interface Automation

User interface automation has been added with Ninox 1.7.0. It's not yet available for Ninox Server and Cloud.

printRecord(recordId, layoutName)
Creates a PDF from the given record and print layout name.

printRecord(record(Invoices, 1), "My Invoice Template")

openPrintLayout(recordId, layoutName)
Opens the print layout editor.

openPrintLayout(record(Invoices, 1), "My Invoice Template")

openRecord(recordId)
Opens the record and jumps to the related table.

openRecord(record(Invoices, 1))

popupRecord(recordId)
Opens the record in a popup form without switching to another table.

popupRecord(record(Invoices, 1))

openTable(tableName, viewName)
Opens a table view.

openTable("Invoices", "All Invoices")

User Management Functions

Pls. note that the following functions do only work for Ninox Server and Cloud installations. They won't return useful results for Ninox App.

user() -- returns the current user value
userId(id) -- returns the user value with given id

userId() -- returns the id of the current user.
userId(user) -- returns the id of the given user value.

userName() -- returns the name of the current user.
userName(user)
 -- returns the name of the given user value.

userFirstName() -- first name of the current user
userFirstName(user) -- first name of the given user value

userLastName() -- last name of the current user
userLastName(user) -- last name of the given user value

userFullName() -- full name of the current user
userFullName(user) -- full name of the given user value

userEmail() -- email address of the current user
userEmail(user) -- email address of the given user value

Other Functions

raw(value) -- returns the internal / raw representation of a value as a text.

html(text)

Returns a rich text representation of a text.

164 Gedanken zu „Funktions- und Sprachreferenz

  1. Hallo,

    ist es möglich, ein Auswahlfeld dynamisch aus selektierten Einträgen aus einer anderen Tabelle zu erstellen?

    Problem: Ich habe drei Tabellen: T1 = Mitarbeiter; T2 = Aufgaben; T3 = Arbeitsprotokoll

    mehrere Einträge aus T1 sind über eine Zuordnungstabelle T4 mit T2 verknüpft. T3 ist mit T1 und T2 verknüpft. Nun kann ich einen neuen Record aus T1 oder T2 erstellen. Erstelle ich einen neuen Record für T3 aus T1 fehlt die Zuordnung zu T2; erstelle ich einen neuen Record für T3 aus T2 fehlt die Zuordnung aus T1.

    Aus diesem Grund möchte ich den neuen Record für T3 immer aus T2 erstellen (da das dort aus Prozesssicht hingehört). Nun muss ich aber immer den Mitarbeiter aus T1 immer manuell zuordnen, was fehleranfällig ist. Besser wäre es, wenn in einem Auswahlfeld nur die Mitarbeiter angezeigt werden, die der Aufgabe auch zugeordnet wurden. Ist das über einen Trigger beim Erstellen eines neuen Records möglich? Und wenn ja, wie könnte es prinzipiell funktionieren?

    Schon mal vorab vielen Dank!
    fhs

    1. Hallo,
      ja, das ist möglich. Können Sie uns einmal die Datanbank an der Sie arbeiten in Kopie zuschicken? Gerne schauen wir hinein und ermitteln eine für Sie passende Lösung. Bitte wählen Sie aus dem Hauptmenü “Archiv sichern unter…” und schicken Sie uns die entstehende .ninox-Datei an support@ninoxdb.de

      Birger – Ninox Support

    2. Hallo fhs,
      die Auswahlfelder lassen sich nur manuell pflegen. Du kannst aber in der Tabelle T3 die Einschränkungen für Mitarbeiter festlegen.
      Die Beziehungsfelder habe ich umbenannt, deswegen lautet die Formel bei mir:

      first(b.Aufgaben[(Aufgabe = a.Aufgabe)].Aufgabe.’Zuständig’.Aufgabe) = a.Aufgabe

      Die Beschränkung hier bedeutet, dass in der Tabelle Mitarbeiter das Feld “Aufgabe” aus der Verknüpfung T1 -> T4 -> T2 soll gleich dem ausgewählten Aufgaben in der Tabelle T3 sein.

      die Beispieldatenbank ist hier:

      https://www.dropbox.com/s/hkzn05bbm2att97/fhs.ninox?dl=0

      Grüße
      Leo

  2. Hallo!

    Sehe gerade, dass es im Standort Feld neben Breiten und Längengrad auch eine Lupe gibt, um die Werte für Längengrad und Breitengrad per Adresse zu ermitteln-> Um den Standort auf der Karte anzeigen zu lassen. Kann ich diese Werte auch per skript ermitteln lassen-> Dann würde ich mir ja den unnötigen Klick auf die Lupe sparen und der Standort wäre sofort in der Karte verzeichnet.
    Danke Lg R

        1. Hallo, in dem Beispiel geht es darum zu zeigen, wie die Inhalte des Standort-Feldes automatisiert befüllt und ausgelesen können. Der Klick auf die Lupe wird benötigt, um die Karte zu öffnen und manuell einen Standort zu wählen.
          Gruß
          Birger – Ninox Support

  3. Guten Tag,
    Wenn ich aus einem popup Fenster versuche mit openRecord einen Datensatz zu öffnen, passiert es alles im Hintergrund. In meinem Fall habe ich die Tabelle, dann ein Formularfenster, dann noch zwei popup -Fenster oben drauf. Im letzten(obersten) Popup-Fenster habe ich eine Schaltfläche und möchte damit alle geöffneten Fenster schließen und ein anderen Datenasatz in der gleichen Tabelle öffnen. Beim Klicken auf die Schaltfläche ändert sich zwar das unterste Fenster, aber um die Daten lesen zu können muss ich erst die zwei oberen popup Fenster manuell schließen. Ein Einsatz von openTable bringt auch nichts – die popup Fenster bleiben stehen und müssen manuell geschlossen werden.
    Gibt es einen Befehl um die vorhandenen popup – Fenster zu schließen?

    Grüße
    Leo

    1. Hallo Leo,
      die Möglichkeit, Records und Popups per Script zu schließen, gibt es derzeit leider (noch) nicht. Dies ist Teil unserer Anforderungsliste (“Change Request”) für künftige Updates. Es wird kommen – ich kann derzeit nicht sagen, wann.
      Birger – Ninox Support

  4. Hallo,

    Ich habe eine Adresse, z.B.

    Sonnentor 1-5/10

    nun möchte ich gerne den Bereich vor dem Leerzeichen und den Bereich danach seperat extrahieren: “Sonnentor” und “1-5/10″ (in z.B. 2 seperate Funktionsfelder)

    weiters möchte ich im 2.ten Funktionsfeld “1-5/10″ die Zahlen vor dem / und danach ebenfalls in 2 verschiedene Felder aufteilen.

    Wie könnte ich das bewerkstelligen? Danke.

        1. Der Befehl “substr(Text, Start, Ende)” erwartet als Parameter einen Text und zwei Zahlen.
          In der Ersten Zeile ist dies: der Text im Feld “Adresse”, die Zahl “0″ und die Zahl des ersten Vorkommens eines Leerzeichens im Feld Adresse (‘index(Adresse, " ")‘).
          In der zweiten Zeile wird das Zeichen _nach_ dem Leerzeichen als Startwert genommen (+1).
          Das kein “Ende”-Wert angegeben ist, wir der String bis zum Ende ausgewählt.
          Grüße
          Birger – Ninox Support

  5. Hallo,
    Ich würde gerne zwei Tabellen dynamisch miteinander kombinieren.
    Tabelle 1: Kompetenzen (“Lernziele” oder “Arbeitsschritte”)
    Tabelle 2 Schüler
    Als Produkt stelle ich mir eine Tabelle vor, bei der jede Spalte eine Kompetenz aus der Tabelle 1 darstellt und jede Zeile den Namen einer Schülerin.
    Idealerweise könnte ich mit einem Script eine neue Tabelle erzeugen, bestimmte Records aus der “Tabelle Kompetenzen”als Felder einfügen und Zeilen mit den Vornamen einer Lerngruppe aus der Tabelle Schüler anlegen.

    Kann ich über ein Script (dynamisch) Felder zu einer Tabelle hinzufügen oder gibt es eine bessere Lösung für mein Vorhaben?
    Besten Dank!

      1. Vielen Dank für die schnelle Antwort. Das Beispiel trifft meinen Bedarf nicht ganz.
        Ich stelle mir eine Tabelle vor, bei der alle Lernziele als Spalten aufgereiht werden (Mathe 1.1, Mathe 1.2,…).
        Für jede Schülerin wird eine Zeile erzeugt. In den Feldern kann ich dann eintragen, auf welchem Kompetenzniveau eine Schülerin ist (lernend, fast am Ziel, Lernziel erreicht, exzellent).
        Spannend wäre nun, wenn ich die Tabelle dynamisch anpassen könnte. Dann könnte ich weitere Testresultate einfügen (Ma 1.1.1, Ma 1.1.2, …), ohne die Haupttabelle händisch modifizieren zu müssen.

        Ma 1.1 | Ma 1.2 | Ma 1.3 | Ma 1.3 | Ma 1.4
        Anna Müller gut exz . LZ err. lernend lernend
        Peter Stolt gut LZ err. exz. lernend lernend
        Petra K. gut exz . LZ err. lernend lernend

        1. Hallo maspi,
          eigentlich ist die Vorlage von Birger voll für dein Anliegen ausreichend. Problem ist nur, dass du die Datenbank als eine Tabelle betrachtest bzw. betrachten möchtest. Ich habe jetzt die Vorlage von Birger noch ein bisschen modifiziert.
          https://www.dropbox.com/s/xf3xdzthiukz8uc/Lernziele.ninox?dl=0

          Die Übersicht , die Du beschrieben hast, ist zwar jetzt in der Tabelle Schüler vorhanden, aber du wirst damit nie so arbeiten können wie mit der Excel-Tabelle. Dafür hast du aber die Möglichkeit z.B. die Daten von der Schüler einzufügen oder die Lernziele zu erweitern usw.

          Grüße
          Leo

  6. Hallo! Zunächst einmal herzlichen Dank für den bisher ausgezeichneten Support!
    Lässt sich eine for-Schleife auch nutzen, um einen Befehl (in meinem Fall das Erstellen neuer Datensätze) wiederholt ausführen zu lassen?
    Für meine Anwendung müsste ich durch Knopfdruck jeweils Einträge mit den Daten der nächsten 4 Montage erzeugen. Kann man so etwas wie “for i in (0,4)” aufrufen?
    Beste Grüße

  7. Hallo,
    die Funktion Delete funktioniert nur in der App. Wenn ich jemandem ins Team einlade und er kein Apple Gerät hat, kann er mit Browser nur eingeschränkt arbeiten.

    Grüße
    Leo

    1. Korrektur.
      Im Browser funktioniert delete nur in den verknüpften Tabellen z.B.
      delete Customer.
      Wenn man aber eine andere Tabelle mit select auswählt (delete select Person) – passiert nichts.

      Grüße
      Leo

  8. Hallo,

    Ich würde gerne meine Records mit Tags versehen. Damit die Tags “normiert” sind würde man sie sinnvollerweise in einer Tabelle sammeln.
    Perfekt wäre eine Autoergänzung oder ein dynamisch ergänztes Mehrfachauswahlfeld.
    Wie könnte man so etwas umsetzen?

  9. Ich habe eine Tabelle mit Kalenderwochen (in dem Beispiel verwalte ich die Auslastung von Mitarbeitern pro Kalenderwoche).
    Ich würde die Tabelle gerne so filtern, dass automatisch nur die Kalenderwoche ab der Aktuellen + 1 angezeigt werden.
    Allerdings funktioniert die Formel “>week(today())” nicht als Filter. Gibt es noch eine andere Möglichkeit?

    1. Hallo,

      ich würde in der Tabelle ein Feld mitneiner Funktion anlegen und dort eine entsprechende Formel hinterlegen. Die funktion kann ja als Rückgabewert Whr oder Falsch, Ja oder Nein, 0 oder 1 liefern. Dann in dieser Spalte den Filter setzen.
      So ähnlich mache ich das in meinen Datenbanken.

Hinterlasse eine Antwort