How to create an organizational chart from CSV

How to turn an HRIS CSV export into a chart of the reporting line: resolve employee_id and manager_id to row numbers, invert the direction the manager column points, and handle orphans and cycles.

A worked example, stage by stage

  1. Read the row, check for a manager

    The first rows do nothing but read the file: "Raise a request against a cost centre", then "Read the requester's row from the HRIS export", then the diamond "Does the row name a manager?". Its No route goes to "Ask the People team to correct the reporting line", because a blank manager_id is a data problem before it is a routing problem. Only the Shape column is filled in at this stage, so the rows are still a list.

  2. Walk manager_id up the file

    "Walk manager_id up to build the approval chain" is the row that does the work, and the three diamonds after it are the checks that walk needs. "Is the requester inside their own approval chain?" catches the cycle, "Is the named approver available?" routes to a delegate, and "Within the line manager's approval limit?" decides whether one signature ends it. Line to now holds row numbers, so the arrows exist, but nothing yet says which exit is which.

  3. Label the escalation branches

    Line text pairs with Line to by position, so "Within limit,Over limit" sends the first number to a signature and the second to "Escalate to the department head". The same pair repeats at the department head and again at the director, which is the escalation ladder your approval-limit column already encodes. Row 18 closes it out with "Take it to the executive committee or withdraw it?".

  4. Add the two lane columns

    The Horizontal lane column carries the level in the reporting line (Employee, Line manager, Department head, Director, Executive committee), so depth in the org tree becomes distance across the canvas. The Vertical lane column carries the function: Requesting line, Finance, People team, Executive office. With both filled in you can read off that the People team appears only when the export was wrong, and Finance only when the spend sits on another line's cost centre.

How it works

  1. Export the columns the routing depends on

    You need employee_id, manager_id and a readable name for each person. Add job title, cost centre, approval limit and any delegate column, because those are what decide where a request stops climbing. Leave out everything the chart will never show (salary, address, start date), since a narrower file is far easier to check by eye, and an unrecognised column is carried through the paste and ignored anyway.

  2. Read the file as text before a spreadsheet does

    Open the export in a text editor first. Check that the delimiter is a comma and not a semicolon, that names containing a comma are wrapped in double quotes, that the file is UTF-8 so accented names survive, and that the first header really is employee_id rather than a byte-order mark followed by employee_id. Each of these fails quietly: columns are matched on header name, so a header that is not exactly what you think it is matches nothing.

  3. Decide which of the two diagrams you are building

    A box per person, arranged by who reports to whom, is a tree and belongs in the org-chart editor. A path a request travels through the reporting line is a flowchart and belongs here: one row per step rather than one row per person, with the export supplying the levels, the limits and the delegates. Decide this before you start numbering rows, because the two shapes do not convert into each other.

  4. Invert manager_id into row numbers

    Sort the rows into the order you want them numbered first, because Line to refers to positions and renumbering afterwards rewires everything. Then, for each person, collect the row numbers of everyone whose manager_id equals that person's employee_id and put them in that person's Line to, comma-separated. Reports become outgoing arrows; manager_id is only the lookup key and never gets pasted into Line to itself.

  5. Resolve the orphans and the cycles in the file

    Sort by manager_id and confirm every value appears as an employee_id somewhere in the same file. The ones that do not are orphans, usually because the export was scoped to one department or to active staff only. Then walk each chain upward and stop if you revisit a row: a pair of rows naming each other is a cycle, and it is either an acting arrangement nobody closed out or two rows edited on the same day by different people.

  6. Paste it in, then add shapes and lanes

    Drop the .csv onto the spreadsheet area of a new chart, or paste the CSV text into it. Set Shape to Decision on the rows that ask a question and Start, Success and Reject on the terminators, put the answers into Line text in the same order as the Line to numbers, and put the level of authority into the Horizontal lane column so each rung of the reporting line gets a lane of its own.

Frequently asked questions

Can QueryChart import an org chart CSV directly?

You get the rows in by dropping the .csv onto the spreadsheet area or pasting the CSV text into it, and columns are matched by header name rather than by position, so the order they sit in does not matter and anything unrecognised is carried through and ignored. What it will not do is infer a hierarchy for you: there is no import wizard, no column-mapping screen and no connector to an HR system. The file has to already say, in the Line to column, which row numbers each row connects to.

Should I use the flowchart editor or the org-chart editor?

If the output is a headcount tree (a box per person, managers above reports, read to answer who reports to whom), use the dedicated org-chart editor, which is built for that shape and keeps a single parent per person. Use the flowchart editor when the reporting line is a route rather than a picture: an approval that climbs until it meets someone with a high enough limit, an escalation path, a request that has to detour through Finance. Those have decisions and exceptions in them, and a decision is not something a tree can draw.

What happens if two people report to each other?

The chart will draw it (a pair of arrows pointing at each other), but anything that walks the chain to the top will not terminate, which is why you check for cycles in the file rather than after the paste. In practice a cycle is an acting arrangement nobody closed out, or two rows edited on the same day by different people. The example chart guards against the routing version of the same problem with the decision "Is the requester inside their own approval chain?", which skips a level instead of looping.

My export is semicolon-delimited and some names contain commas.

Both are normal for HRIS exports and both are fixable in the file. A semicolon-delimited export (common when the system was configured for a European locale) should be re-exported or converted to commas; paste it as it stands and the whole header row lands in a single column, which at least fails obviously rather than subtly. A value containing a comma is legal as long as it is wrapped in double quotes, so "Nakamura, Yuki" stays one field while the same text unquoted becomes two.

How do I keep the chart current when the HRIS changes?

By re-exporting and re-pasting, not by connecting the two: there is no live link between QueryChart and an HR system. That matters less than it sounds, because what you drew is the routing rule rather than the roster: "escalate to the department head when the amount is over the line manager's limit" survives a reorganisation that changes every name in the file. Redo the export when the levels or the limits change and leave it alone when only the people do. /csv-to-flowchart has the short version of the whole conversion.

Open the reporting-line example

The template behind this guide

CSV organizational chart template (approval authority by reporting line) — Turn an HRIS CSV export into a flowchart of who may sign what. The manager_id column becomes an escalation ladder, three authority limits sit on the decisions, and self-approval, delegation and cross-charging each get a route.

More in Process mapping guides