Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The step-by-step guide consists of 3 main sections: Basics, Advanced and Expert.
If you’re new to Ninox, it’s best to start with the basics to learn more about
creating and editing databases and tables,
customizing data fields and forms, as well as
filtering and sorting.
Visit our step-by-step guide for advanced users (soon to show the updated version) to familiarize yourself with
table references,
working with formulas,
sharing (releasing) as well as
importing and exporting data.
Complete your knowledge with our step-by-step guide for experts (soon to show the updated version) to get to grips with
printing,
table relations and
table composition,
triggers,
roles and rights management as well as integrations.
Let’s get started! 🎈
We show you, step by step, everything that Ninox can do
To create your own applications, whether it’s an invoice management system, event calendar or customer management solution (CRM), you normally need detailed knowledge of at least one programming language.
With Ninox, though, you can
get started straight away without any prior programming skills or knowledge about coding and
easily create your own applications that are always flexible and customizable.
But before we get started, we would like to briefly familiarize you with a few terms, as these will keep cropping up.
Of course, you can also navigate to specific topics individually.
Now for the terms, you need to know, as you will keep coming across them ...
You will need about 10 minutes to read through the whole introduction carefully.
Find out about databases, tables, data fields and forms
You’ll need about 45 minutes if you go through the basics step-by-step from start to finish. Of course, you can pause at any time or just look at specific topics.
Build powerful applications with the help of Ninox's documentation
In our documentation, we provide practical info about the Ninox application sorted by topics.
Get started as quickly as possible and start building your application tailored to your needs.
Beginners, advanced users, and experts—we want to address you all equally.
As you'll quickly notice, we're currently fundamentally revising our documentation. And we invite you to actively participate in this revision!
At the bottom of each page, you have the chance to give us quick feedback using the smileys.
We have the best community in the world! So be sure to check our forum as well.
And now have fun browsing!
Your Ninox Product team
Enter your data here and filter as required
In some applications (especially databases), a structured window, box, or other self-contained element provides a visual filter for the underlying data it is presenting.
A form can also be a template into which you enter information (data). For example, first and last names, customer addresses, etc.
A view shows only the data selected for that particular view. You can therefore determine which content should be displayed and how.
With large amounts of data, it makes sense to only display the information that is specifically needed, for instance, you might want to show only those customers who paid by credit card and spent more than €1,000 in the last week.
Applications, often simply called apps, are complete, self-contained computer programs developed for end users.
Applications perform specific and useful tasks that have nothing to do with the IT system itself or its maintenance; and can include mobile and desktop programs.
Ninox is such an application. Ninox runs everywhere via the cloud (i.e. in your browser), but is also available as a native app for Android and Apple.
Learn more about structuring and organizing your data
A database is a collection of data structured so that you can easily search for and retrieve items.
If you take a closer at our logo, you might recognize the standard symbol for databases in it. At least, that’s the idea behind it…
Tables contain data. A table is a database object that stores data in records (rows) and fields (columns).
The data usually relates to a specific category of people or things, such as employees or orders. You’re probably familiar with this from using Excel spreadsheets.
A database can consist of various tables.
Tables are really important when it comes to databases. That’s why we would like to take a look at their structure. But don’t worry, we’ll come back to them again when we work through an example in a moment.
Your first program for your data. Store and link your data sensibly ... and quickly find everything again whenever you need it
Every Ninox project starts with a database where you store your information.
Go to the Ninox homepage and click the Login button in the upper right corner (more about Create account).
Log in to your Ninox account.
Click the Start Ninox button. The Ninox app opens in your browser.
In the app screen, click on New database.
We’re showing our tutorial in the browser version for a Windows desktop. Therefore, some things might look a little different for you.
Like to delve deeper into the topic? Then take a look at our video tutorial.
We will create a new table in a database
Now we will continue working with the Event Management database that we’ve just created.
We will now create an Events tabIe in this Event Management database. There we will store information for each new event, such as the agenda, venue, participants, etc.
A table consists of rows and columns. Information of the same type is stored in a column. For example, the number of participants for an event is always stored in the Participants column.
Each table in a database is assigned a name, ideally so that you know straight away as to which information is held in this database.
Here are the most important terms again.
Open your new Event Management database.
Then click on New table in the next screen.
The table settings open.
Enter a name for your table under Table name. Since this table will hold data about events, we will name it Events (this is a bit shorter).
You don’t need to save it yet, as we are about to continue working in the table settings.
Like to delve deeper into the topic? Then take a look at the corresponding section in our video tutorial.
Choose between a diverse range of templates or design your own database
Ninox offers a variety of different templates that you can use as needed, for instance for your address book, collections, own custom CRM or inventory, and much more. However, here we are creating our own small database from scratch to manage events. Step by step ...
We create our database without a template and select Blank database at the top. This opens an empty database.
Your new database needs a name. In the New database pop-up, enter the name Event Management and then click the Create database button.
Your new database is ready.
We recommend that you simply click through the tutorial in sequence by pressing the Next button (on the bottom right-hand side).
Have fun!
For detailed feedback on what exactly you didn't like or didn't like so much by filling out our short questionnaire. This will be very much appreciated!
If you do not automatically see the + New table option as in the example, please enable the wrench icon in the upper right corner to enter the edit mode .
How to return to the table settings after saving
Before we save the changes, we would like to make a few updates.
You’ve already clicked the Save button? Then we will quickly show you how to return to editing.
Go to the table where you want to make some updates.
Select Edit fields from the drop-down menu and you’re back in the table settings.
A table consists of several fields, each of which holds information of the same type
We will now create a form with various fields in which we want to enter our data.
A form is another way of presenting a table. It is clearer to enter data in a form. Both are possible with Ninox, of course!
For our example, we need the following fields:
More information on the individual Field types
Here you can watch us do it. Watch and copy!
After you have dragged the corresponding fields from the right column to the center in the table settings, it should look like this.
Everything OK? Then we’ll move on...
Like to delve deeper into the topic? Here’s the appropriate section in our video tutorial.
You can customize the options for a data field to suit your needs. For example, you might want to specify that a field must always be filled in, i.e. that it’s a Required field. Simply store this in the field settings.
In the same way, you can specify the
minimum or maximum length for an entry,
add general information, or
specify who should be able to see (or not see) a field.
In our example, let’s configure the Venue choice field as follows:
The field should be a Required field, i.e. it needs to be filled in.
You want it to be shown as a radio button.
You would like to add a Tooltip.
You would like to provide a list with a choice of 4 options.
Click Venue in the table settings. The field settings for the venue, a choice field, open.
Open the field settings.
Under Required in the field settings, select Yes.
Open the field settings.
Under Show as, click Radio buttons.
Open the field settings.
Click More options.
Add your Tooltip (here: “Select the event location”)
We’ve created the venue as a Choice field. Therefore, we will now add various options to the field, which you can then choose from.
You can, of course, add as many options as you like, but we will limit ourselves to 4 in the example.
Open the field settings.
Click + New option.
Add an option and confirm by pressing Enter.
Repeat point 2 and 3 until you have entered all 4 options.
When you’re finished, click OK to return to the table settings.
Click Save to save all your customizations to the table.
In the example, we’ve named the rooms after cities: Berlin, Hamburg, Cologne, and Munich.
When you’ve finished editing, click OK to return to the table settings. Click Save there so that your changes aren’t lost!
After saving the changes, your table should now look like this:
Before we take a look at how to enter data, we’d like to show you a few more options for displaying the Choice field.
You have various options for displaying the different choices in the form
You can display the options stored in a Choice field in 3 different ways.
The desired value is selected from a drop-down menu.
There is a default option, which can be placed at the top of the selection list
There are more than 7 entries (then it’s best to sort them alphabetically)
The options do not need to be compared
A “More” or “Other” option is needed
All options are visible. Simply click on the desired value.
All options should be visible at a glance
When there are 5 or less choices
It should be possible to compare the options
It should be possible to quickly select them
In our example this would probably not be the best choice, as there are 4 options. Nevertheless, we would like to show it to you so that you can get a better idea as to how the different display options compare.
There are up to 3 options
There is a default option
It should be possible to toggle quickly between 2 simple options like On and Off (if you need only Yes and No, we recommend the Yes / No field).
Enable the wrench icon to edit your tables
Edit fields
Add fields
Delete fields
When you close a table in edit mode, the edit mode is also closed. After reopening your table, simply click the wrench icon again to make further changes to your table. If the form doesn’t “slide” into view from the right on its own, simply click on the arrowhead (top right) to display the form.
You will only see the wrench icon if you have admin rights. Only then can you change the composition of a database.
Click the gear icon in the top left corner.
Field type | Field name | Explanation |
---|---|---|
Like to dive deeper into the topic? Then take a look at the corresponding section in our .
You can access the edit mode by clicking on the which you will always see in the upper right corner..
The wrench icon must be enabled before you can make changes to your tables such as
Title
This is where we will later enter the name of an event.
Date
Event date
Participants
Number of participants
Venue
Here we will store various venues, from which you can then choose the one you need in each case.
Agenda
The agenda for the respective event is stored here.
Text
Date
Number
Choice
Text (multiline)
In Ninox, there are 2 ways to number a row and/or record:
The always visible row number
The ID for a record (No.)
This is the row header. The row number is always displayed. It always starts at 1 with the row numbers listed sequentially in ascending order until the end of the table.
The row number refers to a different record depending on how the table is sorted. In our example, the same record appears once in row 3 and once in row 4.
Then there is the unique identification of a record. This is automatically assigned by Ninox when a new record is created. It cannot be changed.
Internally, it plays a considerable role, for example when linking different tables with table references or selecting certain records.
But since you don’t need them for now, Ninox has hidden the IDs column by default. However, you can display them at any time.
Customize forms to meet your needs
Ninox was developed to offer all users as much design freedom as possible. Of course, this also applies to one of the centerpieces of each table: the form.
Customize forms to your liking. This applies to their layout, but also to the fields included in them. Ninox grows with your needs.
Let’s take a look at the Events table that we have just created.
In the Event Management database, click the Events table.
You can see the form in the foreground on the right. The corresponding table is behind it.
The field is outlined with a red frame with one or 2 handles.
Customize the field according to your needs.
Don’t forget to save! To do this, click on Save changes in the upper right corner.
When you’ve finished, don’t forget to save your changes.
Or you can also adjust the order of the fields at the same time ...
If you find that you would like to change the order of the fields, that’s also quite simple.
The field is outlined with a red frame with one or 2 handles.
Drag the field to the desired location.
If everything is to your liking, don’t forget to save your changes in the upper right corner.
Enable the edit mode by clicking the wrench icon in the upper right corner. The edit mode is enabled when the icon is red.
To customize a specific field, hover the mouse over the corresponding field. A dashed gray frame becomes visible and the mouse pointer becomes a cross . Click in the field.
Move the mouse over the corresponding field. A dashed gray frame becomes visible and the mouse pointer becomes a cross . Click in the field.
It’s easy to show columns — or hide information you don’t need. This gets even more interesting when it comes to creating different views. But more about that later.
Using the ID column as an example, we will show you how to display a “hidden” column.
Click on a column header.
In the pop-up, click Show column.
The available columns that are not yet displayed are shown.
Select – here in our example – Id.
The field is inserted after the clicked column. Here: The column with the IDs of the individual records is displayed.
If needed, you can move the column to where you want it by simply dragging it.
In the video, we will also show you how to change the order of the columns.
To hide a column that is not needed, proceed in the same way as for showing it.
Click on the column header you want to hide.
In the pop-up, click Hide column.
The column is no longer displayed.
In the pop-up, you can see all the available columns or data for your table. Again, you can drag them between Visible Columns and Available Columns.
You can also get an overview of the available columns by clicking on the filter icon at the top left.
Display only what you currently need. Or visualize as much as you want
Views provide you with various options for displaying your data. This enables you to consider your data from different perspectives and gain a better overview. This, in turn, helps you make informed decisions.
Just try it out and create different views for our example.
Give the new view a name.
Select an option.
We’ll show you a few views here, based on our example. Due to the lack of data they’re not particularly meaningful, of course, but we think you’ll get an idea of just how powerful these views can be.
Click the plus icon in the tab bar.
Invite colleagues to your workspace to collaborate with them on databases
When you use Ninox in the cloud, you can collaborate with colleagues around the world on your database.
That’s why we’re showing you here how you can invite your colleagues into your workspace so that they can collaborate on your Ninox application.
More information about our subscriptions.
Go to the workspace where you want to invite a colleague.
Click + Invite on the right. A pop-up opens.
Enter the corresponding email address, select which access rights the colleague should have, and in which language he or she should receive the email invitation (English or German).
And go! Send your invitation.
Your colleague will receive an invitation with a link that he or she can use to register or log in to Ninox.
You can see your open invitations in your workspace overview.
By clicking on the appropriate email address, you can
resend or
revoke your invitation.
Congratulations! 💐
You’ve successfully completed the Ninox step-by-step basics tutorial and thus got to grips with the most important basics for building your own application.
Use our Ninox assistant and video tutorials to learn more about using Ninox
If you haven’t met it yet, we would like to quickly introduce you to our Ninox assistant, which welcomes you when you open the Ninox application for the first time.
However, you can also start the assistant manually and get to know Ninox there through our small mini-tours.
Enable (or disable) the tours.
A pop-up opens. Follow the individual chapters. You will find tours on a diverse range of topics. To get started, we recommend Ninox Basics in 70 Seconds.
The Ninox assistant with its tours is currently only available in the browser.
We would also like to recommend the following videos by our colleagues from the support team. You will already be familiar with a lot of what they show and be able to delve deeper into various individual aspects.
Click the gear icon in the upper right corner of the workspace.
Learn more about .
In addition, you will find many other exciting on our channel. The best thing to do is to watch our entire playlist at .
Finally! This option ensures that a date is always output correctly—regardless of the timezone in which a record is accessed.
The enable timezone-independent date option refers only to the date field. The option's available as of version 3.6.
If you use Ninox in the cloud together with other collaborators who are located in different timezones, you may be affected by an issue that can occur when saving a date, e.g., birthday or invoice date:
The value displayed in a date field may differ by 1 day from the entered date.
That is because Ninox stores dates as timestamps. Therefore, depending on the timezone in which you access a database, there is a possibility that a different date is displayed.
The displayed date may also be affected by Daylight Saving Time (DST).
If you work on Ninox databases across different timezones and have implemented a workaround for this issue, please follow our guidelines below before you switch over your databases.
Shortly, you won't need to make any custom adjustments, as date values will automatically be saved correctly. If you experienced issues with the date display in the past, we now offer the option to switch your databases.
Given the large number of databases that already exist, we require a transition period so that users have sufficient time to test and apply this new option to existing databases.
If you have been using workarounds to deal with the date issue, please keep the following in mind when making the switch:
We recommend that you manually back up your databases before switching them over.
Afterwards, check the behavior when you enable the option and adjust your scripts as needed.
The option is enabled at the database level. If you have multiple databases, perform the following steps for each database.
Open your Ninox Public Cloud in the browser (i.e. the web app; also for Apple users: not in the Mac app, as certain functions aren't available there). Then proceed as follows:
In the tab bar, click Options.
Click the button under Timezone-independent date.
A popup appears pointing to this help page and reminding you to perform a manual backup. When you are ready, click Enable.
Still under Options, click the button Rebuild indexes.
If you also use Ninox on a mobile device or via the Mac app, please resynchronize your databases on at least one mobile device (refer to Synchronize content in apps). For now one mobile device will be sufficient as subsequent syncs are faster afterwards). If not, you are...
Done! Check your database entries to ensure they are correct.
If you use mobile devices, you need to "transfer" the timezone-independent date entry to your native apps.
To do so, please synchronize your databases on each mobile device, as well as the Mac app, with the Ninox server.
Tap and hold the database icon (mobile device) or click the database icon (Mac app).
A popup opens. Select Reset synchronization.
Your data is synchronized with the Ninox server.
Done!
If needed, inform your colleagues using mobiles devices about enabling the timezone-independent date and advise they reset synchronization of databases on their mobile devices.
Values entered in a date field are now always displayed correctly, no matter from where you access the database.
For date entries outside the UTC -11:00 and UTC +11:00 timezones, e.g., on the Line Islands of Kiribati, Baker Island, Howland Island, or the Marshall Islands, the international date line may still cause date values to be saved incorrectly.
Starting with Ninox version 3.6, in each newly created database, a date value is automatically stored independent of timezone.
From Ninox version 3.6 onwards, a date—in a date field—is automatically stored independent of timezone in a newly created database.
Prepare your data to get the information you need quickly and easily
You can apply standard sorting and filtering operations by clicking the respective column header. Depending on the field type, you will be shown various sorting and filtering options.
In our example, click on Title and you can arrange the table alphabetically by clicking on Ascending.
If you select the same option for the event date, the events will be sorted by date.
Grouping the entries under Venue will give you an overview of how many and which events are booked per room.
If you are searching for a specific value in a column, enter your search query in the filter and the results will be displayed. In the example here we have searched for events in December 2022.
Learn how to reference tables, work with formulas, share your work, import and export data
Note: The screenshots shown here might look a bit different from what you see in your application but the workflow is the same.
The intermediate tutorial covers the following topics:
As mentioned in the basics tutorial, a table is designed to hold data. In the intermediate tutorial, we cover how table references can enhance your tables.
To begin, we create a separate table called Company. Next, we want to connect all of the data in the Company table with a new field in the Events table. Once done, you can select a record from the Company table by clicking the newly-created field.
To follow along, create the following fields:
Company Name → Text
Industry → Choice: Combobox → List of industries
Event Sponsor? → Choice: Combobox → Yes or No
Address Line 1 → Text
Address Line 2 → Text
City → Text
State → Choice: Combobox → List of states, provinces, etc.
Next, create a section for a Company Representative with the following fields:
Full Name → Text
VIP Guest? → Choice: Switch → Yes or No
Birthdate → Date
To download and import sample data for your new Company table:
Follow the steps in the Importing Data section below to add the Company table data to your database.
Alternatively, if you prefer to manually populate fields with data, use your own sample data or copy some of the text below for inspiration.
Include Headers to better organize your tables.
Example headers ”Company Information” and ”Company Representative:”
To add a header:
From the table view, click the Actions gear icon and then choose Edit fields…
On the right-side panel, select Add layout element.
Drag the Head field on the right to a location in the Fields panel.
Rename the field (e.g., “Company Information”) and hit <ENTER
>.
The next step is to format the header text based on your own personal preferences. In this example, we make the text “Company Information” appear in bold lettering, but other customization options include borders, alignment, size, and background color.
To customize the header:
Select the Company Information header.
Select the Style field.
In the Font Style field, click Bold.
Click the OK button.
In the Field editor, click the OK button.
Click the Save changes button.
The new header is ready:
To add a table reference, return to the Administrator mode and edit fields in the table.
To edit fields in the table:
Navigate to the Events table.
In the top-left corner, click the Actions gear icon.
In the drop-down menu, select Edit fields…
For visual assistance, refer the animated graphic below:
To add a table reference:
In the bottom-right corner of the Edit Fields window, select Create table reference.
A list of all tables appears. The list of tables includes your new Company table.
Drag your newly-created table to the fields area, like you are adding a new field.
Rename your field or name it “Company” like in shown in the example below. Hit <ENTER
> after you type the field name.
Click the Save changes button. Your table reference is ready.
After saving your changes in the previous step, return to the Events table.
Start with the Form view by selecting the Form button at the top of the screen—this displays the form to the right of the table.
A new selection field called Company is visible.
Click anywhere in this field to go to the Company table.
Select a company record or, if your referenced table is very large, enter a search term and matching results appear automatically. For visual assistance, refer to the animated graphic below:
With your newly referenced table, you now have multiple layers of information. In this section, we learn how to ”drill down” into your data.
”Drilling down” is just a fancy way of saying, ”I want more detailed information.” In the example above, we selected ”Otis Manufacturing” as our company.
Your Company field should now list your selection (“Otis Manufacturing Inc. Agriculture…” etc.). Select the field to drill down into the record to view detailed company information. For visual assistance, refer to the animated graphic below:
Formulas enable you to automatically populate fields based on other content. For example, formulas can automatically format text, perform calculations on values, and even use logic to produce conditional information (i.e., “If this is true, then do that...” type statements).
In this tutorial, we use a formula field to automatically calculate age based on a provided birthdate.
If you replicated the Company table as shown above, one of your fields should be Birthdate (created by adding the Date field). For visual assistance, refer to the screenshot below:
Start by navigating to the Company table you created earlier. To jump between tables, select the table name in the main menu. Then select Edit fields.
To navigate to the Company table:
In the top-left corner, click the Actions gear icon.
In the settings drop-down, select Edit fields...
For visual assistance, refer to the animated graphic below:
Let’s add it directly after the Birthdate field, as shown in the animated graphic below:
Now that the Age field has been added, we need to define a formula—this is done in the Formula editor.
To navigate to the Formula editor:
Select the Age field.
In the Formula window, select the Formula field.
The Formula editor appears.
The Formula editor is where the magic happens! This is a 100% drag & drop environment. First, let’s have a look at the four navigation tabs:
Fields: Displays a list of all fields used in the active table
Calculate: Tools to add, subtract, multiple, exponents, etc.
Logic: Tools to create conditional formulas, for example like if / then / else, and, or, =, ≠, etc.
Text / Date: Text formatting and time-related tools
We need to tell Ninox to determine the age of a company representative based on a provided birthdate. To do this, we use the Age formula and apply it to the Birthdate field.
To drag & drop formula:
Select the Text / Date tab.
Drag & drop the Age tool to the Formula editor canvas.
Next, select the Fields tab.
Drag the Birthdate field and drop it into Age.
In the top-right corner, click the OK button.
For visual assistance, refer to the animated graphic below:
To save changes:
In the top-right corner, click the OK button.
The Formula windows re-appears. Click OK button.
The Edit Fields window re-appears. Click the OK button. Your changes are saved.
For visual assistance, refer to the animated graphic below:
To view the Age field:
Click on a table row. The form slides into view from the right.
Check that the Form view is selected.
A new field called Age is visible. The Age field is automatically calculated from the Birthdate.
The default alignment for some fields, such as the new Age field above, is right-aligned.
To change alignment:
From the table view, open the Edit Field screen.
Select the Age field.
Select the Style field.
In the Text align field, select Center.
Click the OK button, click the OK button again, and finally click the Save changes.
Ninox offers some pretty powerful, and easy to use, sharing functionality. At any time you can easily share a view of your work in multiple formats, such as HTML, PDF, Excel, and even JSON.
When a shared view is created, Ninox creates a web address that can be viewed—and copied—in a website browser.
Here’s a rundown of how to do it:
The first step is to activate sharing. When sharing is activated, it means that anyone who has a web address can look at a view. If sharing is deactivated, a shared web address does not work.
To activate sharing:
1. From a table, click the Actions gear icon and select Share this view… 2. In the Activate sharing field, select either Yes.
To create a web address for sharing:
Select Yes to activate sharing. The window expands to display all the different formats.
Select a format: HTML, PDF, Excel, CSV, or JSON.
Ninox automatically creates a web address in the Public URL field.
Click the Globe icon to open a new website tab featuring the shared view.
Feel free to copy & paste the URL to share with your colleagues.
Lastly, remember to leave sharing activated so that your view can be seen. To keep sharing activated, click the OK button.
To deactivate sharing, select No and confirm by clicking the OK button.
Here’s how to create a web address of your view in PDF format:
So far we’ve discussed a couple of different ways to input data into Ninox: manually entering data into fields and using a table reference to add data from another table source.
A third way—and the preferred option for a large amount of data—is to import from a CSV (comma-separated value) file. A CSV file is essentially a spreadsheet with rows & columns… exactly the same structure as a Ninox table!
Let’s talk about how to import a CSV file.
The first step is to select a file, likely from your local computer system or network. You can start the process from either the Table Selection screen:
…or via the Actions gear icon on a Table screen:
No matter which option you choose, click the Choose File button.
An Open or Select window appears (based on your browser). Navigate to the location of a CSV file and select it for import.
For visual assistance, refer to the screenshot below (Google Chrome on Windows):
Don’t worry, you probably won’t need to change any of the settings! Ninox, though, wants to make sure that you are always in control of how your data is used.
One field of interest is the Choose table to import data into which tells Ninox where your CSV content should go.
If you want a brand new table featuring your data, then select Create new table from import. This is automatically selected if you started the process from the Table Selection screen.
If you want your CSV content to be imported into an existing table, then select the drop-down arrow and pick a table to import your data into.
When you’re ready, click the Next button.
In the next step, Ninox gives you the freedom to customize your field names and field types.
To customize fields:
In the Please enter table name field, enter a unique name for your newly-imported table. In this example, we used “Company Contacts.”
In the field name panels on the left, change (or keep) the field names as needed.
In the drop-down menus on the right, change (or keep) the field types as needed. For example, you may want to change the “Industry” field type from “Text” to “Choice” and, later on, populate the field with specific options.
When you’re all done, click the Next button.
The last screen shows a preview of your table populated with some of your data. Check it all out and see if it’s what you’re looking for. If you’re not happy, you can always select Go back and make changes.
If you’re happy with everything, click the Import now button.
Click the OK button. Your imported table is ready.
Ninox can easily export data into CSV or Excel formats. Like Sharing and Importing above, start by clicking the Actions gear icon and then select Export data…
If you decide to export in comma-separated value (CSV) format, then you can customize your export in a few different ways. like including a header, selecting a separator, selecting a date format, etc.
To export in CSV format:
Start by selecting CSV export at the top of the Export data window and then try some different configurations to see how they work.
When all done, click the Open button.
Ninox will create the CSV file and it can be downloaded to your system where you can open or view it as needed.
To export in Excel format, we follow the exact same process except select Excel import in the Export data window.
If you want to use the same formatting number and date formats used in your Ninox table, then remember to select the Maintain number and date formats checkbox.
Lastly, click the Open button and download the Excel file.
You've now implemented the Ninox features designed to manage different aspects of data, from table references and formulas to importing and exporting data.
Enable the edit mode .
If you need a refresher before starting this tutorial, the shows how to create a database, add, edit, and delete a table, use view, how to sort and filter, and how to save your work.
In contrast to manually populating fields with choices like we do in the , a table reference connects another, separate table to a field. In other terms, every single record in this separate table becomes a choice in a field. Linking tables to each other significantly expands your choices.
Refer to the if you need a refresher on .
Download the .
Next, we’re going to add a Formula field and call it “Age.” This process is exactly the same as in the . We add a field and give it a name (remember to hit <ENTER
> after you type “Age”).
If you’d like to try using our sample Company data, you can download a sample data file .
Think of a modularized database like a set of toy blocks. Each block, or module, is a separate piece of the solution and has its own job. Just like you can snap together blocks to make different things, you can connect these modules to build a complete solution or application.
Every module is like its own database. It works by itself and has its own information and tasks it can do. But, when you put these modules together with others, they can share information and do more complex jobs.
Let's take a company as an example. It has departments like sales, human resources (HR), and accounting. In a modularized database, each department has its own module. The sales module keeps track of talking to customers, the HR module looks after employee details, and the accounting module deals with money matters. Each of these parts works on its own, but they can also connect to each other. For example, the HR module could share employee information with the sales module to help track who's selling well.
Think of a modularized database like a set of toy blocks. Each block, or module, is a separate piece of the solution and has its own job. Just like you can snap together blocks to make different things, you can connect these modules to build a complete solution or application.
Every module is like its own database. It works by itself and has its own information and tasks it can do. But, when you put these modules together with others, they can share information and do more complex jobs.
Let's take a company as an example. It has departments like sales, human resources (HR), and accounting. In a modularized database, each department has its own module. The sales module keeps track of talking to customers, the HR module looks after employee details, and the accounting module deals with money matters. Each of these parts works on its own, but they can also connect to each other. For example, the HR module could share employee information with the sales module to help track who's selling well.
Learn how to import or export existing data from Ninox
You may import and export data in Ninox, for example, if you want to transfer data from another program from the start, or if you want to share data with people who don't use Ninox.
Ninox 3.10 introduces 'Mailhook'—a centralized receive-only inbox that stores emails in a Ninox database
Mailhook is available for Private Cloud.
Storage: Each of your emails will be stored as a separate record in a table, and any email attachments will be located in the record attachments section.
Attachments: You can receive email attachments up to 30 MB in size and download them as needed.
Unique email ID: Your email ID consists of a username you provide, combined with the workspace ID. The domain name remains nxdb.tech
.
Mailhook offers a different approach to email management—you can receive messages directly in a designated Ninox mailbox. Mailhook's main function is to centralize email communications, making it easier to keep all emails related to projects or clients organized in one location. Mailhook can initiate automated workflows based on emails, which aid in collaboration and ensure that relevant email information is accessible to all users.
Additionally, Mailhook can fill database fields using information from emails, which could reduce manual data input and help in maintaining an updated database. In terms of privacy and record-keeping, Mailhook complies with privacy regulations and keeps a record of all interactions. You may find Mailhook more convenient as you won't need to switch between multiple communication apps.
To set up an inbox:
Click your profile icon in the top-right corner of the screen.
Select Ninox settings from the drop-down menu.
In the Ninox settings, click Integrations in the left navigation bar.
Click the Email setup tab.
Choose a workspace.
Enter an inbox name.
Enter a username.
Check the box acknowledging the use of your API key.
Click the Generate button.
To open an inbox:
In Email setup, click the down arrow to reveal your email address(es).
Click the kebab menu in the top-right corner of the box.
Click Go to inbox in the drop-down menu.
You are redirected to the database that serves as your inbox.
To delete an inbox:
In Email setup, click the down arrow to reveal your email address(es).
Click the kebab menu in the top-right corner of the box.
Click Delete email address in the drop-down menu.
Your email address is deleted.
Get to know the Ninox assistant
We use tours to interactively show you how Ninox works. The software we use for that acts as an additional "layer" on top of the app and guides you in real-time through the processes in Ninox.
The Ninox assistant runs on Userlane—a no-code #what-is-a-digital-adoption-platform-dap designed specifically for onboarding, employee training, and customer support.
...our assistant playfully shows you how to use Ninox and addresses initial uncertainties in the direct application—complementing the written documentation (the one you are reading right now) as well as our video tutorials.
Our goal is to guide you through Ninox step-by-step in real-time, providing you with an enjoyable user experience right from the start.
We are here to help you understand Ninox' functionality and start building your databases as quickly as possible—ultimately, we want you to succeed with Ninox.
The Ninox assistant is primarily targeted at folks who are new to Ninox. Of course, this doesn't have to stop you from exploring tours—no matter where you are in your Ninox journey.
At the moment, the tours only work in the web app (app.ninox.com)—ideally on a PC. They are less suited for small screens (<640 pixels) such as those of smartphones and tablets.
When logged in to the web app, navigate to the gear icon in the top-right corner to access the global settings.
From the dropdown select Tours. The assistant is enabled.
Some of the tours require admin rights and enabling the edit mode in order to display all steps of a tour.
In such cases, there are 2 variations:
one for users with read rights and
one for users with admin rights.
Depending on the tour, you may see a step but be unable to perform the desired action. In this case, we show an alternative step: contacting the admin of your Ninox workspace to request admin rights.
Ninox tours are sorted into chapters. Currently, there's 6 chapters with a total of 19 tours.
The tours build on each other, i.e. some are only visible after completing a specific tour. So it is perfectly normal that you do not see the complete list all at once.
Enable tours (5 sec)
Welcome (10 sec)
Create a new workspace (5 sec)
Create a database (10 sec)
Add a table (15 sec)
Input data (10 sec)
Customize a form (10 sec)
Global settings (10 sec)
Manage your profile (15 sec)
Invite collaborators (15 sec)
Import data to a new table (25 sec)
Import data to an existing table (25 sec)
for admin users
for read-only users
Export data (10 sec)
for admin users
for read-only users
Manage backups (20 sec)
Rename a database (5 sec)
Delete a database (5 sec)
Create views (10 sec)
Share views (15 sec)
Print tables (5 sec)
Print records (15 sec)
At the end of each tour you complete, a popup appears containing a survey link. In this survey, feel free to tell us what you (don't) like and what else you think the tours are missing.
Explore printing, table relations and composition, roles and rights management, triggers, and connecting to Integromat
Note: The screenshots shown here might look a bit different from what you see in your application but the workflow is the same.
In this section, we focus on unexplored features and leveraging your new skills to get the most out of Ninox.
The topics include:
View tables as either a PDF or as a web page (HTML format) for printing.
To print a table:
Start by navigating to a table.
Click the Actions gear icon.
In the drop-down menu, select Print View.
By default, the table will display as a PDF format directly on your screen or your browser will download the PDF as shown below.
In addition to PDF format, Ninox supports displaying a table as a web page (HTML format) which can then be printed. You can also change the text size used.
To change print options:
Navigate to the Tables screen.
Click the red Admin wrench icon in the upper-right corner to enter admin mode.
Next, select the Options tab. A window appears.
Select Printing Tables…
In the Font size field, change the value to make your text larger or smaller, as needed.
In the Preview as field, you can change from the default PDF format to HTML, which displays a table directly in your web browser.
After changing the printing option to HTML, you can proceed to viewing the table on a web page and then printing it.
To view in HTML format, refer to section Printing a table above.
Next, right-click on the web page and select Print… This process may differ based on your browser and/or operating system—Windows 10 using Chrome is shown below.
In addition to printing tables, you can also print one or more individual records. To print records, click the Print icon when viewing a table.
The first step is to look at how to select records. There is a slight difference between an active record row and a selected record row:
Why is this important? Ninox uses your selections to present printing options for you. Let’s do a quick print, then look at our options in more detail.
Start by making one row active—select a row and it turns blue—and then click the Print icon:
After doing this, the Print screen appears. In the upper-right corner, click the Print icon and then—in the drop-down menu—select either This record or All (x).
Selecting This record prints only the active record—Ninox prepares a PDF and your browser will automatically initiate the download process.
Selecting All (x) prints all records—as above, Ninox prepares a PDF for download.
Let’s try a different way. This time, make 1 row active (“Bioderm Ltd” in the graphic) and choose 3 different rows (“Allstar Sports,” “Otis Manufacturing,” and “Radargus” in the graphic) by selecting row numbers.
Next, click the Print icon:
The Print screen appears. In the upper-right corner, click the Print icon and then—in the drop-down menu—select either This record or All (x).
Selecting This record prints only the active record (“Bioderm”), regardless of whether it was selected or not.
Selecting All (x) prints all selected records (“Allstar Sports,” et al).
Key takeaways:
To print all records, make one row active then select All; alternatively, you can select every single record in the table.
To print selected records, select them by clicking the row numbers, then select All (x).
To print an active record, make the row active, then select This record.
When printing, you can select paper format and margin values to customize your printouts—note that all measurements are in millimeters. In addition, the document width and height fields are auto-populated based on the paper format selection.
As we discussed in the last Intermediate tutorial, tables can be referenced with each other to create more ways to integrate information.
In the example that we worked on, we created a reference from the Events table to the Company table. This enabled us to select a company that was associated with an event—each event could only be associated with one company, but each company could be associated with multiple events.
As a reminder, here’s the Events form. Notice the Company field at the bottom—one company is associated with one event:
…and here’s the Company form. Note that two events are associated with one company:
In this example, a company can sponsor many events, but an event can only have one company sponsor at a time.
This type of table relationship is called a “1:N relation,” which means that one data record from one table is assigned (related) to many data records from another table.
From the Tables screen, select Data Model to get a visualization of this relationship—make sure that your red Admin wrench is selected.
Here’s what it looks like for the Events and Company tables mentioned above:
In this relationship, the Events table is a “child” of the “parent” Company table.
In a 1:N relation like this, there is no cause-and-effect between the tables. Deleting a record in one table has no effect on records in the other table. The two tables simply share data between each other.
In some scenarios, though, you may want to create a cause-and-effect relationship.
For example, if a table populated with telephone numbers is referenced to a table with contact details, then we could create a deeper cause-and-effect relationship between them: when a contact record is deleted, then the associated telephone numbers in the other table would be deleted as well (since the numbers no longer have a purpose on their own).
This type of cause-and-effect relationship between tables is called Composition.
Ninox’s composition feature empowers companies to build robust datasets that can reflect accurate, real-time information.
But let’s not get too far ahead! First, let’s do a step-by-step walkthrough to see how the composition process works.
Using the knowledge you picked up in the intermediate tutorial, create two tables called Telephone Numbers and Contacts. The former is a simple 1-column table comprised of just telephone numbers. The latter is also a simple table with first name, last name, and maybe some basic company details.
Here’s a look at our new Telephone Numbers table:
We format the Telephone default value field to “+1” and also limit the number of characters to 12 (+1 plus 10 digits). Here’s what it looks like:
…and here’s a look at the new Contacts table:
Start by creating a table reference from the Telephone Numbers table to the Contacts table. Do not save yet!
At this stage, we have created a 1:N relation between both tables.
To turn on the composition feature:
Select the newly dragged-and-dropped Contacts field.
In the Composition field, select Yes.
Click the OK button.
Click the Save changes button to confirm.
A peek at the new data model shows a distinctly different visualization:
In this composition relationship, the Contacts table is now a super-table with the sub-table Telephone Numbers fully integrated within it.
Due to this new composition relationship, when a record in a super-table Contacts is deleted, then any associated records in the sub-table Telephone Numbers are also deleted.
Let’s see this in action.
First, we will open the Telephone Numbers sub-table and assign two numbers to the contact, Mr. George Sanderson:
If you need a reminder on how to do this, here is a visualization:
Next, we’ll have a look at the contact record for Mr. George Sanderson in the Contacts super-table. Notice that the two numbers are listed at the bottom:
Since there is a composition relationship, when we delete Mr. George Sanderson from the Contacts super-table, then the two associated telephone number records will also be deleted:
A composition relationship between tables is best used when sub-table records (e.g., telephone numbers) are closely tied to a super-table record (e.g., a contact) and their deletion will not adversely affect any other data.
Another example is an invoice item—such as a client-specific ID number—that is directly tied to an invoice. If an invoice record is deleted, then the invoice item will be deleted as well.
Ninox enables companies to exercise a great degree of control over how users can interact and use the solution. This is supported by a robust user management system that allows Admins to control access for workspace members as well as granular access over tables and even fields!
Ninox offers two default types of roles:
Admin: Can create new databases, change the data model, and manage users
Editor: Can edit and delete databases
When you create a new workspace, you are automatically the Admin of that workspace. Remember in the Explore tutorial we talked about how to invite other users to your workspace? During that process, you, as the Admin, can define what role the invited user will have.
Here’s a reminder:
By default, Ninox offers Admin and Editor roles, but you can also create your own role—these customized roles are used when specifying access to tables and fields.
To start, let’s explore how to assign rights at the table and field levels.
Ninox enables Admins to implement high-level permissions as well as more detailed granularity when it comes to granting rights to both tables and fields.
For tables, Admins can assign rights to user roles for all tables as well as specific tables.
Let’s demonstrate this process by creating a new role for a new user and then applying rights to that role.
To create a new role for a new user:
First, invite the new user by selecting Invite from the Database screen.
Select Create new role.
In the Role name field, enter a name for the new role. In this example, we use “QA Analyst.”
Click the OK button.
Click the Send invitation button.
The invitee receives an invitation via email containing a link. When they click the link, Ninox prompts to formally accept the invitation:
To assign rights on a larger scale across all tables:
From the Workspace screen, select a database. The Tables screen appears.
Click the red Admin wrench icon in the top-right corner.
Select the Security tab.
In this panel you can choose which roles have access to specific rights by selecting a drop-down arrow and then choosing 1 or more roles. By default, rights are assigned to all users (“everyone”) when no choices are made.
When done, click the Save changes button, then the OK button to confirm.
You also have the option of assigning rights to roles for individual tables.
To manage rights for individual tables:
Navigate to a table.
Ensure that the red Admin wrench icon is enabled in the top-right corner.
Click the Actions gear icon and, in the sub-menu, select Edit fields…
In the table panel, modify rights drop-down menus as needed.
By default, if no role if selected, then all users have access to the right.
Rights options available include the following:
Allowed to read: Selected roles can view/read table records
Allowed to write: Selected roles can change/write table records
Create new Records: Selected roles can create new records
Delete Records: Selected roles can delete records
Readable if and Writable if: Admin can enter code that enables user-based conditions for reading/writing tables (not covered in this tutorial)
At the highest level of granularity, you can specify rights at the field/attribute level.
To specify rights for fields:
In the Fields panel, double-click/select a field. The Field Detail panel appears.
Select More options.
In the Allowed to read field, select one or more roles to enable field read access.
In the Allowed to write field, select one or more roles to enable field write access.
Click the OK button.
Triggers are powerful tools that introduce a level of automation in Ninox tables and fields. A trigger is another way of saying, “When x happens, do y.” or “When this happens, do that.”
Triggers can be used in various ways, for example:
Copying values between tables
Automatically changing values when something happens
Automatically retrieving data from a linked table
If you are designing your own app, it's helpful to rely on a formula whenever possible. Sometimes using triggers can be a better option, for example if you need to create new records or pull data from a linked table.
Ninox triggers are implemented in two places: at the table level and at the field level.
In this tutorial, we look only at table-level triggers and how they can be used to introduce automated record updates.
A table-level trigger launches a specific code set either when a record is created (Trigger on create) or when Ninox updates a parent record and it will affect a child record (Trigger after update).
Let’s do a walkthrough of how a trigger can be used to automatically update an invoice number whenever a new record is created.
Imagine that we have a table that consists of invoices where every new record is a new invoice. Instead of manually typing in the next relevant invoice number, we can use a trigger to tell Ninox to automatically assign an invoice number for us.
Start by creating a simple table called Invoices with a Number field called Invoice Number. It should look like this:
Edit the table (i.e., click the Actions gear icon and then select Edit fields…) and, in the Edit Table screen, select the Trigger on create field.
The Code Entry screen appears.
The field Trigger on create is where we define a trigger. The trigger is activated whenever a new record is created in the table.
The Code Entry screen is used to enter Ninox code that can trigger events. In this case, we will enter a code that automatically increases the Invoice Number field by 1 whenever a new record is made (based on the number of the last record).
Enter the code below into the white content panel of the Code Entry screen:
Use the following to copy & paste:
In line 1, we define the variable “i” by finding the last record within the field Invoice Number from the table Invoice.
In line 2, we tell Ninox that the number field Invoice Number should equal our variable “i” plus 1.
Finish by clicking the OK button. The OK button works if the code is accurate/valid. If the code is not accurate or not valid, a warning message appears specifying the part of the code that doesn't work.
In the Edit Table screen, click the Save changes button.
In the animated graphic below, every time the + icon is clicked to add new record, the value in the Invoice Number field increments by 1:
For visual assistance when starting with Invoice Number ”1800:”
This method increments the last-entered invoice record. It does not auto-increment based on the most recent invoice record, i.e., the invoice with the highest invoice number.
This could cause a problem when an old invoice is edited and its number changes to the most recent invoice number. When a new record is created, its number is based on the last entered record and not the most recent record, i.e., the one that was edited.
For visual assistance of the potential issue, refer to the graphic below:
In the graphic above, the most recent invoice is number 24 (row 3), but when we add new records, the trigger tells Ninox to increment based on the last entered invoice, which is number 5 (row 5).
Instead of looking at the “last” record:
We look at the “max” record—the record number that is the maximum, or has the highest, number:
Replace the phrase “last” with the phrase “max.” Here’s what it looks like in the code editor:
With this new code in place, let’s see what happens when we add a new record:
Ninox now looks at all Invoice Number data, determines which one has the highest value (most recent), and then auto-increments new records based on that number.
The Trigger after update feature has a specific purpose: it is used in a child table and is designed to update records after Ninox updates a parent record.
With the help of API, Ninox can integrate with a number of robust software solutions. One of these is Integromat, an online automation platform that enables users to connect multiple applications and substitute manual processes with automated workflows.
If you use Integromat, you can connect Ninox to monitor, list, retrieve, lookup, create, update, or delete records and files in Integromat as well as list teams, databases, and tables in your Ninox account.
From the team workspace, click the Actions gear icon.
Select Integrations... from the drop-down menu. Next, in the Integrations... window, click the Generate button.
After clicking the Generate button, an API key appears. Copy the character string to your clipboard.
To set up the connection:
Open Integromat. In the Dashboard, select Create a new scenario.
In the Integration screen, select Ninox and then click the Continue button.
Select the question mark icon, select Ninox, and then select Get Record. The Ninox dialog box will appear. Click the Add button.
The Create a connection window appears.
In the Connection name field, enter a unique name for the Integromat/Ninox connection.
In the API Key field, paste the API key from your clipboard.
In the Private Cloud URL field, enter your Ninox Private Cloud URL (if you are hosting).
Click the Continue button.
To specify Ninox data:
Select your Ninox Team, Database, and Table.
Click the OK button.
Ninox and Integromat are now connected. You can use Integromat to automate many of your favorite Ninox features, such as:
You’ve not only just connected Ninox with Integromat, but you have completed the independent tutorial as well.
The Ninox 3.10 release introduces 'Pages'—a blank canvas approach to building custom dashboards
Pages are available for Public and Private Cloud as well as On-Premises.
Blank canvas: Start with a blank slate and explore different UI design possibilities.
Direct additions: Effortlessly incorporate UI fields, layout components, sub-tables, and relationship fields.
Multi-tabbed interface: Navigate smoothly with a structured interface.
Administrative control: As an administrator, you can conceal various UI elements for a more simplified experience for non-admins.
Enhanced modularity integration: Ensure an organized application structure, moving away from outdated methods involving dummy tables and side editors.
Pages offer a simpler way to customize UI designs, even without advanced coding. This feature marks Ninox's evolution from a no-code database tool to a low-code application builder, with an easy-to-use drag-and-drop UI builder.
To create a new page:
Open a database or create a new one.
Enable edit mode by clicking the wrench in the upper-right corner.
With edit mode enabled, open a table or create a new one.
In the left navigation sidebar, click the upwards arrow next to + New table.
A new appears: click + New page.
Add fields, formulas, or layout elements to your new page. You can also create relationships between a page and tables or other pages.
The Ninox 3.11 release introduces a simplified way to reconnect modularized databases imported to another workspace
Reconnecting modularized databases is available for Private Cloud and On-Premises.
Reconnecting databases was a long, manual process. When you imported a database backup to a new workspace, you had to manually reconnect each relationship, sometimes doing it over and over for the same database.
When you downloaded and then uploaded a database to a new workspace, its ID would change because it was in a new workspace. This made the tables not recognize each other anymore, and you had to reconnect them again by hand.
When something went wrong during this process, you wouldn't get any error messages. This meant you might not even realize there was a problem.
The whole process is now built into Ninox itself, making everything smoother and avoiding the need for complicated steps or outside tools.
It's mostly automated now, which saves a lot of time and hassle that used to go into managing relationships.
You don't have to use temporary fixes to reconnect databases anymore.
Everything updates on its own, so you don't have to manually keep track of maintenance.
Instead of the old, complicated multi-step process of reconnecting databases, there's now just a few simple steps.
It's easier to spread out your data across different workspaces, making your databases more flexible.
If errors pop up, you'll see messages explaining what went wrong, making it easier to fix issues.
For this example, we connected 2 databases from our templates: Onboarding and Time tracking.
The actual process of reconnecting your databases may vary slightly.
In the workspace overview, click the Reconnect database (1) tile.
In the Reconnect database pop-up, click the dropdown menu (2) to select the database you want to reconnect.
From the dropdown menu, choose the desired database, here it's Onboarding (3).
Click the Next (4) button to proceed.
On the next screen, you'll see Onboarding is ready to be reconnected and that it has relationships with other databases. Choose the desired restored version, here it's Time tracking (5).
Click the Continue to reconnect (6) button.
Finally, confirm the reconnection by clicking the Confirm reconnect (7) button.
Once the reconnection is successful, you'll see a confirmation message stating Onboarding is successfully reconnected. Click OK (8) to close the pop-up.
The Ninox 3.10 release introduces a transformative feature to enhance your experience: the 'do as database ... end' transaction
do as database ... end
is available for Private Cloud and On-Premises.
Simplified database navigation, boosting data access speed and productivity.
Avoids complex API workarounds.
Seamless integration with existing database relationships.
The do as database ... end
transaction greatly simplifies the task of navigating through multiple databases, eliminating the need for shifting between databases or applying advanced workarounds for data access.
The core functionality of do as database ... end
is to allow you to pull data directly from the current database you're operating in without accessing a separate database. Not only is this transaction method more streamlined than the previous API call method, but it also ensures data accuracy, given certain conditions:
The transaction can be applied only when the databases in context have a pre-existing relationship.
For accurate data retrieval, the database name used must be exact.
Database names with special characters should be enclosed in single quotes.
To exemplify, consider 2 databases: Offers and invoices and Procurement.
Open the Offers and invoices database.
Open the Invoices table.
Click the wrench icon in the top-right corner to enable edit mode.
Click the drop-down arrow next to the gear icon on the left and select Edit fields from the dropdown to access the table settings.
In the table settings, select the All databases in current workspace checkbox.
Also in the table settings, click Relationship fields. Under the Procurement database, drag-and-drop the Orders table to Fields.
Click Save to apply changes and close the table settings.
In the Offers and invoices database, create a new formula field and name it Order date.
In the table settings, drag-and-drop Formula from Data fields to Fields.
Click Save to apply changes and close the table settings.
Open a record in the Invoices table, switch to the Invoices tab, hover above the Order date field until you see the wrench icon.
Click the wrench icon to access the field settings.
In the Order date field, click the Formula field to open the formula editor.
In the formula editor, enter the following script:
Click Save to save the script and close the formula editor.
In the Formula pop-up, click OK to apply changes and close the pop-up.
Click Save changes.
Verify that Order date displays the latest order date from the Orders table in the Procurement database.
Before beginning, ensure you've established a relationship between Offers and invoices and Procurement.
In the Offers and invoices database, create a new layout field (button) and name it New invoice.
Click Edit fields and drag-and-drop Formula from Data fields to Fields.
Click Save to apply changes and close the table settings.
Open a record in the Invoices table, switch to the Invoices tab, hover above the New invoice button until you see the wrench icon.
Click the wrench icon to access the field settings.
In the New invoice field, click the On click field to open the formula editor.
In the formula editor, enter the following script:
Click Save to save the script and close the formula editor.
In the Button pop-up, click OK to apply changes and close the pop-up.
Click Save changes.
When you click the New invoice button in the Invoices table in the Offers and invoices database, a new record from Orders with today’s date should pop up.
Verify that the Orders table in the Procurement database contains a new record with today’s date.
To close/disable the tours again, click the icon in the pop-up on the left of your screen. The assistant is disabled.
We've also built a tour for that—try Enable tours (5 sec) directly in Ninox.
function: Navigate directly to specific tabs using page name
and tab name
parameters.
In Ninox 3.10, we introduced an important improvement, the transaction designed to simplify the transfer of data between databases. This transaction removed the need for complex API workarounds. Building upon this progress, brings an essential new feature focused on the reconnection of modularized databases.
Consistent and across both web and native apps.
Intuitive functionality in line with other Ninox transactions; , , and .
A number of options are available for exporting or backing up your data from Ninox
In general, you don't need to worry about your data. When you use Ninox Cloud, Ninox periodically creates automatic backups of your data, and you can restore them whenever you need them.
In addition, however, you may want to download or export your data for a couple of other reasons.
Perform the following steps to export a database in a workspace in one go:
Go to the workspace overview, where you can see all databases of your workspace (team).
Select Create backup.
By default, all options except change history are selected in the following popup. So your backup automatically contains the following values:
all data
all attached files
all comments
Click OK.
In the Manage backups popup, under Manual backups, find the latest backup at the top. Select the appropriate backup and click Download backup. Locate the file in your downloads.
The downloaded file is in the Ninox format (.ninox
).
Perform the following steps to export a table from a database in a workspace (team):
Open the table you want to export.
Select Export data from the dropdown menu.
Select the desired format (CSV or Excel) and click Download.
An introduction to importing CSV files to Ninox
To import a CSV file to an existing or a new table in Ninox:
Go to the database where you want to upload your CSV file.
Click on Import Data.
The Import Wizard opens and you click the Import CSV file button in the Import data pop-up.
That was the quick tour! On the way, you have certainly seen that you can do much more there.
Using the Import Wizard (we named the pop-up this way for simplicity), you can set various options.
Help the Import Wizard by giving it details about the data you want to import.
If you want to import dates, specify the format of the dates to be imported, if possible so that they can be transferred correctly.
Specify which data should be imported and what exactly should happen to it.
Click Next and the following pop-up appears:
In the next step, name the table and assign fields.
If you import data into an existing table, matching field names are automatically assigned to each other.
Keep track of your Ninox activity, analyze and fix problems
The process monitor is a handy tool to observe what's currently happening in your workspaces. It offers a clear view of processes that are running, in queue, or completed. You can sort and filter these processes in various ways.
The tool provides detailed activity logs and the opportunity to peek at the formulas driving each process. If there's an issue, such as an inability to display data or a lack of running processes, the process monitor display a message. It also provides a button to restart your workspace when necessary.
In the top-left corner of the process monitor page, a drop-down menu allows you to select a specific workspace. Here, you can review and manage all the processes within that workspace (1). Alternatively, view all processes across all workspaces simultaneously, providing a comprehensive overview.
The top-center section displays a list of all active, queued, and completed processes (2). Keep track of which tasks are currently being executed, which are waiting in line, and which have already been completed. Sort these processes based on criteria like process ID, start time, or status.
The bottom-left section provides a detailed log of all activities (3). This includes information about when a process was started, how it progressed, and when it was completed. The activity logs help track the execution of processes and troubleshoot any potential issues.
Lastly, the bottom-right section is dedicated to the formula view—a detailed, behind-the-scenes look at the specific formulas being used by each process. Examine these formulas to gain a deeper understanding of how the process works, which can be useful for troubleshooting or improving process efficiency.
The process monitor uses 4 status messages to provide real-time updates and alert you to any potential issues.
These messages appear in specific locations, namely the top and bottom snackbars.
At the bottom snackbar, before you decide to restart a workspace, you'll see a Restart workspace (1) button and a status message stating, While restarting, your databases will be temporarily unavailable (2).
Once a restart is in progress, the process monitor displays a message in the middle of the screen stating, Restarting.
If the process monitor cannot display data for all workspaces, maybe because it doesn't exist or an error has occurred, a status message appears stating, Unable to load data for workspaces.
If there's an issue loading data for a specific workspace, a status message appears stating, Unable to load data for the selected workspace.
There are no running processes in the workspace you're viewing (1). When this happens, the process monitor displays a status message in the top-center stating, This workspace has no running processes. Please select another workspace (2).
You might select a process (1) that does not have any associated activity logs. This could be because it's a new process that hasn't started yet, or there could be some other reason. The process monitor then displays a status message in the bottom-left corner stating, This process has no activity logs. Please select another process (2).
You're reviewing an activity log, but no formula is associated with that particular activity. In such a case, the process monitor displays a status message in the bottom-right corner stating, This activity log has no formula. Please select another activity log (3).
Optimize the structure of your database and increase its performance
If you heavily work with your database, not only add but also repeatedly delete data, it can be helpful to defragment your database from time to time due to the way data is stored in Ninox.
By manually "triggering" defragmentation, Ninox cleans up and rearranges stored data. This optimizes the storage space, which in turn can lead to better performance (access times).
Open the database you want to defragment.
In the database settings, click Options.
At the very bottom of the page, click the Defragment database button.
When you defragment a database, Ninox reorders data in the background. This can reduce the amount of storage needed and increase performance.
In any case, we recommend defragmenting a database if you have deleted large amounts of data.
Hover the mouse over the database you want to export until you see the arrowhead .
Click the gear icon in the upper right corner.
Select the appropriate file on your device and click Open, follow the prompts until you see your data, and click the Import now button in the bottom right corner to import your data. Done!
After that, you will see a preview of the data to be imported. Click Import now. Done!
The following pages on print customization are copied and adapted from the of the third-party integration carbone.io.
To find the process monitor, first click on the gear icon for global settings. Then, select Ninox settings in the top-right corner. After that, select the Process monitor from the navigation bar on the left.
The process monitor uses 3 status messages that appear in specific locations—, , and —to help understand empty states, providing guidance on where to focus your attention next.
More on (external link)
Enable edit mode .
In the following we show you how to duplicate a database in the Ninox Cloud
Here we explicitly show you the procedure in the Ninox Cloud, i.e. in the Web App.
In the corresponding workspace (Team), drag the mouse cursor over the database you want to duplicate.
Click the gray drop-down arrow and select Create backup.
Confirm the Create backup pop-up with OK.
In the next window, Manage backups, you will find the backup you just created at the top (you can also tell by the date and time).
Select Download backup (1) if you want to import/upload the database elsewhere (e.g. via the Import archive action field) or select Restore (2) to directly create a copy of the database in this workspace (Team).
Done!
Tip: If your backup is not shown there right away, the database is probably a bit bigger and needs some more time. You can close the window and open it again later via the Manage Backups > Manual Backups action field and proceed as described above.
Learn the basics of print customization in Ninox
Print customization is available for Private Cloud starting 3.7.7.
The pricing page (section on Essentials) offers info on how many renders per month are available in your subscription.
Any time a dynamic print layout is created (either with or without the use of a function), 1 render is dedicated from the monthly quota.
Ninox uses a third-party integration, carbone.io, to find all markers {}
in a document (.xlsx
, .odt
, .docx
, ...) and replace these markers with Ninox data.
According to the syntax of your markers, the following operations can be performed:
replacing a field
formatting data
repeating a document portion (a table row or anything else)
looping on unlimited nested arrays
conditionally displaying a data based on a test expression
The syntax is similar to using a JSON Array or Object in JavaScript. Combined with features of, for example, Microsoft Word or LibreOffice, you can create documents with:
graphics
headers, footers
automatically repeated table header across pages
insert computed field
page count
etc.
.xhtml
.odt
.ods
.odp
.docx
.xlsx
.pptx
.odg
.pdf
Google Fonts are pre-installed. If a font is not rendering into documents, verify that font is available on Google Fonts.
These functions work with the Blank and Auto print layout options.
printRecord(nid, layoutName)
prints default report
printAndSaveRecord(nid, layoutName)
prints default report and returns the link
These functions work only with the Dynamic print layout option.
printRecord(nid, templateLayoutName, data)
prints dynamic report with your custom layout
printAndSaveRecord(nid, templateLayoutName, data)
prints dynamic report with your custom layout and returns the link
Without a custom script, your template (e.g., a DOCX
file) must follow the proper notation for field names.
Field names need to be written with CamelCase or using underscore _
. If you write a field name with any other characters, including white spaces, data for that field is not rendered.
Examples:
By default, the recursion level is set to a minimum of 3
. The recursion works as follows:
root record = 1
subtable in root = 2
another table within the subtable = 3
etc.
Either leave the recursion level set to its default or consider increasing the number of recursions, based on your needs.
The first step to creating and rendering a report is to set up a new print layout in Ninox.
Open a database to open a table that contains records you want to print.
Alternatively, open a database to open a view that references data from different tables or databases.
Open a record. The record view slides in from right-to-left.
Click the print icon from the toolbar on the right side of your screen. The print layout view opens.
Click the plus icon to create a new layout. The Create new layout popup appears.
Choose Dynamic, then click the Import layout icon.
When selected, the popup displays the name of the file. Click the Create button to finish merging data from your template.
LastName
last_name
Last_Name
last_Name
Last Name
last-name
Next, you have 2 options how to get from a template in a text editor to a rendered PDF in Ninox: or .
Get from a document in a text editor to a printable report in Ninox
Open a text editor, e.g., Microsoft Word, LibreOffice, Open Office, Google Docs, or other.
Choose the type of template you want. Refer to #supported-file-formats.
Use your text editor's functionalities to add a header, a footer, pictures, or dynamic content with JSON data. Follow the links below to learn how to:
insert data into a document -> Substitutions
print a list of elements -> Repetitions
format numbers, dates, and strings -> Formatters
show and hide content conditionally -> Conditioned output
Save your template.
Preview the merged layout. If the document looks as expected, click the Print button, select All or This record to download the PDF
document.
Use the sample data below to understand how to get from a document (= template, here: DOCX
in Microsoft Word) to a rendered report (= result, PDF
in Ninox).
Create a database from the NINOX
backup file from the sample data below.
Once the database is created, open the Invoice table, click any record, then click the Print icon.
View the 2 layouts:
en_invoice_template -> refer to#option-a-without-a-custom-script
en_invoice_template_without_JSON -> refer to #option-b-with-a-custom-script
Open Microsoft Word or another text editor to view the MS Word template A (Option A) and B (Option B).
Depending on which template is used, you either work with or without a custom script.
In Ninox, select a layout, then click the Print icon. Select This record to download the final result, a rendered PDF
report.
Note: For both layouts, we use a global function to correctly display currency.
Both MS Word templates A and B result in the same report. All roads lead to Rome.
What | File format | EN | DE | Notes |
---|---|---|---|---|
MS Word template A
DOCX
no custom script needed, refer to Option A: without a custom script
MS Word template B
DOCX
requires custom script, refer to Option B: with a custom script
rendered report
PDF
watermark on PDF only appears in this demo
database
NINOX
custom script
JSON
global function
JSON
To substitute data in a template, use indicators {d.}
. Indicators {d.}
are substituted for data from your JSON dataset in Ninox.
The following values can be substituted:
a string
a number
a date
Download and print a test PDF to verify that the rendered report contains the desired data and looks as expected in your layout.
The test print contains a watermark. The proof print contains a watermark. The final, "real" print will not have a watermark.
Either toggle ON the option Test print in the Ninox UI, or alternatively use a custom script and the functions printRecord
or printAndSaveRecord
.
Using data from Example: invoice PDF, view the files below: a test print with a watermark and a final print without a watermark.
Works with printRecord and printAndSaveRecord.
The data
object can include the property _options
with testPrint
which overrides the default settings set by the print engine in the Ninox UI, i.e., if you previously toggled OFF Test print.
Add a new layout element, here: a button.
Paste the script below in the formula editor.
Save changes.
Click or tap the button to run the script.
A report (PDF file) is created and downloaded to your local files.
When data is an array of objects, access each object directly using the square bracket notation []
and the reserved word i
, which represents the ith
item of the array.
Zero-based arrays are used:
the first item of an array is [i=0]
or [0]
,
the second item of an array is [i=1]
or [1]
,
etc.
My preferred movie is {d[i=1].movie}
My preferred movie is Matrix
Use aliases to simplify the maintenance of your report avoiding code repetition or to insert markers somewhere in the document where special characters like square brackets []
are not allowed, e.g., in worksheet names.
Aliases can be used to:
write {#... = ...}
to define an alias
write {$...}
to use this alias
Define aliases anywhere in the document, at the end, or at the beginning. Aliases are parsed and removed automatically before rendering.
{#myAlias = d.wheels}
{d.name} need {$myAlias} wheels!
Cars need 4 wheels!
To repeat a section of a document, for example rows, title, or pages, use a "repetition example" with the reserved key word i
and i+1
.
It's not necessary to define where the repetition starts and ends.
The pattern is automatically found and repeated using the first row (i
) as an example. The second row (i+1
) is removed before rendering the result.
Cars |
---|
Cars |
---|
{d.cars[i].brand}
{d.cars[i+1].brand}
Lumeneo
Tesla
Toyota
Repeat nested arrays are managed at unlimited depth. The following example shows a repetition of a whole document.
It is not necessary to completely repeat the first paragraph twice in the template—repeat only the title of the second paragraph to detect where the repetition pattern of the main array ends {d.cars[i+1].brand}
.
The bi-directional loop performs iterations in 2 directions, creating additional columns and rows.
The feature depends significantly on the XML coming from the document.
If the table is badly formed, there may be issues recognizing the elements to repeat, which in turn may create a corrupted document.
Models |
---|
Models |
---|
Models |
---|
Vehicles |
---|
Vehicles |
---|
{d[i].models[i].brand} | {d[i+1].models[i].brand} |
---|
Toyota | Tesla | Lumeneo |
---|
Cars |
---|
Cars |
---|
In the , only distinct rows are kept.
Cars |
---|
Vehicles |
---|
Filters should be the same on the ith+1
marker and all other markers if you want to keep only matching rows. Use an to simplify report maintenance.
People |
---|
People |
---|
People |
---|
People |
---|
People |
---|
People |
---|
{d[i].models[i].size}
{d[i].models[i+1].size }
Prius 2
Prius 3
S
X
|
|
Tesla |
Airbus |
|
|
|
|
Prius 2 | S | Smera |
Prius 3 | X | Néoma |
|
|
Tesla |
Toyota |
Lumeneo |
|
|
Tesla |
Toyota |
Airbus |
Boeing |
|
|
John |
Bob |
|
|
Falcon 9 |
Falcon Heavy |
|
|
Falcon 9 |
Model S |
Access the iterator value when a list is printed into a document.
In {d[i].cars[i].other.wheels[i].tire.subObject:add(.i):add(..i):add(...i)}
The number of dots equals the number of previous i
:
.i
matches the index value of wheels[i]
..i
matches the index value of cars[i]
...i
matches the index value of d[i]
All existing formatters by input data type
Formatters translate raw data into human readable text.
The example below shows how to write "John"
instead of "JOHN"
using 2 chained formatters, and how to translate a raw ISO date into a human readable date.
My name is {d.name:lowerCase:ucFirst}.
I was born on {d.birthday:convDate(YYYY-MM-DD, LL)}.
My name is John.
I was born on Monday 31th 2000.
Formatters accept dynamic variables if parameters start with a .
and are not surrounded by quotation marks.
The following dataset is used in the examples below.
To do mathematical operations:
To insert parent attributes, 2 dots ..
have to be used. To access to grandparents attributes, 3 dots ...
are necessary, etc.:
To read parent objects and their children attributes (no limit in depth):
It returns an error if the attribute does not exist:
It returns an error:
It returns an error if the sub-array is not indexed:
People name | People age |
---|---|
People name | People age |
---|---|
To apply a formatter to data, use the separator :
. Multiple formatters can be used one after another. Each formatter input is the output of the previous one. Some formatters accept static or .
{d.myObject[i].att}
{d.myObject[i].val}
{d.myObject[i+1].att}
{d.myObject[i+1].val}
paul
10
jack
20
bob
30
Formatters can be chained with dynamic parameters to create complex operations, check out the example in Dynamic parameters.
converts from one currency to another
exchange rates are included by default
you can provide a new exchange rate for one report in options.currencyRates
of Carbone.render
or globally with Carbone.set
convCurr()
without parameters converts automatically from options.currencySource
to options.currencyTarget
rounds a number
same as toFixed()
but it rounds number correctly round(1.05, 1) = 1.1
formats number according to the locale
applying a number of decimals depends on the report type:
for ODS
/XLSX
, the number of decimals has to be formatted based on the text editor
for the other type of files, the number of decimals depends on the precision
parameter passed to the formatter
Adds 2 numbers.
Subtracts 2 numbers.
Multiplies 2 numbers.
Divides 2 numbers.
Converts a number to an INT.
Converts a number with English specifications (decimal separator is a dot .
).
Converts a number into string, keeping only decimals.
Converts a number with French specifications (decimal separator is a comma ,
).
Lower case all letters.
Upper case all letters.
Upper case first letter.
Upper case the first letter of all words.
"catch all formatter"
always returns the same message if called
converts user-defined enums to human readable values
user-defined enums must be passed in options
of carbone.render
Removes accents from text.
Renders carriage return \r
and line feed into documents instead of printing them as a string.
supported file formats: DOCX
, PDF
, ODT
, ODS
ODS
support is experimental
use the :convCRLF
formatter before :html
to convert to <br>
tags
example: {d.content:convCRLF:html}
Slices a string with a begin and an end.
Pads the string from the start with another string.
Pads the string from the end with another string.
Returns the length of a string or array.
Flattens an array of a string or a number.
counts and prints a row number of any array
usage example: d[i].id:count()
prints a counter of the current row no matter the value of id
internally replaced by :cumCount
An aggregate formatter calculates a set of values and returns a single value. For example, the average :aggAvg
takes a list of values and returns the average.
The following aggregators are available:
Aggregators can be printed as standalone expressions or can be part of loops to compute custom grouping clauses, e.g., sub-totals, cumulative totals.
No formatters can be chained after hideBegin
, hideEnd
, showBegin
, showEnd
.
Hide and show a part of the document with the following formatters:
hideBegin
/ hideEnd
: hide text block between hideBegin
and hideEnd
if condition is true.
showBegin
/ showEnd
: show a text block between showBegin and showEnd if condition is true.
ifEQ (value)
: Matches values that are equal to a specified value.
ifNE (value)
: Matches all values that are not equal to a specified value.
ifGT (value)
: Matches values that are greater than a specified value.
ifGTE (value)
: Matches values that are greater than or equal to a specified value.
ifLT (value)
: Matches values that are less than a specified value.
ifLTE (value)
: Matches values that are less than or equal to a specified value.
ifIN (value)
: Matches any of the values specified in an array or string.
ifNIN (value)
: Matches none of the values specified in an array or string
ifEM ()
: Matches empty values, string, arrays or objects.
ifNEM ()
: Matches not empty values, string, arrays or objects.
and (value)
: AND
operator between two consecutive conditional formatters.
or (value)
: (default) OR
operator between 2 consecutive conditional formatters.
show (message)
: print a message if a condition is true.
elseShow (message)
: print a message if a condition is false.
Data
one = { d.status1:ifEQ(2):show(two):or(.status1):ifEQ(1):show(one):elseShow(unknown) }
two = { d.status2:ifEQ(2):show(two):or(.status2):ifEQ(1):show(one):elseShow(unknown) }
three = { d.status3:ifEQ(2):show(two):or(.status3):ifEQ(1):show(one):elseShow(unknown) }
one = "one"
two = "two"
three = "unknown"
Supported file formats: DOCX
, ODT
, and PDF
.
when you use the drop
formatter, the tag value is not printed and chained formatters are not executed
use the drop
formatter to delete elements from a document. The first argument passed to :drop(argument1)
is the element to drop
p
to drop paragraphs
usage: {d.text:ifEM:drop(p)}
row
to drop table rows
usage: {d.data:ifEM:drop(row)}
Optionally, use nbrRowsToHide
to set the number of rows to drop as a second argument {d.data:ifEM:drop(row, nbrRowsToHide)}
, such as {d.data:ifEM:drop(row, 3)}
, meaning the current and next two rows is removed if the condition is validated.
By default, the formatter :drop(row)
hides only the current row.
img
to drop pictures
usage: {d.img:ifEM:drop(img)}
chart
to drop charts
usage: {d.dataset:ifEM:drop(chart)}
shape
to drop shape (square, circle, arrows, etc.)
usage: {d.dataset:ifEM:drop(chart)}
Shows a text block between showBegin
and showEnd
if a condition is true.
Use only break lines (shift
+ Enter
) between showBegin
and showEnd
.
Data
Banana{d.toBuy:ifEQ(true):showBegin} Apple Pineapple {d.toBuy:showEnd}grapes
Banana Apple Pineapple grapes
Hides a text block between hideBegin
and hideEnd
if a condition is true.
Data
Banana{d.toBuy:ifEQ(true):hideBegin} Apple Pineapple {d.toBuy:hideEnd}grapes
Banana grapes
Changes the default operator between conditional formatters.
{d.car:ifEQ('delorean'):and(.speed):ifGT(80):show('TravelInTime'):elseShow('StayHere')}
means "if d.car equals 'delorean' AND d.speed is greater than 80, then it prints 'TravelInTime', otherwise it prints 'StayHere'
Changes the default operator between conditional formatters.
{d.car:ifEQ('delorean'):or(.speed):ifGT(80):show('TravelInTime'):elseShow('StayHere')}
means "if d.car equals 'delorean' OR d.speed is greater than 80, then it prints 'TravelInTime', otherwise
it prints 'StayHere'
Matches empty values, string, arrays or objects (null, undefined, [], {}, ...).
Matches not empty values, string, arrays or objects.
matches all values that are equal to a specified value
can be combined with other formatters to create conditional content
returns the initial marker
the state of the condition is not returned
matches all values that are not equal to a specified value
can be combined with other formatters to create conditional content
returns the initial marker
the state of the condition is not returned
Matches values that are greater than a specified value.
Matches values that are greater than or equal to a specified value.
Matches values that are less than a specified value.
Matches values that are less than or equal to a specified value.
Matches any of the values specified in an array or string.
Matches none of the values specified in an array or string.
prints a message if the condition is true
use with other formatters to print conditional content
print a message if the condition is false
use with other formatters to print conditional content
To get the current date in UTC, use the marker {c.now}
in your template. The current date in UTC is returned only if the complement object option.complement
is not overwritten by custom data.
formats dates
takes an output date pattern as an argument
change the timezone
through the option options.timezone
and the lang
through options.lang
Formats intervals/duration.
human+
human
millisecond(s)
or ms
second(s)
or s
minute(s)
or m
hour(s)
or h
year(s)
or y
month(s)
or M
week(s)
or w
day(s)
or d
adds a time to a date
available units: day, week, month, quarter, year, hour, minute, second and millisecond
units are case insensitive, and support plural and short forms
subtracts a time to a date
available units: day, week, month, quarter, year, hour, minute, second and millisecond
units are case insensitive, and support plural and short forms
Creates a date and set it to the start of a unit of time.
Creates a date and set it to the end of a unit of time.
Because preferred formatting differs based on language, there are a few tokens that can be used to format a date based on report language.
There are upper and lower case variations on the same formats. The lowercase version is intended to be the shortened version of its uppercase counterpart.
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|---|---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
returns the sum of all values in a set.
returns the average of a set.
returns the minimum value in a set.
returns the maximum value in a set.
returns the number of items in a set.
the cumulative sums, also known as running totals, returns the total sum of data as it grows with series.
By default, condition formatters have a special behavior, the formatter's result is not propagated to the next formatter if the result of the condition is true. This enables test chaining with .
to drop a group of elements, use or
include the tag within a paragraph, and all the elements it comprises are also removed if the condition is validated ()
include the tag in a table row, and all the elements it comprises are also deleted if the condition is validated ()
include the tag within the image title, description, or alternative text ()
include the tag within the alternative text of the graphic ()
include the tag within the title, description or alternative text of the shape ()
Learn more about why .
Use only break lines (shift
+ Enter
) between hideBegin
and hideEnd
. Learn more about why .
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
date patterns are available in
(Wikipedia)
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
params | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Parameters | Description | Type |
---|
Format | Output | Description |
---|
Format | English locale | Sample output |
---|
target
[optional] convert to this currency ('EUR')
by default it equals options.currencyTarget
string
source
[optional] currency of source data ('USD')
by default it equals options.currencySource
string
precision
number of decimal
number
precision
[optional] number of decimals
number
precisionOrFormat
[optional] number of decimal, or specific format
integer : change default precision of the currency
M : print major currency name without the number
L : prints number with currency symbol (by default)
LL : prints number with major currency name
number
message
text to print
string
type
enum name passed in options
of carbone.render(data, options)
string
begin
Zero-based index at which to begin extraction.
integer
end
Zero-based index before which to end extraction
integer
targetLength
The length of the resulting string once the string has been padded. If the value is less than string length, then string is returned as-is.
number
padString
The string to pad the current str with. If padString is too long to stay within the targetLength, it will be truncated from the end. The default value is " "
string
targetLength
The length of the resulting string once the string has been padded. If the value is less than string length, then string is returned as-is.
number
padString
The string to pad the current str with. If padString is too long to stay within the targetLength, it will be truncated from the end. The default value is " "
string
separator | [optional] item separator ( | string |
objSeparator |
| string |
attributeSeparator |
| string |
attributes | [optional] list of object's attributes to print | string |
start | number to start with (default: 1) | string |
value | [optional] new value to test | mixed |
value | [optional] new value to test | mixed |
value | value to test | string, integer |
value | value to test | string, integer |
value | value to test | integer |
value | value to test | integer |
value | value to test | integer |
value | value to test | integer |
value | value to test | integer |
value | value to test | integer |
message | message to print |
message | message to print |
patternOut | output format | string |
patternIn |
| string |
patternOut | output format: human, human+, milliseconds, seconds,... | string |
patternIn | [optional] input unit: milliseconds, seconds,... | string |
amount | the amount | number |
unit | the unit | string |
patternIn |
| string |
amount | the amount | number |
unit | the unit | string |
patternIn |
| string |
unit | the unit | string |
patternIn |
| string |
unit | the unit | string |
patternIn |
| string |
patternIn | input format | string |
patternOut | output format | string |
| 1360013296 | Unix Timestamp |
| 1360013296123 | Unix Millisecond Timestamp |
| 18 | Two-digit year |
| 2018 | Four-digit year |
| 1-12 | The month, beginning at 1 |
| 01-12 | The month, 2-digits |
| Jan-Dec | The abbreviated month name |
| January-December | The full month name |
| 1-31 | The day of the month |
| 01-31 | The day of the month, 2-digits |
| 0-6 | The day of the week, with Sunday as 0 |
| Su-Sa | The min name of the day of the week |
| Sun-Sat | The short name of the day of the week |
| Sunday-Saturday | The name of the day of the week |
| 0-23 | The hour |
| 00-23 | The hour, 2-digits |
| 1-12 | The hour, 12-hour clock |
| 01-12 | The hour, 12-hour clock, 2-digits |
| 0-59 | The minute |
| 00-59 | The minute, 2-digits |
| 0-59 | The second |
| 00-59 | The second, 2-digits |
| 000-999 | The millisecond, 3-digits |
| +05:00 | The offset from UTC, ±HH:mm |
| +0500 | The offset from UTC, ±HHmm |
| AM PM |
| am pm |
| h:mm A | 8:02 PM |
| h:mm:ss A | 8:02:18 PM |
| MM/DD/YYYY | 08/16/2018 |
| MMMM D, YYYY | August 16, 2018 |
| MMMM D, YYYY h:mm A | August 16, 2018 8:02 PM |
| dddd, MMMM D, YYYY h:mm A | Thursday, August 16, 2018 8:02 PM |
| M/D/YYYY | 8/16/2018 |
| MMM D, YYYY | Aug 16, 2018 |
| MMM D, YYYY h:mm A | Aug 16, 2018 8:02 PM |
| ddd, MMM D, YYYY h:mm A | Thu, Aug 16, 2018 8:02 PM |
Returns the maximum value in a set.
Maximum quantity:
{d.cars[].qty:aggMax}
Maximum quantity by sorting "sort" values above 1:
{d.cars[sort>1].qty:aggMax}
Maximum quantity by multiplying the "qty" by the "sort" attribute:
{d.cars[sort>1].qty:mul(.sort):aggMax:formatC}
Maximum quantity:
10
Maximum quantity by sorting "sort" values above 1:
10
Maximum quantity by multiplying the "qty" by the "sort" attribute:
50
Returns the sum of all values in a set.
Data
Total:
{d.cars[].qty:aggSum}
Total by sorting "sort" values above 1:
{d.cars[sort>1].qty:aggSum}
Total by multiplying the "qty" by the "sort" attribute:
{d.cars[sort>1].qty:mul(.sort):aggSum:formatC}
Total:
21
Total by sorting "sort" values above 1:
19
Total by multiplying the "qty" by the "sort" attribute:
81
The aggSum
aggregator can be used within loops, for instance:
sum-up people's salaries by departments:
{d.departments[i].people[].salary:aggSum}
{d.departments[i].people[].salary:aggSum(.i)}
(alternative)
global sum of all departments, all people's salary:
{d.departments[i].people[i].salary:aggSum}
{d.departments[i].people[i].salary:aggSum(0)}
(alternative)
Change the partition with dynamic parameters:
sum salaries by people by age, regardless of departments
{d.departments[i].people[i].salary:aggSum(.age)}
sum salaries by people by age and gender, regardless of departments
{d.departments[i].people[i].salary:aggSum(.age, .gender)}
Returns the average of a set.
Average quantity:
{d.cars[].qty:aggAvg}
Average quantity by sorting "sort" values above 1:
{d.cars[sort>1].qty:aggAvg}
Average quantity by multiplying the "qty" by the "sort" attribute:
{d.cars[sort>1].qty:mul(.sort):aggAvg:formatC}
Average quantity:
3.5
Average quantity by sorting "sort" values above 1:
4.75
Average quantity by multiplying the "qty" by the "sort" attribute:
13.50
Returns the total sum of data as it grows with series.
The cumulative total of salaries by departments:
{d.departments[i].people[].salary:cumSum}
{d.departments[i+1]}
The cumulative total of salaries by departments and by people:
{d.departments[i].people[i].salary:cumSum}
{d.departments[i+1].people[i+1]}
The cumulative total of salaries by departments: 1000 1700 3200 3400
The cumulative total of salaries by departments and by people: 1000 1500 1700 3200 3400
Returns the number of items in a set.
Count quantity items:
{d.cars[].qty:aggCount}
Count quantity items by sorting "sort" values above 1:
{d.cars[sort>1].qty:aggCount}
Count quantity items by multiplying the "qty" by the "sort" attribute:
{d.cars[sort>1].qty:mul(.sort):aggCount:formatC}
Count quantity items:
10
Count quantity items by sorting "sort" values above 1:
10
Count quantity items by multiplying the "qty" by the "sort" attribute:
50
Create pie charts in ODT documents in LibreOffice
The dataset below is used in a chart that represents the quantity of cheese purchased by french households in 2019.
Group values by cheese types using the following dataset:
ODT
template in LibreOfficeClick the Home tab > Chart button. A column chart appears. Change the chart format by clicking the chart type button from the chart toolbar.
Insert the data dynamically using a loop
and the bindChart
formatter: Click Data Table from the chart toolbar. A popup appears to edit chart values.
The following is not different than Microsoft Word. It's not possible to insert tag {d.value}
inside table cells, except in the first column Categories
.
So you write the category name, then add bindChart
tags. The {bindChart}
formatter is used to bind a variable to a reference tag in the table cell, i.e., "the value X
in the chart must be replaced by the tag Y
."
jn the first cell, the following expression is written: {d.cheeses[i].type} {bindChart(3)=d.cheeses[i].purchasedTonnes}
the cheese type is printed with {d.cheeses[i].type}
, then bindChart
is used to bind the variable d.cheeses[i].purchasedTonnes
to the cell that has the value 3
this means: the purchasedTonnes
value is printed instead of 3
in the first cell of the second row, the expression {d.cheeses[i+1].type} {bindChart(4)=d.cheeses[i+1].purchasedTonnes}
is written
the bindChart
replaces the 4
value by the d.cheeses[i+1].purchasedTonnes
variable
Generate the PDF
report, and the pie chart is automatically filled.
Native charts define how to create graphical visualizations from numerical data within your text editor. The format defines:
the dataset to be used for the visual display and
several different types of graphical displays
such as line charts, pie charts, etc.
The following 2 docs contain examples how to create a pie chart within an ODT
document and a line chart within a DOCX
/PDF
document, respectively:
learn more in Create dynamic reports in LibreOffice
Provide the chart configuration within a JSON dataset. The dataset should include:
the chart format
numerical values
extra options
After configuring, the chart is injected as an SVG
image into the document. Refer to the Apache ECharts library for more details.
supported file formats: PDF
, ODT
, ODS
, ODP
, ODG
, DOCX
, XLSX
In a template, insert a picture as a reference slot.
Place a tag in the alternative text of the picture {d.chartOptions:chart}
with the formatter :chart
. Without :chart
, the attribute {d.chartOptions}
is considered as an image.
Design your JSON dataset by adding an object named chartOptions
. The object must contain ECharts options and your data.
Use the following configuration for a line chart:
Generate the PDF
report.
Build any type of chart, following the documentation below:
supported file formats: DOCX
, ODT
, PDF
. DOCX
/ODT
templates can generate DOCX
/ODT
/PDF
documents
create charts only from your text editor (Microsoft Word or LibreOffice); insert the data series in the XLSX
/ODS
sheet provided by your text editor
charts cannot be copy-pasted from an external XLSX
/ODS
file
external spreadsheets cannot be linked as dynamic series of data
in LibreOffice, the {bindChart()}
tag is required
chart styling (titles, colors, captions, etc.) can only be defined within the text editor
styling from a JSON dataset cannot be edited, unlike ECharts 5 charts
Format | Types | Supported |
---|---|---|
Format | Types | Supported |
---|---|---|
ODT
to DOCX
/ODT
/PDF
or ODS
to XLSX
/ODS
/PDF
DOCX
to DOCX
/ODT
/PDF
or XLSX
to XLSX
/ODS
/PDF
with the option "hardRefresh": true
, such as { "convertTo": "docx", "hardRefresh": true }
DOCX
to DOCX
or XLSX
to XLSX
without the option "hardRefresh": true
translations are supported: cs
, de
, en
, es
, fi
, fr
, it
, ja
, ko
, pl
, pt-br
, ro
, ru
, si
, th
, zh
chart configuration doesn't support external dependencies (maps, JS scripts)
chart styling (titles, colors, captions, etc.) can only be defined within the JSON dataset
the generated chart is an image, so it's not possible to edit the styling within the template, unlike Native charts
2D/3D Column
clustured
, stacked
, percent stacked
2D/3D Bar
clustured
, stacked
, percent stacked
2D/3D Line
line
, stacked
, percent stacked
, line with markers
, stacked line with markers
, percent stacked line with markers
2D/3D Area
area
, stacked
, percent stacked
2D/3D Pie
pie
2D/3D Pie
pie of pie
, bar of pie
Doughtnut
Doughtnut
Combo
Clustured Column/Line
, Stacked Area
Hierarchi
sunburst chart
, treemap chart
Statistical
histogram
, box and whisker
Waterfall
waterfall
, funnel
, stock
, surface
, radar
Scatter
scatter
, bubbles
Map
Map
Column
normal
, stacked
, percent stacked
Bar
normal
, stacked
, percent stacked
Pie
normal
, exploded
, donut
, exploded donut
Area
normal
, stacked
, percent stacked
Line
point only
, points and lines
, lines only
, 3D Lines
Scatter
point only
, points and lines
, lines only
, 3D Lines
Net
point only
, points and lines
, lines only
, Filled
Column and Line
normal
, stacked
Stock
1
, 2
, 3
, 4
Bubble
normal
Apply colors dynamically on elements with the bindColor
marker.
The bindColor
marker is supported on:
text and background colors
table cells background
shapes backgrounds and lines colors for DOCX
files only
Shapes background and lines colors in DOCX
write the bindColor
marker in the document body, not in the alternative text of shapes
the replaced color format must be solely RGB
A bindColor
marker replaces a color reference on the template with a new color coming from your JSON dataset in Ninox.
myColorToBind
a temporary hexadecimal color applied to a text, background or a cell background
used to identify the color to replace
the hexadecimal is case insensitive and the hashtag at the beginning is optional
myFormat
the new color format expected from the marker myVar
myVar
The marker that corresponds to the new color.
Each line in a table can be colorized by one color:
first line: get #0000FF
color
second line: get #00FFFF
color
each line: get the color corresponding to the color key in each user object
The first line get the #0000FF
color and the second line get the #00FFFF
color. Each line get the color corresponding to the color key in each user object.
In Microsoft Word, only a color name can be used to replace the background color of a text. Learn more about the .
available
If a dynamic hyperlink or a HTML anchor tag is injected into a report and the URL verification fails, the formatter :defaultURL
can be used to replace the default error URL.
If the provided URL is not valid, it is replaced by https://carbone.io/documentation.html#hyperlink-validation
.
When inserting dynamic hyperlinks, chain the :defaultURL
formatter to the marker, such as:
It is possible to pass another marker as an argument:
When using the :html
formatter, place the :defaultURL
before:
In Microsoft Word, only a color name can be used to replace the background color of a text.
You can still use hexadecimal colors for the text and cells backgrounds in Microsoft Word.
Microsoft
: get the red
background color
Word
: get the magenta
background color
the background: get the #FFFF00
background color
Hyperlinks can be applied dynamically to elements (texts, images, tables, list) for DOCX
, ODT
, ODS
, and XLSX
documents. Right-click the element and select "hyperlinks" to insert the marker.
example: reduce {d.url}
to d.url
; if http://
appears before d.url
, the hyperlink works
Before injecting hyperlinks dynamically on reports, the URL is verified whether it has a valid format.
If the provided URL is not valid, it is replaced by https://carbone.io/documentation.html#hyperlink-validation
.
expected behavior: text editor automatically replaces curly braces with special characters: %256B
a static URL and a URL coming from a marker, e.g., https://carbone.io{d.url}
, cannot be inserted together
https://carbone.io
is removed automatically and only {d.url}
is kept
do not write the marker with curly braces in XLSX
files
required: a root domain of length between 2 and 256
required: a top level domain like .com
, .org
, .fr
, or other
optional: a protocol, either http://
or https://
. If it doesn't exist the protocol https://
is added
The following dataset is used in the example below that shows how to insert a picture into an ODT
report.
Insert a temporary picture in the template.
Write the marker {d.logo}
in the alternative text of the picture.
To access the alternative text on LibreOffice: Right-click the Image > Format... > Text Alternative.
This replaces the temporary picture by the one linked in the "logo" data. After the document is rendered, the new image from the URL appears on the report. It is also possible to display a list of pictures by writing a loop.
For this example, we set up a database in Ninox that contains a table like the one shown below. The flag preview is optional and is for illustration purposes.
[i+1]
on the second pictureThen, save the ODT
report in LibreOffice.
Click the plus icon to create a new layout. Select Dynamic, then click the Import icon. Select the ODT
report (here: Flag images report.odt
). Once the file is uploaded, click the Create button.
On the right side, toggle Custom JSON on. Then click the formula field under JSON data input. The formula editor opens.
Paste the #data, then click the Save button.
PDF
reportClick the Print icon and select This record to download a PDF
preview.
After the document is rendered, the list of images appears on the PDF
report:
The following dataset is used in the example below that shows how to insert a picture into an ODS
report.
Insert a temporary picture in the template.
Write the marker {d.frenchFlagImage}
in the title picture property.
To access to the title on LibreOffice: Click the Image > Format... > Description > Title.
After the document is rendered, the new image from the data URI appears on the report.
This feature may not work at the time of release. Use in the meantime. We will update this page once it becomes available.
Before continuing, check out this documentation to learn more about .
This feature works with ODT
, ODS
, ODP
, ODG
, XLSX
, and DOCX
files.
If an error occurs for some reasons (fetch failed, image type not supported), a replacement error image is used.
The place to insert the marker on the temporary picture may change depends on the file format:
ODS
, ODP
and ODG
files: set the marker on the image title
ODT
file: set the marker on the image alternative text, image description
DOCX
and XLSX
files: set the marker either on the image title, image description, or alternative text
Accepted images types: .jpeg
, .png
, and .gif
. .svg
are working only for ODS
/ODT
reports.
it is not possible to create images loops in XLSX
, ODS
, and ODG
files, it produces an invalid report
for ODP
, it is not possible to create a loop of images inside a single slide, but it is possible to create images loops through 2 slides or more
The image anchor type changes the rendering behavior and particular cases are not valid.
To update the anchor type of an image on LibreOffice: Right-click the Image > Properties > Type > Anchor.
To update the position type of an image on Word: Double-left-click the Image > Picture Format tab > Position.
imageFit
formatterThis formatter works with ODT
and DOCX
files.
The imageFit
formatter sets how the image should be resized to fit its container. An argument has to be passed to the formatter:
fillWidth
: the replaced image is sized to fill the element’s content-box width
the aspect ratio does not change
contain
: the replaced image is scaled to maintain its aspect ratio while fitting within the element’s content-box (the temporary image)
fill
: the replaced image is sized to fill the element’s content-box (the temporary image)
the entire image will fill the box of the previous image
if the object's aspect ratio does not match the aspect ratio of its box, then the object will be stretched to fit
It is possible to provide a picture directly in the data field as a Base64 Data URIs like the example below.
In the data field, the first part of the Data URIs data:image/jpeg;base64
, has to be removed. Add the $
prefix in the data field.
Insert a temporary picture in the template.
Write the marker {d.dog}
in the alternative text of the picture.
To access the alternative text on LibreOffice: Right-click the Image > Format... > Text Alternative.
Base64 images can only be set only at the root of a JSON object, not in an array nor in a child object.
Anchor type | Print engine behavior |
---|---|
Position type | Print engine behavior |
---|---|
This feature may not work at the time of release. Use in the meantime. We will update this page once it becomes available.
As character
Best choice: the replacement of a single image or a loop of images is possible.
To page To paragraph To character
The image is floating, it not possible to create a loop of images, only a single image replacement is accepted.
In line with text
Best choice: the replacement of a single image or a loop of images is possible.
With text wrapping
The image is floating, it not possible to create a loop of images, only a single image replacement is accepted.
The following pages provide an introduction to writing scripts with Ninox
The Ninox script language (also "NX script language" or "NX script") is designed to automate simple, repetitive operations, as well as complex work sequences, to provide optimal support for your workflows.
We don't distinguish between functions and procedures in the following.
A function returns a specific result based on values of parameters.
A procedure executes a series of successive individual actions.
Ready? Let's go...
The :html
formatter renders HTML content on DOCX
, ODT
and PDF
documents.
Unsupported tags, attributes and styles are skipped and not rendered.
<br>
<b>
<strong>
<i>
<em>
<u>
<s>
<p>
<a href="URL">
<ol>
<ul>
<li>
<del>
<img>
<a href="URL">
When included, the URL format needs to be verified before injecting it into the document. Learn more about #hyperlink-validation.
If a font family or/and a font size is applied on a HTML marker, the content is rendered with the same font properties. Text alignment on the rendered HTML content is not kept.
When the HTML marker is placed inside a paragraph and mixed with other content, the content is pushed in a new paragraph above or below the rendered HTML, refer to Example 2.
To render HTML lists, such as <ol>/<li>
or <ul>/<li>
, create a bullet list on the template then delete it, then the generated report will render the list.
<img>
The image source attribute can be an URL or Data-URL, such as <img src="https://carbone.io/img/favicon.png"/>
or <img src="data:image/jpeg;base64,/9j...."/>
The image size is rendered based on width
and height
attributes provided by the HTML tag, such as <img src="" width="300" height="100"/>
.
values must be pixels
if width
or height
attributes are missing, the size of 5 cm (1.96 in) is applied by default while retaining the image aspect ratio
Find answers to frequently asked questions and known issues for printing dynamic layouts
This may be happening when unsupported characters are used or when Ninox field names and template variables do not match.
Tips for naming Ninox fields
Use CamelCase and underscore _
to write field names in a template. Any other characters and white spaces are not supported.
The text editor you're using may replace quotation marks with ones that cannot be interpreted.
Tips for using quotation marks
showBegin
/hideBegin
) When using conditional formatters showBegin
/showEnd
or hideBegin
/hideEnd
, insert only break lines (shift
+ Enter
).
Break line: The new line is part of the current paragraph by hitting shift
+ Enter
. Behind the scenes, the XML doesn't need to reordered because everything is in the same paragraph.
New line: Close the current paragraph and open a new one, the standard "command" is the Enter
key. Creating a new paragraph automatically inserts a new line. The XML designing the document is getting complex and XML parts have to moved and reordered, which may leave some additional lines on the final report.
This is where you do magic... uh... script
The input of functions or procedures is done via the formula editor in a formula field (always indicated by fx).
These fields are the "entrance" to the formula editor. We collected a few examples for you below.
To use the right quotation marks, perform the following manipulation and use only simple quotation marks ().
Use when you conditionally delete paragraphs, table rows, images, charts or shapes. New lines/break lines are not expected to present any issues in that case.
An overview of all basic features the formula editor offers as of version 3.6.0
At the moment, the new formula editor features are available for the web app (app.ninox.com) as well as the Mac app.
Line numbers are displayed in the left margin of the formula editor window.
Line numbers are always visible by default.
Indents a code block automatically.
Takes your code and prettifies it to conform to a consistent style. Wraps code and adds or removes white space when necessary.
Access the formula editor to format existing code, click OK to leave the editor. The next time you open the formula editor again, this code appears newly formatted.
While you type, a pop-up appears next to the cursor displaying suggestions to complete your script.
To select the first option from the list, press the ENTER
key.
To select another option, use the arrow keys, then confirm your selection with the ENTER
key.
While you type, text is highlighted in different colors.
To trigger syntax highlighting, type an expression.
The current location of the written code is displayed above the formula editor's contents.
The location is displayed automatically.
Displays errors and warnings while you script and suggest corrections.
While you type, gutter line numbers with erroneous code are highlighted and the code itself is underlined in red. To reveal the error message, hover above the line number.
When you make a syntax error, the formula editor only highlights the first error, even when more syntax error follow that first one. This happens because the following script cannot be parsed due to the preceding syntax error. When you make a reference error, the formula editor highlights each error independently of its position in the script. So, when a syntax error precedes a reference error, only the foregoing syntax error is highlighted.
Search and replace text, variables, and expressions within a code block. Works for
Match Whole Word
,
Match Case
, and
Use Regular Expression
.
To search, enter text in the search bar or press CMD+F
(macOS) or Ctrl+F
(Windows).
Highlights corresponding parentheses and automatically completes open parentheses.
To visually locate a parenthesis' match, use the arrow keys to select a parenthesis and highlight its counterpart.
To auto-complete parentheses, type an opening parenthesis.
Create simple arithmetic operations
These operators let you take 2 numeric values, perform a calculation, and return a numeric value. This is mainly about basic arithmetic operations.
Ninox removes
superfluous parentheses—following the precedence rule "first the division, then the addition")—and
superfluous white spaces.
However, Ninox also adds white spaces where they are deemed useful, e.g., for better readability).
Syntax | Color |
---|---|
Operator | Description | Example |
---|
| Addition (also for joining text) |
|
| Subtraction |
|
| Multiplication |
|
| Division |
|
| Modulo |
|
| Parentheses (to change the order in which expressions are processed) |
|
String (text)
Keyword
Function
Built-in value
Variable/Table/Field
Operator
Number
Data type
The most important operators for writing scripts
Two values are compared with each other
This allows you to compare 2 numeric values. The operators return a result that is either true or false. The output in the Ninox field is Yes (true
) or No (false
).
Operator | Description | Examples |
---|
Operator | Description | Examples |
---|
| A "defined as equal to" operator assigns a value to a field or variable. |
|
| A semicolon ends a line. If you define variables (with |
|
| Double quotes highlight text, i.e., everything inside should be used as normal text. |
|
| Single quotes enclose table or field names that contain spaces or special characters so that Ninox detects they belong together. |
=> 425,00 € (VAT not included) Note: |
| A dot lets you access fields of records or values of JSON objects. | For example, access all customer IDs in the Customers table with ( |
| An alternative to double quotes (see above) is a 3 minus sign to help make dynamic text more clear. |
|
| equal |
| not equal |
| less than |
| less than or equal to |
| greater than |
| greater than or equal to |
| contains |
1 + 1 = 3 - 1
Apples = Pears
Apples != Pears
1 + 1 != 3 - 1
4 * 2 < 10
10 < 4 * 2
5 * 2 <= 10
10 <= 4 * 2
10 > 4 * 2
4 * 2 > 10
5 * 2 >= 10
4 * 2 >= 10
"Hello" like "el"
"el" like "Hello"
Make texts dynamic via a script
To make texts dynamic using a script, you have 2 options:
Connect simple strings and fields with the plus operator +
.
Template strings with values inside braces {...}
.
Concatenate simple strings with the +
operator. Use +
to include any data type, e.g., numbers.
At least one of the data types must be a string, so that the output is also a string.
In a table, create a First Name field and paste the following content into a formula field.
Result: Hello Sam! (if the First name field contains the value Sam)
Template strings are indicated by a 3 minus signs ---
at the beginning and end. Everything in between turns into text.
Put braces {...}
around scripts, e.g., to write a serial letter that fetches the relevant data, such as first and last name, address, etc., from a table.
Same as above, but with a template string.
Result: Hello Sam! (if the First name field contains the value Sam)
The name of the variable must not be a keyword. For example, let let
is not allowed.
You can use var
instead of let
to declare a variable. We recommend using let
as var
is a bit outdated.
To personalize texts, for example, send a letter that looks basically the same as an invoice to many recipients with the respective other data, this is easier to do with dynamic texts (see ).
if ... then ... else ... end
Use if ... then ... else ... end
to specify an if-then-else conditional statement that has Ninox check whether a sequence of statements should be executed (if... then...) or what should happen when the input condition is not met (... else...).
The if statement must be an expression that is either true
/yes or false
/no.
The use of comparison operators, such as greater than (>=
), less than (<=
) or equal to (=
) is also suitable for this purpose.
Depending on the result of the comparison, the further procedure is determined.
Create a Total field (number field type), type the following script in a formula field, and vary the value to Total:
Result: If the entered value in the Total field is greater than or equal to €30, payment is made by Card, otherwise payment is made in Cash.
You don't need to specify an alternative sequence, e.g., an else
. This means that a statement is either executed or not.
Result: paymentMethod
is set to Cash by default. However, if the value in the Total number field is greater than €30, the value for paymentMethod
is updated to Card.
Use null
to check whether a data field is empty. So null
does not stand for 0, but for empty. Combined with a branch, it allows you to execute a script even when a field is empty.
Result: If the Total field is empty, a prompt ("Please enter an amount!"
) is displayed.
select ... where
select
lets you access any record of any table within a database using a script. Enter the name of the table from which you want to pull records after the select
command.
Insert the following script in the options of an embedded table view under Formula to display all the records of the Customers (New) table.
Result: All records of the Customers (new) table are displayed in an embedded table.
To avoid displaying all records of a table, limit the selection with select ... where
. Then only the records are displayed which fulfill the condition after where
.
In the Customers table, a choice field Headquarter is available, in which the IDs of the choice values are assigned as
1
= Germany
2
= Austria
3
= Switzerland
4
= France
5
= Spain
6
= Italy
and you'd like to display only the DACH region, i.e., Germany, Austria, and Switzerland.
Result: In an embedded table the records of the table Customers (new) are displayed, which have their company headquarters in 1
(Germany), 2
(Austria), or 3
(Switzerland).
In case you use special characters in a field or table name, e.g., white space, hyphen, underscore etc., put the name between 2 single quotes ('...')
.
... where
You may further filter already selected records, i.e., an array of type [nid
], by specifying the condition to filter by in brackets [...]
after the array.
In contrast to select ... where
, all records are selected first and then filtered. With select ... where
only the records that meet the conditions are selected.
Do you want to dive deeper into the topic? Take a look at the corresponding part of our video tutorial.
Given the amount of data that needs to be processed and the related processing time (performance), we recommend using ...where
since it's faster.
create | delete
To create a record in a specific table by script, specify the corresponding table name in a button after create
.
Result: A new, but empty record in the Customers table.
To fill this new record with data, first store the expression in a variable and then use the variable to access the desired fields.
Initialize the variable newCustomer
with the expression create Customer
to store the record in the variable.
Access the fields of the new record using the dot operator .
and give the new record a unique Customer number consisting of the letter C
and a UNIX timestamp.
Result: A new record in the Customers table with a unique customer number.
Delete records automatically by specifying which records to delete after delete
.
Insert the following script in a button to delete the current record.
This is useful for linking the deletion process to another action, such as triggering an email before the record is removed.
Result: The current record is deleted.
To delete several records, combine delete
with select
.
Result: All records in the Customers table with the status 4
are deleted.
The Ninox 3.11 release introduces "Creatable if" and "Deletable if"—set conditions for record creation and deletion with the formula editor
Creatable if and Deletable if are available for all apps (web app, iPhone/iPad, Mac, Android).
Conditional data management
Creatable if allows for record creation only under specific conditions, for more control over when data is generated.
Deletable if blocks records from being deleted by mistake or without authorization, which safeguards data integrity.
Enhanced compliance
Admins can apply rules that restrict certain actions, such as deleting sent invoices, to ensure adherence to policies.
Increased data efficiency
Admins can manage the life cycle of records, which avoids creating unnecessary or duplicate entries. This makes data handling more efficient.
Greater control in user workflows
Users can only create or delete records under specific conditions or through designated actions, which provides tighter oversight of user activities.
Easier workflow automation
Parts of the workflow, like creating or removing records automatically when certain criteria are met, are streamlined for efficiency.
The features Creatable if and Deletable if offer a nuanced approach to managing data within the formula editor. This is in contrast with the pre-existing methods of create records and delete records, where you only select a user role from a dropdown menu.
While the latter work as a shortcut to manage creation and deletion based on user roles, Creatable if and Deletable if let you specify more precise conditions in the formula editor.
Start by creating a new database:
Go to your workspace and click the New database tile.
Select a database template:
Choose the Offers and invoices template from the list.
Access your database:
Once the database is created, open the Offers and invoices database.
Navigate to the Invoices table:
Within your database, find and click the Invoices table.
Edit fields:
Set permissions:
In the settings pop-up, click Creatable if or Deletable if (3) to define conditions.
Configure conditions:
Use the formula editor that opens to set up your conditions as per the examples provided.
In the formula editor, type userHasRole("Supervisor")
. This means only users with the Supervisor role can create records.
Click Save to close the formula editor.
Click Save in the table settings to apply changes.
To test, attempt to create a record by clicking the plus icon. If unauthorized, a message saying You are not authorized for this action will appear.
In the formula editor, type Status = 1
. This means records with the status Open can be deleted.
Click Save to close the formula editor.
Click Save in the table settings to apply changes.
To test, attempt to delete a record not marked as Open by clicking the trash icon. Upon confirmation, if unauthorized, a message saying You are not authorized for this action will appear.
In , the functions isAdminMode()
, clientLang()
, and userLang()
are mainly for client-side use. When used with Creatable if and Deletable if features, they give false results because they rely on client-side data, which is not available for server-side processes.
Click on the gear icon erscheint, then choose Edit fields (2) to modify table settings.
if ... then ... else if | switch ... case
Create multiple conditional statements by concatenating if-then-else blocks. Write another if
after else
for another condition and so on—continue for as long as needed.
As in the previous example, use the Total number field again and insert the following script into a Formula field:
Result: In the function field you will receive the response "Cash"
, "Card"
, or "Please enter an amount!"
according to the input.
Replace multiple nested conditional statements with switch ... case
. Use this statement to query an expression (switch ...
) for possible results (case ...:
) and set a default behavior (default:
) if the expression does not correspond to any of the results.
Depending on the result, assign the next step accordingly. This helps avoid deeply nested if statements.
Tip: switch ... case
works best when the queried value is a choice field.
There's a choice field Payment method with the following options:
Cash
Bank transfer
Direct debit
Insert the following script into a formula field to display info about the selected payment type:
Result: Based on your entry in the Payment method choice field, exactly one of the following info is visible in your formula field:
Payment method: Cash
Payment method: Bank transfer. Only from €30.
Payment method: Direct debit. Do not forget your signature.
Please select a payment method.
Do you want to dive deeper into the if ... then ... else
topic? Take a look at the corresponding part of our video tutorial.
Do you want to dive deeper into the switch
topic? Take a look at the corresponding part of our video tutorial.
order by
Use order by
to sort an array of records by a specific field. This is useful when sorting an array first before processing it further.
When you use order by
in a View layout item, it is first sorted by a (selected) column header and second by the value specified after order by
.
order by
works best when you sort records by a number.
Result: The entries of the Invoices table are sorted by the Total field (from small to large).
Restrict the selection of records with where
or brackets [...]
.
The value after order by
does not necessarily have to be a field name, it can also be manipulated by functions, for example.
Result: The entries with today's date of the Invoices table are sorted by the number in the Invoice no. text field.
3
refers to the position of the number within the invoice no., which in our case, for example, starts with the 4th position: NO-12574
(0
=N
, 1
= O
, 2
=-
, 3
= 1
(the first number)).
Order by
works best when you sort records by a number.
Be careful when sorting strings. Strings are not sorted alphabetically, but according to the index of the characters. So first all upper case letters are sorted alphabetically, then the lower case letters.
ABcD is thus sorted to ABDc. To get the desired result, simply unify the values by upper()
or lower()
. Then all initial letters are first set to upper case or lower case respectively.
Result: ABcD
Alternative: Use the Ninox function sort()
instead of order by
.
You have a table Example for order by with a First name field. It contains the following records: Aaron, Eddi, conrad, beate, Dahlia, and Fatima. Insert the following script into a formula field.
Result: Aaron, Dahlia, Eddi, Fatima, beate, conrad
This is not the desired alphabetical sorting...
We add upper()
, which sets all entries to upper case for sorting.
If you only need the list of names and not the records themselves, we recommend using sort()
:
Result: Aaron, beate, conrad, Dahlia, Eddi, Fatima
do as transaction ... end | do as server ... end | do as deferred ... end
Ninox executes scripts in a perpetual exchange between the browser or app and the server. Usually, this works fine because the exchange is fast enough to process a script quickly.
However, in some cases you may further optimize the performance of your scripts by placing instructions in special code blocks.
To ensure scripts are executed within the same transaction, it's best to use do as transaction
.
do as transaction
was developed specifically for mobile apps (iPhone, iPad, Android) and desktop app (Mac) to process scripts locally. For example, when the internet connection is interrupted.
When use do as transaction
in the web app, the script is always executed on the server.
The nesting of loop and select
commands is usually very performance-heavy, so we recommend wrapping such scripts in a do as transaction
block to speed up the process.
If there are any issues executing the script for whatever reason, the transaction is discarded, i.e., a transaction is either executed completely or not at all.
Let's assign a Contact from the Contacts table a matching ID to the Contact field in each record of the Companies table. The entire process is executed within do as transaction
.
Result: All records in the Companies table are linked to an entry from the Contacts table within one transaction.
Occasionally, it may be beneficial to fully execute a portion of your script on the server first, before sending it back to your computer or app.
We don't recommend using do as server
in triggers because triggers in a browser are always executed on the server as well as locally in the app. Rather use do as server
in buttons.
do as server
is most often used in conjunction with the http()
function to execute API calls server-side first. This bypasses the browser's CORS (cross-origin resource sharing) policy, which would otherwise block the http
call. Then you receive the requested data from the server.
Some functions cannot be executed on the server because they are related to your browser or app, e.g., alert()
.
Let's get some data from a table in a database. First, you send a GET
request to the respective database. Using the dot operator .
, access the values of the response
.
Result: The result
value of the response
is returned, which in this case consists of only one record and the information contained in the individual fields.
Normally Ninox executes write transactions in sequence.
Some of these write transactions may take more time, causing subsequent transactions to wait a bit. This may cause Ninox to slow down unintentionally.
Use the do as deferred
statement to ensure read transactions within a write transaction are split off into a separate (read) transaction—all of which can be executed in the background.
When you modify data in a large table, this may take several seconds instead of a few milliseconds. Downstream statements then have to wait until all data is completely modified.
do as deferred
speeds up the processing of statements because statements that occur between do as deferred
and end
are processed separately and thus do not interfere with other processes.
Optimize a status change with a resulting triggered email as follows.
Set a field Status = 3
. This causes the trigger stored in the Status field to trigger after change the following instructions (see code block):
The field sent on is set to today's date.
An email with a payment request is sent. This is executed separately.
Result: All records whose status is set to 3
have today's date stored in the Sent On field. In a detached transaction, an email requesting payment is also sent to all records with the status 3
.
for ... in ... do ... end | for ... from ... to ... do ... end | while ... do ... end
Loops allow you to automatically execute a code block multiple numbers of times in succession. For example, apply the statements of a code block to each element of an array.
One of the most important loops you need to know about—it'll be very helpful when writing your scripts.
After for
, select the corresponding variable name for the item in the list that you want to change.
for
loop is structured as follows:Line 1: Not yet part of the loop but useful because it's easier to read: the records are stored in a variable.
Line 2: The loop starts with for
[it follows a label for a single element from the list to be traversed] in
[it follows the list] do
.
Line 3: statement of what should be done.
Line 4: end
terminates the loop (termination).
You'd like to assign all customers who have status 2
a new one, status 1
. First, select the customers with status 2
in the Customers (new) table. Then assign status 1
to each of these customers (customer
).
Result: All customers who have status 2
are assigned status 1
.
This loop is especially suitable when working with numeric values since instead of an array, a sequence of numbers will be iterated.
On each pass, 1
is added to the loop variable (increment = 1
). It starts with the value after from
(inclusive) and ends before the value after to
(exclusive).
Result: 60
The values of the array with the indices 0
, 1
and 2
are added. 10
+ 20
+ 30
= 60
.
Change the height of the increment with step
.
Result: 50
The values of the array with the indices 0
, 2
and 4
are added. 10
+ 30
+ 10
= 50
.
for i in range(0, 10)
is the equivalent of for i from 0 to 10
.
This loop is executed until the condition after while
is no longer true.
Declare a counter variable, for example, which is incremented on each loop pass until the condition is no longer true. The condition is correct (true
) as long as the variable is less than a specified value.
Result: 0 1 2 3 4 5 6 7 8 9
In most cases, for ... in ... do ... end
is the preferred choice.
function
Create your own functions with Ninox to automate workflows according to your needs.
write a script once and use it throughout the database
concise scripts because you only need your own function and don't have to insert the entire script once or even multiple times
To define a function, use function
followed by whatever name you choose. Then, in parentheses, specify which parameters are to be used. These are separated by commas.
parameterName : parameterType
To create a function without parameters, insert empty parentheses ()
.
Like scripts, the last line in the definition of the function is the return value.
To use your functions across the entire database, enter the function in the tab bar of the database under Options in Global functions.
Enable edit mode
Click the Options tab
Enter your function(s) under Global Functions.
Insert the function in a formula field of a table and that function is only available in that formula field. This is useful when keeping repetitive sections short, or when your function refers to the current table, respectively.
Let's create a function hello
to greet a person and tell them their age. First, pass the function a string for the name and a number for the age as parameters. These parameters are inserted into a given sentence at the appropriate positions.
Result: Hello Mom. You are 100 years old!
If you called the function like this: hello("Mom", 100)
Unfortunately, not all data types are currently supported by user-defined functions.
These following data types are already available for creating user-defined functions.
Result: Aaron, beate, conrad, Dahlia, Eddi, Fatima
More about .
More about .
More about calls.
Tip: Get familiar with the difference between and .
This prevents subsequent transactions from getting blocked and boosts performance.
If the condition is not set to false
on any of the passes, there's a risk of ending up in an infinite loop, causing Ninox to explode.
Options are displayed when you're in edit mode .
parameterName | parameterType |
---|
Data type | Description | Example |
---|
name | text |
age | number |
To run a given script only once and cache and return the output value
To close all record forms
To close full-screen mode
To close the top record form
To return the ID of the current database
To create a duplicate of a given record
To clear the cache of the database and the values stored by cached()
To open a given record in full-screen mode
To open a given page
To jump to the related table and open a given record
To open a given table
To save a given record in a given layout as a PDF in the internal file system and return a link to the file
To return a record of a table by a given ID
To force Ninox to wait for a given number of milliseconds before continue running the code
To return an array with unique elements
To return Yes (true
) if the database is synced with the Ninox cloud
An overview of the array functions
To create a new array by merging 2 arrays of a similar type
To return the average of a number array
To return Yes (true
) if the given value equals a given selection
To return all items of an array in one string
To check if a string or an array contains an exact match
To return the number of concrete items in an array
To return all attachments of a record as an array
To return the first item of an array
To return the start position of the first match in a string or an array
To extract a value of an array or an object
To return a string consisting of all items of the given string array separated by a given separator
To return the last item of an array
To return the count of all characters in a string or all items in an array
To return the highest or latest value of an array
To return the lowest or earliest value of an array
To return the IDs of the selected choice values of a given multiple choice field
To return an array of consecutive numbers
To sort an array in descending order
To extract a subrange from a string or array
To sort values in ascending order
To split a string into an array at each separator
To split a string into an array by using a regular expression
To return the total sum of a number array
To return an array with unique elements
| corresponds to the data type |
|
| is a number |
|
| is either true or false |
| is a date |
|
| is a time |
|
| corresponds to the data type |
|
Table name | corresponds to a record from the specified table |
|
See all Ninox functions at a glance. Each feature is linked to a separate page.
To return the absolute value of a number
To calculate the arccosine
To return the number of full years between now and a given date (e.g. a person’s age)
To open a pop-up with an alert message
To create a temporary file on the Ninox server
To convert given time-related values to an appointment
To create a new array by merging 2 arrays of a similar type
To calculate the arcsine
To calculate the arctangent
To calculate the arctangent of the quotient of x/y
To return the average of a number array
To open the barcode scanner and return the scanned value as a string
To run a given script only once and cache and return the output value
To capitalize the first letter of each word
To round up a given number to the nearest integer
To evaluate multiple-choice fields
To return the currently used language of the browser or app in abbreviated form
To close all record forms
To close full-screen mode
To close the top record form
To return or convert to a color value
To return all items of an array in one string
To check if a string or an array contains an exact match
To calculate the cosine
To return the number of concrete items in an array
To create an event in the Apple Calendar App
To create a reminder in the Apple Reminder App
To add content to a temporary file on the Ninox server
To create a text file with a given name and content
To dynamically create customizable, styled, multi-sheet Excel files directly from databases
To create a zip archive including all files of a given file array
To return the ID of the current database
To convert to or return a date value
To convert to or return a timestamp
To return the day of the month from a given date value as a number
To return the number of days between 2 dates
To convert an angle from radians to degrees
To pop up a dialog with answer options
To create a duplicate of a given record
To return the duration of an appointment
To convert a given value to an email value
To return the end of an appointment.
To return Yes (true) if the number is even
To calculate the natural exponential function
To extract a substring from a given string using a regular expression
To return a specific file based on the file name from a given record
To return the metadata, like file name, size and modification date of a file based on a given record and file name
To return all attachments of a record as an array
To return the first item of an array
To round down a given number to the nearest integer
To format a given value
To create a JSON string of a valid JSON object
To convert a given JSON object into XML text, which might be optically structured
To return a rich text representation of any value
To send an HTTP request
To return an icon
To import a file from a URL and save it as an attachment of a record
To return the start position of the first match in a string or an array
To clear the cache of the database and the values stored by cached()
To return Yes (true) if the edit mode is on
To return Yes (true) if the database is locked
To return Yes (true) if a password is needed to activate the edit mode
To extract a value of an array or an object
To return a string consisting of all items of the given string array separated by a given separator
To return the last item of an array
To return the latitude value of a given location value
To return the count of all characters in a string or all items in an array.
To calculate the natural logarithm
To convert a file to base64 format
To convert a file to URL-compliant base64 format
To return a location value with a given title, latitude, and longitude
To calculate the logarithm
To return the longitude of a given location value
To return a string in lower case
To fill up a given length with given padding at the beginning
To return the highest or latest value of an array
To return the lowest or earliest value of an array
To return the month from a given date value as a number
To return a given month as a number out of a string
To return the full month name of a given date value
To identify the type of environment that is currently being used
To return the current timestamp
To convert a given value to a number
To return the IDs of the selected choice values of a given multiple choice field
To return Yes (true) if the number is odd
To open a given record in full-screen mode
To open a record in a given layout in the print layout editor
To jump to the related table and open a given record
To open a given table
To convert a string to a link and open it in the standard web browser
To convert a JSON string to a JSON object
To convert an XML string to a JSON object
To convert a value to a phone value
To open a given record in a pop-up form
To calculate the power of a number
To save a given record in a given layout as a PDF in the internal file system and return a link to the file
To print to a PDF from a given record in a given layout and open the file with a program set as default
To print the visible columns of a given view according to your database settings (PDF or HTML)
To return the quarter of a given date value as a number
To send a SQL command to a connected SQL database and return the record data.
To convert an angle from degrees to radians
To return a random number
To return an array of consecutive numbers
To return the internal raw text representation of a given value
To return a record of a table by a given ID
To remove a key-value pair from a given JSON object
To replace a pattern in a string with a given replace
To replace the matches of a given regular expression with a given string in a given text.
To round a given number
To fill up a given length with a given padding at the end
To sort an array in descending order
To send a SQL command to a connected SQL database
To send an email out of Ninox
To update or add a key-value pair in a given JSON object
To return an URL of a specific file
To return a URL of a given view
To return the signum of a number
To calculate the sine
To force Ninox to wait for a given number of milliseconds before continue running the code
To extract a subrange from a string or array
To sort values in ascending order
To split a string into an array at each separator
To split a string into an array by using a regular expression
To calculate the square
To calculate the square root
To return the start timestamp of an appointment
To convert a given value to a string
To convert a given string to a styled object
To return a substring out of a given text
To return a substring out of a given text with a given start and a given end
To return the total sum of a number array
To return the ID of a table
To calculate the tangent
To return the ID of the current workspace
To check if a text has matches with a given regular expression
To convert a value to a string and possibly reflect the format options
To return the current time
To convert a given time-related value to a time interval, i.e. a duration
To convert a given time-related value to a timestamp
To return the current date (without time).
To remove preceding and following spaces
To return an array with unique elements
To unshare all views of a given table
To unshare a given file
To unshare a given view of a given table
To return a string in the upper case
To convert a value to a link
To decode a given string from a URL-compliant format into text
To convert a given string into a URL-compliant string based on the ASCII character set
To return a link for a given record or view
To return the current or a specific user
To return the email address of a user
To return the first name of a user
To return the full name of a user
To return Yes (true) if a user has a given role
To return the ID of a user
To return Yes (true) if the current user has the admin role
To return the last name of a user
To return the username of a user
To return the role of the current or a given user
To return all roles of a user
To return the IDs of all collaborators in an array
To return Yes (true) if the database is synced with the Ninox cloud
To return the calendar week of a given date value
To return the weekday of a given date value as a number
To return a given weekday name as a number
To return the full weekday name of a given date value
To return the number of working days between 2 given dates
To return the year of a given date value
To return the month and the year of a given date value
To return the quarter and the year of a given date value
To return the week and the year of a given date value
"Mom" = "Mom"
"Mom" = "Dad"
An overview of date- and time-related functions
To return the number of full years between now and a given date (e.g. a person’s age)
To convert given time-related values to an appointment
To create an event in the Apple Calendar App
To create a reminder in the Apple Calendar App
To convert to or return a date value
To convert to or return a timestamp
To return the day of the month from a given date value as a number
To return the number of days between 2 dates
To return the duration of an appointment
To return the end of an appointment.
To format a given value
To return the month from a date value as a number
To return a given month as a number out of a string
To return the full month name of a given date value
To return the current timestamp
To return the quarter of a given date value as a number
To return the start timestamp of an appointment
To return the current time
To convert a given time-related value to a time interval, i.e. a duration
To convert a given time-related value to a timestamp
To return the current date (without time).
To return the calendar week of a given date value
To return the weekday of a given date value as a number
To return a given weekday name as a number
To return the full weekday name of a given date value
To return the number of working days between 2 given dates
To return the year of a given date value.
To return the month and the year of a given date value
To return the quarter and the year of a given date value
To return the week and the year of a given date value
An overview of functions to help you to manage files and printing
To create a temporary file on the Ninox server
To add content to a temporary file on the Ninox server
To create a text file with a given name and content
To dynamically create customizable, styled, multi-sheet Excel files directly from databases
To create a zip archive including all files of a given file array
To return a specific file based on the file name from a given record
To return the metadata, like file name, size, and modification date of a file based on a given record and file name
To return all attachments of a record as an array
To import a file from a URL and save it as an attachment of a record
To convert a file to base64 format
To convert a file to URL-compliant base64 format
To open a record in a given layout in the print layout editor
To save a given record in a given layout as a PDF in the internal file system and return a link to the file
To print to a PDF from a given record in a given layout and open the file with a program set as default
To print the visible columns of a given view according to your database settings (PDF or HTML)
To return an URL of a specific file
To unshare a given file
To unshare a given view of a given table
An overview of functions, that help you to format and convert data types
To convert given time-related values to an appointment
To create a new array by merging 2 arrays of a similar type
To dynamically create customizable, styled, multi-sheet Excel files directly from databases
To convert to or return a date value
To convert to or return a timestamp
To convert a given value to an email value
To format a given value
To create a JSON string of a valid JSON object
To convert a given JSON object into XML text, which might be optically structured
To return a rich text representation of any value
To convert a file to base64 format
To convert a file to URL-compliant base64 format
To return a string in lower case
To return a given month as a number out of a string
To return the full month name of a given date value
To convert a given value to a number
To convert a JSON string to a JSON object
To convert an XML string to a JSON object
To convert a number or string to a phone value
To remove a key-value pair from a given JSON object
To update or add a key-value pair in a given JSON object
To convert a given value to a string
To convert a given string to a styled object
To convert a value to a string and possibly reflect the format options
To convert a given time-related value to a time interval, i.e. a duration
To convert a given time-related value to a timestamp
To return a string in the upper case
To convert a string to a link
An overview of mathematical functions to perform tasks on numbers
To return the absolute value of a number
To calculate the arccosine
To calculate the arcsine
To calculate the arctangent
To calculate the arctangent of the quotient of x/y
To return the average of a number array
To round up a given number to the nearest integer
To calculate the cosine
To convert an angle from radians to degrees
To return Yes (true
) if the number is even
To calculate the natural exponential function
To round down a given number to the nearest integer
To format a given value
To calculate the natural logarithm
To calculate the logarithm
To return the highest or latest value of an array
To return the lowest or earliest value of an array
To return Yes (true
) if the number is odd
To calculate the power of a number
To convert an angle from degrees to radians
To return a random number
To round a given number
To return the signum of a number
To calculate the sine
To calculate the square
To calculate the square root
To return the total sum of a number array
To calculate the tangent
An overview of the functions related to your user interface
To open a pop-up with an alert message
To open the barcode scanner and return the scanned value as a string
To close all record forms
To close fullscreen mode
To close the top record form
To return or convert to a color value
To pop up a dialog with answer options
To return an icon
To identify the type of environment that is currently being used
To open a given record in fullscreen mode
To open a given page
To open a record in a given layout in the print layout editor
To jump to the related table and open a given record
To open a given table
To open a given record in a pop-up form
To convert a given string to a styled object
An overview of text-related functions
To capitalize the first letter of each word
To return Yes (true
) if the given value equals a given selection
To return all items of an array in one string
To check if a given string contains the exact given match
To create a text file with a given name and content
To extract a substring from a given string using a regular expression
To format a given value
To return a rich text representation of any value
To return the first position of appearance of a match in a string starting
To return a string consisting of all items of a given string array separated by a given separator
To return the count of all characters in a string or all items in an array
To output a string in lower case
To fill the missing space with a given padding at the beginning
To return the internal raw text representation of a given value
To replace a pattern in a string with a given replace.
To replace any "find" with "replace" in a "text"
To fill the missing space of the given padding at the end, if the length of a given string is shorter than a given length
To extract a sub-array
To split a string into an array at each separator
To convert a given value to a string
To return a styled text element
To return a new string out of a given text
To return a new string out of a given text with a given start and a given end
To return Yes (true
) if a given text matches a given regular expression.
To convert a value to a string that possibly reflects the format options
To remove preceding and following spaces
To output a string in the upper case
An overview of all user management related functions
To return the currently used language of the browser or app in abbreviated form
To return Yes (true
) if the edit mode is on
To return Yes (true
) if the database is locked
To return Yes (true
) if a password is needed to activate the edit mode
To return the type of platform that is currently being used
To return the current or a specific user
To return the email address of a user
To return the first name of a user
To return the full name of a user
To return Yes (true
) if a user has a given role
To return the ID of a user
To return Yes (true
) if the current user has the admin role
To return the last name of a user
To return the username of a user
To return the role of a user
To return all roles of a user
To return the IDs of all current users in an array
To return the absolute value of a number
The function removes existing signs and returns the absolute, positive value of a number.
It happens rather rarely, but for certain calculations, it may be necessary to continue calculating with the positive value of a possibly negative result. In such cases the function saves querying the value and, if necessary, changing the sign by multiplication.
abs(number)
number
Result: 9.3
sign
, which returns the signum of a number.
To return the number of full years between now and a given date
Use this function to calculate the current number of full years that have passed since a given date.
The most common application is certainly the calculation of the age of a person based on the date of birth, but other uses are also conceivable:
depreciation periods
special termination rights that might be possible after a certain term (e.g. real estate loan)
determination of anniversaries, etc.
The current date is always used for this calculation.
age(date)
number
Result: Age in years on the current day, starting from the value of the Date of birth field.
Result: 45 (on May 27, 2021)
An overview of functions to connect your databases to external services and think outside the box
To create an event in the Apple Calendar App
To create a reminder in the Apple Calendar App
To return the ID of the current database
To create a JSON string of a valid JSON object
To convert a given JSON object into XML text, which might be optically structured
To return a rich text representation of any value
To send an HTTP request
To extract a value of an array or an object
To return the latitude value of a given location value
To convert a file to base64 format
To convert a file to URL-compliant base64 format
To return a location value with a given title, latitude, and longitude
To return the longitude of a given location value
To convert a string to a link and open it in the standard web browser
To convert a JSON string to a JSON object
To convert an XML string to a JSON object
To send a SQL command to a connected SQL database and return the record data.
To return the internal raw text representation of a given value
To remove a key-value pair from a given JSON object
To send a SQL command to a connected SQL database
To send an email out of Ninox
To update or add a key-value pair in a given JSON object
To return an URL of a specific file
To return a URL of a given view
To return the ID of a table
To return the ID of the current workspace
To unshare all views of a given table
To unshare a given file
To unshare a given view of a given table
To convert a value to a link
To decode a given string from a URL-compliant format into text
To convert a given string into a URL-compliant string based on the ASCII character set
To return a link for a given record or view
To add content to a temporary file on the Ninox server
This function adds the given content to a temporary file, which will be accessed via a given link created by createTempFile()
.
The respective file must have been created already and still exist when executed.
Use this function in combination with createTempFile()
to render large or long-running exports.
appendTempFile(link, string)
appendTempFile(string, string)
void
appendTempFile(myURL, myContent)
To add content to a temporary file on the Ninox server.
Result: First, a temporary CSV file is created on the server and the link to the file is saved in the URL field. Then data from the Customers table will be added line by line to the file.
The function can be executed only on the client. Learn more about
, which creates a temporary file on the Ninox server.
To convert given time-related values to an appointment
This function helps you to create a from-to-appointment based on 2 timestamps. Instead of the 2nd timestamp, you can also specify a duration and Ninox will return the end timestamp automatically.
If the Start and End timestamp are on the same day, the 2nd won’t be on display. Otherwise, both dates will be displayed, and you should give it enough space to show.
appointment(any, any)
appointment
Your result format may be different depending on your settings.
appointment(start, end)
/ appointment(start, duration)
To convert 2 given time-related values to an appointment.
It doesn't matter if you add the end or the start first, Ninox will automatically select the earliest timestamp as a start.
Result:
03/06/2021 17:00 – 03/16/2021 19:00 (US)
06/03/2021 17:00 – 16/03/2021 19:00 (UK)
Result:
05/22/2021 10:00 - 11:45 (US)
22/05/2021 10:00 - 11:45 (UK)
datetime
, which converts to or returns a timestamp.
To open a pop-up with an alert message
This function will trigger a pop-up with an alert message and an OK button.
You can use this function to display information to the user, which they need to confirm if they want to continue.
If you need to provide options for the user to choose from, we recommend dialog()
.
The function can be executed only on the client. Learn more about execution context
If you call this function more than once within the same script, only the last function call will be executed, so the user has only one box to confirm.
alert(any)
void
Result: Add the code block to a button, and you'll get a popup with an OK button when clicking on it.
Result: This is the time at this very moment: 17:18. (will show the exact time when the popup is triggered.
dialog
, which pops up a dialog with answer options.
Be careful when deleting tables. Depending on the structure of your database, information from a table might be used in other places as well
To prevent you from “accidentally” deleting a table, we’ve made the corresponding button slightly less accessible. And, of course, you will be asked again to confirm whether you really want to delete your table.
This way we want to make sure that you really only delete tables that you no longer need.
Go to the table you want to delete.
Select Edit fields from the drop-down menu. They are in the table settings.
You will find the Delete table button at the bottom left.
If you delete a table, all the data it contains will also be deleted, so make sure you save the data beforehand if necessary.
Click the gear icon in the top left corner.
To create a new array by merging 2 arrays of a similar type
With this function, you can merge 2 arrays of the same data type and create a new array consisting of the values of both arrays.
It might be helpful to merge arrays for evaluation so that you only need to query only 1 array.
If you need to merge more than 2 arrays, just execute the function as often as needed.
array([any], [any])
[any]
array(myArray1, myArray2)
Result: 1,2,3,4,5,6
join
, which returns a string consisting of all items of the given string array separated by a given separator.
slice
, which extracts a subrange from a string or array.
If needed, encrypt a rendered report with a password.
Either toggle ON the option Set password in the Ninox UI, or alternatively use a custom script and the functions printRecord
or printAndSaveRecord
.
Works with printRecord and printAndSaveRecord.
The data
object can include the property _options
with pdfPassword
which overrides the default settings set by the print engine in the Ninox UI, if you previously toggled OFF Set password.
An empty password like""
will not encrypt your report.
Add a new layout element, here: a button.
Paste the script below in the formula editor.
Save changes.
Click or tap the button to run the script.
A report (PDF file) is created and downloaded to your local files. When you open the PDF from your browser, you are prompted to enter a password to open the document.
Returns the minimum value in a set.
Minimum quantity:
{d.cars[].qty:aggMin}
Minimum quantity by sorting "sort" values above 1:
{d.cars[sort>1].qty:aggMin}
Minimum quantity by multiplying the "qty" by the "sort" attribute:
{d.cars[sort>1].qty:mul(.sort):aggMin:formatC}
Minimum quantity:
1
Minimum quantity by sorting "sort" values above 1:
2
Minimum quantity by multiplying the "qty" by the "sort" attribute:
4
Of course, Ninox also allows you to import data, but in our example, we’ll first show you how easy it is to enter data directly into your form.
There are 2 ways to do this:
In the form (our recommendation)
In the table
Click in a line and enter your data in the form that opens (on the right).
Alternatively, you can enter your data directly into the table. This is a little less convenient, but in some cases, it may be a little faster.
Double-click in a field and start typing. Use the Tab key to move to the next field (or double-click again).
Like to delve deeper into the topic? Then please have a look at the corresponding section in our video tutorial.
If the form doesn’t “slide” into view from the right on its own, simply click on the arrowhead (top right) to display the form.
Learn how to create line charts in DOCX/PDF documents in Microsoft Word
The dataset below is used in a chart that represents the weather temperature during a short period.
Group temperatures history by dates (minimum, maximum, average) using the following dataset:
DOCX
template in Microsoft WordClick the Insert tab > Chart menu > Line > 2D Line to insert a line chart.
As soon as the chart is created, Microsoft Word opens an Excel spreadsheet to edit charts values.
Delete default values, and insert temperature values by looping through the temps
list.
After each loop expression that contains [i]
in the first row, use the expression [i+1]
in the next line.
Dynamic charts do not support only one [i+1]
for multiple [i]
expressions.
Generate the PDF
report, and the line chart is automatically filled.
Manage
: get #00FFFF
reference color, to be replaced by #FF0000
coming from the {d.color}
marker
dynamic
: get #FF00FF
reference color, to be replaced by #00FF00
coming from the {d.color2}
marker
color
: get #0000FF
reference color in the background, to be replaced by #00FF00
coming from the {d.color3}
marker
107 industry-standard barcode formats are supported for PDF
, DOCX
, ODT
, XLSX
, ODS
, ODP
, and ODG
documents.
as dynamic image: the recommended solution to generate industry-standard barcodes
as font: not recommended to use, and only 4 barcodes are supported
Parameters | Description | Type |
---|---|---|
type
Barcode type: ean13
, ean8
, code128
, code39
, gs1-128
, qrcode
, swissqrcode
, and more...
string
Generate dynamic charts into documents with 2 solutions:
native charts of Microsoft Word or LibreOffice: design and configure visualizations from your text editor
ECharts 5 charts as images: design and configure visualizations from your JSON data set
Generate barcodes as image following the same logic as for Pictures:
Insert a temporary picture in your template (white JPEG
image, or cat PNG
image). The temporary image is used to find the location to insert the barcode.
Write the marker followed by the barcode formatter into the alternative text, description, or title of the image. The format should be: {d.value:barcode(type)}
. Refer to Pictures for more info.
Insert the type
of barcode as a first argument of the formatter :barcode
. Refer to the#list-of-supported-barcodes below.
Generate the document.
Barcode options are available and can be passed to the barcode
formatter as a second argument, such as :barcode(type, options1, options2, ...)
. Refer to the #list-of-barcodes-options below.
This example shows how to insert 3 barcodes as images:
ean13
qrcode
gs1
Retrieve your barcode data as JSON
from your database.
Edit your template in a text editor, insert 3 temporary images. For each image, write as an alternative text tags:
First image: {d.urlQrCode:barcode(qrcode)}
Second image: {d.productCodeBarEan13:barcode(ean13)}
Third image: {d.productGs1:barcode(gs1-128)}
To scale the barcode, chain the formatter :imageFit
, such as {d.urlQrCode:barcode(qrcode):imageFit(contain)}
. Learn more about the #imagefit-formatter.
Pass the option as a second argument in any order. The option must keep the format "optionName:value", such as {d.number:barcode(qrcode, width:300, height:100, includetext:false, scale:1)}
.
Barcode name | Type |
---|---|
Option name | Type | Description |
---|---|---|
EAN-5 (5 digit add-on)
ean5
EAN-2 (2 digit add-on)
ean2
EAN-13
ean13
EAN-8
ean8
UPC-A
upca
UPC-E
upce
ISBN
isbn
ISMN
ismn
ISSN
issn
Code 128
code128
GS1-128
gs1-128
GS1-14
ean14
SSCC-18
sscc18
Code 39
code39
Code 39 Extended
code39ext
Italian Pharmacode
code32
Pharmazentralnummer (PZN)
pzn
Code 93
code93
Code 93 Extended
code93ext
Interleaved 2 of 5 (ITF)
interleaved2of5
ITF-14
itf14
Deutsche Post Identcode
identcode
Deutsche Post Leitcode
leitcode
GS1 DataBar Omnidirectional
databaromni
GS1 DataBar Stacked
databarstacked
GS1 DataBar Stacked Omnidirectional
databarstackedomni
GS1 DataBar Truncated
databartruncated
GS1 DataBar Limited
databarlimited
GS1 DataBar Expanded
databarexpanded
GS1 DataBar Expanded Stacked
databarexpandedstacked
GS1 North American Coupon
gs1northamericancoupon
Pharmaceutical Binary Code
pharmacode
Two-track Pharmacode
pharmacode2
Code 25
code2of5
Industrial 2 of 5
industrial2of5
IATA 2 of 5
iata2of5
Matrix 2 of 5
matrix2of5
COOP 2 of 5
coop2of5
Datalogic 2 of 5
datalogic2of5
Code 11
code11
BC412
bc412
Codabar
rationalizedCodabar
USPS Intelligent Mail
onecode
USPS POSTNET
postnet
USPS PLANET
planet
Royal Mail 4 State Customer Code
royalmail
AusPost 4 State Customer Code
auspost
Royal Dutch TPG Post KIX
kix
Japan Post 4 State Customer Code
japanpost
MSI Modified Plessey
msi
Plessey UK
plessey
Telepen
telepen
Telepen Numeric
telepennumeric
PosiCode
posicode
Codablock F
codablockf
Code 16K
code16k
Code 49
code49
Channel Code
channelcode
Flattermarken
flattermarken
Custom 1D symbology
raw
Custom 4 state symbology
daft
Miscellaneous symbols
symbol
PDF417
pdf417
Compact PDF417
pdf417compact
MicroPDF417
micropdf417
Data Matrix
datamatrix
Data Matrix Rectangular
datamatrixrectangular
Data Matrix Rectangular Extension
datamatrixrectangularextension
Royal Mail Mailmark
mailmark
QR Code
qrcode
Swiss QR Code
swissqrcode
Micro QR Code
microqrcode
Rectangular Micro QR Code
rectangularmicroqrcode
MaxiCode
maxicode
Aztec Code
azteccode
Compact Aztec Code
azteccodecompact
Aztec Runes
aztecrune
Code One
codeone
Han Xin Code
hanxin
DotCode
dotcode
Ultracode
ultracode
GS1 Composite 2D Component
gs1-cc
EAN-13 Composite
ean13composite
EAN-8 Composite
ean8composite
UPC-A Composite
upcacomposite
UPC-E Composite
upcecomposite
GS1 DataBar Omnidirectional Composite
databaromnicomposite
GS1 DataBar Stacked Composite
databarstackedcomposite
GS1 DataBar Stacked Omnidirectional Composite
databarstackedomnicomposite
GS1 DataBar Truncated Composite
databartruncatedcomposite
GS1 DataBar Limited Composite
databarlimitedcomposite
GS1 DataBar Expanded Composite
databarexpandedcomposite
GS1 DataBar Expanded Stacked Composite
databarexpandedstackedcomposite
GS1-128 Composite
gs1-128composite
GS1 Data Matrix
gs1datamatrix
GS1 Data Matrix Rectangular
gs1datamatrixrectangular
GS1 QR Code
gs1qrcode
GS1 DotCode
gs1dotcode
HIBC Code 39
hibccode39
HIBC Code 128
hibccode128
HIBC Data Matrix
hibcdatamatrix
HIBC Data Matrix Rectangular
hibcdatamatrixrectangular
HIBC PDF417
hibcpdf417
HIBC MicroPDF417
hibcmicropdf417
HIBC QR Code
hibcqrcode
HIBC Codablock F
hibccodablockf
HIBC Aztec Code
hibcazteccode
width
integer
Width a number as millimeters.
Example: {d.number:barcode(qrcode, width:300)}
. To scale the barcode, it is possible to chain the formatter :imageFit
, such as: {d.number:barcode(qrcode, width:300):imageFit(contain)}
.
height
integer
Height a number as millimeters.
Example: {d.number:barcode(qrcode, height:10)}
. To scale the barcode, it is possible to chain the formatter :imageFit
, such as: {d.urlQrCode:barcode(qrcode, height:10):imageFit(contain)}
.
scale
integer
Quality of the barcode as a number between 1
to 10
. It multiplies the width and height, creating a bigger resolution barcode. Example: {d.number:barcode(qrcode, scale:3)}
includetext
boolean
Show the text and takes a Boolean as value, true
or false
.
Example: {d.number:barcode(qrcode, includetext:false)}
textsize
integer
Change the text size. Example: {d.number:barcode(qrcode, textsize:20)}
textxalign
string
Change the alignment of the text horizontally. Takes only 4 values: left
, center
, right
, or justify
. The default value is center. Example: {d.number:barcode(qrcode, textxalign:right)}
textyalign
string
Change the alignment of the text vertically. Takes only 3 values: below
, center
, or above
. The default value is below.
Example: {d.number:barcode(qrcode, textyalign:above)}
rotate
string
Rotate the barcode and the text. Takes only 4 values (case insensitive): N
for not rotated, R
for 90 degree right rotation, L
for 90 degree left rotation, I
of 180 degree rotation. Example: {d.number:barcode(qrcode, rotate:R)}
barcolor
string
Color of bars as hexadecimal #RRGGBB
(6 characters required & case insensitive).
Example: {d.number:barcode(qrcode, barcolor:#1FDE25)}
textcolor
string
Color of the text as hexadecimal #RRGGBB
(6 characters required & case insensitive).
Example: {d.number:barcode(qrcode, textcolor:#1FDE25)}
backgroundcolor
string
Color of the background as hexadecimal #RRGGBB
(6 characters required & case insensitive).
Example: {d.number:barcode(qrcode, backgroundcolor:#1FDE25)}
eclevel
string
Specify the error correction level: L
for Low, M
for Medium (default), Q
for Quality and H
for High. Option ONLY FOR QRCODES, Micro QR Code, GS1 QR Code, HIBC QR Code, or Swiss QR Code. Example: {d.number:barcode(qrcode, eclevel:Q)}