P6 .xer Files Explained
An .xer file is Primavera P6's native export format, and it's the most common way a P6 schedule changes hands: from contractor to owner, from scheduler to claims consultant, from one software tool to another. It's plain text, which means you can open it and see what's inside. This post covers the structure of the file, the tables that matter for scheduling, the gotchas that cause most import problems, and a checklist for when one lands in your inbox.
What an .xer file is
When you export a project from P6 in its native format, you get an .xer file. It contains the project's data as a set of database tables, written as tab-delimited text. A single .xer can hold one project or several. It can include activities, relationships, WBS, calendars, resources and assignments, activity codes, user-defined fields, and project settings, depending on what was in the project and the export options.
What it does not contain is a picture of the schedule. Layouts, filters, column choices, bar colors, and print settings live elsewhere. Two people can import the same .xer and see completely different screens. If you need someone to see exactly what you saw, send a PDF alongside it.
The file structure
Open an .xer in a text editor and you'll see lines that begin with a marker:
| Marker | Meaning |
|---|---|
ERMHDR | The first line. Header with the P6 version, export date, and some export metadata. |
%T | Start of a table. The table name follows. |
%F | Field names for that table, tab-separated. |
%R | One row of data, tab-separated in the same order as the %F line. |
%E | End of file. |
A trimmed example of the activity table, with tabs shown as spaces and most fields omitted:
%T TASK
%F task_id proj_id wbs_id clndr_id task_code task_name task_type status_code target_drtn_hr_cnt remain_drtn_hr_cnt
%R 10021 501 7730 88 A1000 Footings Area A TT_Task TK_Complete 40 0
%R 10022 501 7730 88 A1010 Underslab Plumbing A TT_Task TK_Active 32 16
%R 10023 501 7731 88 A1020 SOG Pour Area A TT_Task TK_NotStart 16 16
%R 10024 501 7729 90 M1000 Substantial Completion TT_FinMile TK_NotStart 0 0
The numeric IDs (task_id, wbs_id, clndr_id) are P6's internal keys. The task_code is the activity ID people see. Tables reference each other by the internal keys, not by activity ID.
The tables that matter
A full export includes dozens of tables. For scheduling, these are the core:
| Table | What it holds |
|---|---|
PROJECT | Project-level settings, including the data date (last_recalc_date), planned start, and scheduled finish |
PROJWBS | The WBS hierarchy, including the project's root node |
TASK | Activities: IDs, names, types, status, durations, dates, float, constraints |
TASKPRED | Relationships: predecessor, successor, type, and lag |
CALENDAR | Calendars, with work weeks and exceptions encoded in a single text field |
ACTVTYPE, ACTVCODE, TASKACTV | Activity code types, their values, and which activities carry which values |
RSRC, TASKRSRC | Resources and their assignments to activities |
UDFTYPE, UDFVALUE | User-defined field definitions and values |
SCHEDOPTIONS | Scheduling options, such as how out-of-sequence progress is handled |
Durations are in hours
This is the one that catches everyone. P6 stores durations, lags, and float as hours: target_drtn_hr_cnt, remain_drtn_hr_cnt, lag_hr_cnt, total_float_hr_cnt. A 5-day activity on an 8-hour-a-day calendar is stored as 40. On a 10-hour calendar it's 50.
To convert back to days, you need the hours per day for the activity's calendar. If a tool assumes 8 hours everywhere and the project uses 10-hour days, every duration and float value comes in 25% long. If you see durations like 6.25 days on an import, check the calendar's hours per day first.
Relationships
Each row in TASKPRED links a pred_task_id to a task_id with a pred_type (PR_FS, PR_SS, PR_FF, or PR_SF) and a lag_hr_cnt. Relationships to activities in other projects are allowed; they'll reference a pred_proj_id different from the activity's own. If the other project isn't in the file, those links can't be rebuilt, and the activities on either side may become open ends. See relationship types for what each type means.
Activity types and status
task_type tells you whether an activity is a task-dependent activity (TT_Task), a resource-dependent activity (TT_Rsrc), a start milestone (TT_Mile), a finish milestone (TT_FinMile), a level of effort (TT_LOE), or a WBS summary (TT_WBS). status_code is TK_NotStart, TK_Active, or TK_Complete. Actual dates are in act_start_date and act_end_date.
Calendars
The CALENDAR table holds each calendar's name, type (global, project, or resource), hours per day, and a clndr_data field that encodes the work week and every exception in a compact nested format. Exceptions are stored as date serial numbers rather than readable dates. Calendars are where imports most often go quietly wrong: a missing holiday or a misread work week shifts every date without producing an error. Calendars, holidays, and weather days covers why calendars matter so much.
What's not in the file, or not always
- Baselines. A baseline in P6 is a separate project. It travels in an .xer only if the person exporting included it, usually as its own project in the file. If you're reviewing an update against a baseline, ask for both or ask for the baseline separately.
- Global data that wasn't used. Exports typically include only the calendars, codes, and resources the exported projects reference.
- Layouts and filters. As above, not included.
- Reliable calculated values. Early dates, late dates, and float are stored from the last time the schedule was calculated. If someone edited logic and exported without rescheduling, the stored dates and the logic disagree. Reschedule after import and compare.
Encoding and version issues
An .xer is text, so it has a character encoding. P6 exports have commonly used a Windows code page rather than UTF-8. Activity names with accented characters, special dashes, or symbols can come through garbled if the reading tool guesses the wrong encoding. If names look mangled, that's usually why.
The header line records the P6 version that produced the file. Newer P6 versions add fields and tables. Older tools reading a newer file usually ignore what they don't recognize. Going the other direction (a newer file into an older P6) can fail. If an import fails outright, the version mismatch is the first thing to check.
A checklist when you receive an .xer
- Check the header. Which P6 version, and when was it exported?
- Confirm the projects. How many are in the file, and is the baseline there if you need it?
- Check the data date. It's
last_recalc_datein thePROJECTtable. It should match the update period. - Check calendars. Hours per day, work week, holidays. Spot-check a few activities' durations in days.
- Reschedule and compare. Calculate the schedule after import and compare the finish date and a few activities' float to what the sender reported. A difference means a setting, a calendar, or the stored dates don't match the logic.
- Count relationships and open ends. Activities with no predecessor or no successor beyond the start and finish milestones should be rare. A DCMA 14-point check covers this and more.
- Look at constraints. Hard constraints in the
TASKtable (cstr_type,cstr_date) can hold dates in place regardless of logic. - Ask for a PDF of the layout the sender uses, so you know what they were looking at.
Reading one without P6
You don't need a P6 license to look inside an .xer. Any text editor will open it, and a spreadsheet can split the tab-delimited rows into columns once you separate the tables. That's enough to answer quick questions: how many activities, what calendars, what's the data date.
For anything more, you want a tool that rebuilds the network and recalculates it. schedule.construction imports .xer files directly in the browser, so you can review the network and run DCMA-style quality checks without a P6 seat. Whatever you use, verify the calculated finish against the sender's, per step 5 above. For moving schedules the other way, or between other tools, see moving schedules between P6, MS Project, and everything else.
Key takeaways
- An .xer is tab-delimited text:
%Tstarts a table,%Flists fields,%Ris a row. - Durations, lags, and float are stored in hours. Convert using each calendar's hours per day.
- Baselines and layouts don't travel unless someone deliberately includes them.
- Stored dates reflect the last calculation, not necessarily the current logic. Reschedule after import and compare.
- Calendars and encoding are the usual sources of quiet import errors.