# Importing tasks from a spreadsheet — Routelink

Source: https://routelink.app/help/importing-tasks/importing-tasks-from-a-spreadsheet/

# Importing tasks from a spreadsheet

Upload a CSV or Excel file of orders and turn it into stops ready to plan, including how to export from your ERP in the format Routelink expects.

If your orders already live in a spreadsheet, uploading that file is the fastest way to start the day. The same file format works whether you keep orders in Excel by hand or export them from an ERP, accounting package or warehouse system each morning.

## 1\. Start from the template

On the planning screen, choose **Upload**, then **Download template**. You’ll get an Excel file with the header row already in place.

Either fill this in directly, or copy the header row into whatever your own system produces. Getting the headers right is the whole job — everything else follows from it.

## 2\. Match the column names

Routelink reads the **first worksheet** of an `.xlsx` or `.csv` file. Row 1 must be the header row, and every row after it is one stop.

Columns can appear in any order, and any extra columns of your own are ignored, so there’s no harm in leaving internal fields in the export. What matters is the names. Capitalisation and stray spaces don’t matter, so `Address`, `ADDRESS` and `address` all work, but beyond that they must match exactly — there are no alternative spellings.

This is worth emphasising, because it fails quietly. A column headed `Qty` instead of `quantity`, or `Tel` instead of `phone`, is simply ignored. Nothing is flagged and the data just doesn’t arrive. If a field comes through blank after an import, a misspelled header is the first thing to check.

Routelink needs a name and an address for every stop. Everything else is optional, but each one makes the stop more useful:

| Column | Required | What it does |
| --- | --- | --- |
| `address` | **Yes** | The full address on one line. The more complete, the better the match. |
| `name` | **Yes** | Contact name, shown to the driver and used in notifications. |
| `phone` | No | Contact number, needed to send notifications. Export as text. |
| `email` | No | Contact email, needed to send notifications. |
| `company` | No | Trading name, shown alongside the contact. |
| `type` | No | `delivery`, `pickup` or `service`. Defaults to `delivery`. |
| `reference` | No | Your order or invoice number, carried through end to end. |
| `notes` | No | Access instructions, gate codes, anything the driver should know. |
| `description` | No | What’s being delivered. |
| `quantity` | No | Total number of units, as a whole number. |
| `price` | No | Order value in cents. |
| `weight` | No | Total weight in kilograms. |
| `volume` | No | Total volume in litres. |
| `latitude` | No | Decimal degrees, if you already hold coordinates. |
| `longitude` | No | Decimal degrees, if you already hold coordinates. |

A few notes on the fiddly ones:

**Address** must be one column, not several. If your system stores address line 1, line 2, suburb, city and postal code separately, join them together with commas in the export.

**Phone** should be cast to text before it leaves your database. If it comes out as a number, leading zeros are stripped and `0839423067` arrives as `839423067`.

**Quantity** is the total number of individual pieces at the stop, not the number of order lines. An order of 20 bags, 10 bags and 2 bundles is `32`.

## 3\. Get the units right

Three columns trip people up more than anything else. Send the wrong unit and the import still succeeds — the numbers are just wrong, which is worse.

| Column | Unit | Example |
| --- | --- | --- |
| `price` | Cents, as a whole number | R4,691.00 becomes `469100` |
| `weight` | Kilograms | 264 kg becomes `264` |
| `volume` | Litres | 1.082 m³ becomes `1082` |

**Price** is in minor units. Multiply your rand total by 100 and round to a whole number. Don’t send decimals, currency symbols or thousands separators.

**Weight** is in kilograms. Decimals are fine, up to three places. If your system stores grams, divide by 1,000.

**Volume** is in litres. Decimals are fine, up to three places. To convert: one cubic metre is 1,000 litres, and length × width × height in centimetres divided by 1,000 gives litres.

These three feed the capacity warnings shown against each vehicle when you plan, so an order sent in grams instead of kilograms looks a thousand times lighter and won’t trigger a warning it should have. Leave a column blank and it’s treated as zero, which is what you want for a service call with no goods on board.

## 4\. Write addresses that match well

Geocoding turns each written address into map coordinates. It is much more reliable when the address includes the suburb or city and the postal code.

Avoid internal shorthand (“Warehouse 3”, “same as last week”) — those will never place on the map.

## 5\. Add coordinates if you have them

`latitude` and `longitude` are optional, but if your system already holds verified coordinates for your customers, send them.

When both are present, Routelink places the stop exactly where you say and skips the address lookup entirely. That means the row cannot be held back for an unrecognised or ambiguous address, which is the single most effective way to guarantee a clean import. The `address` column is still required, because that’s what the driver reads.

If either one is missing, Routelink falls back to looking up the address text.

A few rules:

*   Use decimal degrees, like `-33.96128` and `18.47215`. Latitude is negative in South Africa.
*   Five decimal places is roughly one metre of accuracy. More is fine.
*   Degrees, minutes and seconds (`33°57'40"S`) are not accepted, and neither is a single combined `lat,lng` field.
*   Leave both blank when you don’t know them. Don’t send `0` — zero is a valid coordinate and would drop the stop in the Atlantic Ocean.

## 6\. Export it from your ERP

Skip this step if you’re working in a spreadsheet by hand.

Alias every column in your query to the exact lowercase names above and the file comes out ready to upload. A query along these lines is usually all it takes:

```
SELECT
    'delivery'                              AS type,
    c.contact_name                          AS name,
    CAST(c.phone AS VARCHAR(20))            AS phone,
    c.company_name                          AS company,
    c.email                                 AS email,
    CONCAT_WS(', ', a.line1, a.line2,
                    a.suburb, a.city,
                    a.postal_code)          AS address,
    o.delivery_instructions                 AS notes,
    o.order_number                          AS reference,
    o.item_summary                          AS description,
    CAST(o.total_units AS INT)              AS quantity,
    CAST(ROUND(o.total_incl_vat * 100, 0)
         AS BIGINT)                         AS price,
    ROUND(o.total_weight_grams / 1000.0, 3) AS weight,
    ROUND(o.total_volume_cm3 / 1000.0, 3)   AS volume,
    a.latitude                              AS latitude,
    a.longitude                             AS longitude
FROM   orders o
JOIN   customers c ON c.id = o.customer_id
JOIN   addresses a ON a.id = o.delivery_address_id
WHERE  o.dispatch_date = @dispatch_date
AND    o.status = 'ready';
```

Adjust the table names and SQL dialect to suit your system. The shape is what matters.

One finished row looks like this — an order of 45 units worth R4,691.00, weighing 264 kg and taking up 1,082 litres:

```
type,name,phone,company,email,address,notes,reference,description,quantity,price,weight,volume,latitude,longitude
delivery,Andy Minnaar,0839423067,,andy@example.co.za,"110 Campground Rd, Rondebosch, Cape Town, 7700",Bell is broken please phone,ORD-0A2FQQLE,"20x 5kg Charcoal bags, 10x 10kg Charcoal bags",45,469100,264,1082,-33.96128,18.47215
```

Note that any value containing a comma — the address and the description here — is wrapped in double quotes. Most export tools handle this for you.

## 7\. Upload and review

Open the planning screen for the day you’re importing into, choose **Upload**, and pick your file.

Every row appears in an editable grid before anything is created, so this is your chance to check the numbers look sensible. You can correct any cell in place, or delete rows you don’t want to bring in. When you’re happy, choose **Import Tasks**.

Anything that fails validation is highlighted with a note explaining the problem, so you can fix it and import again.

## 8\. Check the results before planning

Where no coordinates were supplied, Routelink looks the address up, and a row is held back for review if that lookup returns no match, more than one possible match, or only a partial match — a street that exists with a number that doesn’t, for example. Those rows stay on screen so you can fix the address and retry; everything else imports normally.

Common problems:

*   **Address not found.** Fix the address or place the stop manually on the map. See [An address didn’t geocode](https://routelink.app/help/troubleshooting/an-address-did-not-geocode).
*   **Matched to the wrong place.** Usually caused by a duplicate street name in another suburb. Add the suburb and re-check.
*   **Duplicate rows.** Worth removing before you plan, so you don’t send a driver twice.

Once everything is placed correctly, select your tasks and plan as normal.

## Common mistakes

*   **A misspelled header.** The column is ignored silently. Check the spelling against the table above.
*   **Price sent in rands.** R4,691.00 sent as `4691` imports as R46.91.
*   **Weight sent in grams.** Divide by 1,000 first.
*   **Volume sent in cubic metres or cubic centimetres.** Convert to litres.
*   **Phone exported as a number.** Leading zeros disappear.
*   **Address split across several columns.** Only the one named `address` is read.
*   **`0` sent for unknown coordinates.** Leave the cells empty instead.
*   **`NULL` or `N/A` written into empty text cells.** Leave them genuinely blank.

## Doing it every day

Once the file is right, save the query as a scheduled export in your system so it lands somewhere predictable each morning. The upload itself is then a thirty-second job.

If you’d rather skip the file altogether, orders can be pushed straight into Routelink from your own systems — see our [integrations](https://routelink.app/integrations), or talk to us about connecting your ERP directly.

Still stuck? Email [support@routelink.app](mailto:support@routelink.app) and we'll help you out.
