Import a schedule from your ERP
Turn a CSV or Excel export from your ERP into scheduled jobs.
The importer is a wizard that reads your export, shows you what it plans to create, and writes nothing until you press the button on the last step. It runs entirely against the file you upload: SAP, Epicor, Oracle and a hand-built spreadsheet all go through the same six steps.
Two of those steps are yours to get right. Check columns decides which of your columns feeds which field, and Preview is the last place to catch a part that is about to be created by mistake.
Before you start
- Production Scheduler is part of the Scheduling Engine module. The tab strip renders for every organization, so seeing the Scheduler tab is not proof you are entitled to it. See Module entitlement.
- A CSV or Excel export from your ERP, with one row per task.
- Owner or Administrator, because an import can create parts and operations for the whole organization. The Import button itself is not role-gated in the dashboard. See Roles reference.
Prepare the file
Export your schedule as CSV, .xlsx or .xls. Each row becomes one task, and rows that share a value in the order column become one job. That is the row grouping, and it is the behavior you want from a routing export: if your ERP writes one row per operation, leave the file as it is and let the importer group it.
Only two fields have to be mapped: Job / Order number and Task name. Everything else is optional, and a column you do not map is either ignored or kept in the task's notes.
Map the smallest set that gets a usable schedule on the first import. Order number, task name, quantity and due date are enough to see the week on the board. Add the part, operation and machine columns on the next import, once you trust what the matching is doing.
The header row does not have to be the first row. The parser scans the first ten rows of each sheet and picks the one that looks most like headers, so the title and filter rows that ERP exports put on top are fine. Two columns with the same header are read as Resource and Resource (2); a column with no header at all becomes Column 7.
Does the file leave my browser?
No. Parsing, column detection, date parsing and status translation all run locally, with no network call and no AI. The only thing sent to IoTFlows is the jobs and tasks you confirm on the last step.
If you would rather start from a file that already fits, press Download sample template on the upload step. It writes schedule-import-template.csv, one column per mappable field with an example value, and five rows across two order numbers so you can see the grouping.
Upload the file
- Open the Scheduler tab of the Production page. See Open the board.
- Press Import in the control bar, at the right of the row above the board.
- Drag the export onto the drop zone, or click it to browse.
Uploading the export from your ERP. CSV and Excel are both accepted.
A parsed file shows as a card reading the file name and 412 rows · 17 columns. Press Continue on the card, or the button in the footer.
If the workbook has more than one sheet, the dialog lists every non-empty sheet with its row count and waits for you to pick one. It never guesses across sheets.
If the file will not upload
| What you see | What happened |
|---|---|
| Please upload a .csv, .xlsx or .xls file. | The file has another extension. Re-export it. |
| No data found in this workbook. | Every sheet in the workbook is empty, or has headers with no rows under them. |
| No columns detected. Make sure one of the first rows contains headers. | The parser found no header-like row in the first ten rows. Delete the preamble above your headers. |
| No data rows found in the file. | The sheet has headers and nothing else. |
Read file
The Read file step has nothing to decide. IoTFlows matches each of your headers to a field by keyword, guesses the date format from the values in your due-date column, seeds the ERP status codes, and loads your parts, operations, machines, members, priorities and existing production jobs so the later steps can match against them.
Detection is a header-keyword match, not a reading of your data. Each header is scored against every field's keyword list and assigned to its best match, and no column is used twice, so Prodn Supervisor lands on Assignee and Confirmed Finish Date lands on Due date without either being named in the field list.
If you have saved a setup whose column headers are exactly this file's headers, it is applied here and the dialog toasts Applied your saved setup "SAP weekly export". See Save the mapping for next time.
The step ends on Check columns by itself.
Check the columns
This is the step that decides what your file means. Each row names an IoTFlows field on the left and carries a Column in your file drop-down on the right. Choose Not in my file to leave a field unmapped.
A field the detector filled carries a green ✓ auto-matched chip. A required field it could not fill is lifted into a Please check these first section at the top of the panel, and the footer button stays disabled until both required fields are mapped.
Checking the column mapping. Only Job / Order number and Task name are required.
Import fields
| Field | Section | Required | Matches against | Example | Auto-detected from |
|---|---|---|---|---|---|
| Job / Order number | Required | Yes | Existing production jobs, by title | PO-1001 | order, job, work order, wo, production order, job num, job number |
| Task name | Required | Yes | Your parts by name, when Part is unmapped or does not match | Engrave Nameplate 2-1/2 x 1 | task name, task, material description, item description, op desc, operation description |
| Part | Common | No | Your parts, by part number first and then by name | Y841070 | material number, part number, part, item number, sku |
| Operation | Common | No | Operations on the matched part, by name | Engraving | operation, op, routing operation, routing, activity, process, op code, op seq |
| Quantity | Common | No | Nothing. 1.000 is read as 1 | 25 | order quantity, quantity, qty, order qty |
| Due date | Common | No | Nothing. Parsed with the format you pick below | 11/04/2025 | confirmed finish date, due date, due, finish date, need by, ship date |
| Status | Common | No | The status table below | Open | system status, status, order state, state |
| Assignee | Common | No | Members, by username, email or full name | jsmith | assignee, assigned to, owner, prodn supervisor, supervisor, operator |
| Asset / Machine | Common | No | Machines, by custom name, custom ID, machine name or machine ID | Laser-01 | asset, machine, work center, workcenter, resource, equipment, resource id, resource desc |
| Priority | Advanced | No | Your work order priorities, by name | High | priority |
| Time estimate | Advanced | No | Nothing. Reads 2h 30m, 1.5h, 90m, 1d, or a bare number as minutes | 2h 30m | time estimate, duration, estimate, run time, runtime, hours |
| Budget | Advanced | No | Nothing. $1,250.50 is read as 1250.50 | 500 | budget, cost, amount |
| Description | Advanced | No | Nothing | Customer rush order | description, details, long description |
| Notes | Advanced | No | Nothing | Handle with care | notes, note, comment, comments, remarks |
| Setup hours | Advanced | No | Nothing. Added to production hours | 0.5 | est setup hours, setup hours, setup time, setup |
| Production hours | Advanced | No | Nothing. Added to setup hours | 3.0 | est prod hours, prod hours, production hours, run hours, labor hours |
The Section column is how the importer classifies a field, not a heading you will see. The panel shows anything needing attention first and folds the rest under Everything else we matched.
Setup and production hours beat Time estimate. When either is mapped, their sum in hours becomes the task's time estimate and a mapped Time estimate column is ignored. When none of the three is mapped and the row matched an operation that has a cycle time, IoTFlows estimates the task from that cycle time and the quantity.
Columns with no field of their own are listed under Extra columns as chips. Click any you want to keep and its values are written into each task's notes as Customer PO: 44812, one line per column.
Tell the importer how to read your dates
11/4/25 is November 4 in one plant and March 11 in another, so the date format is a choice, not a guess. Pick one from My file's dates look like and the panel parses the first date in your file next to it: "11/4/2025" → 2025-11-04 in green, or "11/4/2025" doesn't match, try another option in red.
The options are month/day/year with a four-digit or two-digit year, 4.11.2025, ISO 2025-11-04, compact 20251104, an Excel date number, and Auto-detect per value. A two-digit year of 00 to 69 reads as 2000s, 70 to 99 as 1900s.
Dates land at noon in your organization's timezone, so a day-only date cannot drift across a date boundary. 00/00/0000 is read as a deliberate blank. Anything else that will not parse leaves that task with no due date and adds to the Invalid dates count on the preview.
Status translation
When a Status column is mapped, the panel lists each ERP code it knows about next to what it will become. Change any of them, and the change travels with the saved setup.
| ERP token | Maps to |
|---|---|
CRTD | Open |
REL | Open |
PCNF | In Progress |
CNF | In Progress |
PRC | In Progress |
TECO | Completed |
CLSD | Completed |
DLV | Completed |
Plain English works with no codes at all. open, new, todo and backlog become Open; in progress, started, active and running become In Progress; on hold, hold, paused and blocked become On Hold; closed, complete, done and finished become Completed; approved, accepted and signed off become Approved. A value it does not recognize imports as Open.
Why did a closed order import as closed when the cell says six things?
SAP writes every active status at once, for example CLSD PRT CNF DLV PRC GMPS MACM SETC. The importer does not take the first token: it takes the most advanced one it recognizes, in the order Approved, Completed, On Hold, In Progress, Open. A trailing * on a truncated token is stripped first.
Match people
The Match people step appears only when an Assignee column is mapped. It lists every distinct value in that column with the number of tasks behind it, and what each one resolved to.
A value matches a member on their username, email address or full name. It does not match on the IoTFlows organization handle, which never appears in an ERP export.
Matching is fuzzy, meaning a value does not have to be written exactly the way IoTFlows has it. The importer tries the exact value, then the value with case and punctuation flattened, then a match on shared words, then a spelling that differs by no more than two characters. Approximate matches are worth a look: J. Smith and jsmith both land on Jane Smith, but so could jsmyth.
Matching assignee names from your ERP to IoTFlows members.
For anything left over, open Assign to member and pick the person, or pick Leave unassigned to say that the value is not a member at all. Match automatically puts the row back to whatever the fuzzy match found.
Every choice you make here is remembered for this organization, so the same supervisor code resolves by itself on every future import. Open Saved people at the bottom of the step to review or remove them. The list lives in this browser, not on the server, so a colleague importing from their own machine starts with an empty one.
Leaving a value unmatched is not an error. Those tasks import with no assignee, and the footer button says so: Continue - 2 left unmatched.
Check the preview
The preview is exactly what will be created. Five tiles across the top count New jobs, Added to existing, Tasks, New parts and Invalid dates.
An order number that already has a job is reused, not duplicated. Its tasks are added under the existing job, and the tile counts it as Added to existing. The match is case-insensitive, against the first word of an existing job's title, which is what the importer titles a job it creates.
Importing the same file twice
Jobs are deduplicated; tasks are not. Re-importing a file you already imported attaches a second copy of every task to the same job. Narrow the export to the rows that are new, or hide the rows you already have before importing.
The preview. Parts that do not match are auto-created, which is the main source of duplicates after an import.
What gets created alongside the tasks
A part your file names that your organization does not have is created rather than skipped, because a task with no part and no operation schedules nothing. Those creations are collected in a panel headed We'll add 4 new items to your system, where every name is editable.
- A name that already exists wins over creating. Before a part is slated for creation, its name is checked against your parts, and an exact match links the row to that part instead. The row is tagged matched by name in the table.
- Each new part gets at least one operation, because a part with none cannot carry a task. With an Operation column mapped, the operation takes the file's value: a bare
20becomesOP20, a code likeMILLstaysMILL. With no operation column, they are namedOP10,OP20,OP30by position. - Parts you already have that carry no operation get one too, listed separately under Existing parts that need an operation.
- Every part the import creates is stamped with
[ERP import weekly.xlsx 2026-09-20]in its description, so the whole set is findable afterwards.
On any row you can rename the part, choose Link to existing… to point it at a part you already have, or tick Skip to create nothing.
Auto-created parts are the main source of duplicates
A part number your ERP writes as Y841070 and IoTFlows holds as Y-841070 will not match, so the import creates a second part, and every count and cost against it lands on the wrong record. Read the new-items panel before importing, and link anything you recognize.
Fix rows in the table
Open What we matched to your system for a field-by-field count of what matched and what did not: assignees, machines and priorities that found nothing import blank, and are listed here rather than left for you to find on the board.
Everything in the table is editable. Click a cell to change the task name, quantity, due date, time estimate, part, operation, machine, priority, assignee or status, and click the eye icon on a row to hide it. Hidden rows are struck through, tagged won't import, and dropped from the totals and from the creation plan.
A small amber dot next to a matched value means it was matched approximately rather than exactly. Use Columns to show a field your file did not map, or to hide one you do not want to read.
The footer button counts what you are about to create: Import 12 jobs · 47 tasks. Nothing has been written up to this point.
Run the import
Press the button. The importer creates the new parts and operations first, then each job, then its tasks. A progress bar tracks each phase, and the Parts & operations bar appears only on a run that is creating parts.
The Import step after it finishes: what was created, what did not fully go through, and the two downloads.
Leave the dialog open while it runs. The close button is disabled until it finishes, and closing afterwards refreshes the board behind it.
When it is done you get Import complete, a count of tasks created, skipped and failed, and a toast reading Imported 47 tasks · created 4 parts. Download report writes a CSV with one row per imported row, carrying the result, the reason and the new work order's ID.
When rows do not import
Anything that did not fully go through is listed under the counters, in red when the thing does not exist and amber when it exists but is incomplete.
| What you see | What happened |
|---|---|
| Part "Y841070" could not be created | The part was not created. Its tasks still import, without a part or an operation. |
| Could not add operations to "Bracket" | The part exists with no operation, so its tasks import with no operation. |
| Job PO-1001 could not be created | The job failed, and none of its tasks were imported. |
| Task "Deburr & Inspect" (order PO-1002) could not be created | That one task was not created. Everything else in the job was. |
| Task "Anodize" (order PO-1002) was created, but its status did not save | The task exists and reads Open. Set the status on the board. |
| 3 tasks failed. Download the retry file to re-send them | A toast summarizing the red rows above. |
| Imported with 2 warnings. Some details didn't save (retry file available) | Everything was created, but a detail on two of them did not save. |
Download retry file writes a JSON file holding every failed call with its endpoint and payload. It is not something you can re-upload here: it exists so the failure can be diagnosed or replayed by IoTFlows. Send it with your support request. See Get support.
A generic Something went wrong or An error occurred means the request failed and nothing was saved.
Save the mapping for next time
A mapping profile, called a saved setup on screen, is one named copy of everything you decided on the Check columns step: the column mapping, the extra columns you kept in notes, the status code map and the date format.
Saving the mapping so the next import from the same ERP skips the mapping step.
To save one, type a name into Save current setup as… at the top of the Check columns step and press Save. Name it after the export, not the week: SAP weekly export rather than Week 38.
The next file whose headers are exactly the same, in the same order, picks it up on the Read file step by itself and the row reads Applied. Headers have to match exactly, which is deliberate: an SAP setup can never be applied to an Epicor file.
Change anything after a setup is applied and the row stops reading Applied. Re-apply puts the saved values back, and Revert goes back to what the detector suggested. The trash icon deletes a setup.
You do not need a saved setup for a one-off file. Detection fills most of the panel on its own, and a setup that only ever matches one file is a name to remember for nothing. Save one when the same export lands every week.
Saved setups live in your browser
Both saved setups and saved people are stored in this browser for this organization, not on the server. A colleague importing the same export from their own machine gets none of it, and clearing site data loses all of it. Two people who both run imports should each save their own.
Clean up after an import
Work through this in the first few minutes, while the result screen is still open.
- Archive the parts you did not mean to create. Archive created parts on the result screen archives every part that import created, in one click. It is the fastest way out of a run that matched nothing, and it is only on screen until you close the dialog.
- Find the rest by their tag. Parts created by an import carry
[ERP import <file> <date>]in their description, so an import you cleaned up a day later is still identifiable. Archiving a part cannot be undone from the dashboard, so read the name before you archive it. See Edit or delete. - Fill in the blanks the matching left. Assignees, machines and priorities that matched nothing imported empty. The What we matched to your system panel counted them, and the board is where you set them: see Edit in place.
- Give the undated tasks dates. Tasks that imported with an unparseable date have no due date, so they sit outside the Gantt's timeline. See Schedule work that has no dates.
- Delete what should not be there. Jobs in the scheduler control bar opens the job list, where a job can be renamed or deleted. Individual tasks are deleted from the board, and a deleted work order is recoverable on the server for 30 days: see Undo and redo.
Then read the board. An import of a few hundred tasks usually double-books something, and the issues panel is the fastest way to see what: Find and fix problems in the schedule.
See also
The Schedule issues pill on the scheduler Gantt is the one place that lists everything wrong with the board: machines booked twice at the same time, serialized pieces two work orders both need, tooling with no units free, past-due work and work waiting on a predecessor that cannot finish in time. It is always on screen, including at zero, and its count is distinct work orders rather than findings. Conflicts and violations come first and carry one-click fixes that move the task to the earliest free slot; the two at-risk sections come last and are folded, because moving an overdue job's date is a judgment call rather than a repair.
Board membership decides who can be assigned work on the Scheduler. Your organization has one production board, and you add people to it as named members or as whole teams. The Invite to Scheduler dialog writes as you click, with no Save step: one click adds a person or a team, a crown marks a board owner, and a trash icon removes access. Owner is recorded on the board but the dashboard does not gate anything on it today.







