Skip to main content
Import loads products into your catalogue from a spreadsheet — and, when your file has the optional stock columns, receives their opening stock with its expiry date and lot. Export takes your catalogue back out as Excel or CSV and never carries quantities. Both sit on the Inventory toolbar.

The two rules that explain everything else

Import brings stock in only when you ask it to, in words that can only mean that. The sheet says: “To receive stock at the same time, fill the optional opening_stock, stock_location and expiry_date columns.” A row without an opening_stock value becomes a product and nothing else, and a column called “qty” or “on hand” from another system is never read as stock.Export deliberately leaves on-hand quantities out — “Stock on hand is not included — quantities are managed through Receive and Dispense, so re-importing this file never overwrites your live stock.”
Your stock levels live in ClinikEHR and nowhere else. Stock from an import is received — it becomes a lot with its expiry date and a ledger entry, exactly as if you had used Receive — and a file can never overwrite what you already hold. Everyday deliveries still come in through Receive, or in bulk through the separate Opening stock button — see Stock control.

What you’re looking at

Neither is a page — each opens a sheet over the screen you are on. Import opens Bulk-import items, badged Catalog Import. Under Start from the template sits Download sample CSV — “Download the sample CSV to see the required headers, expected formats, and two example rows.” Below it, Upload your file is a Click to upload or drag and drop target, constrained to “.csv, .xlsx or .xls — max 5MB, up to 1000 rows”. While it reads, the sheet says Reading spreadsheet…; afterwards Replace file swaps the upload. The Preview is the part worth slowing down for. Three badges count what it found — {n} new, {n} to update and {n} need fixing — and every row is labelled either new or “updates existing · matched on upc” (or sku). A row that changes nothing says so: “No changes — this row matches what is already stored.” A Field reference below lists all 27 catalogue columns with their hints — required ones carry a star — followed by the four optional stock columns. When your file carries opening stock, each preview row shows it, for example “Opening stock 40 → Main Pharmacy · expires 2027-03-31 · lot B24-0192”. That “to update” count is the word “import” hiding an update. Each row is matched against your catalogue on its barcode first, then its SKU. A match updates that product and leaves untouched any column your sheet omits; no match creates a new product. So a corrected price list is a legitimate re-import rather than a duplicate-maker — provided your barcodes and SKUs are right. Where they are missing or wrong, the same product arrives twice under two names. Export opens Export inventory catalog, badged Catalog Export. It shows “{n} item(s) ready to export”, a File format choice — Excel (.xlsx), “Formatted workbook — opens natively in Excel.”, the default, or CSV (.csv), “Plain text — universal, opens anywhere.” — and the full Columns included list. The footnote reads “The export is logged against the audit trail.” An empty catalogue can still open both. Export simply refuses, its button reading No items to export rather than handing you a header row with nothing under it.

Import your catalogue

1

Open the importer

Select Import on the Inventory toolbar.
2

Start from the template — or your old system's export

Select Download sample CSV; a toast confirms “Sample template downloaded”. Fill your products into that file — or upload the item list your previous POS produced as it is. Common vendor headers are recognised: Item Description becomes the product name, Department Name the category (departments also decide the item type — drugs become medications, personal care becomes cosmetics, everything else a supply), Average Unit Cost the unit cost, Regular Price the sell price, and UPC the barcode. When the importer reads a file this way, the preview shows How we read your columns, naming every guess it made and every column it did not import — check that panel before importing.
3

Upload the file

Select Click to upload or drag and drop. Only .csv, .xlsx and .xls are accepted, up to 5 MB.
4

Read the preview before you commit

Check {n} new and {n} to update against what you expected. A file you meant as new products showing mostly “to update” is matching things you did not intend to change — stop and check your barcode column.
5

Import

The button names the outcome — Add {n}, update {n} — then reports Submitted, Created, Updated and Failed. Anything that failed comes back through Download failed rows with error column: fix that file and re-upload only it.

Bring opening stock and expiry dates in with the import

Add these four columns to the right of the catalogue columns (the sample CSV already has them, empty): What the importer checks before anything is written:
  • An expiry date is needed for stock of any product with Track lot & expiry on (the default). Set requires_lot to false for things that do not expire.
  • A date written all in numbers, like 03/04/2027, is refused — it is the 3rd of April in one country and the 4th of March in another, and a wrong guess ages your stock by a month. Write it as YYYY-MM-DD.
  • A date that has already passed is refused, as is a location name that does not exist.
  • A row that fails any stock check is not imported at all, so you never end up with the product but not its stock.
After the import, the result shows Opening stock received for {n} items. Importing the same file again updates the products but never receives the same opening stock twice.
Upload a sales report exported from an old till system and the importer recognises it — “POS report recognised and converted” — strips duplicate and subtotal rows, and numbers repeated price variants “#2” for you to rename. It never reads that report’s quantities as stock — use Opening stock for those.

Export your catalogue

1

Open the exporter

Select Export on the toolbar.
2

Choose the file format

Excel (.xlsx) if a person will read it; CSV (.csv) if it is going into another system. Both carry identical columns.
3

Check the columns

Columns included names all 27, from Item name and Item type through Barcode (UPC/EAN), Reorder level, Unit cost, Sell price, Controlled schedule and Track lot & expiry. No quantity column exists.
4

Download it

The button reads Download {n} item(s) as Excel, and the toast confirms “Exported {n} item(s) as Excel.”
Stock movements and valuations come from Reports on the same toolbar instead. Sales figures live in the reports workbench.

Who can do this

Role decides whether Inventory opens at all — a Cashier / Till Operator reaches only POS and Sales, so neither button is theirs. Permission decides what happens to the products once they are in: importing writes catalogue rows, and the stock that fills them is gated. The role bundles say a Dispensing Supervisor holds the till authorisations and none of the stock ones. Receiving and adjusting are not permission-gated at all — the two toggles that implied they were (Receive deliveries into stock, Adjust stock counts) were never checked by anything and were removed in August 2026 — so anyone who can open Inventory can receive against an imported catalogue. View cost prices and margin and Manage suppliers and purchase orders, the two rows below, are checked on the server. Where cost is denied, the Catalog screen reads “Hidden — needs authorisation from your clinic owner.” — never a zero, because a zero would be read as a free product.
The export file carries Unit cost and Sell price for every product, whether or not the person downloading it can see the margin column on screen. Hidden on screen is still a plain number in the file. Treat an exported catalogue as commercially sensitive and send it accordingly.
Two behaviours surprise people:
  • Enforcement is opt-in, per person. A colleague never saved in the permissions sheet is unrestricted, and the sheet warns “Saving starts enforcing”.
  • A denied action is recorded; an allowed one is not. Hiding Inventory from a sidebar is a convenience, not a security boundary.
See Staff permissions.

Check it worked

  • After an import: the new products appear on the Catalog tab and are searchable at the till. Products imported without opening_stock show zero on hand until you receive stock — that is correct, not a failed import. Products imported with it show that stock on the Stock tab, in its lot, with its expiry date.
  • The Created and Updated tiles match what the preview promised.
  • After an export: the file opens, the row count matches your catalogue, and the columns match the Columns included list.

Common issues

Split the file. A catalogue large enough to exceed 5 MB is nearly always several suppliers’ lists in one workbook. Import by supplier or category instead — a batch that goes wrong is quick to spot and quick to redo.
The file is something else, or was renamed rather than converted. Open it in Excel or Sheets and save it again as .csv or .xlsx.
The file parsed as none of the three formats — usually an unusual encoding from another tool. Re-saving it from a spreadsheet program fixes it in almost every case.
A header row and nothing under it. Check you have not uploaded the empty template, and that products start on the row directly below the headers with no blank separator row.
The importer only reads a column called opening_stock as stock, and the How we read your columns panel lists any other quantity column as not imported. Rename your column to opening_stock, add stock_location and expiry_date, and upload again — or bring quantities in through Opening stock or a Stock Count.
The date is written all in numbers with the day and month in an order that cannot be told apart. Write it as YYYY-MM-DD (2027-03-31) or with the month’s name (31 Mar 2027). If your spreadsheet keeps changing it back, format the column as Text before typing.
The row has an opening_stock value but no expiry date, and the product tracks lots and expiry. Add the date, or set requires_lot to false if the product genuinely has no expiry.
The product saved but its stock could not be received — for example, your clinic requires expiry dates on new lots, or a hazardous product was sent to a location that is not hazardous-rated. Download failed rows with error column gives you just those rows to fix and re-upload; the products will simply update.
Every row failed validation. Compare your headers against the sample CSV — a renamed or missing required column invalidates every row at once. Item name and Item type are the two that must be there.
Those rows matched an existing barcode or SKU. Either the products are already in your catalogue under different names, or two suppliers share a code. Fix the codes in the spreadsheet before importing, not afterwards.
Your catalogue is empty. The exporter reads your whole catalogue, so this genuinely means there is nothing there yet.

FAQ

Opening stock, yes — fill the opening_stock, stock_location and expiry_date columns and each product’s stock is received into a lot with that expiry date. It is received once: it can never overwrite or top up what you already hold, which is what stops a stale spreadsheet from changing the shelf. For stock of products already in your catalogue, Opening stock on the same toolbar works too, and everyday arrivals go through Receive.
Nothing bad, as long as your barcodes or SKUs are filled in: the second run matches every row and updates it, leaving the products as they are, and any opening stock in the file is not received a second time. Rows with no code to match on are the ones that duplicate.
No. The export has no quantity column to bring back, so a round trip through a spreadsheet cannot change what you hold. It is the safe way to edit prices in bulk.
Excel for anything a person will read, and if your spreadsheet mangles accents or currency symbols on import. CSV if the file is going into another system.
The sheet asks for up to 1,000 rows and 5 MB per file. Larger catalogues go in several batches, which is the better habit anyway — one supplier or one category per file.