All features

Import & export

In and out, as a spreadsheet

You never have to retype anything. Clients, contacts, projects, tasks, timesheets, subscriptions, domains, websites and hosting all travel as a file, with stable column headers so an export re-imports unchanged. Every import is computed through in full without saving a thing, and then either lands completely or not at all.

A file, or simply pasted

You pick a file, or you paste the cells you already had selected in Excel or Google Sheets, in which case the first row is the header. The kind of file is worked out from the content rather than the extension, and so is the character encoding, so an export from a Dutch Excel full of accents is read instead of refused. There is a ceiling of 2,000 rows and 200 columns at a time, and over that ceiling you get an error and never a truncation: silently importing the first 2,000 rows of a 2,500-row file is the worst outcome available, because it looks like it worked. If an Excel file holds formulas with no calculated result written alongside them, the wizard tells you how many cells that is before you go on.

  • CSV, comma- or semicolon-separated
  • TSV and tab-separated text
  • Excel (.xlsx), with a worksheet picker
  • A pasted table, straight out of your spreadsheet

Saying what each column means

Once the file is read you get one row per column of your file, with the first real values from it beside them under "Examples". Next to those, "Import as" is where you say what the column means in schakl.: an ordinary field, one of your own custom fields, or "Do not import". The choice is suggested from your own header row, Dutch headers included, and whatever is not recognised stays blank so that you choose rather than inherit something wrong. Unmapped columns are skipped, so a file with ten columns of which three matter needs no tidying first. "Match existing records on" reads Automatic, and you can override it.

  • The sample values make a shifted column visible before anything is saved
  • A mapping is positional, so the file is fingerprinted when it is read
  • Change the file after that and the wizard says so, and asks you to check the columns again

Check first, then all at once

"Check file" runs the whole import without saving anything: how many records are new, how many would be updated, and which rows hold an error, numbered the way you count rows in your spreadsheet. Only after a clean check does "Import" become available, and that import is all or nothing. If something is wrong, nothing is saved, not even the rows that were fine; you fix the file and try again rather than discovering half of it already landed. Checks that can name a row belong in that preview: a phone number is coerced to international notation in that row's own country, and a number one digit short is reported against that row and that column, not as one nameless error after the fact.

An import is not a back door

An imported row travels exactly the same create or update path the form does: the same validation, the same events, the same side effects and the same line on the activity trail. Your own custom fields are ordinary columns there, and required fields stay required. What a row is matched on differs per type and is stated in the wizard; where there is no honest key the import always creates, because task titles and time entries legitimately repeat. Anything carrying an approval deliberately does not travel at all: leave is requested, not bulk-written.

  • Clients: on the client number, otherwise the name
  • Contacts: on the e-mail address
  • Projects, subscriptions and hosting: on the name
  • Domains: on the domain name, a pasted URL being reduced to its bare root first
  • Websites: on the domain the site sits on
  • Tasks and timesheets: always created

An export that comes back

An export holds the whole list as you have filtered it, not just the page you can see, and includes your own custom fields. The column headers are stable keys rather than labels, so the file is recognised unchanged when you put it back: export, edit two columns, import is the simplest way to change fifty records at once. Modules also contribute columns to each other's sheets, so a client export carries the contact person along (first name, last name, e-mail, phone, job title), created and linked in the same row on the way back in; the first one becomes that client's primary contact. Those columns only appear for someone who may write contacts, so you never hit a refusal halfway through a file. And exporting keeps working when a licence expires: a module that goes read-only still lets you take your data with you.

On every list, and a permission of its own

Export and Import sit beside the column picker on every list that can travel as a file, with that list's filters carried into the export — not tucked away, because somebody holding a spreadsheet of domains should not have to know a settings screen exists. Instellingen → Import & export is the overview of what can travel at all, and exports the whole unfiltered set. Bulk import and export is a permission of its own, on top of the ordinary read or write permission for the entity itself, and it is admin-only by default: carrying the client list or the domain register out of the building in one file is a different act from opening one record, and that is a decision an agency makes per person. It is one permission across every entity, so the decision is made once instead of per screen; a client with a portal login can therefore never pull a list with it. Both gates are mirrored in the interface too, so a button that would refuse is never drawn.

Want to know more?

The documentation describes every module in detail, from installation to permissions.

The demo is on its way

The live demo isn't ready yet. We're working hard on it and are excited to share it here as soon as it's done.

Go to the docs

More features