diff --git a/docs/changes-report.html b/docs/changes-report.html index 99bc7152d9..d3ec969a35 100644 --- a/docs/changes-report.html +++ b/docs/changes-report.html @@ -33,7 +33,7 @@ diff --git a/docs/changes.rss b/docs/changes.rss index 8a86172726..e8d0baab69 100644 --- a/docs/changes.rss +++ b/docs/changes.rss @@ -5,17 +5,17 @@ http://mpxj.org/changes-report.html These are the latest changes of this project. en - Fri, 08 Nov 2024 19:27:02 GMT + Wed, 13 Nov 2024 17:12:08 GMT Jon Iles - 2024-11-08T19:27:02Z + 2024-11-13T17:12:08Z en 13.6.1 http://mpxj.org/changes-report.html#a13.6.1 <p>Version 13.6.1 is available with 1 fixed issues.</p> - Fri, 08 Nov 2024 19:27:02 GMT + Wed, 13 Nov 2024 17:12:08 GMT http://mpxj.org/changes-report.html#a13.6.1 - 2024-11-08T19:27:02Z + 2024-11-13T17:12:08Z diff --git a/docs/dependency-updates-report.html b/docs/dependency-updates-report.html index 8df6614e2b..759c1a82c0 100644 --- a/docs/dependency-updates-report.html +++ b/docs/dependency-updates-report.html @@ -32,7 +32,7 @@ diff --git a/docs/faq/index.html b/docs/faq/index.html index a214dddd1a..462add4476 100644 --- a/docs/faq/index.html +++ b/docs/faq/index.html @@ -1904,6 +1904,14 @@

.NET

something like this: <Project Sdk="Microsoft.NET.Sdk">. If your csproj file is different you will need to create a new SDK-style project. Sample projects in this form can be found in this repository.

+

I have an application which uses MPXJ.Net and runs fine on my local machine, +but fails with a Segmentation Fault when run in Docker +When using Docker to host an application built with MPXJ.Net, you may find +that the application crashes with a segmentation fault when invoking MPXJ.Net +code. The issue is likely to be a library missing from the Docker image. +Adding the following line to your Dockerfile will ensure that the +most common missing library is added: +RUN apt-get update && apt-get install -y libfontconfig

log4j2

When you start MPXJ, you may see the following message written to the console:

ERROR StatusLogger Log4j2 could not find a logging implementation.
diff --git a/docs/issue-management.html b/docs/issue-management.html
index c0e02731b1..5a16316fbf 100644
--- a/docs/issue-management.html
+++ b/docs/issue-management.html
@@ -32,7 +32,7 @@
 
         
       
diff --git a/docs/mailing-lists.html b/docs/mailing-lists.html
index ea31c0490b..9f70f5c58c 100644
--- a/docs/mailing-lists.html
+++ b/docs/mailing-lists.html
@@ -32,7 +32,7 @@
 
         
       
diff --git a/docs/plugin-updates-report.html b/docs/plugin-updates-report.html
index 3ac96cbed7..ed685e4f89 100644
--- a/docs/plugin-updates-report.html
+++ b/docs/plugin-updates-report.html
@@ -32,7 +32,7 @@
 
         
       
diff --git a/docs/project-info.html b/docs/project-info.html
index 311fb198fc..3076e62926 100644
--- a/docs/project-info.html
+++ b/docs/project-info.html
@@ -32,7 +32,7 @@
 
         
       
diff --git a/docs/project-reports.html b/docs/project-reports.html
index 64a03fc667..1bb0433e3f 100644
--- a/docs/project-reports.html
+++ b/docs/project-reports.html
@@ -32,7 +32,7 @@
 
         
       
diff --git a/docs/scm.html b/docs/scm.html
index 36c2387d55..16c6c6abcc 100644
--- a/docs/scm.html
+++ b/docs/scm.html
@@ -32,7 +32,7 @@
 
         
       
diff --git a/docs/search/search_index.json b/docs/search/search_index.json
index 5497c5c4f7..5f2baf933f 100644
--- a/docs/search/search_index.json
+++ b/docs/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Introduction","text":"

Welcome to MPXJ! This library enables you to read project plans (sometimes known as schedules or programmes) from a variety of file formats and databases, and can also write that information to a variety of file formats.

The library is based on data structures which follow the way schedule data is represented by Microsoft Project, extended to accommodate features and concepts from other applications.

"},{"location":"#sponsors","title":"Sponsors","text":"

Work to build and maintain MPXJ is kindly supported by my sponsors:

Head over to my sponsors page if you'd like to see your name and logo here, or if you just want to say thanks you could buy me a coffee!

"},{"location":"#file-formats","title":"File Formats","text":"

MPXJ can read file formats including MPX, MPP, MSPDI, MPD, Planner, Primavera P6 PMXML and XER, Primavera P3, SureTrak, Asta Powerproject, Asta Easyplan, Phoenix, Fasttrack, GanttProject, TurboProject, ConceptDraw PROJECT, Synchro, Gantt Designer, SDEF, Sage 100 Contractor Schedule Grid, Project Commander and Deltek Open Plan BK3.

MPXJ can also write schedule data as MPX, MSPDI, PMXML, XER, Planner and SDEF files.

More details of the supported file formats can be found here.

"},{"location":"#languages","title":"Languages","text":"

MPXJ is written and maintained in Java, however this is no barrier to using its functionality in other languages. Thanks to IKVM, MPXJ is available for .Net, allowing it to be used from any .Net language.

There is also now a Ruby Gem which provides native Ruby access to read from schedule files using MPXJ, and a Python package which wraps the Java library to provide full read/write access to schedule files.

You may be able to leverage MPXJ from other languages too, for example the PHP/Java Bridge can be used to expose the complete MPXJ API in PHP.

"},{"location":"#contact","title":"Contact","text":"

Having problems? Need support? All the details you need can be found on the support page.

Using MPXJ successfully somewhere? I'd love to hear from you about your experiences. Do tell me what's missing or what could be better - I can use this feedback to guide future development work. It would also be great to add a link to your website from the MPXJ users page.

Finally, if you're deriving value from MPXJ, please consider sponsoring me, to ensure I can continue enhancing and maintaining the library, or just buy me a coffee - thank you!

"},{"location":"#licensing","title":"Licensing","text":"

MPXJ is distributed under the terms of the GNU LGPL a copy of which can be found in the root of the distribution. Please read this license carefully! It will cost you nothing to use MPXJ commercially or non-commercially, but you must comply with the terms of the license.

Please see the legal folder within the distribution for details of the licences for the third party libraries used by MPXJ.

"},{"location":"#acknowledgements","title":"Acknowledgements","text":"

This library includes functionality provided by:

  • POI
  • IKVM
  • RTF Parser Kit
  • SQLITE-JDBC
  • ZLIB/CONTRIB
  • JWAT
  • JSOUP

This library has been built with the assistance of:

  • JProfiler
  • Araxis Merge
"},{"location":"CHANGELOG/","title":"Changelog","text":""},{"location":"CHANGELOG/#1361-unreleased","title":"13.6.1 (unreleased)","text":"
  • Update the MPXJ ruby gem to allow access to calendar data.
"},{"location":"CHANGELOG/#1360-2024-11-06","title":"13.6.0 (2024-11-06)","text":"
  • Added the Task.getBaselineTask() methods. For applications where a separate baseline schedule is present or a baseline has been manually added to the ProjectFile instance, these methods will allow you to access the underlying baseline task instance from the current task instance.
  • Added the Activity Percent Complete attribute to the Task class. The value of this attribute will be the Duration, Physical or Units percent complete value, based on the Percent Complete Type setting. This attribute is provided as a convenience to match the Activity Percent Complete type value shown in P6.
  • Improve retrieval of custom field values for certain MPP files.
  • Improve handling of PMXML files with more than 11 baselines.
  • Improve handling of unexpected data types when writing JSON files.
  • Added the Relation.getPredecessorTask() and Relation.getSuccessorTask() methods.
  • Marked the Relation.getSourceTask() and Relation.getTargetTask() methods as deprecated, use the Relation.getPredecessorTask() and Relation.getSuccessorTask() instead.
  • Ensure that with \"Link Cross Project Relations\" enabled when reading XER or PMXML files, the predecessor and successor lists for both tasks related acrosss projects are correctly populated.
"},{"location":"CHANGELOG/#1351-2024-10-28","title":"13.5.1 (2024-10-28)","text":"
  • Fix CVE-2024-49771: Potential Path Traversal Vulnerability (Contributed by yyjLF and sprinkle).
"},{"location":"CHANGELOG/#1350-2024-10-17","title":"13.5.0 (2024-10-17)","text":"
  • Added support for reading and writing Resource Role Assignments for Primavera schedules. The Resource.getRoleAssignments() method retrieves a map representing the roles a resource is assigned to, along with the skill level for each assignment. The Resource.addRoleAssignment() and Resource.removeRoleAssignment() methods allow role assignments to be added and removed.
  • Added support for the Resource Primary Role attribute, which is read from and written to Primavera schedules.
  • Improve handling Boolean attributes with default values when reading XER files.
  • Added the getShowStartText, getShowFinishText and getShowDurationText methods to the Task class. When working with manually scheduled tasks in Microsoft Project, users can potentially supply arbitrary text for the Start, Finish and Duration attributes. Microsoft Project still stores appropriate values for these attributes, which can be accessed in MPXJ as Start, Finish and Duration, but where the user has supplied text, these attributes are available as Start Text, Finish Text, and Duration Text. The methods added by this change allow the caller to determine which version of each attribute should be shown to the user in order to replicate what they see in Microsoft Project.
"},{"location":"CHANGELOG/#1342-2024-10-08","title":"13.4.2 (2024-10-08)","text":"
  • Added the ProjectCalendarDays.getCalendarHours() method to allow direct access to the ProjectCalendarHours instances for each day of the week.
"},{"location":"CHANGELOG/#1341-2024-10-07","title":"13.4.1 (2024-10-07)","text":"
  • Added the ProjectCalendarDays.getCalendarDayTypes() method to allow direct access to the DayType instances for each day of the week.
"},{"location":"CHANGELOG/#1340-2024-09-18","title":"13.4.0 (2024-09-18)","text":"
  • Added support for reading and writing resource shifts for P6 schedules.
  • Ensure the Scheduling Progressed Activities project property is populated when reading Phoenix schedules.
  • When reading milestones from an Asta schedule, ensure that the Activity Type attribute is populated to allow start milestones and finish milestones to be differentiated.
  • Fix an issue which occurred when writing MSPDI files with manually scheduled tasks starting on non-working days where their timephased data is split as days.
"},{"location":"CHANGELOG/#1331-2024-08-30","title":"13.3.1 (2024-08-30)","text":"
  • Handle duplicate custom field value unique IDs when reading MSPDI files.
  • Handle missing remaining early start date when reading timephased data from a P6 schedule.
"},{"location":"CHANGELOG/#1330-2024-08-22","title":"13.3.0 (2024-08-22)","text":"
  • When reading multiple Primavera schedules from the same source, MPXJ now ensures that instances of activity code definitions, user defined field definitions, locations, units of measure, expense categories, cost accounts, work contours, and notes topics are shared across projects. This will allow you to, for example, filter tasks from multiple projects using a Location instance. Previously each project had its own independent instances for each of these types, which could not be used across multiple projects.
  • When reading Powerproject schedules, ensure that the Activity ID attribute for WBS entries is populated using Powerproject's Unique Task ID attribute.
  • Add support for reading timephased planned work from MPP files for manually scheduled tasks (Contributed by Fabian Schmidt).
"},{"location":"CHANGELOG/#1322-2024-08-14","title":"13.2.2 (2024-08-14)","text":"
  • Add missing constructors to TimephasedCost and TimephasedWork in MPXJ.Net.
"},{"location":"CHANGELOG/#1321-2024-08-13","title":"13.2.1 (2024-08-13)","text":"
  • Make the MPXJ.Net assembly strong named.
"},{"location":"CHANGELOG/#1320-2024-08-12","title":"13.2.0 (2024-08-12)","text":"
  • Implemented the UserDefinedField.Builder class.
  • Marked the UserDefinedField constructor as deprecated. Use the builder class instead.
  • Marked the UserDefinedField.setDataType() method as deprecated. Use the builder class instead.
  • Updated to address an issue when writing XER files where a project does not have an explicit Unique ID value, and there are project UDF values.
  • Added the convenience method ActivityCode.addValue to make it easier to add a value to an activity code.
"},{"location":"CHANGELOG/#1310-2024-07-26","title":"13.1.0 (2024-07-26)","text":"
  • Updated to POI 5.3.0
  • Add support for reading and writing timephased data for activities in P6 schedules which have a \"manual\" curve. (Note: MPXJ does not currently support translating timephased data between different applications, so timephased data read from an MPP file won't be written to a P6 schedule and vice versa).
  • Add an attribute to the ResourceAssignment class to represent timephased planned work. This is read from/written to P6 as Budgeted Work.
  • Update Phoenix schemas to ensure that cost types are represented as doubles.
  • Updated to avoid reading apparently invalid resources from Project Commander files.
  • Correct the Finish attribute for resource assignments when reading PMXML files.
  • Improve accuracy of the RemainingDuration attribute for resource assignments when writing PMXML files.
  • Improve recognition of non-working days when reading calendars certain PMXML files.
  • Add support for the Resource Assignment field Remaining Units. (Note: this field defaults to the same value as Units if it is not explicitly populated).
  • Ensure the Resource Assignment field Remaining Units is read from and written to P6 schedules.
  • Improve handling of invalid calendar exception data when reading P6 schedules from XER files or a P6 database.
  • Improve the implementation of the Unique ID sequence generator used by MPXJ to avoid issues when multiple classloaders are used.
  • Deprecated the original StructuredNotes constructor. A new version of the constructor takes an additional ProjectFile argument.
  • Deprecated the original UserDefinedField constructor. A new version of the constructor takes an additional ProjectFile argument.
  • Add support for reading and writing the Project Website URL attribute for P6 schedules.
  • Add support for the Notes attribute as part of the ProjectProperties class.
  • Ensure that project notes are read from and written to PMXML files.
  • Usability improvements to the Notes class hierarchy to make it easier to update notes.
  • Improvements to notes handling when writing PMXML files to make it easier to construct structured notes using plain text.
"},{"location":"CHANGELOG/#1302-2024-07-08","title":"13.0.2 (2024-07-08)","text":"
  • When writing XER files, provide a default value for the Resource ID if it is not populated.
"},{"location":"CHANGELOG/#1301-2024-07-04","title":"13.0.1 (2024-07-04)","text":"
  • For XER files, ignore the \"null\" resource when writing resource rates.
  • When reading MPP files, ensure that Enterprise Custom Field Unique IDs are unique across entities.
"},{"location":"CHANGELOG/#1300-2024-06-20","title":"13.0.0 (2024-06-20)","text":"
  • NOTE: this is a major release containing breaking changes. When updating from a 12.x release it is recommended that you first update to the most recent 12.x release and deal with any deprecation warnings before moving to this release.
  • NOTE: the original net.sf.mpxj NuGet packages are now deprecated and will be replaced by the MPXJ.Net NuGet Package in the next major MPXJ release. The net.sf.mpxj packages will continue to be maintained until then, at which point they will no longer be distributed. Please migrate your code to use MPXJ.Net at the earliest opportunity, and open an issue in the GitHUb issue tracker if you encounter problems.
  • Updated to use JAXB3. Among other things this change ensures compatibility with Spring Boot 3. Note that this may be a breaking change for you if you own application uses JAXB2.
  • When reading P6 schedules, the custom properties (as retrieved using ProjectProperties.getCustomProperties) will no longer contain scheduling options. These are now all available as attributes of the ProjectProperties class.
  • Removed redundant setUniqueID methods from immutable objects. These previously threw UnsupportedOperationException when called.
  • The ProjectEntityWithUniqueID interface no longer contains the setUniqueID method. Entities with a mutable Unique ID attribute now implement the ProjectEntityWithMutableUniqueID interface, which inherits from the ProjectEntityWithUniqueID interface.
  • The MSPDIReader and PrimaveraXERFileReader classes no longer provide getter and setter methods for Encoding, use the Charset getter and setter methods instead.
  • Removed the XerFieldType class and replaced usages of it with the DataType class.
  • The deprecated ActivityCode() constructor and addValue method have been removed.
  • The deprecated ActivityCodeValue() constructor and setParent method have been removed.
  • The deprecated CostAccount() constructor and getDescription method have been removed.
  • The deprecated CustomFieldValueItem methods getParent and setParent have been removed.
  • The deprecated ExpenseCategory() constructor has been removed.
  • The deprecated ExpenseItem(Task) constructor and all setter methods have been removed.
  • The deprecated JsonWriter methods setEncoding and getEncoding have been removed.
  • The deprecated Location.Builder() constructor has been removed.
  • The deprecated NotesTopic() constructor has been removed.
  • The deprecated ObjectSequence method reset has been removed.
  • The deprecated PlannerWriter methods setEncoding and getEncoding have been removed.
  • The deprecated PrimaveraXERFileWriter method setEncoding has been removed.
  • The deprecated ProjectCalendar method getDate has been removed.
  • The deprecated ProjectCalendarHelper method getExpandedExceptionsWithWorkWeeks has been removed.
  • The deprecated ProjectEntityContainer methods getNextUniqueID, renumberUniqueIDs and updateUniqueIdCounter have been removed.
  • The deprecated ProjectFile methods expandSubprojects and updateUniqueIdCounters have been removed.
  • The deprecated ProjectReader method setProperties and setCharset have been removed.
  • The deprecated ProjectWriterUtility class has been removed.
  • The deprecated RateHelper methods accepting a ProjectFile argument have veen removed.
  • The deprecated Relation(Task,Task,RelationType,Duration) constructor has been removed.
  • The deprecated RelationContainer.addPredecessor(Task,Task,RelationType,Duration) method has been removed
  • The deprecated Resource methods setAvailableFrom, setAvailableTo, setMaterialLabel and setMaxUnits have been removed.
  • The deprecated ResourceAssignment method getCalendar has been removed.
  • The deprecated Step(Task) constructor and all setter methods have been removed.
  • The deprecated Task method addPredecessor(Task,RelationType,Duration) has been removed
  • The deprecated TimephasedUtility methods segmentBaselineWork(ProjectFile, ...) and segmentBaselineCost(ProjectFile, ...) methods have been removed.
  • The deprecated UnitOfMeasure.Builder() constructor has been removed.
"},{"location":"CHANGELOG/#12103-2024-06-14","title":"12.10.3 (2024-06-14)","text":"
  • Add new project property IsProjectBaseline. When using the readAll method to retrieve a set of schedules, if the data source contains both schedules and baselines this property will be true for the ProjectFile instances which represent a baseline.
"},{"location":"CHANGELOG/#12102-2024-06-03","title":"12.10.2 (2024-06-03)","text":"
  • Added a missing unique ID mapping when writing resource assignment resource unique IDs to MSPDI files (Contributed by Alex Matatov)
  • Handle null field type when reading outline code values from an MPP9 file.
"},{"location":"CHANGELOG/#12101-2024-05-22","title":"12.10.1 (2024-05-22)","text":"
  • Ignore missing PropertySets when reading MPP files (Contributed by Fabian Schmidt).
  • Corrected handling of the \"24 Hour Calendar\" Relationship Lag Calendar setting when reading and writing XER files (Based on a contribution by Alex Matatov)
"},{"location":"CHANGELOG/#12100-2024-05-13","title":"12.10.0 (2024-05-13)","text":"
  • When a baseline is added using one of the ProjectFile.setBaseline methods, ensure that the relevant baseline date is set in ProjectProperties.
  • Marked the JsonWriter methods setEncoding and getEncoding as deprecated, use setCharset and getCharset instead.
  • Marked the PlannerWriter methods setEncoding and getEncoding as deprecated, use setCharset and getCharset instead.
  • Marked the PrimaveraXERFileWriter method setEncoding as deprecated, use setCharset instead.
  • Marked the ProjectCalendarHelper method getExpandedExceptionsWithWorkWeeks as deprecated, use ProjectCalendar.getExpandedCalendarExceptionsWithWorkWeeks instead.
  • Marked the ProjectReader method setCharset as deprecated. Readers which support setting the Charset now implement the HasCharset interface, which includes Charset getter and setter methods.
  • Implemented the UniversalProjectWriter class. This complements the UniversalProjectReader class by providing a simple way for MPXJ users to write project files without having to be concerned with details of the individual ProjectWriter classes. This is intended to replace the ProjectWriterUtility class. Note that the ProjectWriterUtility has a somewhat brittle mechanism to determine the output file format from the supplied output file name. This is not replicated by UniversalProjectWriter, users are expected to provide their own code to determine the appropriate file format.
  • Marked the ProjectWriterUtility class as deprecated.
"},{"location":"CHANGELOG/#1293-2024-04-24","title":"12.9.3 (2024-04-24)","text":"
  • Improve handling of non-standard timestamp formats in XER files.
"},{"location":"CHANGELOG/#1292-2024-04-19","title":"12.9.2 (2024-04-19)","text":"
  • Ensure calendars in Asta schedules have the correct name.
  • Improve assignment of calendars to summary tasks when reading Asta schedules.
  • Preserve calendar hierarchy when reading Asta schedules.
"},{"location":"CHANGELOG/#1291-2024-04-17","title":"12.9.1 (2024-04-17)","text":"
  • Fix an issue where UniversalProjectReader would raise an exception when handling an unknown file type.
  • Ensure that resource type is included as part of the resource assignment data when writing PMXML files.
"},{"location":"CHANGELOG/#1290-2024-04-11","title":"12.9.0 (2024-04-11)","text":"
  • Updated UniversalProjectReader to add getProjectReaderProxy methods to allow access to the instance of the reader class which will be used to read a schedule, prior to the schedule being read. This will allow the reader to be configured, or schedule to be ignored without reading its content.
  • Deprecated the ProjectReader.setProperties method. This method was originally implemented to allow settings to be passed to reader classes when using UniversalProjectReader. You can now use UniversalProjectReader.getProjectReaderProxy to achieve this.
  • Add from method to all Builder classes to allow initialisation from existing objects.
  • The CostAccount.Builder class now provides two notes methods to allow formatted or unformatted notes to be added to cost accounts.
  • The CostAccount method getDescription() has been marked as deprecated. Use the getNotes() or getNotesObject() method instead.
  • The CustomFieldValueItem methods getParent and setParent have been marked as deprecated. Use the getParentUniqueID and setParentUniqueID methods instead.
  • JSON output from MPXJ now includes more detail for custom field definitions read from MPP files.
  • When reading a PMXML file, populate the Early/Late Start/Finish date attributes from the Remaining Early/Late Start/Finish date attributes.
  • Fix an issue reading WBS ID for P3 and SureTrak schedules.
"},{"location":"CHANGELOG/#1281-2024-03-11","title":"12.8.1 (2024-03-11)","text":"
  • Improve reading resource assignments from certain FastTrack FTS files.
"},{"location":"CHANGELOG/#1280-2024-03-04","title":"12.8.0 (2024-03-04)","text":"
  • Add experimental support for reading Deltek Open Plan BK3 files.
  • Implemented the Relation.Builder class.
  • Marked the Relation(Task,Task,RelationType,Duration) constructor as deprecated, use the Relation.Builder class instead.
  • Marked the RelationContainer.addPredecessor(Task,Task,RelationType,Duration) method as deprecated, use the RelationContainer.addPredecessor(Relation.Builder) method instead.
  • Marked the Task.addPredecessor(Task,RelationType,Duration) method as deprecated, use the Task.addPredecessor(Relation.Builder) method instead.
  • Add a notes attribute to the Relation class and ensure that it is read from and written to P6 schedules.
  • Read the Relationship Lag Calendar setting from Phoenix 5 files. (Contributed by Rohit Sinha)
  • Don't write a material label to an MSPDI file for a resource which isn't a material.
  • Update representation of Work Variance when writing MSPDI files to more closely match output from Microsoft Project.
  • Updated to ensure that when schedules are read from XER files or P6 databases, labor and nonlabor work amounts are combined for the Actual, Remaining and Planned work attributes. This is now consistent with the existing behavior when reading PMXML files.
  • Added support for new Task attributes Actual Work Labor, Actual Work Nonlabor, Remaining Work Labor, Remaining Work Nonlabor, Planned Work Labor, Planned Work Nonlabor, when reading and writing P6 schedules.
  • Update default readAll method on reader classes to ensure that if the reader is unable to read any schedule data, an empty list is returned rather than a list containing null.
  • Ensure that Task Start and Finish dates are both the same when reading milestones from PMXML files, and that the correct date is used depending on whether we have a Start Milestone or a Finish Milestone.
"},{"location":"CHANGELOG/#1270-2024-02-07","title":"12.7.0 (2024-02-07)","text":"
  • Added support for reading and writing the project property Baseline Calendar Name to and from MPP and MSPDI files.
  • Ensure Start Variance and Finish Variance are read from and written to MSPDI files in the correct format.
  • Improve accuracy of large Work Variance values read from MSPDI files.
  • Add support for the Calendar GUID attribute, which is read from MPP and MSPDI files, and written to MSPDI files.
  • Ensure Activity Codes are available when reading Phoenix PPX files even if they are also being used to construct the task hierarchy.
  • Ensure Activity Codes Values are populated when reading Phoenix PPX files. (Contributed by Rohit Sinha)
  • When writing an MSPDI file, derive the TimephasedData Unit attribute from the duration of the timephased data item.
  • Fixed an issue with the ProjectCalendar.getPreviousWorkFinish method when called with a time which was already at the end of a period of work.
  • Ensure that the proj_node_flag is set for the root WBS node when writing XER files.
"},{"location":"CHANGELOG/#1260-2024-01-22","title":"12.6.0 (2024-01-22)","text":"
  • Updated PMXML schema to version 23.12.
  • Ensure that baselines in PMXML files written by Oracle Primavera Cloud are read.
  • Fix an issue reading certain XER files and P6 databases where activities lost the relationship with their parent WBS entry.
  • Added ResourceAssignment.getEffectiveCalendar method.
  • Deprecated ResourceAssignment.getCalendar method, use getEffectiveCalendar method instead.
  • Improved reading timephased baseline work from MPP files.
  • Added new versions of the TimephasedUtility.segmentBaselineWork and segmentBaselineCost methods which take a ProjectCalendar instance as the first argument rather than a ProjectFile instance.
  • Deprecated the TimephasedUtility.segmentBaselineWork and segmentBaselineCost methods which take a ProjectFile instance as the first argument.
  • Added a new version of the ProjectCalendar.getDate() method which just takes a date and a duration as its arguments. This method handles both positive and negative durations.
  • Marked the original version of the ProjectCalendar.getDate() method as deprecated. Use the new version instead.
  • Improve recognition of task splits when reading MPP and MSPDI files.
"},{"location":"CHANGELOG/#1250-2023-12-18","title":"12.5.0 (2023-12-18)","text":"
  • Add support for the following Resource Assignment attributes: Remaining Early Start, Remaining Early Finish, Remaining Late Start, and Remaining Late Finish.
  • Ensure that the Resource Assignment attributes Remaining Early Start and Remaining Early Finish are read from and written to PMXML files.
  • Ensure that the Resource Assignment attributes Remaining Early Start, Remaining Early Finish, Remaining Late Start, and Remaining Late Finish are read from and written to XER files.
  • Improve accuracy of reading and writing the ProjectProperties Relationship Lag Calendar attribute for PMXML files.
  • All P6 scheduling and leveling options which were previously made available via the ProjectProperties custom properties map are now deprecated. These properties now have individual getter and setter methods available on the ProjectProperties class. Note: this may be a breaking change if you were creating schedules from scratch, populating the custom properties map, then writing PMXML or XER files. In this case you will need to update your code, for all other use cases your code will continue to work unchanged until the next major version of MPXJ.
  • Added support for reading and writing the ProjectProperties attributes Baseline Type Name, Baseline Type Unique ID, and Last Baseline Update Date for baseline projects in PMXML files.
  • When reading projects from PMXML files, if the creation date attribute is not present in the file fall back to populating the ProjectProperties creation date attribute with the PMXML date added attribute.
  • When writing PMXML files, ensure the date added attribute for projects is populated with the creation date.
  • Add the CustomFieldContainer.remove method to allow field configurations to be removed.
  • Updated the UserDefinedFieldContainer.remove method to ensure that any associated field configuration is removed from the CustomFieldContainer.
  • Ensure that Microsoft Project's \"unknown\" resource (with Unique ID zero) is not exported to XER files.
  • Ensure that resource assignments which are not associated with an Activity or a Resource are not written to XER files.
  • Durations are written to PMXML files in hours. We now round to 2 decimal places to allow minutes to be represented, and avoid unnecessary precision.
  • Currency amounts written to PMXML files are now rounded to 8 decimal places to more closely match the behavior of P6, and avoid unnecessary precision.
  • Decimal amounts other than currency and duration are written to PMXML files with 15 decimal places to more closely match the behavior of P6.
  • Fix an issue reading ConceptDraw calendars.
  • Fixed a misspelled field name in the JSON output (Contributed by Daniel Taylor).
  • Improved handling of the Resource Assignment Planned and Remaining Units and Units per Time attributes read from and written to P6 schedules.
  • Added support for the following project properties: Activity ID Prefix, Activity ID Suffix, Activity ID Increment and Activity ID Based On Selected Activity, and ensure these are read from and written to P6 schedules.
"},{"location":"CHANGELOG/#1240-2023-11-23","title":"12.4.0 (2023-11-23)","text":"
  • Added support for the WBS Code Separator attribute to ProjectProperties.
  • Avoid creating duplicate ActivityCodeValue instances when reading Asta PP files.
  • Added a new version of the ProjectFile.expandSubprojects method which takes a boolean argument indicating if external tasks should be removed. Passing true to this method will recreate predecessor and successor relationships using the original tasks rather than the placeholder external tasks, and will remove the external tasks.
  • Marked the ProjectFile.expandSubprojects() method as deprecated, use the new version which takes a boolean argument instead.
  • Ensure the ProjectProperties name attribute is set correctly when reading XER files and P6 databases.
  • The ProjectEntityContainer method renumberUniqueIDs has been marked as deprecated.
  • The ProjectEntityContainer method getNextUniqueID has been marked as deprecated. Use ProjectFile.getUniqueIdObjectSequence(class).getNext() instead.
  • The ProjectEntityContainer method updateUniqueIdCounter has been marked as deprecated as it is no longer required.
  • The ProjectFile method updateUniqueIdCounters has been marked as deprecated as it is no longer required.
  • The ObjectSequence method reset has been marked as deprecated as it is no longer required.
  • When creating a Location instance using the Builder class, a Unique ID will be generated if one is not supplied.
  • The no-arg Location.Builder constructor has been marked a deprecated. Use the constructor which requires a ProjectFile instance instead.
  • Implemented the ExpenseItem.Builder class.
  • Marked the ExpenseItem(task) constructor as deprecated, use the ExpenseItem.Builder class instead.
  • Marked all ExpenseItem setter methods a deprecated. The ExpenseItem class will be immutable in the next major release.
  • Marked no-arg UnitOfMeasure.Builder() constructor as deprecated, use the UnitOfMeasure.Builder(ProjectFile) constructor instead.
  • Implemented the Step.Builder class.
  • Marked the Step(task) constructor as deprecated, use the Step.Builder class instead.
  • Marked all Step setter methods a deprecated. The Step class will be immutable in the next major release.
  • Marked the NotesTopic constructor as deprecated, use the NotesTopic.Builder(ProjectFile) constructor instead.
  • Implemented the ExpenseCategory.Builder class.
  • Marked the ExpenseCategory constructor as deprecated, use the ExpenseCategory.Builder class instead.
  • Implemented the CostAccount.Builder class.
  • Marked the CostAccount constructor as deprecated, use the CostAccount.Builder class instead.
  • Implemented the ActivityCodeValue.Builder class.
  • Marked the ActivityCodeValue constructor as deprecated, use the ActivityCodeValue.Builder class instead.
  • Marked the ActivityCodeValue.setParent method as deprecated, use the ActivityCodeValue.Builder class instead.
  • Marked the ActivityCode.addValue method as deprecated, use the ActivityCodeValue.Builder class instead to create an ActivityCodeValue instance and add it directly to the list held by the parent ActivityCode.
  • Implemented the ActivityCode.Builder class.
  • Marked the ActivityCode constructor as deprecated, use the ActivityCode.Builder class instead.
  • Only predecessor Relation instances are now stored in RelationContainer, successors are generated dynamically. You will only notice a difference if you are iterating over the RelationContainer collection directly, in which case you will only see predecessors.
"},{"location":"CHANGELOG/#1230-2023-11-07","title":"12.3.0 (2023-11-07)","text":"
  • Retrieve role availability data when reading a schedule from a P6 database.
  • Populate the project's Name and Title attributes when exporting an MSPDI file.
  • Ensure the Project ID attribute is populated when writing an XER file.
  • Don't include null tasks (blank tasks) when writing an XER file.
  • Strip control characters from entity names written to MSPDI files and XER files.
  • Ensure resource material labels written to MSPDI files meet Microsoft Project's naming requirements.
  • Ensure the activity code value Name attribute is populated when read from an Asta PP file.
  • Don't allow multiple values for an activity code when writing XER and PMXML files.
  • The MSPDI and MPX writers now dynamically renumber Unique ID values which are too large for Microsoft Project. The original schedule is no longer modified to achieve this.
"},{"location":"CHANGELOG/#1220-2023-10-12","title":"12.2.0 (2023-10-12)","text":"
  • Add the UnitOfMeasure class to represent the unit of measure for a material resource. The unit of measure corresponds to the current \"material label\" attribute of a resource. The Resource.getMaterialLabel() method will now retrieve the label from the UnitOfMeasure instance associated with the resource. The Resource.setMaterialLabel() method is now deprecated, the Resource.setUnitOfMeasure() or Resource.setUnitOfMeasureUniqueID() methods should be used instead.
  • Unit of measure for material resources are now read from and written to Primavera schedules.
  • Improve task duration and percent completion calculation for Asta PP files.
  • Improve date parsing when reading XER files written by older versions of P6.
  • Added the setIgnoreErrors method to the Primavera database reader class, and MSPDI, Schedule Grid, and SDEF file reader classes. The current default behavior of ignoring data type parse errors is unchanged. Calling setIgnoreErrors(false) on one of these reader classes will ensure that an exception is raised when a data type parse error is encountered.
  • Added the ProjectFile.getIgnoredErrors() method. The default behavior for MPXJ reader classes is to ignore data type parse errors. If any errors have been ignored when reading a schedule, details of these errors can be retrieved by calling the ProjectFile.getIgnoredErrors() method.
  • Handle duplicate relation unique IDs when reading schedules.
  • Include resource availability table in JSON output.
  • Add the Resource field Default Units, and ensure this field is read and written for P6 Schedules.
  • Updated the Resource attribute Max Units to ensure that this is calculated from the resource's availability table. Note that the Resource.getMaxUnits() method will return the resource's Max Units attribute for the current date. To retrieve the Max Units for a different date, use the AvailabilityTable.getEntryByDate() method.
  • Marked the Resource.setMaxUnits() method as deprecated. The Max Units attribute is derived from the resource's availability table. Changes to Max Units should now be made by modifying the availability table.
  • Updated the Resource attribute Available From to ensure that this is calculated from the resource's availability table. Note that the Resource.getAvailableFrom() method will return the resource's Available From attribute for the current date. To retrieve the Available From attribute for a different date, use the AvailabilityTable.availableFrom() method.
  • Marked the Resource.setAvailableFrom() method as deprecated. The Available From attribute is derived from the resource's availability table. Changes to the Available From attribute should now be made by modifying the availability table.
  • Updated the Resource attribute Available To to ensure that this is calculated from the resource's availability table. Note that the Resource.getAvailableTo() method will return the resource's Available To attribute for the current date. To retrieve the Available To attribute for a different date, use the AvailabilityTable.availableTo() method.
  • Marked the Resource.setAvailableTo() method as deprecated. The Available To attribute is derived from the resource's availability table. Changes to the Available To attribute should now be made by modifying the availability table.
"},{"location":"CHANGELOG/#1213-2023-09-25","title":"12.1.3 (2023-09-25)","text":"
  • Added the Project Properties attribute Relationship Lag Calendar and implemented read and write support for this for P6 schedules. (Contributed by Rohit Sinha).
  • Improve compatibility of PMXML files with P6 EPPM by moving the Schedule Options tag.
  • Ensure Baseline Projects in PMXML files include Schedule Options and Location Object ID.
"},{"location":"CHANGELOG/#1212-2023-09-21","title":"12.1.2 (2023-09-21)","text":"
  • Updates to improve compatibility with versions of Java after Java 8.
  • Ensure timestamps with fractional sections are read correctly from Phoenix PPX files (Based on a contribution by Rohit Sinha).
  • Improve handling of double quotes when reading and writing XER files.
  • To allow XER files written by MPXJ to be imported correctly by P6, ensure that they have a single top level WBS entry (Based on a contribution by Alex Matatov)
  • Ensure that ProjectProperties.getCustomProperties() returns an empty Map rather than returning null if no custom properties have been configured.
  • Ensure project calendars and project activity codes are nested within the project tag of PMXML files.
"},{"location":"CHANGELOG/#1211-2023-08-23","title":"12.1.1 (2023-08-23)","text":"
  • Fix an issue preventing native SQLite library from loading when using the .Net version of MPXJ on macOS.
"},{"location":"CHANGELOG/#1210-2023-08-22","title":"12.1.0 (2023-08-22)","text":"
  • Write schedule options to PMXML and XER files.
  • Fix an arithmetic error in RateHelper when converting a rate from minutes to hours.
  • Introduced new methods to RateHelper accepting a TimeUnitDefaultsContainer argument rather than a ProjectFile for greater flexibility. Marked methods taking a ProjectFile argument as deprecated.
  • Ensure Early Finish and Late Finish are populated for Asta milestones and tasks.
  • Don't attempt to calculate total slack if start slack or finish slack are missing.
  • Ensure completed tasks are not marked as critical.
  • Improve handling of non-standard Boolean values in MPX files.
  • Improve Total Slack calculation for P6 projects.
  • Handle finish milestones with null actual start date for actual duration calculation when reading PMXML files (Contributed by Andrew Marks).
"},{"location":"CHANGELOG/#1202-2023-07-25","title":"12.0.2 (2023-07-25)","text":"
  • Ensure that the Fixed Cost attribute is rolled up from activities to WBS entries when reading P6 schedules.
"},{"location":"CHANGELOG/#1201-2023-07-21","title":"12.0.1 (2023-07-21)","text":"
  • Improve resource hierarchy handling.
  • Improve handling of external tasks read from MSPDI files.
  • Improve handling of resource assignments read from Asta PP files containing multiple baselines.
  • Improve filtering to ignore hammock tasks in Asta PP files and ensure that non-hammock items are not incorrectly ignored.
  • Improve handling of bars without additional linked data read from Asta PP files.
  • Ensure that invalid duplicate Unique ID values encountered when reading schedule data are renumbered to maintain uniqueness.
  • Improve reading certain FastTrack FTS files.
  • Roll up the expense item at completion values read from P6 schedules to the task Fixed Cost attribute.
"},{"location":"CHANGELOG/#1200-2023-06-29","title":"12.0.0 (2023-06-29)","text":"
  • NOTE: this is a major version release, breaking changes have been made to the MPXJ API as documented below.
  • Timestamps, dates, and times are now represented by java.time.LocalDateTime, java.time.LocalDate and java.time.LocalTime respectively, rather than java.util.Date as they were originally.
  • For .Net users, new ToDateTime and ToNullableDateTime extension methods have been provided to convert java.time.LocalDateTime, java.time.LocalDate, java.time.LocalTime to DateTime instances.
  • For .Net users, new ToJavaLocalDateTime, ToJavaLocalDate and ToJavaLocalTime extension methods have been provided to convert DateTime instances to java.time.LocalDateTime, java.time.LocalDate, and java.time.LocalTime.
  • The class net.sf.mpxj.Day has been replaced by java.time.DayOfWeek.
  • All code previously marked as deprecated has been removed.
  • Added support for reading and writing the Activity attribute \"Expected Finish\" for P6 schedules.
"},{"location":"CHANGELOG/#1154-2023-06-27","title":"11.5.4 (2023-06-27)","text":"
  • Improve accuracy of dates read from Synchro, Suretrak and Turboproject files.
  • By default ignore errors in individual records read from XER files. This matches P6's behavior when importing XER files. Use the PrimaveraXERFileReader.setIgnoreErrors method to change the behavior.
"},{"location":"CHANGELOG/#1153-2023-06-19","title":"11.5.3 (2023-06-19)","text":"
  • When writing an XER file, provide the necessary default values to allow non-P6 schedules to be successfully imported into P6.
  • Ensure multi-day exceptions are written to XER files correctly.
  • Ensure GanttProject exception dates are read correctly.
  • More closely match the Planner predecessor lag calculation.
  • Ensure that java.sql.Date values are correctly formatted when writing XER files.
  • When reading from a P6 database, check to ensure the location table is present before attemting to read locations.
"},{"location":"CHANGELOG/#1152-2023-06-08","title":"11.5.2 (2023-06-08)","text":"
  • Improve accuracy of calendar data read from certain Powerproject schedules.
  • Improve handling of unusual XER files with calendar time ranges expressed in 12-hour format.
  • Correctly parse midnight represented as 24:00:00 from MSPDI files written by certain non-Microsoft Project applications.
  • For MSPDI files produced by applications other than Microsoft Project which have an incorrectly nested calendar hierarchy, avoid pruning derived calendars which are referenced elsewhere in the hierarchy.
"},{"location":"CHANGELOG/#1151-2023-05-24","title":"11.5.1 (2023-05-24)","text":"
  • Improve read performance when working with large schedules.
  • Improve read and write performance of code handling resource calendars.
  • Updated to use sqlite-jdbc 3.42.0.0
"},{"location":"CHANGELOG/#1150-2023-05-19","title":"11.5.0 (2023-05-19)","text":"
  • Added the ability to read Subproject data embedded in MSPDI files.
  • Added the ability to read timephased baseline work and cost from MSPDI files.
  • Added the ability to write timephased baseline work and cost to MSPDI files.
  • Improve accuracy of timephased baseline work read from MPP files.
  • Ensure that non-recurring calendar exceptions take precedence over recurring calendar exceptions.
  • Avoid creating duplicate calendar exceptions when reading Asta PP files.
  • Added the Bar Name attribute to Task, which is accessed using the getBarName and setBarName methods. This is populated with the name of the bar to which a task belongs when reading an Asta Powerproject schedule.
  • When reading schedules from XER files and P6 databases, ensure durations without a value are returned as null rather than as a zero duration.
"},{"location":"CHANGELOG/#1140-2023-05-08","title":"11.4.0 (2023-05-08)","text":"
  • Added the \"Resource Pool File\" attribute to ProjectProperties, which represents the full path of the resource pool used by an MPP file. This attribute is accessible via the getResourcePoolFile and setResourcePoolFile methods.
  • Added the getResourcePoolObject method to allow the resource pool file to be located and read
  • Added support for reading the task attribute Subproject GUID from MPP files. This attribute can be accessed via the getSubprojectGUID and setSubprojectGUID methods.
  • Added support for the task attribute \"External Project\". When this attribute is true it indicates that the task represents a subproject. The attribute is accessed via the getExternalProject and setExternalProject methods.
  • When reading an MSPDI file with external task predecessors, MPXJ now attempts to recreate the placeholder external tasks which would be present if the equivalent MPP file was read.
  • External task predecessors are now represented when writing an MSPDI file.
  • Added the Task method getSubprojectObject which allows the caller to retrieve a ProjectFile instance representing the external project linked to a task.
  • Added the Task method expandSubproject. For task which represent an external project, this method automatically loads the external project and attaches the tasks it contains as children of the current task. This is analogous to the behavior in Microsoft Project where a subproject is expanded to reveal the tasks it contains.
  • Added the ProjectFile method expandSubprojects which identifies any tasks in the project which represent an external project and expands them, linking the tasks from the external project as children of the task in the parent project. Note that the method works recursively so multiple levels of external tasks will be expanded.
  • Updated to ensure that the internal_name attribute of a UserdefinedField is generated if not present.
  • Updated to avoid an exception when reading notebook topics from PMXML files.
  • Marked the Task method setSubprojectName as deprecated. Use the setSubProjectFile method instead.
  • Marked the Task method getSubprojectName as deprecated. Use getSubprojectFile instead.
  • Marked the Task method setExternalTaskProject as deprecated. Use the setSubprojectFile method instead.
  • Marked the Task method getExternalTaskProject as deprecated. Use the getSubprojectFile method instead.
  • Marked the ProjectFile method getSubProjects as deprecated. Use the subproject attributes on individual tasks instead.
  • Marked the Task methods getSubProject and setSubProject as deprecated. Use the subproject attributes instead.
"},{"location":"CHANGELOG/#1132-2023-04-29","title":"11.3.2 (2023-04-29)","text":"
  • Improve default values provided for P6 calendars with missing data.
  • Implement both \"planned dates\" and \"current dates\" strategies for populating P6 baselines.
  • Ensure the Project GUID is read from MPP files.
"},{"location":"CHANGELOG/#1131-2023-04-21","title":"11.3.1 (2023-04-21)","text":"
  • Improve accuracy of resource assignment Actual Start and Actual Finish dates when reading MPP files.
  • Avoid generating timephased data for zero duration tasks.
  • Improve preservation of custom timephased data start and end times.
"},{"location":"CHANGELOG/#1130-2023-04-12","title":"11.3.0 (2023-04-12)","text":"
  • Implemented PrimaveraXERFileWriter to allow MPXJ to write XER files.
  • Updated the ActivityCode class to ensure that both the scope Project ID and EPS ID can be represented when reading a P6 schedule. (Potentially breaking change if you were using this class).
  • Ensure secondary constraint date and type are written to PMXML files.
  • Ensure leveling priority is written to PMXML files.
  • Ensure WBS UDF values are written to PMXML files.
  • Ensure integer UDF values are read correctly from XER files and P6 databases.
  • Add methods to allow the project's default calendar unique ID to be set and retrieved.
  • Add method to allow a calendar's parent calendar unique ID to be retrieved.
  • Add method to allow a task's parent task unique ID to be retrieved.
  • Add methods to allow a resource assignment's role unique ID to be set and retrieved.
  • Add methods to allow a resource assignment's cost account unique ID to be set and retrieved.
  • Add method to allow a cost account's parent unique ID to be retrieved.
  • Add method to allow an expense item's cost account unique ID to be retrieved.
  • Add method to allow an expense item's category unique ID to be retrieved.
  • Added WorkContour.isDefault() method to allow \"built in\" resource curves/work contours to be distinguished from user defined curves.
  • Updated to retrieve the project's start date from Phoenix PPX files (Contributed by Rohit Sinha).
  • Provide access to notebook topics from P6 schedules via the ProjectFile.getNotesTopics() method.
  • Capture unique ID of Activity and WBS notes from P6 schedules.
  • Improve the calculation used to determine At Completion Duration of activities when reading XER files and P6 databases.
  • Improve representation of certain duration values written to MSPDI files.
  • Improve accuracy of certain work calculations where the specified time period does not start with a working day.
  • Fix an issue which caused negative timephased work values to be generated when reading certain MPP files.
  • Fix an issue reading XER files where the critical_drtn_hr_cnt field is expressed a decimal rather than an integer.
  • Fix an issue populating the WBS attribute for activities read from certain XER files.
"},{"location":"CHANGELOG/#1120-2023-03-13","title":"11.2.0 (2023-03-13)","text":"
  • The project property Critical Slack Limit is now represented as a Duration rather than as an Integer. (Potentially breaking change if you were using this property directly).
  • TaskType is now a simple enum with all Microsoft Project specific functionality moved into TaskTypeHelper. (Potentially breaking change if you were using the TaskType methods getInstance or getValue in your code)
  • When reading the task type from P6 schedule the mapping to the MPXJ TaskType enum has been updated to more closely match P6. The main changes are that the P6 type \"Fixed Units\" now maps to TaskType.FIXED_WORK and the \"Fixed Duration & Units\" type now maps to a new enumeration value TaskType.FIXED_DURATION_AND_UNITS.
  • Added support for reading project calendar exceptions from Phoenix schedules (based on a contribution by Rohit Sinha).
  • The Resource attribute Active now defaults to true if the schedule being read doesn't support or contain a value for this attribute.
  • Add support for reading and writing the Resource's Active flag for P6 schedules.
  • Add support for reading and writing the Resource's Default Units/Time value for P6 schedules.
  • Add support for reading and writing the Project's Critical Slack Limit value for P6 schedules.
  • Fixed an issue reading certain types of Enterprise Custom Fields containing date values.
  • Ensure activity code value parent can be set to null.
  • Improved existing .Net extension methods and added support for more types.
  • Added NuGet package icon
  • Simplified NuGet packaging
"},{"location":"CHANGELOG/#1110-2023-02-15","title":"11.1.0 (2023-02-15)","text":"
  • Write activity code definitions and activity code assignments to PMXML files.
  • Added support for \"secure\" and \"max length\" attributes to the ActivityCode class.
  • Added getChildCodes method to ActivityCode and ActivityCodeValue to make it easier to traverse activity code values hierarchically.
  • Added setDescription method to Step class to make it simpler to add a plan text description.
"},{"location":"CHANGELOG/#1100-2023-02-08","title":"11.0.0 (2023-02-08)","text":"
  • User defined fields read from P6, Asta and GanttProject schedules are now represented by instances of UserDefinedField. They will no longer be mapped to custom field instances.
  • Enterprise Custom Fields read from MPP and MSPDI files are now represented by instances of UserDefinedField.
  • When writing MSPDI files, UserDefinedField instances which were originally read from enterprise custom fields will be written to the MSPDI file as enterprise custom fields.
  • When writing MSPDI files, UserDefinedField instances which were from applications other than Microsoft Project will automatically be mapped to available custom fields.
  • When writing MPX files, UserDefinedField instances will automatically be mapped to available custom fields.
  • The UserDefinedField type implements the FieldType interface and so can be used with the FieldContainer get and set methods to work with the contents of the user defined fields.
  • The ProjectFile.getUserDefinedFields() method has been added to provide access to all user defined fields defined in the project.
  • The CustomFieldContainer returned by ProjectFile.getCustomFields() will contain entries for all UserDefinedField instances.
  • The various getFieldTypeByAlias and getFieldByAlias methods will retrieve user defined fields by name.
  • Added the convenience method ProjectFile.getPopulatedFields() to retrieve details of all populated fields across the project. This avoids the caller having to individually retrieve the populated fields from the tasks container, resource container and so on.
  • Updated the getPopulatedFields methods to return a Set of FieldType rather than a Set of TaskField, ResourceField etc.
  • The various getPopulatedFields methods will include instances of UserDefinedField in the returned collection if relevant.
  • All ENTERPRISE_CUSTOM_FIELDn values have been removed from the TaskField, ResourceField, AssignmentField and ProjectField enumerations.
  • The getEnterpriseCustomField and setEnterpriseCustomField methods have been removed from ProjectProperties, Task,ResourceandResourceAssignment`.
  • Project UDFs are now read from P6 schedules.
  • Project UDFs are now written to PMXML files.
  • All code previously marked as deprecated has been removed.
"},{"location":"CHANGELOG/#10162-2023-01-29","title":"10.16.2 (2023-01-29)","text":"
  • Updated to improve reading resource attributes from certain MPP14 files.
"},{"location":"CHANGELOG/#10161-2023-01-26","title":"10.16.1 (2023-01-26)","text":"
  • Updated to make resource curve definitions (work contours) available in the WorkContourContainer. This container is accessed using the ProjectFile.getWorkContours() method.
"},{"location":"CHANGELOG/#10160-2023-01-24","title":"10.16.0 (2023-01-24)","text":"
  • Improve accuracy when normalising timephased data.
  • Add support for reading activity steps from XER files, PMXML files and Primavera databases.
  • Add support for writing activity steps to PMXML files.
  • Updated PMXML schema to version 22.12.
  • Updated methods in the GanttBarCommonStyle and GanttBarStyle classes to use a FieldType instance rather than a TaskField instance to allow more flexibility. (Note: this may be a breaking change if you are currently using these classes.)
  • Optionally include some Microsoft Project layout data in JSON output.
"},{"location":"CHANGELOG/#10150-2023-01-11","title":"10.15.0 (2023-01-11)","text":"
  • Avoid writing invalid characters to PMXML, MSPDI and Planner XML files.
  • Improve handling of slack values for schedules which only contain a value for total slack.
  • Add support for reading constraint type and constraint date from Phoenix schedules (based on a contribution by Rohit Sinha).
  • Improve timephased data calculation when assignment has zero units.
  • Improve handling of very large duration values when reading and writing MSPDI files.
  • Ensure the Task attributes Active, Constraint Type, Task Mode, and Type always have a value.
  • Ensure the Resource attributes Type, Calculate Costs from Units, and Role always have a value.
  • Ensure the Resource Assignment attributes Calculate Costs from Units, Rate Index, and Rate Source always have a value.
  • Add version number constant to the Java source, accessible as MPXJ.VERSION.
  • Ensure that UDF values are read for WBS entries in PMXML files.
  • Avoid writing duplicate resource assignments to MPX files.
"},{"location":"CHANGELOG/#10141-2022-11-25","title":"10.14.1 (2022-11-25)","text":"
  • Fix CVE-2022-41954: Temporary File Information Disclosure Vulnerability (Contributed by Jonathan Leitschuh)
"},{"location":"CHANGELOG/#10140-2022-11-21","title":"10.14.0 (2022-11-21)","text":"
  • Handle missing default calendar when reading a PMXML file.
  • When reading an MPP file using a file name or File instance, ensure a more memory-efficient approach is used.
  • Improve reading certain FastTrack FTS files.
  • Improve generation of timephased data where working time ends at midnight.
  • Improve generation of timephased data for tasks with a calendar assigned.
"},{"location":"CHANGELOG/#10130-2022-11-16","title":"10.13.0 (2022-11-16)","text":"
  • Add support for reading a resource assignment's cost account from P6 schedules.
  • Add support for writing a resource assignment's cost account to PMXML files.
  • Read resource assignment custom field definitions present in MPP14 files.
  • Improve identification of deleted resources when reading MPP9 files.
  • Ensure tasks with task calendars in MPP files are handled correctly when generating timephased data.
  • Improve generation of timephased data for material resource assignments.
  • Improve accuracy of timephased data when reading certain MPP files.
"},{"location":"CHANGELOG/#10120-2022-11-01","title":"10.12.0 (2022-11-01)","text":"
  • Added the Resource Assignment attribute Calculate Costs From Units, and added read and write support for Primavera schedules.
  • Added the Resource attribute Calculate Costs From Units, and added read and write support for Primavera schedules.
  • Added the Resource and Role attribute Sequence Number, and added read and write support for Primavera schedules.
  • Added the WBS attribute Sequence Number, and added read and write support for Primavera schedules.
  • Ensure activity type is read from Phoenix schedules. (Contributed by Christopher John)
  • Deprecate the CostAccount method getSequence and replace with getSequenceNumber to improve naming consistency.
  • Deprecate the ExpenseCategory method getSequence and replace with getSequenceNumber to improve naming consistency.
  • Avoid possible ArrayIndexOutOfBoundsException when reading GUID values from MPP files (Contributed by Rohit Sinha).
"},{"location":"CHANGELOG/#10110-2022-09-27","title":"10.11.0 (2022-09-27)","text":"
  • Deprecated the Resource methods getParentID and setParentID. Replaced with getParentResourceUniqueID and setParentResourceUniqueID for clarity and consistency.
  • Added the Resource methods setParent and getParent.
  • Added the ChildResourceContainer interface and ResourceContainer.updateStructure method to ensure that resources can be accessed hierarchically when reading a schedule.
  • Added the ResourceAssignment methods getFieldByAlias and setFieldByAlias to simplify working with custom fields, and mkae the API consistent with existing methods on Task and Resource.
  • Added the TaskContainer methods getCustomFields and getFieldTypeByAlias to simplify access to task custom fields.
  • Added the ResourceContainer methods getCustomFields and getFieldTypeByAlias to simplify access to resource custom fields.
  • Added the ResourceAssignmentContainer methods getCustomFields and getFieldTypeByAlias to simplify access to resource assignment custom fields.
  • Added the getCustomFieldsByFieldTypeClass method to CustomFieldContainer to allow retrieval of custom field details by parent class.
  • Deprecated the CustomFieldContainer method getFieldByAlias to be replaced by getFieldTypeByAlias to provide a more consistent method name.
  • Don't attempt to write unknown extended attributes to MSPDI files.
  • Don't populate graphical indicator data if the graphical indicator is not enabled.
  • Don't set custom field aliases to empty strings.
  • Added the CustomFieldContainer method add.
  • Deprecated the CustomFieldContainer method getCustomField, which is replaced by the get method (which returns null if the field type is not configured) and the getOrCreate method (which will return an existing configuration or create a new one if the requested field does not yet have a configuration).
"},{"location":"CHANGELOG/#10100-2022-09-13","title":"10.10.0 (2022-09-13)","text":"
  • Add an option to import Phoenix schedules as a flat set of tasks with separate activity codes, rather than creating a hierarchy of tasks from the activity codes. Note the default is to disable this behavior so existing functionality is unchanged. (Contributed by Christopher John)
  • Add a setProperties method to reader classes to allow configuration to be supplied via a Properties instance rather than having to call setter methods. Properties passed to the UniversalProjectReader version of this method will be forwarded to the reader class UniversalProjectReader chooses to reader the supplied file. Properties for multiple reader classes can be included in the Properties instance, each reader class will ignore irrelevant properties.
  • Added the get method to Task, Resource, ResourceAssignment and ProjectProperties as a replacement for the getCurrentValue method. The new get method is paired with the existing set method to provide read and write access to attributes of these classes. This change is intended to improve the interfaces to these classes by making them more consistent, and thus easier to understand.
  • Deprecated the getCurrentValue method on the Task, Resource, ResourceAssignment and ProjectProperties classes. Use the new get method instead.
  • Add getter and setter methods for the Resource attributes Cost Center, Budget Cost, Budget Work, Baseline Budget Cost, Baseline Budget Work, Baseline Budget Cost 1-10, and Baseline Budget Work 1-10.
  • Add getter and setter methods for the Task attributes Response Pending, Scheduled Start, Scheduled Finish, Scheduled Duration, Budget Cost, Budget Work, Baseline Budget Cost, Baseline Budget Work, Baseline Budget Cost 1-10, and Baseline Budget Work 1-10.
  • Added support for the Resource Cost Centre attribute for MSPDI files.
  • Move MPP file-specific functionality for determining baseline values from the Task class into the MPP reader class.
  • Improve handling of the TaskMode attribute.
  • Don't set a Task's Critical attribute unless we have valid slack values.
  • Ensure ResourceAssignment calculated fields are returned correctly when using the getCurrentValue method.
  • Ensure ProjectProperties calculated fields are returned correctly when using the getCurrentValue method.
  • Updated to use jsoup 1.15.3
"},{"location":"CHANGELOG/#1091-2022-08-31","title":"10.9.1 (2022-08-31)","text":"
  • Ensure monthly and yearly recurrences are calculated correctly when the supplied start date is the same as the first recurrence date (Contributed by Rohit Sinha).
  • Add support for reading task calendars from Phoenix files (Contributed by Rohit Sinha).
  • Improve reliability of ProjectCleanUtility when using the replacement strategy.
"},{"location":"CHANGELOG/#1090-2022-08-23","title":"10.9.0 (2022-08-23)","text":"
  • Added the ResourceAssignment.getEffectiveRate method to allow the cost rate effective on a given date for a resource assignment to be calculated. For P6 schedules this will take account of the cost rate configuration included as part of the resource assignment.
  • For P6 schedules, the ResourceAssignment.getCostRateTable method now takes in account any cost rate configuration details from the resource assignment when determining which table to return.
  • A resource's Standard Rate, Overtime Rate and Cost per Use are now all derived from the resource's cost rate table, and not stored as attributes of the resource itself.
  • The resource methods setStandardRate, setOvertimeRate, and setCostPerUse have been deprecated. These attributes can now only be set or updated by modifying the resource's cost rate table.
  • When writing MPX files, only include attributes which have a non-empty, non-default value in at least one task or resource.
  • When writing MPX files, ensure attributes which have calculated values are used.
  • Add support for reading a resource assignment's rate type from P6 schedules. The rate type is accessed via the ResourceAssignment.getRateIndex method. The value returned by this method can be used to select the required rate using the CostRateTableEntry,getRate method.
  • Add support for writing a resource assignment's rate type to PMXML files.
  • Add support for reading a resource assignment's role from P6 schedules. The role is accessed via the ResourceAssignment.getRole and ResourceAssignment.setRole methods.
  • Add support for writing a resource assignment's role to PMXML files.
  • Add support for reading a resource assignment's override rate (Price / Unit) from P6 schedules. The rate is accessed via the ResourceAssignment.getOverrideRate and ResourceAssignment.setOverrideRate methods.
  • Add support for writing a resource assignment's override rate (Price / Unit) to PMXML files.
  • Add support for reading a resource assignment's rate source from P6 schedules. The rate source is accessed via the ResourceAssignment.getRateSource and ResourceAssignment.setRateSource methods.
  • Add support for writing a resource assignment's rate source to PMXML files.
"},{"location":"CHANGELOG/#1080-2022-08-17","title":"10.8.0 (2022-08-17)","text":"
  • When reading P6 schedules, all five cost rates for a resource are now available via the CostRateTableEntry.getRate method.
  • All five rates from each cost rate table entry can now be written to PMXML files.
  • When reading files written by Microsoft Project, resource rate values now use the same units as seen by the end user rather than defaulting to hours as was the case previously. (For example, if the user sees $8/day in the source application, you will receive a Rate instance of $8/day rather than $1/hr).
  • The values for a resource's standard rate, overtime rate, and cost per use attributes are now derived from the cost rate table. The values stored on the resource itself are only used if a cost rate table for the resource is not present.
  • The Resource methods getStandardRateUnits and getOvertimeRateUnits are deprecated. Use the getStandardRate and getOvertimeRate methods to retrieve a Rate instance which will include the units for these rates.
  • The Resource methods setStandardRateUnits and setOvertimeRateUnits are deprecated. Supply Rate instances to the setStandardRate and setOvertimeRate methods with the required units instead.
  • The CostRateTableEntry methods getStandardRateUnits and getOvertimeRateUnits are deprecated. Use the getStandardRate and getOvertimeRate methods to retrieve a Rate instance which will include the units for these rates.
  • Ensure rates are formatted \"per hour\" when writing MSPDI and PMXML files.
  • Include cost rate tables in JSON output.
"},{"location":"CHANGELOG/#1070-2022-08-09","title":"10.7.0 (2022-08-09)","text":"
  • Use Jackcess to read Asta MDB and Microsoft Project MPD files. This allows these file to be read on platforms other than Windows.
  • Improve support for reading correctly typed values for enterprise custom fields from MPP files.
  • Improve array index validation when reading GUID values from MPP files.
"},{"location":"CHANGELOG/#1062-2022-06-29","title":"10.6.2 (2022-06-29)","text":"
  • Ensure ProjectCleanUtility can load dictionary words from distribution jar.
  • Improve handling of calendars without days read from PMXML files.
"},{"location":"CHANGELOG/#1061-2022-06-14","title":"10.6.1 (2022-06-14)","text":"
  • Updated to use POI 5.2.2
  • Updated to use sqlite-jdbc 3.36.0.3
  • Updated to use jsoup 1.15.1
"},{"location":"CHANGELOG/#1060-2022-06-08","title":"10.6.0 (2022-06-08)","text":"
  • Added support for reading and writing the unique ID of P6 user defined fields via new getUniqueID and setUniqueID methods on `CustomField (based on a suggestion by Wes Lund).
  • Added support for reading and writing scope, scope ID, and sequence number attributes for activity codes (based on a suggestion by Wes Lund).
  • Added support for reading and writing sequence number and color attributes for activity code values (based on a suggestion by Wes Lund).
  • Added isWorking method to ProjectCalendarException to make it clearer how to determine if the exception changes the dates it is applied to into working or non-working days.
  • Improve reading task start from certain Planner files.
  • Improve reading predecessor lag values from Planner files.
  • Ensure calendar hierarchy is written correctly to Planner files.
  • Don't write null tasks to Planner files as Planner will not read files which contain them.
  • When writing Planner file, ignore constraint types which Planner can't represent.
  • Don't write emply predecessor lists to Planner files.
  • Improve handling of lag duration when writing Planner files.
  • Improve ProjectCalendar start date calculation when we have long runs of non-working days.
  • Performance enhancement for timephased data normalisation.
"},{"location":"CHANGELOG/#1050-2022-05-24","title":"10.5.0 (2022-05-24)","text":"
  • The ProjectCalendarWeek methods addCalendarHours(), attachHoursToDay, removeHoursFromDay have been removed. Use addCalendarHours(day), removeCalendarHours(day) instead. (Note: this will be a breaking change if you were using the original methods to create or modify a schedule)
  • The ProjectCalendar methods attachHoursToDay and removeHoursFromDay have been removed. Use the addCalendarHours and removeCalendarHours methods instead. (Note: this will be a breaking change if you were using the original methods to create or modify a schedule)
  • The class hierarchy for ProjectCalendarHours and ProjectCalendarException has been simplified, but there should be no impact for uses of these classes.
  • The ProjectCalendarHours class now implements the List interface. Methods in this class not part ofthe List interface have been deprecated in favour of the equivalent List methods.
  • Updated MPXWriter to ensure: calendar names are quoted if necessary, all calendars have names, all calendar names are unique.
  • Updated MPXReader to recognise wk as a valid time unit.
  • Updated MPXWriter, PrimaveraPMFileWriter, SDEFWriter and PlannerWriter to ensure any working weeks defined by a calendar are represented by exceptons.
  • Updated MSPDIWriter to ensure any working weeks defined by a calendar are represented in the \"legacy\" exception definition used by Microsoft Project prior to 2007.
  • Updated SDEFWriter to ensure: only relevant calendars are written, and derived calendars are flattened.
  • When reading Planner schedules MPXJ will no longer create an \"artificial\" resource calendar for each resource. Resources will be linked directly to the calendar used in the original schedule.
  • Add support for reading the P6 calendar type and personal calendar flag from P6 schedules.
  • Add support for writing the calendar type and personal calendar flag to PMXML files.
  • Updated the calendar class hierarchy: ProjectCalendar and ProjectCalendarWeek both now inherit from a new class ProjectCalendarDays. Note that ProjectCalendar is no longer a subclass of ProjectCalendarWeek.
  • The getHours and isWorkingDay methods have been moved up to ProjectCalendar from the ProjectCalendarWeek class.
  • The ProjectCalendar method copy has been deprecated, without replacement.
  • Added a getWork method to ProjectCalendar which calculates the amount of work given a Day instance.
  • Added removeWorkWeek and removeCalendarException methods to ProjectCalendar.
  • Recurring exceptions are now added to a ProjectCalendar using the addCalendarException method which takes a recurringData instance its argument.
  • The ProjectCalendarException method setRecurringData has been removed, recurring exceptions should be added using the addCalendarExcepton method described above. (Note: this will be a breaking change if you were creating recurring exceptions)
"},{"location":"CHANGELOG/#1040-2022-05-05","title":"10.4.0 (2022-05-05)","text":"
  • Remove getParent, setParent, and isDerived from ProjectCalendarWeek. (Note: this will be a breaking change if you were working with ProjectCalendarWeek directly).
  • The ProjectProperties methods getDefaultCalendarName() and setDefaultCalendarName() have been deprecated. Use getDefaultCalendar() and setDefaultCalendar() instead.
  • Ensure that percent complete values can be read from MSPDI files even if the values are decimals.
  • Improve handling of the default calendar when reading certain MSPDI files.
  • Improve reading certain Phoenix PPX files.
  • Improve reading certain FastTrack FTS files.
  • Improve formatting of time project properties when written to JSON.
  • Improve reading MPP files generated by Microsoft Project 16.0.15128.20158 and later versions.
"},{"location":"CHANGELOG/#1030-2022-04-29","title":"10.3.0 (2022-04-29)","text":"
  • General improvements to make calendar data read from different file formats more consistent.
  • When reading P6 and Powerproject schedules MPXJ will no longer create an \"artificial\" resource calendar for each resource. Resources will be linked directly to the calendars they use in the original schedule.
  • Update MPXWriter and MSPDIWriter to ensure that, when written, calendars are correctly structured in the form required by Microsoft Project.
  • JsonWriter now includes calendar data as part of its output.
  • The ProjectCalendar methods setMinutesPerDay, setMinutesPerWeek, setMinutesPerMonth and setMinutesPerYear have been deprecated, use setCalendarMinutesPerDay, setCalendarMinutesPerWeek, setCalendarMinutesPerMonth and setCalendarMinutesPerYear instead.
  • The ProjectCalendar method setResource has been deprecated and will not be replaced. Use the Resource method setCalendar or setCalendarUniqueID to link a calendar with a resource.
  • The ProjectCalendar method getResource has been deprecated. Use the getResources method instead to retrieve all resources linked with a calendar.
  • The Resource methods addResourceCalendar, setResourceCalendar, getResourceCalendar, setResourceCalendarUniqueID and getResourceCalendarUniqueID have been deprecated and replaced by addCalendar, setCalendar, getCalendar, setCalendarUniqueID and getCalendarUniqueID respectively.
"},{"location":"CHANGELOG/#1020-2022-03-06","title":"10.2.0 (2022-03-06)","text":"
  • Improvements to writing currency, rate and units amounts to MSPDI files.
  • When reading MPP and MSPDI files, calendar exceptions representing a single range of days, but defined as a recurring exception are converted to a range of days, removing the unnecessary recurring definition.
  • Added StructuredTextParser to replace original code handling calendar data, project properties and curve data read from XER files and Primavera databases. Can also be used to extract data from Primavera Layout Files (PLF).
  • Improve recognition of contoured resource assignments read from MPP files.
  • Improve retrieval of resource assignment confirmed, response pending, linked fields, and team status pending flags from certain MPP files.
"},{"location":"CHANGELOG/#1010-2022-01-29","title":"10.1.0 (2022-01-29)","text":"
  • Improve PMXML file compatibility with P6.
  • Strip any trailing invalid characters from text read from FTS files.
  • Ensure all tasks read from Powerproject and Project Commander have unique IDs.
  • Correct expansion of exceptions from a weekly recurring calendar exception.
  • Ensure that expanded calendar exceptions are written to file formats which do not support recurring exceptions.
  • Ensure that start and finish dates are set when reading milestones from GanttProject files.
"},{"location":"CHANGELOG/#1005-2022-01-11","title":"10.0.5 (2022-01-11)","text":"
  • Ensure Task.getActivityCodes() returns an empty list rather than null when no activity code values have been assigned.
  • Default to using ASCII when reading and writing SDEF files, as per the SDEF specification.
  • Provide methods to set and get the charset used when reading and writing SDEF files.
"},{"location":"CHANGELOG/#1004-2022-01-07","title":"10.0.4 (2022-01-07)","text":"
  • Added support for reading Code Library values (as Activity Codes) from Powerproject files.
  • Updated ProjectCleanUtility to provide a \"replace\" strategy alongside the original \"redact\" strategy.
"},{"location":"CHANGELOG/#1003-2021-12-22","title":"10.0.3 (2021-12-22)","text":"
  • Fix issue with null tasks from certain MPP files introduced in 10.0.2.
"},{"location":"CHANGELOG/#1002-2021-12-16","title":"10.0.2 (2021-12-16)","text":"
  • Improve identification of null tasks for certain MPP files.
"},{"location":"CHANGELOG/#1001-2021-12-10","title":"10.0.1 (2021-12-10)","text":"
  • Avoid false positives when detecting password protected MPP files.
"},{"location":"CHANGELOG/#1000-2021-12-01","title":"10.0.0 (2021-12-01)","text":"
  • Added support for .NET Core 3.1
  • Nuget packages now explicitly target .NET Framework 4.5 (net45) and .NET Core 3.1 (netcoreapp3.1)
"},{"location":"CHANGELOG/#983-2021-11-30","title":"9.8.3 (2021-11-30)","text":"
  • Improve reliability when reading certain Phoenix files.
  • Ensure multiple trailing nul characters are stripped from text when reading schedules from a Primavera database.
"},{"location":"CHANGELOG/#982-2021-11-01","title":"9.8.2 (2021-11-01)","text":"
  • Improve accuracy of identifying null tasks in certain MPP files.
  • Improve accuracy of identifying valid tasks in certain MPP files.
  • Ensure hierarchical outline code values are read correctly from MSPDI files.
  • Improve support for files produced by recent versions of FastTrack.
"},{"location":"CHANGELOG/#981-2021-10-13","title":"9.8.1 (2021-10-13)","text":"
  • Added support for Phoenix 5 schedules.
  • Improve handling of null tasks read from MPP files.
"},{"location":"CHANGELOG/#980-2021-09-30","title":"9.8.0 (2021-09-30)","text":"
  • Introduced the BaselineStrategy interface and implementing classes. (Note: this includes a breaking change if you were using the ProjectFile.setBaseline method and supplying a lambda. You will now need to implement a BaselineStrategy and set this in ProjectConfig before setting a baseline).
  • Improved accuracy of baseline attributes for Primavera schedules.
"},{"location":"CHANGELOG/#970-2021-09-28","title":"9.7.0 (2021-09-28)","text":"
  • Add Sprint ID and Board Status ID attributes to task.
  • Introduce the TimeUnitDefaultsContainer to allow constants for time unit conversions to be obtained from both project properties and calendars.
  • Duration attributes are no longer returned as Duration instances by the ruby gem, they are now returned as floating point numbers. By default, durations are expressed in seconds. A new optional argument to MPXJ::Reader.read allows you to change the units used to express durations. (Note: this is a breaking change for users of the ruby gem)
  • Update JsonWriter to use a relevant calendar when converting durations.
  • Ensure default calendar is set correctly when reading XER and PMXML files, and P6 databases.
  • Use default hours per day/week/month/year when reading P6 XER files or databases if these values are not present.
  • Ensure that the minutes per day/week/month/year attributes are copied when a calendar is copied.
  • When reading P6 schedules, roll up calendar for WBS entries when child activities all share the same calendar.
  • Generate missing minutes per day/week/month/year for calendars read from P6 schedules.
  • Inherit minutes per day/week/month/year from base calendars (Note: minor method signature changes on ProjectProperties and ProjectCalendar).
  • Allow explicit values to be set for project minutes per week and minutes per year.
  • Fall back on defaults for project minutes per day/week/month/year attributes.
"},{"location":"CHANGELOG/#960-2021-09-13","title":"9.6.0 (2021-09-13)","text":"
  • Add Planned Start and Scheduled Finish to project properties.
  • Add attribute_types method to Ruby classes.
  • Updated to use POI 5.0.0.
  • Corrected source of Must Finish By project property when reading XER files or P6 databases.
  • When reading PMXML files, ensure that the activity calendar is set before calculating slack.
  • Remove unused field TaskField.PARENT_TASK.
  • Ensure task Unique ID and task Parent Unique ID attributes are treated as mandatory when written to JSON.
  • Fix an issue with Ruby gem where a task's parent was not being retrieved correctly in some circumstances.
"},{"location":"CHANGELOG/#952-2021-08-22","title":"9.5.2 (2021-08-22)","text":"
  • Add Must Finish By date to project properties.
  • Add support for the task attributes Longest Path, External Early Start and External Early Finish, and ensure they can be read from P6 schedules.
  • Rename ProjectFile.getStartDate() and ProjectFile.getFinishDate() methods for clarity. Original method names are marked as deprecated
  • Ensure that all activities in a PMXML file have a CalendarID attribute to ensure compatibility with older versions of P6.
  • Ensure that the user's selected progress period is used to set the project's status date attribute when reading Asta PP files.
  • Ensure that a task's Complete Through attribute is not advanced to the start of the next working day (the behaviour of Microsoft Project prior to 2007 was to report Complete Through as the start of the next working day. This change ensures MPXJ matches versions of Microsoft Project from 2007 onwards. Previous behaviour can be restored using the ProjectConfig.setCompleteThroughIsNextWorkStart() method).
  • Deprecate task getSplitCompleteDuration() and setSplitCompleteDuration() in favour of getCompleteThrough() and setCompleteThrough().
  • Improved the implementation of the TaskContainer.synchronizeTaskIDToHierarchy method.
  • Update jsoup to 1.14.2.
"},{"location":"CHANGELOG/#951-2021-07-01","title":"9.5.1 (2021-07-01)","text":"
  • When applying a baseline using ProjectFile.setBaseline, gracefully handle duplicate task key values.
  • Handle missing values populating cost rate table from an MPP file.
"},{"location":"CHANGELOG/#950-2021-06-30","title":"9.5.0 (2021-06-30)","text":"
  • Added support for reading baseline data from embedded baselines in PP files.
  • Correct resource assignment percent complete values read from PP files.
  • JsonWriter no longer writes attribute type information by default. (The original behaviour can be restored by calling setWriteAttributeTypes(true) on your JsonWriter instance).
  • The MPXJ Ruby Gem now generates explicit methods to access attributes rather than relying on \"method_missing\" to intercept and act on attribute access.
  • Don't write Assignment Task GUID, Assignment Resource GUID or Resource Calendar GUID to JSON.
  • Don't write a value for Assignment Work Contour to JSON if the contour is the default value (i.e. flat).
  • Don't write a value for Assignment Resource Request Type to JSON if the type is the default value (i.e. none).
  • Don't write a value for Task Earned Value Method to JSON if the method matches the project default.
  • Don't write a value for Task Type to JSON if the type matches the project default.
  • Stop writing a default value (-1) for Parent Task ID to JSON if the task does not have a parent.
  • Stop writing a default value (-1) for Task Calendar ID to JSON if the task does not have a calendar.
  • When reading resource assignments from an MPP file, don't record Project's internal representation of a null resource ID (-65535), record the resource ID explicitly as null.
  • For MPX and Planner files, don't write resource assignments for the \"null\" resource.
  • Handle missing status date when reading P6 schedules from XER files or database.
  • When reading MPP files, treat UUIDs which are all zeros as null.
  • Deprecate the 10 Resource Outline Code get and set methods and replace with get and set methods which take an index argument.
  • Provide a helper method (PrimaveraHelper.baselineKey) to encapsulate key generation for setting Primavera baselines.
"},{"location":"CHANGELOG/#940-2021-06-11","title":"9.4.0 (2021-06-11)","text":"
  • Read custom value lists for resource custom fields from MPP files (based on a suggestion by Markus H\u00f6ger).
  • Added support for reading custom fields from Asta Powerproject files.
  • Ensure short data type values are written to JSON files as numeric values.
  • Ensure delay data type values are written to JSON files as duration values.
  • Don't write zero rates to JSON files.
  • Introduced a separator into rate values when written to a JSON file to make it clear that the value is a rate not a duration (for example: 5.00h is now 5.00/h).
  • When writing an enum value of a JSON file, ensure we write the original enum name rather than the value return by toString. This provides more meaningful output (Potentially breaking change if you use the Ruby gem or consume the JSON output directly. Affected attributes are project properties: currency symbol position, time format, date format, bar text date format, schedule from, mpx file version; resource attribute: type).
  • Ensure invalid cost rate table data is handled gracefully when reading from MSPDI files.
  • Handle missing data when reading MSPDI files (based on a contribution by Lord Helmchen).
  • Improve population of summary task names when reading from Powerproject PP files.
  • Correctly read hierarchical resource outline codes from MPP files (based on a suggestion by Markus H\u00f6ger).
"},{"location":"CHANGELOG/#931-2021-05-18","title":"9.3.1 (2021-05-18)","text":"
  • Preserve multiple assignments between an activity and a resource when reading P6 schedules.
  • Renamed WorkContour.isFlat to isContourFlat and WorkContour.isContoured to isContourManual.
  • Include an entry for 0% in the WorkContour curve definition.
  • Fix an issue where non-working days were not being treated correctly in date calculations if they happen to still have time ranges attached.
"},{"location":"CHANGELOG/#930-2021-05-06","title":"9.3.0 (2021-05-06)","text":"
  • Add support for reading roles from P6 databases, XER and PMXML files, and for writing roles to PMXML files. Roles are represented as resources. The new resource Boolean attribute \"Role\" is used to distinguish between Resource instances which represent resources and those which represent roles.
  • Add support for reading resource curves from P6 databases, XER and PMXML files, and for writing resource curves to PMXML files. The WorkContour enum is now a class, and instance of this class are used to represent resource curves. The curves are available via the work contour attribute of resource assignments.
  • Corrected the data type of the task physical percent complete attribute.
  • Improve handling of non-standard relationship type representations encountered in XER files and P6 databases.
"},{"location":"CHANGELOG/#926-2021-04-26","title":"9.2.6 (2021-04-26)","text":"
  • Handle invalid baseline numbers when reading MSPDI files.
  • Improve custom field handling when reading GanttProject files.
"},{"location":"CHANGELOG/#925-2021-04-20","title":"9.2.5 (2021-04-20)","text":"
  • Add launcher batch file and shell script.
  • Improve handling of calculated task attributes when writing a project to a different format.
  • Ensure that dates are rolled up to summary tasks when reading FastTrack files.
  • Improve support for Synchro 6.3 SP files.
"},{"location":"CHANGELOG/#924-2021-04-09","title":"9.2.4 (2021-04-09)","text":"
  • Fix an issue reading resource rate information GanttProject files.
"},{"location":"CHANGELOG/#923-2021-04-08","title":"9.2.3 (2021-04-08)","text":"
  • Fix an issue reading Planned Duration from P6 databases and XER files.
  • Ensure Duration and Actual Duration are populated for WBS entries when reading P6 schedules.
"},{"location":"CHANGELOG/#922-2021-04-07","title":"9.2.2 (2021-04-07)","text":"
  • Fix issue with WBS ordering when writing PMXML files.
"},{"location":"CHANGELOG/#921-2021-04-04","title":"9.2.1 (2021-04-04)","text":"
  • Improve Task critical flag calculation when reading PMXML files.
  • Improve support for Synchro 6.3 SP files.
"},{"location":"CHANGELOG/#920-2021-03-30","title":"9.2.0 (2021-03-30)","text":"
  • Improve accuracy when reading subprojects from MPP files.
  • Add Remaining Late Start and Remaining Late Finish attributes to Task.
  • Add Critical Activity Type attribute to Project Properties
  • Read Remaining Early Start, Remaining Late Start, Remaining Early Finish and Remaining Late finish from and write to PMXML files.
  • Read Remaining Late Start and Remaining Late finish from P6 database and XER files.
  • Ensure that WBS entries without child activities are not marked as critical.
  • Don't attempt to set the critical flag when reading XER and PMXML files where the schedule is using \"longest path\" to determine critical activities. (MPXJ currently doesn't have enough information to be able to determine the correct value for the critical flag in this situation).
  • Ensure cost, duration, date and work attributes are rolled up to WBS entries for P6 schedules read from PMXML files, XER files and P6 databases.
  • Populate baseline cost, duration, finish, start and work when reading from XER files, PMXML files and P6 databases where the \"Project Baseline\" has been set to \"Current Project\".
"},{"location":"CHANGELOG/#910-2021-03-11","title":"9.1.0 (2021-03-11)","text":"
  • Add methods to the ProjectFile class to attach a ProjectFile instance as a baseline. The baselines attached to the ProjectFile will be used to populate the relevant baseline attributes in the current schedule.
  • Added experimental support for writing baseline projects to PMXML files.
  • Added the Project GUID attribute.
  • When reading PMXML files, the list of projects returned by the readAll method will include any baseline projects present in the file.
  • When reading PMXML files which include the current baseline project, use this to populate the relevant baseline attributes in the main schedule.
  • The Project Unique ID property is now an integer rather than a string.
  • When reading Primavera schedules, populate the project properties Project ID and Baseline Project Unique ID.
  • Handle Primavera resource rates which don't have a start or finish date.
  • Handle MSPDI files with resource availability tables which don't have a start or finish date.
  • Ensure that the Activity ID field is populated consistently for WBS entries in PMXML files compared to the same schedule read from an XER file or P6 database.
  • Ensure duration of manually scheduled tasks in MPP files is represented correctly.
"},{"location":"CHANGELOG/#900-2020-02-18","title":"9.0.0 (2020-02-18)","text":"
  • NOTE: this release introduces breaking changes!
  • All fields which are non-user defined, but were previously being returned by MPXJ as custom fields are now represented as explicit field types. Custom fields now only contain values for user-defined custom fields.
  • All code previously marked as deprecated has been removed.
  • When reading an XER file or a P6 database, some custom project property names have been updated. LagCalendar is now CalendarForSchedulingRelationshipLag, RetainedLogic is now WhenSchedulingProgressedActivitiesUseRetainedLogic, ProgressOverride is now WhenSchedulingProgressedActivitiesUseProgressOverride, IgnoreOtherProjectRelationships is now WhenSchedulingProgressedActivitiesUseProgressOverride, and StartToStartLagCalculationType is now ComputeStartToStartLagFromEarlyStart.
  • Updated PMXML schema to version 20.12.
  • Fix an issue where GUID values were not being read correctly from XER files and P6 databases.
  • Percent complete type is now available as a task attribute for P6 schedules from any source.
  • Ensure that percent complete values are stored in the appropriate attributes when reading P6 schedules. (NOTE: Previously the \"reported\" percent complete value was stored as the tasks \"percent complete\" attribute. Now this holds the schedule percent complete value, and the percent work complete and physical percent complete attributes are also populated. To determine which value should be reported for a task, see the \"percent complete type\" extended field attribute.)
  • Correctly handle default calendar when reading and writing PMXML files.
  • Update the sort order of WBS entries and activities in PMXML files to match the order exported by P6.
  • Match the way P6 exports the WBS code attribute for PMXML files.
  • Update the representation of Boolean values when writing PMXML files to match the form exported by P6.
  • Set the task type attribute when reading PMXML files.
  • Improve duration and actual duration calculations when reading XER files and P6 databases.
  • Fix an issue where resource assignment costs were not being read correctly from PMXML files.
  • Read and write the suspend date and resume date attributes for PMXML files.
  • General improvements to the SDEF writer.
  • Updated to rtfparserkit 1.16.0.
"},{"location":"CHANGELOG/#851-2021-01-07","title":"8.5.1 (2021-01-07)","text":"
  • Don't write unused enterprise custom field definitions to MSPDI files. This ensures that MS Project will open these files correctly.
"},{"location":"CHANGELOG/#850-2021-01-06","title":"8.5.0 (2021-01-06)","text":"
  • Notes in their original format (HTML from P6, RTF from MS Project) can now be retrieved via the getNotesObject method on Task, Resource, and ResourceAssignment. Plain text notes can still be retrieved via the getNotes method. If you were previously using the \"preserve note formatting\" flag to retrieve the original formated version of a note, you will now need to use the getNotesObject method.
  • Write WBS and Activity notes to PMXML files.
  • PMXML compatibility improvements to ensure files can be successfully imported into P6.
"},{"location":"CHANGELOG/#840-2020-12-29","title":"8.4.0 (2020-12-29)","text":"
  • Previously when reading PMXML files, XER files, and P6 databases, a set of baseline attributes on tasks and assignments (including Start, Finish, Duration, Cost and Work) were being populated with planned values rather than baseline values. These baseline attributes are no longer being set. The values they previously contained are now available as custom fields.
  • Read activity notepad entries for XER, PMXML files and P6 databases.
  • Read schedule and leveling options from PMXML files and P6 databases.
  • Improve support for reading activity cost and work from PMXML files.
"},{"location":"CHANGELOG/#835-2020-12-15","title":"8.3.5 (2020-12-15)","text":"
  • Fix CVE-2020-35460: zip slip vulnerability (with thanks to Sangeetha Rajesh S, ZOHO Corporation)
"},{"location":"CHANGELOG/#834-2020-12-10","title":"8.3.4 (2020-12-10)","text":"
  • Updated PMXML schema to version 19.12.
  • Ensure that we always set the activity planned start and planned finish dates when writing a PMXML file.
  • Updated the getPopulatedFields methods to ignore fields with default values.
  • Made the Resource ID attribute available as a resource's TEXT1 custom field, with the alias \"Resource ID\" when reading PMXML and XER files, or from a P6 database. (Note that presently for XER files and P6 databases, the Resource ID value is also read into the initials attribute. This behaviour is deprecated and will be removed in the next major MPXJ release).
  • Populate the Resource ID with the value read from a P6 schedule when writing a PMXML file.
  • Ensure that the hours per day, week, month and year attributes are read from and written to PMXML files.
  • Fix an issue causing the hours per day calendar attribute to be read inaccurately from XER files and P6 databases.
  • Read assignment actual overtime cost and work attributes from PMXML files.
  • Update calculation of assignment work, cost and units attributes for PMXML files.
"},{"location":"CHANGELOG/#833-2020-11-24","title":"8.3.3 (2020-11-24)","text":"
  • Added cost rate table support when reading from and writing to PMXML files.
  • Added a getPopulatedFields method to the TaskContainer, ResourceContainer and ResourceAssignmentContainer classes. This will retrieve the set of fields which are populated with a non-null value across the whole project for Tasks, Resources, and ResourceAssignments respectively.
  • Add START_ON, FINISH_ON constraint types. \u00a7 MANDATORY_START, MANDATORY_FINISH constraint types. MANDATORY_START/FINISH are now represented as MUST_START/FINISH_ON. This change allows users to distinguish between START/FINISH_ON and the MANDATORY_* constraints when reading P6 schedules.
  • Improve handling of cost rate tables and availability tables when writing to an MSPDI file.
  • Handle P6 databases and XER files with user defined fields of type FT_FLOAT.
  • Align invalid XER record behaviour with P6.
  • Handle Planner files which don't contain an allocations tag.
  • Gracefully handle MPP files with missing view or table data.
"},{"location":"CHANGELOG/#832-2020-10-22","title":"8.3.2 (2020-10-22)","text":"
  • Added support for \"new tasks are manual\" project property (Contributed by Rohit Sinha)
  • Improved support for reading and writing outline codes and extended attributes for MSPDI files (Based on a contribution by Dave McKay)
  • Improved handling of enterprise custom fields when reading MPP files
  • Update Primavera database and XER readers to avoid potential type conversion errors when the caller provides their own field mappings.
  • Improve handling of some MPP12 MPP file variants.
  • Avoid error when reading timephased data from certain MPP files.
  • Gracefully handle MPP files with missing view data.
  • Update junit to 4.13.1.
"},{"location":"CHANGELOG/#831-2020-10-14","title":"8.3.1 (2020-10-14)","text":"
  • Minor updates to PlannerReader.
"},{"location":"CHANGELOG/#830-2020-10-13","title":"8.3.0 (2020-10-13)","text":"
  • Add the \"userDefined\" attribute to the CustomField class to allow caller to determine if the field has been created by a user or MPXJ.
  • Add support for reading expense items, expense categories and cost accounts from XER files, PMXML files and Primavera databases.
  • Add support for writing expense items, expense categories and cost accounts to PMXML files.
  • Updated the XER file reader to ignore invalid records rather than reporting an error, matching the behaviour of P6
  • Updated the XER file reader to ensure that activity suspend and resume dates are read correctly.
  • Updated the XER file reader to ensure that if the reader returns the project selected by the caller when the caller supplies a value for project ID.
  • Updated PMXML reader to avoid user defined field collisions.
  • Updated PMXML reader to add setProjectID and listProjects methods.
  • Update the .net extension method ToIEnumerable to work with java.lang.Iterable rather than java.util.Collection
"},{"location":"CHANGELOG/#820-2020-09-09","title":"8.2.0 (2020-09-09)","text":"
  • All readers, including the UniversalProjectReader, now support a readAll method. If a file or database contains more than one project the readAll method can be used to retrieve them all in one operation. If the file format doesn't support multiple schedules, readAll will just return a single schedule.
  • Add PrimaveraDatabaseFileReader to encapsulate access to SQLite Primavera databases.
  • Ensure that the summary flag is true for WBS items in Primavera schedules, even if they have no child activities.
  • Ensure that the critical flag is rolled up appropriately to WBS items when reading Primavera schedules.
  • Set export flag property when reading projects from a PMXML file.
  • Corrected data type of resource assignment Work Contour field.
  • Corrected data type of resource fields: BCWS, BCWP, ACWP, SV, CV, and Work Contour.
  • Corrected data type of task fields: CV, ACWP, VAC, CPI, EAC, SPI, TCPI, and Work Contour.
"},{"location":"CHANGELOG/#814-2020-08-31","title":"8.1.4 (2020-08-31)","text":"
  • Fix CVE-2020-25020: XXE vulnerability (with thanks to Sangeetha Rajesh S, ZOHO Corporation)
  • Import milestone constraints from Asta schedules (Contributed by Dave McKay)
  • Handle elapsed durations in Asta schedules (Based on a contribution by Dave McKay)
  • Correctly determine the constraint type for tasks with ALAP placement with or without predecessors when reading from Asta schedules (Contributed by Dave McKay)
  • Gracefully handle a missing table name when reading an XER file.
  • Gracefully handle an unexpected calendar data when reading an XER file.
  • Correctly handle XER files with multibyte character encoding.
  • Import all schedule and leveling options from XER files.
  • Ensure project calendars are read from PMXML files.
  • Added readAll methods to PrimaveraPMFileReader to allow all projects contained in a PMXML file to be read in a single pass.
"},{"location":"CHANGELOG/#813-2020-06-25","title":"8.1.3 (2020-06-25)","text":"
  • Improve reliability when reading custom field values from certain MPP12 files.
  • Improve accuracy of activity percent complete when reading from certain XER files or P6 databases.
  • Improve accuracy of WBS percent complete when reading from certain XER files or P6 databases.
  • Improve accuracy of task durations when reading Asta schedules.
  • Fix an issue handling the end date of calendar exceptions when reading Asta schedules.
  • Fix an issue with correctly identifying the calendar applied to summary tasks when reading Asta schedules.
  • Populate percent complete, duration, actual start, actual finish, early start, late start, early finish and late finish attributes for summary tasks when reading Asta schedules.
  • The percent complete value reported for tasks when reading Asta schedules is now Duration Percent Complete. The Overall Percent Complete value originally being returned is available in a custom field.
"},{"location":"CHANGELOG/#812-2020-06-18","title":"8.1.2 (2020-06-18)","text":"
  • Improve detection of unusual MSPDI file variants.
  • Updated to read task notes from FastTrack FTS files.
"},{"location":"CHANGELOG/#811-2020-06-17","title":"8.1.1 (2020-06-17)","text":"
  • Improve support for Synchro 6.2 SP files.
"},{"location":"CHANGELOG/#810-2020-06-11","title":"8.1.0 (2020-06-11)","text":"
  • Experimental support for reading Project Commander schedules.
  • Update to use JAXB 2.3.2.
  • Avoid failures caused by unreadable OLE compound documents when the UniversalProjectReader is trying to determine the file type.
  • Strip trailing ASCII NUL characters from text fields when reading from a Primavera database.
  • Improve accuracy of task order when reading Phoenix files.
  • Improve accuracy of task data when reading some MPP file variants.
  • Improve reliability when reading certain SureTrak files.
"},{"location":"CHANGELOG/#808-2020-04-20","title":"8.0.8 (2020-04-20)","text":"
  • Improve handling of numeric character references invalid for XML 1.0 in PMXML files.
  • Improve handling of resource calendars read from Planner files.
  • Improve handling of resource calendars read from MPX files.
  • Ignore the milestone flag when reading MPX files if the task has a non-zero duration.
  • Ensure JSON files can be written when Unique ID predecessor/successor attributes have been read from an MPX file.
"},{"location":"CHANGELOG/#807-2020-04-17","title":"8.0.7 (2020-04-17)","text":"
  • Updated to rtfparserkit 1.15.0.
  • Improve handling of PMXML files with empty calendar exception time ranges.
"},{"location":"CHANGELOG/#806-2020-03-05","title":"8.0.6 (2020-03-05)","text":"
  • Updated to use POI 4.1.2.
  • Improve handling of some XER file variants.
"},{"location":"CHANGELOG/#805-2020-02-07","title":"8.0.5 (2020-02-07)","text":"
  • Allow users to determine WBS attribute content with \"wbs is full path\" flag for Primavera readers.
  • Ensure summary task start and finish dates are populated when reading PMXML files.
  • Use baseline start and finish dates as planned start and finish dates when writing PMXML files.
  • Late start and late finish dates are now written to PMXML files.
"},{"location":"CHANGELOG/#804-2020-02-06","title":"8.0.4 (2020-02-06)","text":"
  • Update sqlite-jdbc dependency to 3.30.1
  • Improve handling of characters invalid for XML 1.0 in PMXML files generated by P6.
"},{"location":"CHANGELOG/#803-2020-01-27","title":"8.0.3 (2020-01-27)","text":"
  • Improve handling of zero value durations, costs and units from certain MPP files.
  • Improve percent complete calculation for certain XER file and P6 Database schedules.
  • Improve percent complete calculation for certain P3 schedules.
  • Improve handling of incorrectly encoded characters in PMXML files generated by P6.
  • Ensure that negative durations can be written to and read from MSPDI files in the format understood by MS Project.
"},{"location":"CHANGELOG/#802-2020-01-16","title":"8.0.2 (2020-01-16)","text":"
  • Improve handling of zero duration tasks read from Phoenix files.
"},{"location":"CHANGELOG/#801-2020-01-05","title":"8.0.1 (2020-01-05)","text":"
  • Add missing nuget dependency
"},{"location":"CHANGELOG/#800-2020-01-02","title":"8.0.0 (2020-01-02)","text":"
  • MPXJ now requires Java 8 or later.
  • Removed deprecated methods.
  • Updated to use POI 4.1.1.
  • Updated to use IKVM 8.1.5717.0.
"},{"location":"CHANGELOG/#798-2019-12-27","title":"7.9.8 (2019-12-27)","text":"
  • Added support for reading and writing outline code/custom field lookup tables for MSPDI files.
  • Added sample code to demonstrate creation of timephased work.
  • Populate project status date attribute when reading Asta schedules.
  • Populate parent attribute when reading activity code values from Primavera schedules.
  • Improve configurability of PrimaveraDatabaseReader and PrimaveraXERFileReader.
  • Made JAXB JARs an explicit dependency to avoid issues with recent Java versions which do not include them.
"},{"location":"CHANGELOG/#797-2019-11-25","title":"7.9.7 (2019-11-25)","text":"
  • Round percent complete values read from Asta files to two decimal places to avoid values like 99.9999999%.
"},{"location":"CHANGELOG/#796-2019-11-22","title":"7.9.6 (2019-11-22)","text":"
  • Improve support for FastTrack files.
"},{"location":"CHANGELOG/#795-2019-11-19","title":"7.9.5 (2019-11-19)","text":"
  • Added flag to manage compliance with password protection. (Contributed by ztravis)
  • Improve support for Synchro 6.1 SP files.
  • Fix an issue where the task hierarchy was not correctly represented when reading a PMXML file.
"},{"location":"CHANGELOG/#794-2019-11-08","title":"7.9.4 (2019-11-08)","text":"
  • Add support for reading Sage 100 Contractor schedule grid files.
  • Ensure attribute names are valid when exporting JSON.
  • Improve handling of custom field lookup values (Based on a contribution by Nick Darlington).
  • Fix an issue when copying a calendar which has exceptions defined.
"},{"location":"CHANGELOG/#793-2019-09-10","title":"7.9.3 (2019-09-10)","text":"
  • Add support for reading task early finish and late finish attributes from Asta PP files.
  • Ensure XER files containing secondary constraints can be read correctly.
  • Preserve calendar IDs when reading from XER files and P6 database (Based on a contribution by forenpm).
  • Ensure base calendars are read correctly for P6 schedules.
  • Ensure MPP files with unexpected auto filter definition data are handled gracefully.
  • Preserve leveling delay format when reading tasks from MSPDI files.
  • Ensure unexpected structure of timephased data is handled gracefully when reading MPP files.
"},{"location":"CHANGELOG/#792-2019-08-19","title":"7.9.2 (2019-08-19)","text":"
  • Add support for reading and writing secondary constraints from P6 schedules (Based on a contribution by Sruthi-Ganesh)
  • Improve support for Synchro SP files containing blank tasks.
  • Make constraint type mapping consistent when reading and writing PMXML files.
  • Improve handling of leveling delay units and actual duration units (Based in a contribution by Daniel Schmidt).
  • Improve handling of certain types of malformed MPP files.
  • Improve handling of certain types of malformed SDEF files.
  • Map P6 Equipment resource type to cost rather than work (Contributed by forenpm)
  • Improve handling of certain MPP files containing large numbers of blank tasks.
  • Improve handling of certain MPX files containing trailing delimiters.
"},{"location":"CHANGELOG/#791-2019-07-01","title":"7.9.1 (2019-07-01)","text":"
  • Set task start, finish and percent complete when reading SDEF files.
"},{"location":"CHANGELOG/#790-2019-07-01","title":"7.9.0 (2019-07-01)","text":"
  • Add support for reading SDEF files.
"},{"location":"CHANGELOG/#784-2019-06-27","title":"7.8.4 (2019-06-27)","text":"
  • Add support for reading data links (linked fields) configuration from MPP files.
  • Updated to avoid an infinite loop when processing certain corrupt files (Contributed by ninthwaveltd).
  • Update MSPDI generation to ensure MS Project correctly recognises complete tasks without resource assignments.
  • Ensure that activity codes are read for P6 schedules.
  • Improve support for reading custom field values derived from custom field lookup tables in MPP files.
  • Improve support for MPP files written with the June 2019 update of Microsoft Project.
"},{"location":"CHANGELOG/#783-2019-05-24","title":"7.8.3 (2019-05-24)","text":"
  • Improve handling of task baseline start, start, baseline finish, finish and slack fields read from FTS files.
"},{"location":"CHANGELOG/#782-2019-05-19","title":"7.8.2 (2019-05-19)","text":"
  • Improve handling of MPP files with missing Props.
  • Improve handling of custom field lookup tables for MPP12 files.
  • Correctly write activity duration type to a PMXML file (Contributed by Sebastian Stock)
  • Improve handling of Activity Type and Activity ID when writing PMXML files (Based on a contribution by Sebastian Stock)
  • Update PMXML file reader for greater consistency with XER and P6 database readers (Activity ID, Activity Type, Status, and Primary Resource ID)
  • Improve handling of certain FTS files.
  • Improve handling of task notes from MPP8 files.
  • More accurately read predecessors and successors from Asta PP files (Based on a contribution by Dave McKay)
  • When a schedule is read from P6, P3, or SureTrak, Task.getSummary will return true only if a task is part of the WBS
  • Improve support for reading the Synchro Scheduler 2018 SP files.
  • Added Task.hasChildTasks() method.
  • Fixed Issue 330: Splits data coming in as null for all tasks
"},{"location":"CHANGELOG/#781-2019-02-13","title":"7.8.1 (2019-02-13)","text":"
  • Improve support for reading the Synchro Scheduler 2018 SP files.
  • Add support for reading Gantt Designer GNT files.
  • Improve handling of non-standard MSPDI files.
  • Improve handling of non-standard GanttProject files.
  • Update MSPDI generation to ensure MS Project correctly recognises complete milestones without resource assignments.
  • Improve support for reading user defined fields from PMXML files.
  • Ignore hammock tasks when reading PP files.
"},{"location":"CHANGELOG/#780-2019-01-18","title":"7.8.0 (2019-01-18)","text":"
  • Added support for reading and writing GUIDs for Tasks, Resources, and Assignments in MSPDI files.
  • Updated Java build to use Maven
  • Updated to provide a general performance improvement (Based on a contribution by Tiago de Mello)
  • Updated to fix an issue when the Microsoft JDBC driver is used to access a P6 database in SQL Server 2005
  • Fixed Issue 332: Asta lag sign incorrect (Based on a contribution by Dave McKay)
  • Fixed Issue 333: Asta constraints lost (Contributed by Dave McKay)
  • Fixed Issue 335: MSDPI into Asta doesn't import Calendar exceptions (Contributed by Dave McKay)
"},{"location":"CHANGELOG/#771-2018-10-23","title":"7.7.1 (2018-10-23)","text":"
  • Read additional schedule options from XER files. (Contributed by forenpm)
  • Improve handling of some types of MPP file with missing resource assignment data.
  • Ensure that resource assignment flag fields are read correctly for all MPP file types (Based on a contribution by Vadim Gerya).
  • Ensure that timephased actual work is handled correctly for material resources (Contributed by Vadim Gerya).
  • Improve accuracy when reading resource type from MPP files.
  • Improve compatibility of generated MSPDI files with Asta Powerproject (Contributed by Dave McKay).
"},{"location":"CHANGELOG/#770-2018-10-12","title":"7.7.0 (2018-10-12)","text":"
  • Add support for reading the Synchro Scheduler SP files.
  • Add support for reading the activity code (ID) from Asta files.
  • When reading a Phoenix file, set the project's status date to the data date from the storepoint.
  • Handle MSPDI files with timephased assignments that don't specify a start and end date.
"},{"location":"CHANGELOG/#763-2018-10-04","title":"7.6.3 (2018-10-04)","text":"
  • Add support for reading Remaining Early Start and Remaining Early Finish task attributes from P6. (Contributed by forenpm)
  • Add support for reading Retained Logic and Progressive Override project attributes from P6. (Contributed by forenpm)
  • Fix incorrect sign when calculating start and finish slack (Contributed by Brian Leach).
  • Correctly read predecessors and successors from Phoenix files.
"},{"location":"CHANGELOG/#762-2018-08-30","title":"7.6.2 (2018-08-30)","text":"
  • Add support for nvarchar columns when reading from a P6 database.
  • Updated to correctly read percent lag durations from MSPDI files (based on a contribution by Lord Helmchen).
  • Updated the data type for the ValueGUID tag in an MSPDI file (based on a contribution by Lord Helmchen).
"},{"location":"CHANGELOG/#761-2018-08-29","title":"7.6.1 (2018-08-29)","text":"
  • Improve handling of MPP files where MPXJ is unable to read the filter definitions.
  • Improve handling of SureTrak projects without a WBS.
  • Improve handling of SureTrak and P3 WBS extraction.
  • Handle unsupported ProjectLibre POD files more gracefully.
  • Improve detection of non MS Project compound OLE documents.
  • Gracefully handle XER files which contain no projects.
"},{"location":"CHANGELOG/#760-2018-07-13","title":"7.6.0 (2018-07-13)","text":"
  • Added support for reading ConceptDraw PROJECT CDPX, CPDZ and CPDTZ files.
  • Add support for reading the export_flag attribute from XER files. (Contributed by forenpm)
  • Use correct licence details in Maven pom.xml (contributed by Mark Atwood).
  • Improve UniversalProjectReader's handling of XER files containing multiple projects.
"},{"location":"CHANGELOG/#750-2018-06-19","title":"7.5.0 (2018-06-19)","text":"
  • Added support for reading activity codes from P6 databases, XER files, and PMXML files.
  • Added support for reading user defined values from a P6 database.
  • Added support for PRX files which contain a SureTrak database.
  • Added support for reading the resource \"enterprise\" attribute from MPP12 and MPP14 files.
  • Improve performance when reading user defined values from XER files.
  • Improved support for older Primavera PMXML files.
  • Updated to rtfparserkit 1.11.0 for improved RTF parsing.
"},{"location":"CHANGELOG/#744-2018-06-06","title":"7.4.4 (2018-06-06)","text":"
  • Improve handling of calendar exceptions in MPX files.
  • Improve handling of MPP files with large numbers of null tasks.
  • Improve robustness when reading timephased data.
  • Correctly sort Primavera schedules containing WBS entries with no child activities.
"},{"location":"CHANGELOG/#743-2018-05-25","title":"7.4.3 (2018-05-25)","text":"
  • Add support for reading the resource \"generic\" attribute from MPP files.
  • Add a Unique ID attribute to the Relation class and populate for schedule types which support this concept.
  • Store the Primavera Project ID as Unique ID in the project properties.
  • Update MerlinReader to ensure support for Merlin Project Pro 5.
"},{"location":"CHANGELOG/#742-2018-04-30","title":"7.4.2 (2018-04-30)","text":"
  • Gracefully handle malformed duration values in MSPDI files.
  • Gracefully handle unexpected calendar exception data structure in certain MPP files.
  • Improve handling of certain unusual MPP12 files.
  • More work to gracefully handle POI issue 61677, allowing affected MPP files to be read successfully.
"},{"location":"CHANGELOG/#741-2018-04-16","title":"7.4.1 (2018-04-16)","text":"
  • Add methods to list projects available in P3 and SureTrak database directories.
  • Avoid NPE when a work pattern can't be located in an Asta Powerproject PP file.
  • Avoid array bounds exception when reading certain PRX files.
  • Read outline code value lists from MPP9 files.
  • Handle SureTrak projects without a WBS.
"},{"location":"CHANGELOG/#740-2018-03-23","title":"7.4.0 (2018-03-23)","text":"
  • Added support for reading Primavera SureTrak databases from directories, zip files, and STX files.
  • Added support for PP files generated by Asta Powerproject from version 13.0.0.1
"},{"location":"CHANGELOG/#730-2018-03-12","title":"7.3.0 (2018-03-12)","text":"
  • Added support for reading Primavera P3 databases from directories, zip files, and PRX files.
  • Improve robustness when reading MPP files containing apparently invalid custom field data.
  • Improve UniversalProjectReader byte order mark handling.
  • Fixed Issue 324: Fields with lookup unreadable when a field has custom name.
"},{"location":"CHANGELOG/#721-2018-01-26","title":"7.2.1 (2018-01-26)","text":"
  • More work to gracefully handle POI issue 61677, allowing affected MPP files to be read successfully.
  • Avoid divide by zero when calculating percent complete from certain Primavera PMXML files.
  • UniversalProjectReader updated to recognise MPX files with non-default separator characters.
  • Update FastTrack reader to handle invalid percentage values on resource assignments.
  • Update FastTrack reader to handle variations in UUID format.
  • Read the full project name from XER files and the Primavera database and store it in the project title attribute.
"},{"location":"CHANGELOG/#720-2018-01-18","title":"7.2.0 (2018-01-18)","text":"
  • Added support for reading TurboProject PEP files.
  • Handle numeric values with leading spaces in XER files.
  • Fix array bounds error when reading constraints from certain MPP files.
"},{"location":"CHANGELOG/#710-2018-01-03","title":"7.1.0 (2018-01-03)","text":"
  • Added support for reading GanttProject GAN files.
  • Ensure that calendar exception dates are read correctly from XER files and P6 databases regardless of the user's timezone.
  • Read working day calendar exceptions from XER files and P6 database.
  • Mark some ProjectFile methods as deprecated.
"},{"location":"CHANGELOG/#703-2017-12-21","title":"7.0.3 (2017-12-21)","text":"
  • Use the Windows-1252 character set as the default when reading XER files.
  • Gracefully handle POI issue 61677 to allow MPP affected MPP files to be read successfully.
  • Handle recurring calendar exceptions read from MSPDI files without an occurrence count.
  • Improve robustness of FastTrack schedule reader.
  • Avoid reading empty calendar exceptions from MPX files.
"},{"location":"CHANGELOG/#702-2017-11-20","title":"7.0.2 (2017-11-20)","text":"
  • Further improvements to task pruning for Asta PP files.
"},{"location":"CHANGELOG/#701-2017-11-20","title":"7.0.1 (2017-11-20)","text":"
  • Improve robustness when reading MPP files when using certain 64-bit Java runtimes.
  • Populate the project's comments property when reading an MSPDI file.
  • Ensure that tasks are not discarded when reading PP files from older Asta versions.
  • Fixed Issue 319: Wrong date ranges for split tasks
  • Fixed Issue 222: getDefaultTaskType() not returning correct default task type
"},{"location":"CHANGELOG/#700-2017-11-08","title":"7.0.0 (2017-11-08)","text":"
  • Added support for reading recurring exceptions from MPP and MSPDI files.
  • Updated RecurringTask class interface (Note: this is a breaking API change)
  • MSPDI writer now uses save version 14 by default (Note: this may affect applications which consume MSPDI files you generate)
  • Correctly handle MSPDI files with Byte Order Marks.
  • Handle MSPDI files with varying namespaces.
  • Improve robustness Merlin file reader.
  • Improve extraction of task start and finish dates from PMXML files only containing partial data.
  • Prevent POI from closing the input stream when using UniversalProjectReader
  • Fixed Issue 321: Cannot read mpp file using getProjectReader.
"},{"location":"CHANGELOG/#621-2017-10-11","title":"6.2.1 (2017-10-11)","text":"
  • Gracefully handle corrupt MPP files.
  • Improve reading and writing slack values for MSPDI files.
  • Improve activity hierarchy extraction from Phoenix files.
  • Fixed Issue 243: MSPDI Slack values not correctly set while loading.
"},{"location":"CHANGELOG/#620-2017-10-06","title":"6.2.0 (2017-10-06)","text":"
  • Added support for reading Work Weeks from MPP files.
  • Add support for calendar exception names for MPP and MSPDI files.
  • Updated to use POI 3.17.
  • Improve accuracy of calendar exception dates read from XER files and P6 database.
  • Only write non-default user-defined field values to a PMXML file.
  • Use Primavera P6 17.7 XML schema.
  • Gracefully handle corrupt document summary information in MPP files.
  • Don't duplicate exceptions when reading from an MSPDI file.
  • Fixed Issue 231: MPP DataType: Non-unique enumeration value.
  • Fixed Issue 258: Calendar Work Week missing from MPP data extraction.
  • Fixed Issue 318: TimephasedWork Negative TotalAmount.
  • Fixed Issue 320: Date conversion fails in PrimaveraReader.
"},{"location":"CHANGELOG/#612-2017-09-12","title":"6.1.2 (2017-09-12)","text":"
  • Gracefully handle incomplete records in XER files.
"},{"location":"CHANGELOG/#611-2017-08-30","title":"6.1.1 (2017-08-30)","text":"
  • Ensure all classes in the gem are required
"},{"location":"CHANGELOG/#610-2017-07-28","title":"6.1.0 (2017-07-28)","text":"
  • Provide Task.getEffectiveCalendar() method
  • Populate missing finish dates in MSPDI files
"},{"location":"CHANGELOG/#600-2017-07-22","title":"6.0.0 (2017-07-22)","text":"
  • Gracefully handle invalid calendar data in XER files.
  • Handle XER files containing blank lines.
  • Add support for reading resource rates and availability tables from P6 (Contributed by Brandon Herzog).
  • Include overtime in work and cost fields when reading from P6 (Contributed by Brandon Herzog).
  • Read default project calendar from P6 (Contributed by Brandon Herzog).
  • Read resource rate and assignment units from P6 (Contributed by Brandon Herzog).
  • Set ignore resource calendar flag for tasks from P6 (Contributed by Brandon Herzog).
  • Change P6 costs to be calculated from resource assignment to support XER files without the cost table (Contributed by Brandon Herzog).
  • Map anticipated end date to deadline for P6 (Contributed by Brandon Herzog).
  • Update task work to include actual and remaining work when reading from P6 (Contributed by Brandon Herzog).
  • Calculate summary task work fields by summing up children when reading from P6 (Contributed by Brandon Herzog).
  • Set task project name when reading from P6 (Contributed by Brandon Herzog).
  • Fix \"00:00\" calendar finish times to parse as end of day when reading from P6 (Contributed by Brandon Herzog).
  • Add default working hours if a calendar does not specify any hours when reading from P6 (Contributed by Brandon Herzog).
  • Read fiscal year start month from P6 (Contributed by Brandon Herzog).
  • Fix bug in rollup of child task dates containing null values that could set incorrect end date when reading from P6 (Contributed by Brandon Herzog).
  • Fix date offset in parse of P6 calendar exceptions (Contributed by Brandon Herzog).
  • Fix count of P6 UDFs that map to same data type (Contributed by Brandon Herzog).
  • Add support for reading Resource and Assignment UDFs from P6 (Contributed by Brandon Herzog).
  • Update P6 UDFs to fill into multiple field types to expand storage capacity, for example into TEXT and ENTERPRISE_TEXT (Contributed by Brandon Herzog).
  • Use only the WBS as activity code for WBS tasks instead of also appending name for P6 tasks (Contributed by Brandon Herzog).
  • Add the ability to link task Relations that cross project boundaries in XER files (Contributed by Brandon Herzog).
  • Add function to clear all exceptions from ProjectCalendar instances (Contributed by Brandon Herzog).
  • Reading the lag calendar scheduling option as the \"LagCalendar\" custom project property when reading from P6 (Contributed by Brandon Herzog).
  • Updated UDF parsing to handle values as booleans if the user chooses to map them to Flag fields (Contributed by Brandon Herzog).
"},{"location":"CHANGELOG/#5140-2017-07-13","title":"5.14.0 (2017-07-13)","text":"
  • Improve handling of activity codes read from Phoenix files
  • Calculate percent complete for tasks read from Phoenix files
  • Populate task duration with Original Duration attribute when reading from XER files or P6 databases.
  • Ensure that task finish dates are read correctly from Phoenix files.
  • Improve UniversalProjectReader's handling of non-MPP OLE compound documents.
  • Improve task hierarchy and ordering when reading some MPP files.
"},{"location":"CHANGELOG/#5130-2017-06-27","title":"5.13.0 (2017-06-27)","text":"
  • Further improve handling of WBS, bar, and task structure from Asta files.
"},{"location":"CHANGELOG/#5120-2017-06-26","title":"5.12.0 (2017-06-26)","text":"
  • Improve handling of WBS, bar, and task structure from Asta files.
"},{"location":"CHANGELOG/#5110-2017-06-20","title":"5.11.0 (2017-06-20)","text":"
  • Improve handling of malformed durations in MSPDI files.
  • Improve performance when reading MPP files with certain kinds of timephased data.
  • Raise a specific \"password protected\" exception type from the Ruby gem.
  • Fix an issue with the storage of the \"earned value method\" task attribute.
"},{"location":"CHANGELOG/#5100-2017-05-23","title":"5.10.0 (2017-05-23)","text":"
  • Improve handling of deleted tasks in MPP files.
  • Improve handling of invalid predecessor tasks in MPX files.
  • Improve handling of invalid saved view state in MPP files.
  • Fixed Issue 313: Empty baseline dates populated with garbage date instead of null.
"},{"location":"CHANGELOG/#590-2017-04-27","title":"5.9.0 (2017-04-27)","text":"
  • Add support for reading ProjectLibre POD files (from ProjectLibre version 1.5.5 onwards).
  • Correct getter method name for \"file application\" project property.
"},{"location":"CHANGELOG/#580-2017-04-21","title":"5.8.0 (2017-04-21)","text":"
  • Updated to use POI 3.16 (note new dependency on Apache Commons Collections required by POI).
  • Improve support for estimated durations in Merlin files.
  • Read task notes from Asta files.
  • Improve support for reading resource rates from Phoenix files.
  • Add \"file application\" and \"file type\" to project properties to determine source of schedule data.
"},{"location":"CHANGELOG/#571-2017-03-22","title":"5.7.1 (2017-03-22)","text":"
  • Improve support for Phoenix Project Manager XML files.
"},{"location":"CHANGELOG/#570-2017-03-20","title":"5.7.0 (2017-03-20)","text":"
  • Add support for FastTrack Schedule files.
  • Ensure that timephased data calculations correctly handle entry to and exit from DST.
  • Fixed Issue 306: Microsoft Project 2016: Issue with assignment 'Work Contour' attribute.
"},{"location":"CHANGELOG/#565-2017-03-07","title":"5.6.5 (2017-03-07)","text":"
  • Improve handling of invalid calendar data in MSPDI files
  • Improve handling of XER files containing multi-line records
  • Improve handling of malformed MPX files
  • Fixed Issue 308: Add support for elapsed percent to MSPDI writer
  • Fixed Issue 310: MPX percent lag incorrect
"},{"location":"CHANGELOG/#564-2017-02-16","title":"5.6.4 (2017-02-16)","text":"
  • UniversalProjectReader now recognises and handles byte order marks
  • Fixed Issue 307: TimeUnit.ELAPSED_PERCENT read incorrectly from MPP files
"},{"location":"CHANGELOG/#563-2017-02-08","title":"5.6.3 (2017-02-08)","text":"
  • Added a parameter to the Ruby gem to allow the maximum JVM memory size to be set.
  • Updated to rtfparserkit 1.10.0 for improved RTF parsing.
"},{"location":"CHANGELOG/#562-2017-02-06","title":"5.6.2 (2017-02-06)","text":"
  • Fixed Issue 305: Failed to Parse error with Primavera 15.2 or 16.1 XML files
"},{"location":"CHANGELOG/#561-2017-02-03","title":"5.6.1 (2017-02-03)","text":"
  • Correct resource assignment handling for Phoenix Project Manager schedules.
"},{"location":"CHANGELOG/#560-2017-01-29","title":"5.6.0 (2017-01-29)","text":"
  • Add support for Phoenix Project Manager schedules.
"},{"location":"CHANGELOG/#559-2017-01-27","title":"5.5.9 (2017-01-27)","text":"
  • Improve robustness of date parsing for MPX files.
"},{"location":"CHANGELOG/#558-2017-01-23","title":"5.5.8 (2017-01-23)","text":"
  • Fix NPE when reading graphical indicators with unknown field type.
"},{"location":"CHANGELOG/#557-2017-01-13","title":"5.5.7 (2017-01-13)","text":"
  • Fix percent complete NaN value for some Primavera schedules.
"},{"location":"CHANGELOG/#556-2017-01-06","title":"5.5.6 (2017-01-06)","text":"
  • Fix incorrectly set critical flag for primavera schedules.
"},{"location":"CHANGELOG/#555-2017-01-06","title":"5.5.5 (2017-01-06)","text":"
  • Updated to rtfparserkit 1.9.0 for improved RTF parsing
  • Improve calendar exception parsing for Primavera XER and database readers.
  • Ensure the task summary flag is set correctly for Primavera schedules.
  • Rollup baseline, early and late start and finish dates to WBS for Primavera schedules.
  • Rollup baseline duration, remaining duration and percent complete to WBS for Primavera schedules.
  • Use the project's critical slack limit value when setting the critical flag on a task.
  • Experimental support for reading Merlin Project schedules.
"},{"location":"CHANGELOG/#554-2016-12-01","title":"5.5.4 (2016-12-01)","text":"
  • Default to UTF-8 encoding when generating JSON files
"},{"location":"CHANGELOG/#553-2016-11-29","title":"5.5.3 (2016-11-29)","text":"
  • Correctly read text from MPP files when default charset is not UTF-8.
  • Improve accuracy when reading MPP9 files.
"},{"location":"CHANGELOG/#552-2016-11-02","title":"5.5.2 (2016-11-02)","text":"
  • Add Primavera Parent Resource ID as a specific resource attribute (Based on a contribution by Dave McKay).
  • PMXML writer generates currency record (Based on a contribution by Dave McKay).
  • PMXML writer defaults Activity PercentCompleteType to Duration (Based on a contribution by Dave McKay).
  • PMXML writer records currency and parent attributes for Resource (Based on a contribution by Dave McKay).
  • PMXML writer resource assignments include RateSource and ActualOvertimeUnits attributes(Based on a contribution by Dave McKay).
  • MSPDI reader: gracefully handle invalid calendar exceptions..
  • PMXML writer: gracefully handle missing data.
  • Planner writer: gracefully handle missing data.
"},{"location":"CHANGELOG/#551-2016-10-14","title":"5.5.1 (2016-10-14)","text":"
  • Update universal project reader to support zip files.
  • Update ruby to align error handling with universal project reader.
"},{"location":"CHANGELOG/#550-2016-10-13","title":"5.5.0 (2016-10-13)","text":"
  • Universal project reader.
  • Avoid NPE when reading PMXML files.
  • Fixed Issue 297: Missing extended attributes
  • Fixed Issue 300: CrossProject field omission causes issues when importing to P6
"},{"location":"CHANGELOG/#540-2016-10-06","title":"5.4.0 (2016-10-06)","text":"
  • Updated to use POI 3.15.
"},{"location":"CHANGELOG/#533-2016-08-31","title":"5.3.3 (2016-08-31)","text":"
  • Avoid NPE when field type is unknown.
  • Improve Ruby error reporting.
  • Improve support for non-standard time formats in MPX files
  • Improve support for MPP14 files with very large numbers of blank tasks
"},{"location":"CHANGELOG/#532-2016-08-31","title":"5.3.2 (2016-08-31)","text":"
  • When reading an XER file, treat FT_STATICTPYE user defined fields as text.
"},{"location":"CHANGELOG/#531-2016-07-01","title":"5.3.1 (2016-07-01)","text":"
  • Add data date attribute to PMXML output.
  • Update PMXML writer to avoid NPE.
  • Update PMXML writer to allow task field used for Activity ID to be chosen.
  • Updated to avoid NPE when reading an XER file where project not under EPS.
  • Generate Task IDs if missing from MSPDI file
"},{"location":"CHANGELOG/#530-2016-06-10","title":"5.3.0 (2016-06-10)","text":"
  • Add support for PP files generated by Asta Powerproject from version 13.0.0.3 onwards
  • Minor improvements to SDEF support.
  • Updated to rtfparserkit 1.8.0
  • Improve finish time handling in PMXML files (contributed by lobmeleon)
"},{"location":"CHANGELOG/#522-2016-03-11","title":"5.2.2 (2016-03-11)","text":"
  • Add support for resource assignment Stop and Resume attributes for MPP and MSPDI files
  • Fixed Issue 291: PrimaveraPMFileWriter.write fails with java.lang.IllegalArgumentException
  • Fixed Issue 292: Microsoft Project 2016 : Need to set 'Stop' and 'Resume' properties for net.sf.mpxj.ResourceAssignment
"},{"location":"CHANGELOG/#521-2016-02-11","title":"5.2.1 (2016-02-11)","text":"
  • Add support for PP files generated by Asta Powerproject up to version 13.0.0.3
"},{"location":"CHANGELOG/#520-2016-02-08","title":"5.2.0 (2016-02-08)","text":"
  • Add support for PP files generated by Asta Powerproject 11, Powerproject 12, Easyplan 2, Easyplan 3, Easyplan 4, Easyplan 5 and Easyplan 6
  • Fixed Issue 285: Unsupported encoding command ansicpg949
  • Fixed Issue 288: AvailabilityTable getEntryByDate does not work properly
"},{"location":"CHANGELOG/#5118-2016-01-25","title":"5.1.18 (2016-01-25)","text":"
  • Fixed Issue 285: Unsupported encoding command ansicpg1254
  • Fixed Issue 286: NullPointerException in CriteriaReader.getConstantValue
  • Fixed Issue 287: Allow a character encoding to be specified when reading an XER file
  • Write Primavera Primary Resource Unique ID to Task field Number1
"},{"location":"CHANGELOG/#5117-2015-12-30","title":"5.1.17 (2015-12-30)","text":"
  • Improve support for reading MPP files generated by Project 2016
  • Handle missing time component of a time stamp field when reading an MPX file.
"},{"location":"CHANGELOG/#5116-2015-12-18","title":"5.1.16 (2015-12-18)","text":"
  • Improve support for reading MPX files generated by SureTrak
"},{"location":"CHANGELOG/#5115-2015-12-16","title":"5.1.15 (2015-12-16)","text":"
  • Fix WBS and Activity ordering for tasks from Primavera.
"},{"location":"CHANGELOG/#5114-2015-12-09","title":"5.1.14 (2015-12-09)","text":"
  • Strip unescaped control characters from JSON output.
"},{"location":"CHANGELOG/#5113-2015-11-26","title":"5.1.13 (2015-11-26)","text":"
  • For schedules imported from Primavera ensure tasks representing activities are ordered by Activity ID within the WBS to match Primavera.
"},{"location":"CHANGELOG/#5112-2015-11-16","title":"5.1.12 (2015-11-16)","text":"
  • Avoid NPE when writing MSPDI files with timephased data (contributed by Bruno Gasnier)
  • Improve resource assignment constructor (based on a contribution by Bruno Gasnier)
  • Improve MPX French translations (contributed by Bruno Gasnier)
  • Add calendar specific minutes per day, week, month, and year (based on a contribution by Bruno Gasnier)
  • Add support for reading and writing GUID attribute for PMXML, XER files and Primavera database.
"},{"location":"CHANGELOG/#5111-2015-11-12","title":"5.1.11 (2015-11-12)","text":"
  • Avoid NPE when reading MPP14 custom properties.
  • Ensure calculated task attributes are present in JSON output.
  • Handle MSPDI files written by German versions of Microsoft Project (based on a contribution by Lord Helmchen)
  • Fixed Issue 277: synchronizeTaskIDToHierarchy clears list of tasks
  • Fixed Issue 273: PrimaveraPMFileWriter throws Exception at write(..)
  • Fixed Issue 281: Parent task is always null when reading a Primavera XER file
  • Ensure that Task.getSuccesors() and Task.getPredecessors() return an empty list rather than null.
"},{"location":"CHANGELOG/#5110-2015-09-09","title":"5.1.10 (2015-09-09)","text":"
  • Improve FixedMeta2 block size heuristic to improve reliability when reading MPP14 files.
"},{"location":"CHANGELOG/#519-2015-08-29","title":"5.1.9 (2015-08-29)","text":"
  • Ensure Resource BookingType is read correctly from MPP files
  • Added basic custom field attributes to JSON output
  • Added Ruby methods to work with custom field aliases
  • Fix to infinite loop condition when writing calendar (contributed by lobmeleon)
  • Fixed Issue 274: MPXJ getNotes() API returns garbled value for multibyte characters
  • Fixed Issue 268: Unsupported encoding error when reading resource notes
  • Fixed Issue 256: Incorrect resource types are read (contributed by Colin Rodriguez)
  • Symmetry between Primavera PM reader/writer (contributed by lobmeleon)
  • Added UDF support to PMXML file reader and writer(contributed by lobmeleon)
  • Updated to rtfparserkit 1.4.0
"},{"location":"CHANGELOG/#518-2015-07-13","title":"5.1.8 (2015-07-13)","text":"
  • Another attempt at getting tzinfo-data dependency working
"},{"location":"CHANGELOG/#517-2015-07-13","title":"5.1.7 (2015-07-13)","text":"
  • Updated ruby gem to make tzinfo-data dependency conditional on platform
"},{"location":"CHANGELOG/#516-2015-07-13","title":"5.1.6 (2015-07-13)","text":"
  • Updated ruby gem to allow timezone to be provided
"},{"location":"CHANGELOG/#515-2015-06-05","title":"5.1.5 (2015-06-05)","text":"
  • Updated to use IKVM 8.0.5449.1
"},{"location":"CHANGELOG/#514-2015-06-03","title":"5.1.4 (2015-06-03)","text":"
  • Updated to generate Activity ID for Primavera WBS.
  • Updated to correct Primavera duration percent complete calculation.
"},{"location":"CHANGELOG/#513-2015-05-18","title":"5.1.3 (2015-05-18)","text":"
  • Updated to ensure Ruby reads Boolean attributes correctly.
"},{"location":"CHANGELOG/#512-2015-05-18","title":"5.1.2 (2015-05-18)","text":"
  • Updated to ensure Ruby recognises short type as an integer.
"},{"location":"CHANGELOG/#511-2015-05-18","title":"5.1.1 (2015-05-18)","text":"
  • Updated to use ruby-duration gem to avoid conflict with ActiveSupport::Duration.
"},{"location":"CHANGELOG/#510-2015-05-17","title":"5.1.0 (2015-05-17)","text":"
  • Updated to ensure that PrimaveraDatabaseReader.setSchema accepts null or empty string
  • Ensure conversion to/from .Net DateTime takes account of timezone and daylight savings (based on a contribution by Timour Koupeev)
  • Updated to use POI 3.12.
  • Removed ProjectFile.getTaskFieldAliases, replaced by ProjectFile.getCustomField().getFieldByAlias
  • Removed ProjectFile.getResourceFieldAliases, replaced by ProjectFile.getCustomField().getFieldByAlias
"},{"location":"CHANGELOG/#500-2015-05-06","title":"5.0.0 (2015-05-06)","text":"
  • Added project properties to the JSON output
  • Added support for project properties to the Ruby wrapper
  • Added support for reading data from a standalone Primavera P6 SQLite database
  • Fixed Issue 267: XXE security vulnerability
  • Fixed Issue 266: Task Number fields not saved to file if the value would floor to zero
  • Fixed Issue 255: Not all project calendars are read in for Project 2013 files (based on a contribution by Colin Rodriguez)
  • Renamed TaskContainer class to ChildTaskContainer
  • Renamed ProjectHeader class to ProjectProperties
  • Introduced ProjectConfig class
  • Introduced TaskContainer class
  • Introduced ResourceContainer class
  • Introduced ResourceAssignmentContainer class
  • Introduced ProjectCalendarContainer class
  • Renamed ProjectFile.getProjectHeader to getProjectProperties
  • Renamed ProjectFile.getCalendar to getDefaultCalendar
  • Renamed ProjectFile.setCalendar to setDefaultCalendar
  • Renamed MppReader.getReadHeaderOnly to getReadPropertiesOnly
  • Renamed MppReader.setReadHeaderOnly to setReadPropertiesOnly
  • Renamed ProjectFile.getCalendarUniqueID to ProjectConfig.getNextCalendarUniqueID
  • Renamed ProjectFile.getResourceUniqueID to ProjectConfig.getNextResourceUniqueID
  • Renamed ProjectFile.getTaskUniqueID to ProjectConfig.getNextTaskUniqueID
  • Renamed ProjectFile.getAssignmentUniqueID to ProjectConfig.getNextAssignmentUniqueID
  • Renamed ProjectFile.getResourceID to ProjectConfig.getNextResourceID
  • Renamed ProjectFile.getTaskID to ProjectConfig.getNextTaskID
  • Renamed ProjectHeader.getApplicationName to getShortApplicationName
  • Renamed ProjectHeader.setApplicationName to setShortApplicationName
  • Renamed ProjectHeader.setCalendarName to setDefaultCalendarName
  • Renamed ProjectHeader.getCalendarName to getDefaultCalendarName
  • Moved ProjectFile.getProjectFilePath to ProjectHeader.getProjectFilePath
  • Moved ProjectFile.setProjectFilePath to ProjectHeader.setProjectFilePath
  • Moved ProjectFile.getApplicationName to ProjectHeader.getFullApplicationName
  • Moved ProjectFile.setApplicationName to ProjectHeader.setFullApplicationName
  • Moved FileCreationRecord.setDelimiter to ProjectHeader.setMpxDelimiter
  • Moved FileCreationRecord.getDelimiter to ProjectHeader.getMpxDelimiter
  • Moved FileCreationRecord.setProgramName to ProjectHeader.setMpxProgramName
  • Moved FileCreationRecord.getProgramName to ProjectHeader.getMpxProgramName
  • Moved FileCreationRecord.setFileVersion to ProjectHeader.setMpxFileVersion
  • Moved FileCreationRecord.getFileVersion to ProjectHeader.getMpxFileVersion
  • Moved FileCreationRecord.setCodePage to ProjectHeader.setMpxCodePage
  • Moved FileCreationRecord.getCodePage to ProjectHeader.getMpxCodePage
  • Moved ProjectFile.getMppFileType to ProjectHeader.getMppFileType
  • Moved ProjectFile.setMppFileType to ProjectHeader.setMppFileType
  • Moved ProjectFile.getApplicationVersion to ProjectHeader.getApplicationVersion
  • Moved ProjectFile.setApplicationVersion to ProjectHeader.setApplicationVersion
  • Moved ProjectFile.setAutoFilter to ProjectHeader.setAutoFilter
  • Moved ProjectFile.getAutoFilter to ProjectHeader.getAutoFilter
  • Removed ProjectFile.getAliasTaskField, replaced by ProjectFile.getTaskFieldAliases().getField()
  • Removed ProjectFile.getAliasResourceField, replaced by ProjectFile.getResourceFieldAliases().getField()
  • Removed ProjectFile.getTaskFieldAlias, replaced by ProjectFile.getTaskFieldAliases().getAlias()
  • Removed ProjectFile.setTaskFieldAlias, replaced by ProjectFile.getTaskFieldAliases().setAlias()
  • Removed ProjectFile.getResourceFieldAlias, replaced by ProjectFile.getResourceFieldAliases().getAlias()
  • Removed ProjectFile.setResourceFieldAlias, replaced by ProjectFile.getResourceFieldAliases().setAlias()
  • Removed ProjectFile.getTaskFieldAliasMap, replaced by ProjectFile.getTaskFieldAliases
  • Removed ProjectFile.getResourceFieldAliasMap, replaced by ProjectFile.getResourceFieldAliases
  • Removed ProjectFile.addTable, replaced by ProjectFile.getTables().add()
  • Removed ProjectFile.getTaskTableByName, replaced by ProjectFile.getTables().getTaskTableByName()
  • Removed ProjectFile.getResourceTableByName, replaced by ProjectFile.getTables().getResourceTableByName()
  • Removed ProjectFile.addFilter, replaced by ProjectFile.getFilters().addFilter()
  • Removed ProjectFile.removeFilter, replaced by ProjectFile.getFilters().rmoveFilter()
  • Removed ProjectFile.getAllResourceFilters, replaced by ProjectFile.getFilters().getResourceFilters()
  • Removed ProjectFile.getAllTaskFilters, replaced by ProjectFile.getFilters().getTaskFilters()
  • Removed ProjectFile.getFilterByName, replaced by ProjectFile.getFilters().getFilterByName()
  • Removed ProjectFile.getFilterByID, replaced by ProjectFile.getFilters().getFilterByID()
  • Removed ProjectFile.getAllGroups, replaced by ProjectFile.getGroups()
  • Removed ProjectFile.getGroupByName, replaced by ProjectFile.getGroups().getByName()
  • Removed ProjectFile.addGroups, replaced by ProjectFile.getGroups().add()
  • Removed ProjectFile.addView, replaced by ProjectFile.getViews().add()
  • Removed ProjectFile.setViewState, replaced by ProjectFile.getViews().setViewState()
  • Removed ProjectFile.getViewState, replaced by ProjectFile.getViews().getViewState()
  • Removed ProjectFile.getResourceSubProject, replaced by ProjectFile.getSubProjects().getResourceSubProject()
  • Removed ProjectFile.setResourceSubProject, replaced by ProjectFile.getSubProjects().setResourceSubProject()
  • Removed ProjectFile.addSubProject, replaced by ProjectFile.getSubProjects().add()
  • Removed ProjectFile.getAllSubProjects, replaced by ProjectFile.getSubProjects
  • Removed ProjectFile.fireTaskReadEvent, replaced by ProjectFile.getEventManager().fireTaskReadEvent()
  • Removed ProjectFile.fireTaskWrittenEvent, replaced by ProjectFile.getEventManager().fireTaskWrittenEvent()
  • Removed ProjectFile.fireResourceReadEvent, replaced by ProjectFile.getEventManager().fireResourceReadEvent()
  • Removed ProjectFile.fireResourceWrittenEvent, replaced by ProjectFile.getEventManager().fireResourceWrittenEvent()
  • Removed ProjectFile.fireCalendarReadEvent, replaced by ProjectFile.getEventManager().fireCalendarReadEvent()
  • Removed ProjectFile.fireAssignmentReadEvent, replaced by ProjectFile.getEventManager().fireAssignmentReadEvent()
  • Removed ProjectFile.fireAssignmentWrittenEvent, replaced by ProjectFile.getEventManager().fireAssignmentWrittenEvent()
  • Removed ProjectFile.fireRelationReadEvent, replaced by ProjectFile.getEventManager().fireRelationReadEvent()
  • Removed ProjectFile.fireRelationWrittenEvent, replaced by ProjectFile.getEventManager().fireRelationWrittenEvent()
  • Removed ProjectFile.fireCalendarWrittenEvent, replaced by ProjectFile.getEventManager().fireCalendarWrittenEvent()
  • Removed ProjectFile.addProjectListener, replaced by ProjectFile.getEventManager().addProjectListener()
  • Removed ProjectFile.addProjectListeners, replaced by ProjectFile.getEventManager().addProjectListeners()
  • Removed ProjectFile.removeProjectListener, replaced by ProjectFile.getEventManager().removeProjectListener()
  • Removed ProjectFile.addGraphicalIndicator
  • Removed ProjectFile.getGraphicalIndicator, replaced by ProjectFile.getCustomFields().getCustomField().getGraphicalIndicator()
"},{"location":"CHANGELOG/#476-2015-03-18","title":"4.7.6 (2015-03-18)","text":"
  • Added a Ruby wrapper for MPXJ
  • Added the ability to export project data as JSON, to make it easier to work with in languages other than Java
  • Added support for the Assignment attribute Resource Request Type
  • Primavera database and XER readers updated to match WBS visible in Primavera for each task. Previous behaviour of generating a unique WBS for each task can be restored using a flag set on the readers.
  • Avoid NPE when calculating Task Completed Through
  • Read Task Earned Value Method correctly from MPP files
  • Fix issue where some floating point attributes were returning NaN
"},{"location":"CHANGELOG/#475-2015-02-27","title":"4.7.5 (2015-02-27)","text":"
  • Handle invalid Primavera calendar data gracefully
"},{"location":"CHANGELOG/#474-2015-02-25","title":"4.7.4 (2015-02-25)","text":"
  • Fixed Issue 257: Failed to read project containing CodePage 1250 text.
  • Fixed Issue 259: MS Project 2010: tasks with null baseline dates
  • Incorrect task end date read from Primavera XER and database
  • Incorrect percent complete read from Primavera XER, database, and PMXML files
  • Failed to read fields held at the end of a fixed data block
  • Added support for Task Baseline Estimated Duration, Baseline Estimated Start, Baseline Estimated Finish, Baseline Fixed Cost, and Baseline Fixed Cost Accrual
  • Added the ability to customise the fields read from a Primavera database or XER file.
  • Added Task Activity Type and Task Status as additional fields read from Primavera database and XER and files
  • Changed Task physical percent complete methods for consistency to use Number rather than Integer
"},{"location":"CHANGELOG/#473-2014-12-23","title":"4.7.3 (2014-12-23)","text":"
  • Updated to use POI 3.11.
  • Updated to use rtfparserkit 1.1.0 for Java 6 compatibility.
"},{"location":"CHANGELOG/#472-2014-12-15","title":"4.7.2 (2014-12-15)","text":"
  • Updated to fix Maven dependency issue.
"},{"location":"CHANGELOG/#471-2014-12-08","title":"4.7.1 (2014-12-08)","text":"
  • Added a flag to MPPReader to indicate that only the project header should be read.
"},{"location":"CHANGELOG/#470-2014-12-04","title":"4.7.0 (2014-12-04)","text":"
  • Implemented new RTF parser for stripping RTF to improve performance and accuracy
  • Removed non-API code from the top level package
  • Improved support for reading built-in and custom project properties from MPP files.
  • Improved resilience of MPP file reading to unknown data structures
  • Fixed issue which could cause an infinite loop when ordering tasks in a file containing multiple consecutive blank tasks
  • Fixed issue where free text versions of task start, finish, and duration fields were not being read correctly from MPP14 files
"},{"location":"CHANGELOG/#462-2014-11-11","title":"4.6.2 (2014-11-11)","text":"
  • Fixed issue with custom duration field units not read correctly from MSPDI files
  • Fixed Issue 223: Problems with the lag calculated in the relation
  • Outline code not read correctly from MPP file written by Project 2013
  • Fixed Issue 239: Defensive changes to avoid exceptions when reading MPP files
  • Fixed Issue 250: Deleted tasks being read from mpp file
  • Added DotNetInputStream and DotNetOutputStream classes for ease of use under .Net.
  • Updated to automatically generate and package MpxjUtilities.dll
"},{"location":"CHANGELOG/#461-2014-10-17","title":"4.6.1 (2014-10-17)","text":"
  • Fixed NuGet metadata
"},{"location":"CHANGELOG/#460-2014-10-17","title":"4.6.0 (2014-10-17)","text":"
  • Added support for NuGet.
  • Fixed an issue where the ID and Unique ID resource attributes were being read incorrectly from MPP14 files.
  • Fixed an issue where the project's default duration format was not being used
  • Fixed Issue 248: Reading .MPP file using MPXJ 4.2 reads extra unintentional ResourceAssignment with the task which is not seen in Task Sheet in Microsoft Project
  • Fixed Issue 235: All resources have \"Material\" property
  • Fixed Issue 247: Updated Primavera PM XML file reader to capture the Project ID to align with data read from XER file/database (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to ensure task percent complete supports Physical Percent, Duration Percent and Units Percent (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to ensure task baseline values match values read from XER file/database (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to ensure task actual duration to matches value read from XER file/database (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to read the task duration (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to read task LateStart, LateFinish, EarlyStart, EarlyFinish attributes correctly (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to read task Start and End correctly (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to identify milestones (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to set the task Critical attribute (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to include costs (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera XER/Database readers to read task Start and End correctly (contributed by Nathaniel Marrin)
  • Migrated tests to JUnit 4
"},{"location":"CHANGELOG/#450-2014-03-01","title":"4.5.0 (2014-03-01)","text":"
  • Added the ability to call the .Net version of MPXJ from COM.
  • Added support Primavera decimal database columns.
  • Added support for user defined task fields (contributed by Mario Fuentes).
  • Added POM for current Maven versions (contributed by Nick Burch)
  • Fixed Issue 213: Unable to load mpp from project-2013
  • Fixed Issue 226: Primavera currency files without currency information
  • Fixed Issue 227: PrimaveraReader cannot handle files with more than 30 user defined fields
  • Fixed Issue 224: setMilestone() issue
  • Fixed Issue 210: MPXJ 4.4 and 2013 files - invalid load of task data
  • Updated to fix an issue with Asta Powerproject PP file tokenization
  • Updated to fix an issue where valid WBS values containing .0 are corrupted
  • Updated to allow Primavera hours per day to be a decimal value
  • Updated to support Primavera PM XML files generated by Primavera versions up to P6v8.3 (contributed by Mario Fuentes)
  • Updated to set the StatusDate attribute in the project header from a Primavera database, XER file or PM XML file.
  • Updated to use (a patched version of) POI 3.10.
"},{"location":"CHANGELOG/#440-2013-03-14","title":"4.4.0 (2013-03-14)","text":"
  • Added support for writing Primavera PM XML files.
  • Added support for reading Asta Powerproject PP and MDB files.
  • Added support for writing SDEF files (Contributed by William Iverson).
  • Added support for reading Enterprise Custom Fields 1-50 for Task, Resources, and Resource Assignments.
  • Added MpxjExtensionMethods assembly to simplify working with Java types in .Net (Contributed by Kyle Patmore)
  • Provided two new .Net DLL versions in addition to the original version. These allow properties to be accessed in a \".Net style\", and for languages apart from VB, provide .Net style method names.
  • Updated to remove the distinction between base calendar and resource calendars in the ProjectFile class.
  • Updated to improve support for custom outline codes (Contributed by Gary McKenney)
  • Fixed Issue 189: getTimephasedOvertimeWork can return TimephasedWork with NaN
  • Fixed Issue 190: Support for timephased cost for cost type resources
  • Fixed Issue 195: Rolled Up tasks don't use default duration units
  • Fixed Issue 199: Extract Primavera Task ID
  • Updated to fix an issue where the resource assignment delay attribute was not being read from or written to MSPDI files correctly
  • Updated to fix an issue where derived calendars were not being read correctly from MPP files
  • Updated to use IKVM 7.2.
"},{"location":"CHANGELOG/#430-2012-02-08","title":"4.3.0 (2012-02-08)","text":"
  • Added support for reading Primavera PM XML files.
  • Added support for reading timephased cost, and timephased baseline cost and baseline work from MPP files.
  • Added support for Work Weeks in MSPDI files (SourceForge feature request 23).
  • Updated to use IKVM 7.0.
  • Updated to fix SourceForge bug 3290224: Incorrect order of tasks when writing an MSPDI file (contributed by Jonathan Besanceney).
  • Fixed Issue 161: ResourceAssignment.getTaskUniqueID() returns null.
  • Fixed Issue 169: Wrong project name in MPX file.
  • Fixed Issue 170: Wrong title in XML file when importing from XER file.
  • Fixed Issue 168: Wrong record number for resource calendar in MPX file.
  • Fixed Issue 171: In the XML file the element field SaveVersion is missing.
  • Fixed Issue 167: Loop when import task with 0% on units of works in resources.
  • Fixed Issue 163: French locale NA incorrect.
  • Fixed Issue 175: Invalid dependency between child and parent.
  • Fixed Issue 174: Missing tasks from MS Project 2010 mpp file.
  • Fixed Issue 179: Wrong WBS code and WBS when converting a Primavera XER file.
  • Fixed Issue 177: Error reading XER file with German localisation for numbers.
  • Fixed Issue 166: TimephasedResourceAssignments with negative TotalWork.
  • Fixed Issue 181: Wrong currency symbol in the exported file.
  • Fixed Issue 104: TimephasedResourceAssignment end date not correct.
  • Fixed Issue 116: Calendar hours are incorrect.
  • Fixed Issue 188: NullReferenceException with getTimephasedBaselineWork.
  • Fixed Issue 191: Outline number is null when opening Project 2003 MPP file.
  • Fixed Issue 192: Unable to parse note (unknown locale).
  • Fixed Issue 193: MPP9Reader marks all tasks after a null task as null.
  • Updated to fix an issue where the Task critical attribute was incorrectly calculated for some manually scheduled tasks.
  • Updated to fix an issue where the Task summary attribute was not set correctly when using certain methods to add or remove child tasks.
  • Updated to fix an issue where subprojects were not read correctly (Contributed by Gary McKenney).
"},{"location":"CHANGELOG/#420-2011-06-23","title":"4.2.0 (2011-06-23)","text":"
  • Added support for resource assignment fields Baseline Cost 1-n, Baseline Work 1-n, Baseline Start 1-n, Baseline Finish 1-n, Start 1-n, Finish 1-n, Date 1-n, Duration 1-n, Cost 1-n, Text 1-n, Number 1-n, Flag 1-n, for MPP, MPD, and MSPDI files.
  • Added support for task suspend date, task resume date, and task code read from Primavera, and represented in MS Project custom fields Date1, Date2, and Text1 respectively.
  • Added support for retrieving the table associated with any view.
  • Fixed Issue 158: Error converting Mpp to planner.
  • Fixed Issue 157: MSPDI Linklag for TimeUnit.Percent.
  • Fixed Issue 156: Error reading calendars for 2010 files.
  • Fixed Issue 159: Duplication of calendar id.
  • Fixed Issue 153: Wrong task start.
  • Fixed Issue 156: Wrong start and finish dates for 2010 files.
"},{"location":"CHANGELOG/#410-2011-05-30","title":"4.1.0 (2011-05-30)","text":"
  • Updated ProjectFile class to change default value for \"auto\" flags to simplify programmatic creation of project files.
  • Added support for Manual, Start Text, Finish Text, and Duration Text attributes in MSPDI files.
  • Added support cost resource type for MPP12, MPP14 and MSPDI files.
  • Added Task.removePredecessor method (contributed by Leslie Damon).
  • Added \"read presentation data\" flag to MPPReader - allows clients to save time and memory when MPP presentation data not required.
  • Added support for reading Primavera calendars (contributed by Bruno Gasnier).
  • Added support for resource assignment leveling delay for MPP, MPD, and MSPDI files.
  • Added support for \"unassigned\" resource assignments.
  • Added support for task manual duration attribute for manually scheduled tasks in MPP14 and MSPDI files.
  • Added support for resource NT account attribute for MPP9, MPP12, and MPP14 files.
  • Added support for physical % complete for MPP9, MPP12, and MPP14 files.
  • Fixed Issue 120: MPXJ API returns the incorrect start date of a manual task.
  • Fixed Issue 123: Task id incorrect after importing from MPP14 file.
  • Fixed Issue 124: MPXJ 4.0 fails to work with Project 2010 format.
  • Fixed Issue 128: Index was outside the bounds of the array.
  • Fixed Issue 131: header.getHonorConstraints() is not working in case of MPP.
  • Fixed Issue 139: Empty notes appear for all tasks when saving in XML format.
  • Fixed Issue 122: All Extended Attributes always added when using MSPDIWriter.
  • Fixed Issue 144: Baseline/Actual Work in 2010 MPP missing.
  • Fixed Issue 114: ResourceAssignment getCalendar not using IgnoreResourceCalendar flag
  • Fixed Issue 146: ExternalTaskProject value missing.
  • Fixed Issue 137: Deleted Primavera tasks handling problem.
  • Fixed Issue 143: Latest CVS version gives wrong values for inactive field.
  • Fixed Issue 125: Task ID order when creating a project file is not correct.
  • Fixed Issue 106: Invalid tasks that should not be there.
  • Updated to fix task calendars read incorrectly from MPP14 files.
  • Updated to fix incorrect month duration assumption (contributed by Frank Illenberger).
  • Updated to fix incorrect number format in MSPDI file in non-English locales (contributed by Frank Illenberger).
  • Updated to fix incorrect resource assignment actual work attribute for MPP14 files.
  • Updated to fix incorrect task leveling delay attribute for MPP9, MPP12, and MPP14 files.
  • Updated to fix leveling delay and link lag when writing an MSPDI file (contributed by Frank Illenberger).
  • Updated to fix incorrect assignment actual start date when writing an MSPDI file.
  • Updated to improve support for material resources in MSPDI files.
  • Updated to reduce overall size of MSPDI files by not writing default values.
  • Updated to use IKVM 0.46.0.1.
  • Updated to use POI 3.7.
  • Updated to make task, resource, and assignment fields read from MPP files data-driven, rather than hard coded.
"},{"location":"CHANGELOG/#400-2010-05-25","title":"4.0.0 (2010-05-25)","text":"
  • Added support for reading Microsoft Project 2010 MPP files.
  • Added support for reading Primavera P6 XER files.
  • Added support for reading Primavera P6 databases.
  • Updated to target Java 1.6.
  • Added Russian locale (Contributed by Roman Bilous).
  • Relation.getDuration() is always giving result in 'HOUR' fmt.
"},{"location":"CHANGELOG/#320-2010-01-20","title":"3.2.0 (2010-01-20)","text":"
  • Added support for Resource cost rate tables (Based on code by Andrei Missine).
  • Added support for Resource availability (Based on code by Andrei Missine).
  • Added support for successors (Based on an idea by John D. Lewis).
  • Added support for task and resource GUIDs.
  • Added a flag to allow raw timephased data to be retrieved from MPP files.
  • Updated to fix logical operator read issue in MPP auto filters (Contributed by Andrei Missine).
  • Fixed Issue 94: MPXJ Issue: Related to Project Calendar.
  • Fixed Issue 90: POI License in legal folder of download wrong.
  • Updated to fix Steelray bug 15468: Null Pointer Exception reading task constraints.
  • Fixed Issue 102: Planner writer causes Null Pointer exception.
  • Fixed Issue 100: getRecurring() task is not working
  • Fixed Issue 98: getStandardRateFormat() is returning 'null'
  • Fixed Issue 97: getWeekStartDay() is not working.
  • Fixed Issue 96: getDaysPerMonth() is not working.
  • Fixed Issue 101: Resource.getNotes() not working for MPP12 file.
  • Fixed Issue 105: MPP: getEditableActualCosts() is not behaving correctly.
  • Updated to use POI 3.6.
  • Updated to use IKVM 0.42.0.3.
  • Updated to make MPX duration parsing more lenient (Contributed by Jari Niskala).
  • Updated to make MPP Var2Data extraction more robust (Contributed by Jari Niskala).
  • Updated to implement MSPDI context caching to improve performance (Contributed by Jari Niskala).
  • Updated to improve MPP file task structure validation. (Contributed by Jari Niskala).
  • Updated to improve MPX file parsing. (Contributed by Jari Niskala).
  • Updated to automatically populate missing WBS attributes. (Contributed by Jari Niskala).
  • Updated to refactor the Relation class (note minor method name changes).
  • Updated to add default calendar to Planner output.
"},{"location":"CHANGELOG/#310-2009-05-20","title":"3.1.0 (2009-05-20)","text":"
  • Fixed Issue 73: Plan file fails to load.
  • Fixed Issue 72: Resource Assignment Normaliser rounding problem.
  • Fixed Issue 78: Column alignment values are incorrect.
  • Fixed Issue 76: NullPointerException in parseExtendedAttribute() (Contributed by Paul Pogonyshev).
  • Fixed Issue 74: .0 at the end of WBS code and outline number (Contributed by Paul Pogonyshev).
  • Fixed Issue 79: Too strict net.sf.mpxj.mpd.ResultSetRow.
  • Fixed Issue 80: Generated planner file can't be opened.
  • Fixed Issue 82: Support for loading global.mpt.
  • Fixed Issue 81: Lowercase table name won't work with db on linux machines.
  • Fixed Issue 71: Standard Calendar localization import problem.
  • Fixed Issue 83: Strange duration conversion from database
  • Fixed Issue 86: FilterCriteria not being read in properly (Contributed by James Styles)
  • Updated to fix Steelray bug 12335: Infinite loop when reading an MPP9 file.
  • Updated to fix Steelray bug 8469: Subproject flag not set correctly.
  • Updated to fix potential NPEs (Suggested by Steve Jonik).
  • Updated EncryptedDocumentInputStream to wrap rather than extend the POI DocumentInputStream to allow use with POI 3.5. (Contributed by Josh Micich)
  • Updated to provide strong names for .Net DLLs.
"},{"location":"CHANGELOG/#300-2009-01-25","title":"3.0.0 (2009-01-25)","text":"
  • Updated to the Project 2007 MSPDI schema.
  • Updated to POI 3.2.
  • Updated to use the SAX parser with JAXB rather than DOM to reduce memory consumption.
  • Updated MPX output to prevent Project 2007 complaining.
  • Fixed Issue 68: Task getNumber*() methods return inaccurate large values.
  • Fixed Issue 56: Duplicate task in file.getChildTasks() when opening MPX.
  • Fixed Issue 57: Relation.getTask returns null.
  • Fixed Issue 58: Task.getSplits() not consistent.
  • Fixed Issue 60: WBS Field not imported Mpp12.
  • Fixed Issue 63: There are some conflict in TaskField.
  • Fixed Issue 66: MSPDIReader is not setting calendarName in projectHeader.
  • Fixed Issue 67: Write resource calendar with exceptions only.
  • Fixed Issue 69: File loses predecessors.
  • Fixed Issue 70: Resources not bring read.
  • Updated to fix incorrect duration calculations where minutes per week were not being used (Contributed by Jonas Tampier).
  • Updated split task implementation to represent splits as DateRange instances rather than as hours.
  • Added .Net DLLs using IKVM.
  • Added support for reading timephased resource assignment data from MPP files.
  • Added support CurrencyCode, CreationDate, LastSaved and HyperlinkBase project header fields.
  • Added support for reading recurring task data from MPP files.
  • Added methods to MPXReader and MPXWriter to allow the caller to determine the supported locales.
  • Added Spanish locale (Contributed by Agustin Barto).
  • Added support for durations with percentage time lag (Contributed by Jonas Tampier).
  • Added support MSPDI file split tasks.
"},{"location":"CHANGELOG/#210-2008-03-23","title":"2.1.0 (2008-03-23)","text":"
  • Updated to POI 3.0.2
  • Updated to address an out of memory exception raised when processing certain MPP12 files.
  • Updated to fix a problem caused by duplicate ID values in MPP12 files.
  • Updated to fix a problem with the subproject unique ID calculation (Contributed by Jari Niskala).
  • Fixed Issue 48: Import from Project 2007 ignores some tasks.
  • Fixed Issue 52: Crash on priority not set in MSPDI-file.
  • Fixed Issue 51: Resource start/finish dates with MSP 2007.
  • Fixed Issue 51: MS Project 2007: Calendar exceptions dates are wrong.
  • Added support for Enterprise task and resource fields.
  • Added support for Baseline task and resource fields.
  • Added support for extracting non-English (i.e. character set encoded) text from note fields.
  • Added support for Chinese MPX files (contributed by Felix Tian).
  • Added support for reading project start and end dates from all MPP file types (Bug #1827633).
  • Added support for password protected MPP9 files (Contributed by Jari Niskala)
  • Added support for calendar exceptions for MPP12 files (Contributed by Jari Niskala)
  • Added support for value lists and descriptions for custom fields (Contributed by Jari Niskala)
  • Added support for timescale formats (Contributed by Jari Niskala)
  • Added support for the project file path attribute (Contributed by Jari Niskala)
  • Added support for the ignore resource calendar attribute (Contributed by Jari Niskala)
  • Added support for the resource actual overtime work attribute (Contributed by Jari Niskala)
  • Added support for the resource material label attribute (Contributed by Jari Niskala)
  • Added support for the resource NT account attribute (Contributed by Jari Niskala)
  • Improved support for hyperlinks (Contributed by Jari Niskala)
  • Improved support for custom fields in MPP12 files (Contributed by Jari Niskala)
"},{"location":"CHANGELOG/#200-2007-10-07","title":"2.0.0 (2007-10-07)","text":"
  • Migrated to Java 5
  • Introduced generics
  • Introduced enums
  • Updated to POI 3.0.1
  • Updated to JAXB 2.1.4
  • Changed company details from Tapster Rock to Packwood Software
"},{"location":"CHANGELOG/#100-2007-08-30","title":"1.0.0 (2007-08-30)","text":"
  • Added support for reading MPD files via JDBC
  • Added support for reading Planner files
  • Added support for over allocated flag to all MPP file formats.
  • Added support for calculating duration variance from MPP files.
  • Added support for calculating start and finish variance from MPP files.
  • Added support for attribute change listeners for Task and Resource classes.
  • Added support for start slack, finish slack, free slack and total slack read from MPP files.
  • Added support for external tasks.
  • Added unique ID generation for calendars read from MPX files.
  • Added support for the status date property of the project.
  • Fixed a timezone related bug when handling dates for calendar exceptions (Contributed by Todd Brannam).
  • Fixed incorrect calculation of lag times for some MPP files.
  • Fixed missing predecessor tasks in certain rare MPP9 files.
  • Fixed incorrect MPX file AM/PM text setting in certain locales.
  • Fixed an ArrayIndexOutOfBoundsException.
  • Fixed a ClassCastException.
  • Fixed a zero length string error.
  • Fixed a duration rounding error when reading MSPDI files.
  • Fixed incorrect \"as late as possible\" constraint handling.
  • Incorrect late start date read from an MPP9 file.
  • Incorrect total slack calculation.
  • Added a default for the task constraint type attribute to prevent a possible NPE when writing an MSPDI file.
  • Added a default resource calendar name where the resource name is empty.
  • Updated the Column.getTitle method to take account of user defined column aliases.
  • Updated to add another condition to the test for deleted tasks in MPP8 files.
  • Updated to significantly improve the performance of writing MSPDI files.
"},{"location":"CHANGELOG/#092-2006-03-07","title":"0.9.2 (2006-03-07)","text":"
  • Added support for split views.
  • Added support for graphical indicators.
  • Added a workaround for a bug in MS Project which is seen when calendar exceptions are exported to an MSPDI file. If the exception contained seconds and milliseconds, MS Project marked every day as being affected by the exception, not the day or range of days specified.
  • Updated to make date/time/number formats generic, and thus available to end users. For example, this allows users to format currencies in line with the settings in the project file.
  • Standardised on minutes per day and minutes per week, rather than hours per day and hours per week.
  • Provided additional time ranges for calendar exceptions.
  • Refactored Task and Resource to use TaskField and ResourceField to identify fields.
  • Updated to automatically generate WBS for tasks read from MPP files when no WBS information is present in the file.
  • Fixed a bug when reading MPP files where task finish dates appeared before the start date where a \"start no later than\" constraint was in use.
  • Fixed a bug which resulted in invalid MPX files being generated when a project either had no tasks, or it had no resources.
  • Fixed a long-standing bug where the calendar records were being written into MPX files after they were referred to in the project summary record.
  • Fixed a bug where WBS and Outline Levels were not being auto generated correctly when an MPP file contained a project summary task.
  • Fixed a bug where split tasks were not being reported correctly.
"},{"location":"CHANGELOG/#091-2006-01-26","title":"0.9.1 (2006-01-26)","text":"
  • Major API rewrite.
  • Added a flag called \"expanded\" to the Task class to represent whether a task in an MPP9 file is shown as expanded or collapsed by MS Project.
  • Fixed a bug in the relation code in MpxjQuery (contributed by Shlomo Swidler).
  • Modified MPXDateFormat, MPXTimeFormat and MPXCurrencyFormat to derive them from DateFormat and NumberFormat.
  • Added support for MPT files.
  • Fixed a bug which could case an NPE when reading certain MPP9 files.
  • Added support for the \"marked\" attribute for MPP9 files.
  • Added support for reading split task data from MPP9 files.
  • Added support for reading calculate multiple critical paths flag.
  • Fixed a bug which could case an array out of bounds exception in the Priority (contributed by Frank Illenberger).
  • Fixed bug #1346735 \"Priorities of the tasks are exported incorrectly\".
  • Added code to allow tasks, resources, resource assignments and calendars to be removed from the data structure.
  • Implemented Italian MPX file format translation (contributed by Elio Zoggia).
  • Cleaned up calendar usage.
  • Added support for retrieval of custom document summary fields from the project header (contributed by Wade Golden).
  • Updated to use checkstyle 4.0 and fixed warnings.
  • Rationalised duration conversions into a set of methods in the MPXDuration class.
  • Replaced various file format conversion utilities with the general purpose MpxjConvert utility.
  • Fixed an issue where tasks with a percent complete value, but no resource assignments, would not write correctly to an MSPDI file.
  • Added an accessor method for resource calendars.
  • Unique ID generation was not correct for tasks, resources and calendars if these entities were added to an existing project file.
  • Fixed a compatibility issue with POI3
  • Added an event listener to the project file to allow notifications of resources and tasks being read and written to and from a file.
  • Fixed a compiler warning when build with JDK5.
  • Fixed a bug where a project start date was not being set correctly in the project header.
  • Added support for reading the project header \"calendar name\", \"schedule from\" and \"revision\" values from MPP files.
  • Fixed split task support.
  • Enhanced TableFontStyle implementation.
"},{"location":"CHANGELOG/#0025-2005-08-11","title":"0.0.25 (2005-08-11)","text":"
  • Added support for reading all properties from an MPP9 file which define the visual appearance of the Gantt Chart view shown in Microsoft Project (development funding courtesy of Steelray).
  • Tidied up constructors. Added no-argument constructors to the MPPFile and MSPDIFile classes.
  • Fixed incorrect value in WorkGroup enumerated type.
  • Implemented the resource assignment work contour property (contributed by Wade Golden).
  • Implemented correct handling for MPX files using different character set encodings (suggested by Frank Illenberger).
  • Fixed task duration calculation when importing an MPP file with a \"non-standard\" hours-per-day setting (contributed by Wade Golden).
  • Updated to ensure that the MPX task fixed attribute, and the MPP/MSPDI task type attribute are correctly handled.
  • Updated to implement the remaining project header attributes supported by the MSPDI file format.
  • Updated to add support for reading the MPX 3.0 files generated by Primavera (courtesy of CapitalSoft).
  • Fixed incorrect assumptions about conversion of durations to hours when writing MPX files (contributed by Frank Illenberger).
  • Updated to calculate remaining work for resource assignments on import, to allow MSPDI export of this data to work correctly (contributed by Frank Illenberger).
  • Updated to add another condition to the test for deleted tasks in MPP8 files.
  • Updated to fix a problem with reading assignment data from MPP9 files.
  • Rationalised the location of the JUnit tests and the sample files.
  • Fixed a problem where the project start and end dates reported in the project header were incorrect.
  • Fixed an array out of bounds exception when reading an MPP9 file.
  • Updated to allow MPXCalendarHours to accept an arbitrary number of time periods.
  • Introduced the Day class to replace the use of arbitrary integers to represent days of the week.
  • Added the ability to query the task assignments for a resource using the Resource.getTaskAssignments() method.
  • Fixed a problem with number formats in MSPDI files.
  • Updated the MPP View class to extract the view type.
  • Updated to ensure that duration values read from an MSPDI file are converted into the appropriate duration units, rather than being left as hours as the durations are represented in the MSPDI file.
  • Implemented French MPX file format translation (contributed by Benoit Baranne).
  • Fixed a bug reading assignment work contour attribute.
  • Updated to make failure more graceful when a Microsoft Project 4.0 MPP file is encountered.
  • Fixed a bug where deleted constraints in an MPP9 file were not being ignored.
  • Updated to make replace the int relation type in the Relation class with instances of the RelationType class.
  • Updated to derive RelationList from AbstractList.
  • Added sample code to MpxjQuery to illustrate retrieval of information from Relation instances.
  • Updated MpqjQuery to parse MSPDI files as well as MPP and MPX files.
  • Added support for early start, early finish, late start, late finish to MPP files.
  • Updated MPP9 file support to handle start as late as possible constraints.
  • Added support for subproject file information in MPP9 files.
  • Fixed a bug where occasionally a task in MPP9 files were not being read.
  • Fixed a NegativeArrayIndexException thrown when reading certain MPP8 files.
  • Reduced the memory used by MPXJ by anything up to 60%, particularly when reading large MPP files.
  • Fixed a bug when reading MPX files where the field delimiter was not comma, and task relation lists contained more than one entry.
  • Updated to fix unreliable retrieval of project start and end dates from certain MPP files.
  • Fixed schedule from value in MSPDI files (contributed by Frank Illenberger).
  • Fixed a bug when reading durations in elapsed days from an MPP file.
  • Tasks can now have arbitrary priority values. These values are mapped to/from the fixed MPP8/MPX priority values where necessary.
"},{"location":"CHANGELOG/#0024-2005-01-10","title":"0.0.24 (2005-01-10)","text":"
  • Fixed a bug (again!) where deleted resource assignments in MPP9 files were still seen by MPXJ.
  • Updated to use class instances instead of primitives to represent some enumerated types.
  • Updated to implement support for reading and writing all the basic Resource attributes found in MSPDI files.
  • Updated to implement support for reading and writing all the basic Task attributes found in MSPDI files.
  • Updated to implement support for reading and writing all the basic Project Header attributes from MPP8 and MPP9 files.
  • Made MSPDI file parsing more robust to allow it by default to cope with non-schema-compliant XML in the same manner as MS Project. Implemented a new compatibility flag to allow this behaviour to be disabled in favour of strict parsing.
  • Merged DateTimeSettings, CurrencySettings, and DefaultSettings into the ProjectHeader class. This change makes the project header data easier to use as it is in a single place. It also makes the entities used to describe a project consistent with the contents of the MPP and MSPDI file formats.
"},{"location":"CHANGELOG/#0023-2004-11-17","title":"0.0.23 (2004-11-17)","text":"
  • Fixed a bug where MPXJ was still using the default locale of the user's machine to create localised MPX files when a normal international MPX file was expected.
  • Fixed a bug where the incorrect record delimiter was being used in by the MPX RelationList class.
  • Fixed a bug where the method Task.getText21 was not retrieving the correct text value.
  • Fixed a bug where the task unique ID values were being truncated unnecessarily.
  • Fixed a bug where calendar exceptions were not testing the range of dates between the start and end date correctly.
  • Fixed a bug where the priority of a task was being escalated when converting between an MPP9 file and an MSPDI file.
  • Fixed a bug where a deadline was incorrectly being added to a task when importing data from an MPP9 file.
  • Fixed a bug where deleted resource assignments in MPP9 files were still seen by MPXJ.
  • Fixed a bug where MPXFile attributes were not being correctly copied by the copy constructor.
  • Fixed a rounding error in MPXCalendar.getDaysInRange (contributed by Wade Golden)
  • Updated to make MPXJ more robust in the face of unexpected offsets in MPP8 file format.
  • Updated support for password-protected files to allow write-reserved files to be read.
  • Updated to use the latest version of JAXB, as shipped in Sun's Java Web Services Developer Pack (JWSDP) version 1.4.
  • Updated the distribution to include the redistributable files from the JWSDP JAXB implementation. Users will no longer need to download JWSDP separately in order to make use of MPXJ's MSPDI functionality.
  • Updated to prevent empty notes records being added to tasks and resources when reading an MSPDI file.
  • Updated to improve accuracy when converting an MPP file to an MSPDI file.
  • Added support for blank task rows in MPP8 files.
  • Added support for blank resource rows in MPP8 files.
  • Added support for Portuguese MPX files.
  • Added support reading and writing extended attributes (apart from outline codes) for MSPDI files.
  • Added support for the Resource Type attribute.
"},{"location":"CHANGELOG/#0022-2004-07-27","title":"0.0.22 (2004-07-27)","text":"
  • Fixed a bug where task data was not being read correctly from very large MPP9 files.
  • Fixed a bug where certain MPP8 files were not read correctly when no constraint data is present.
  • Fixed a bug where certain MPP9 files were not read correctly.
  • Fixed a bug where MPP9 files containing invalid resource data were not read correctly.
  • Fixed a bug where MPXJ was using the default locale of the user's machine to create localised MPX files when a normal international MPX file was expected.
  • Fixed a bug where MPXJ not correctly handling embedded line breaks when reading and writing MPX files.
  • Removed arbitrary restrictions on the number of various entities, originally taken from the MPX specification.
  • Updated MPX documentation for Task.getFixed and Task.setFixed.
  • Updated MPP9 file code to improve handling invalid offset values.
  • Updated to remove leading and trailing spaces from MPX task field names before processing.
  • Updated to detect password protected files and raise a suitable exception.
  • Implemented an enhancement to improve file loading speed by an order of magnitude for files with a large number of tasks or resources (based on a contribution by Brian Leach).
  • Implemented support for Maven.
  • Updated MpxCreate utility to allow it to create both MPX and MSPDI files.
  • Added new JUnit test for confidential customer data.
  • Added support for the resource assignment remaining work attribute for MPP8, MPP9 and MSPDI files.
"},{"location":"CHANGELOG/#0021-2004-05-06","title":"0.0.21 (2004-05-06)","text":"
  • Fixed a bug where the task start date attribute was not always correct for MPP8 files.
  • Fixed a bug causing valid tasks to be incorrectly identified as being deleted in MPP8 files.
  • Fixed a bug causing an exception when reading certain MPP9 files.
  • Updated to allow localised MPX files to be written and read.
  • Implemented support for German MPX files.
  • Implemented generic mechanism for dealing with task field aliases.
  • Implemented task field alias read/write for MSPDI files.
  • Implemented task field alias read for MPP9 files.
  • Implemented resource field alias read/write for MSPDI files.
  • Implemented resource field alias read for MPP9 files.
"},{"location":"CHANGELOG/#0020-2004-03-15","title":"0.0.20 (2004-03-15)","text":"
  • Fixed a bug where alternative decimal delimiters and thousands separators were not being handled correctly when reading and writing MPX files.
  • Fixed a bug causing a null pointer exception when writing an MSPDI file.
  • Fixed a bug in MSPDI files where default values were being written incorrectly for some task attributes.
  • Fixed a bug with MSPDI file date handling in non GMT time zones.
  • Fixed a bug in processing calendar data where data block is not a multiple of 12 bytes
  • Fixed a bug processing tables where column data is null
  • Fixed checkstyle code warnings.
  • Fixed Eclipse code warnings.
  • Updated to include version 2.5 of the POI library.
  • Added support for task calendars.
"},{"location":"CHANGELOG/#0019-2003-12-02","title":"0.0.19 (2003-12-02)","text":"
  • Fixed a bug reading table data from certain MPP8 files
  • Updated MSPDI support to use the latest version of JAXB (from JWSDP-1.3)
  • Re-implemented base and resource calendars as a single MPXCalendar class
  • Updated support for base calendars and resource calendars for all file formats
  • Improved MPXException to print details of any nested exception when a stack trace is printed.
  • Removed unnecessary use of ByteArray.java
  • Added support for the following task fields: ActualOvertimeCost, ActualOvertimeWork, FixedCostAccrual, Hyperlink, HyperlinkAddress, HyperlinkSubAddress, LevelAssignments, LevelingCanSplit, LevelingDelay, PreleveledStart, PreleveledFinish, RemainingOvertimeCost, RemainingOvertimeWork.
"},{"location":"CHANGELOG/#0018-2003-11-13","title":"0.0.18 (2003-11-13)","text":"
  • Fixed a bug with writing MS Project compatible MSPDI XML files in non-GMT timezones.
  • Fixed a bug with writing MSPDI XML files in non-GMT timezones.
  • Fixed a bug causing an exception when zero length calendar names were present
  • Fixed a bug causing MPP8 flags to be read incorrectly. Note that flag 20 is still not read correctly.
  • Fixed a bug with the \"Microsoft Project Compatible Output\" flag for MSPDI files.
  • Fixed a bug reading task text 10.
  • Added new MPXFile.setIgnoreTextModel() method to allow MPXJ to ignore faulty text version of task or resource model records in MPX files.
  • Improved invalid MPX data error handling and reporting.
  • Added BaseCalendar.getDate method to allow end dates to be calculated based on a start date and a duration of working time.
  • Made MPXDateFormat implement java.io.Serializable to allow MPXDate to serialize correctly.
  • Updated the ant build file to allow MPXJ to be built without the components that depend on JAXB
  • Rationalised setDefaultStartTime and setDefaultEndTime methods
  • Added MppXml utility
  • Added support for querying view information held in MPP files.
  • Added support for querying table information held in MPP files. (NB This allows the user to retrieve column information, including user defined column names)
  • Added support for outlinecode1-10 fields in MPP9 files.
  • Added support for resource \"available from\" and \"available to\" fields.
  • Verified that MPXJ will read MPP files written by Microsoft Project 2003 (they are still MPP9 files).
"},{"location":"CHANGELOG/#0017-2003-08-05","title":"0.0.17 (2003-08-05)","text":"
  • Fixed a bug where a decimal point was being appended to the currency format even if no decimal digits were required.
  • Fixed a bug where special characters appearing in the currency symbol were not being quoted.
  • Fixed a bug that caused resource assignments to be incorrectly read from some MPP8 files.
  • Added a new write method to MPXFile allowing the user control over the character encoding used when writing an MPX file.
"},{"location":"CHANGELOG/#0016-2003-07-04","title":"0.0.16 (2003-07-04)","text":"
  • Fixed bug causing some extended boolean attributes to be read incorrectly.
  • Fixed bug causing MPP8 file task data to be read incorrectly under certain circumstances.
  • Updated calendar duration code to account for calendar exceptions.
"},{"location":"CHANGELOG/#0015-2003-06-17","title":"0.0.15 (2003-06-17)","text":"
  • Fixed a bug causing resource assignments to be duplicated in an MPX file created programmatically.
  • Fixed a bug causing an incorrect duration value to be read from an MPP9 file.
  • Fixed a bug causing invalid MPX files to be written in locales which don't use a period as the decimal separator.
  • Fixed a bug causing embedded quote and comma characters in task and resource notes to be handled incorrectly.
  • Added simple JUnit test to demonstrate iteration through relationships.
  • Added an example of programmatically creating a partially complete task to the MPXCreate.java example.
  • Added default values to the MPX project header.
  • Added support for reading the RemainingDuration field from an MPP9 file.
  • Updated predecessor and successor method documentation.
  • Updated Task.get/set ResourceInitials and Task.get/set ResourceNames method documentation.
  • Updated to extract the following fields from resource assignment data in MPP files which were previously not imported: ActualCost, ActualWork, Cost, Finish, Start, Units, Work.
"},{"location":"CHANGELOG/#0014-2003-05-28","title":"0.0.14 (2003-05-28)","text":"
  • Updated to extract the following fields from resource data in an MPP9 file which were previously not imported: Flag1-Flag20.
  • Added the method MPPFile.getFileType to allow the type of MPP file (MPP8: 98, MPP9: 2000,2002) to be determined.
  • Updated API to make classes final and constructors package access only where appropriate.
  • Updated to use of 6 byte long int fields for cost and work values for MPP8.
  • Fixed error in reading task fixed cost for MPP8.
  • Updated to extract the following fields from task data in an MPP8 file which were previously not imported: Contact, Cost1-Cost10, Date1-Date10, Duration1-Duration10, EffortDriven, Finish1-Finish10, Flag1-Flag20, HideBar, Milestone, Number1-Number20, Rollup, Start1-Start10, Text1-Text30, Type, WBS.
  • Updated to extract the following fields from resource data in an MPP8 file which were previously not imported: Code, Cost1-Cost10, Date1-Date10, Duration1-Duration10, EmailAddress, Finish1-Finish10, Number1-Number20, Start1-Start10, Text1-Text30
  • Added support for task and resource note fields in MPP8 files.
  • Added support for the OvertimeCost task attribute for all file formats.
  • Updated to extract calendar data from MPP8 files.
  • Updated resource notes to fix end of line handling problem.
  • Added functionality to read default settings and currency settings data from MPP files.
"},{"location":"CHANGELOG/#0013-2003-05-22","title":"0.0.13 (2003-05-22)","text":"
  • Implemented support for the Microsoft Project 98 file format.
  • Fixed a bug that prevented task and resource note text from being read.
  • Updated to remove a Java 1.4 dependency introduced in 0.0.12. Will now work with Java 1.3.
  • Updated to correct handling of carriage returns embedded in note fields.
"},{"location":"CHANGELOG/#0012-2003-05-08","title":"0.0.12 (2003-05-08)","text":"
  • Fixed incorrect handling of timezones and daylight saving time.
  • Fixed incorrect task structure generated from outline levels.
  • Updated to extract the notes fields from tasks and resources read from an MPP file.
  • Added the option to remove or preserve the RTF formatting from the note fields from an MPP file.
  • Updated to extract the following fields from task data in an MPP file which were previously not imported: Text11-Text30, Number6-Number20, Duration4-Duration10, Date1-Date10, Cost4-Cost10, Start6-Start10, Finish6-Finish10
  • Updated to extract the following fields from resource data in an MPP file which were previously not imported: Text6-Text30, Start1-Start10, Finish1-Finish10, Number1-Number20, Duration1-Duration10, Date1-Date10, Cost1-Cost10
"},{"location":"CHANGELOG/#0011-2003-04-15","title":"0.0.11 (2003-04-15)","text":"
  • Fixed error in format string used in one of the example files.
  • Fixed error where double byte characters were being read incorrectly.
  • Fixed error where deleted constraints were being resurrected when read from an MPP file.
  • Updated to extract the following fields from task data in an MPP file which were previously not imported: Flag11-Flag20, Rollup, HideBar, EffortDriven.
"},{"location":"CHANGELOG/#0010-2003-04-08","title":"0.0.10 (2003-04-08)","text":"
  • Corrected Actual Start and Actual End fields from MPP file.
  • Fixed bug where time values were being broken by daylight saving time in the user's default locale.
  • Updated to extract the following fields from task data in an MPP file which were previously not imported: Actual Work, Baseline Work, Cost Variance, Deadline, Remaining Work, Work.
  • Updated to extract the following fields from resource data in an MPP file which were previously not imported: Actual Cost, Actual Overtime Cost, Actual Work, Baseline Work, Cost, Cost Variance, Max Units, Overtime Cost, Overtime Rate, Overtime Work, Peak, Regular work, Remaining Cost, Remaining Overtime Cost, Remaining Work, Standard Rate, Work, Work Variance
"},{"location":"CHANGELOG/#009-2003-04-03","title":"0.0.9 (2003-04-03)","text":"
  • Fixed bug when handling certain types of modified MPP file where resources have been updated.
  • Added sample MPP files for bugs to the JUnit tests.
  • Added support for summary flag import from MPP files.
  • Added automatic summary flag update when creating an MPX file programmatically.
  • Added new constructor to the MSPDIFile class to allow MSPDI files to be created from scratch.
"},{"location":"CHANGELOG/#008-2003-03-27","title":"0.0.8 (2003-03-27)","text":"
  • Added support for estimated durations.
  • Fixed bug in handling certain types of modified MPP file where tasks have been updated.
  • Added the facility to auto generate outline numbers.
"},{"location":"faq/","title":"Frequently Asked Questions","text":""},{"location":"faq/#general-questions","title":"General Questions","text":"

Can I use MPXJ to write MPP files?

Not at present. Although it is technically feasible to generate an MPP file, the knowledge we have of the file structure is still relatively incomplete, despite the amount of data we are able to correctly extract. It is therefore likely to take a considerable amount of development effort to make this work, and it is conceivable that we will not be able to write the full set of attributes that MPXJ supports back into the MPP file - simply because we don't understand the format well enough. You are therefore probably better off using MSPDI which does support the full range of data items present in an MPP file.

I'm generating output using MPXJ, and when my end users open the file in Microsoft Project, I want to control the appearance of the project data that they see. Can I do this with MPXJ?

In short, the answer to this question is no. The only file format which allows you to control the appearance of project data when opened in Microsoft Project is MPP. Just to clarify, visual appearance in this context refers to the view that appears when the project opens, the filtering applied to the view, the table data visible, the columns in the table, bar styles, text styles and so on. While MPXJ can read this information from an MPP file, none of the supported output file formats contain these attributes.

When I double click on an MPX file to open it in Microsoft Project, I end up with two copies of the file open. What's happening?

This isn't an issue with MPXJ - but we have an answer for you anyway! The problem is caused by an incorrect setting in Microsoft Windows which controls the way MPX files are opened. To fix the setting, open the Control Panel and click on the \"Folder Options\" icon. Select the \"File Types\" tab and scroll down the list of file types until you find an entry for MPX. Once you have found the entry for MPX, click on it to highlight it, then press the \"Advanced\" button at the bottom right hand side of the dialog. In the list of actions that you are now presented with, click on the word \"open\" to highlight it, then click the \"Edit\" button on the right hand side of the dialog. Finally, ensure that the \"Use DDE\" check box is not checked, and you can now finish by clicking OK on each of the open dialogs to dismiss them. You should now find that double clicking on an MPX file will now only open one copy of the file in Microsoft Project.

I use a version of Java older than Java 8, can I use MPXJ?

The last version of MPXJ which supports versions of Java prior to Java 8 is version 7.9.8.

I use a Java 1.4 JVM, but MPXJ is built with a later version of Java, is there anything I can do which will allow me to use it?

Yes there is. Assuming you are using a version of MPXJ prior to 8.0.0, try using Retroweaver.

"},{"location":"faq/#known-issues-with-mpxj","title":"Known Issues with MPXJ","text":"

I have an MPP file created by MS Project 98, and some Flag field values are incorrect.

The MPP8 file format is rather cryptic, and one part of it that I have yet to really understand fully is how the Flag fields are stored. I've spent a lot of time looking at this and have not made a lot of progress, so at the moment no further work is being undertaken to fix this. Contributions of insights, knowledge or fixed code for this problem are welcome. You'll find a bug for this item logged in the SourgeForge bug tracker.

When I read an MPP file I sometimes see an extra task or resource record.

What you are seeing are \"hidden\" tasks and resources which newer versions of Microsoft Project appear to use as placeholders for summary information about all of the tasks and all of the resources in a project. We're not sure exactly which versions of Project hold data like this, although we think this is only relevant for the MPP9 and MPP12 file formats. We've also noticed that the information in these hidden tasks and resources may not be reliable, so don't place too much emphasis on them in your application.

You can ignore the first resource if it has a null value as its name. The attributes of this resource should actually be a summary of all of the resource combined, e.g. utilisation, actual work, remaining work and so on for the complete set of \"real\" resources.

You can ignore the first task if it has an outline level of zero, this task will be a summary of all the \"real\" tasks in the project. You may also find that the name of this task matches the name of the project.

My localised version of MS Project won't read the MPX files created by MPXJ, or MPXJ won't read the MPX files written by my localised version of MS Project.

Localised versions of MS Project (i.e. those which have been translated for use in a non-English locale) read and write MPX files which include localised text strings. The end result of this is that an English/International version of MS Project can't read MPX files produced by a localised version of MS Project, and vice versa.

MPXJ supports a small number of non-English locales, and can read and write MPX files correctly for those locales. You can also use MPXJ to translate MPX files from one locale to another. The MPXFile.setLocale() method must be called prior to reading or writing an MPX file in order to set the required locale. By default, MPXJ will always produce MPX files for the International/English locale, regardless of the locale for which your operating system if configured.

Supported locales for MPX files currently include German, Spanish, French, Italian, Portuguese, Swedish, and Simplified Chinese. Producing a translation for your locale is very easy, please contact us for details on how you can help us to do this.

When I write an MPX file, changes to the project header settings I've made seem to be lost, what's happening?

One of the first things the MPXWriter's write method does is to determine the current locale and update various project settings (for example, currency and date formats) to match the selected locale. This behaviour can be changed so that the settings in the project are left unmodified by setting the useLocaleDefaults parameter to false when calling the write method (for versions of MPXJ up to and including 3.0.0) or by calling the method setUseLocaleDefaults on the MPXWriter instance before calling the write method (for versions of MPXJ after 3.0.0).

"},{"location":"faq/#unit-tests","title":"Unit Tests","text":"

I am trying to run the MPXJ unit tests and I'm having problems with failures in JAXB functionality. What's happening?

Older versions of JAXB were known to have issues with the JUnit classloader, so running the JUnit test runner with the -noloading command line option, other taking other steps to disable JUnit classloading was recommended. This problem is not believed to affect the more recent version of JAXB now used by MPXJ.

"},{"location":"faq/#net","title":".NET","text":"

When using MPXJ from .NET Core I get an error similar to No data is available for encoding 437. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.

By default .NET Core does not include all of the character encodings which may be used by MPXJ (and which are present by default in .NET Framework). To resolve this issue add the following to your code:

System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);\n

I have set up a simple test project using MPXJ.Net, and when I try to do anything with MPXJ, an exception is thrown

One of the libraries MPXJ depends on throws and catches one or more exceptions as part of its normal flow of control. These exceptions are handled, so you can keep pressing continue, and your code should run normally after that. Visual Studio is breaking on these exceptions even though they are handled. You can prevent this behavior by adding this condition to the \"Common Language Runtime Exceptions\" entry in the exception settings window in Visual Studio: Module Name Not Equals org.glassfish.*, as illustrated below.

I have set up a simple test project using MPXJ.Net, and when I try to do anything with MPXJ, Visual Studio crashes

This is the same problem as described above. MPXJ is catching an exception being raised in one of MPXJ's dependencies and, in the process, crashing. The solution is the same: add the condition described above to ensure that Visual Studio ignores this exception.

I have set up a simple test project using MPXJ.Net, but when I run it I get this error System.IO.FileNotFoundException: 'Could not load file or assembly 'mpxj, Version=(version number), Culture=neutral, PublicKeyToken=(token)' or one of its dependencies. The system cannot find the file specified.'

This is typically caused by MPXJ.Net being added as a dependency to a non SDK-style project. MPXJ.Net will only work with an SDK-style project. If you open your csproj file in a text editor, the first line should look something like this: <Project Sdk=\"Microsoft.NET.Sdk\">. If your csproj file is different you will need to create a new SDK-style project. Sample projects in this form can be found in this repository.

"},{"location":"faq/#log4j2","title":"log4j2","text":"

When you start MPXJ, you may see the following message written to the console:

ERROR StatusLogger Log4j2 could not find a logging implementation.\nPlease add log4j-core to the classpath. Using SimpleLogger to log to the console.\n

MPXJ uses Apache POI to read MPP files. Apache POI uses log4j2 to write log messages. By default the only dependency POI has on log4j2 is to its interfaces. If you're not already using log4j2 as part of your code, and you don't explicitly include the rest of the log4j2 implementation jar files, you'll see the warning message shown above. This message can safely be ignored, it's just telling you that any log messages POI produces will be written to the console. If you would like to silence this message, you can supply the following argument to the JVM:

-Dlog4j2.loggerContextFactory=org.apache.logging.log4j.simple.SimpleLoggerContextFactory\n

If you are using the Python version of MPXJ, you can provide the argument as shown below when you initialize jpype.

jpype.startJVM(\"-Dlog4j2.loggerContextFactory=org.apache.logging.log4j.simple.SimpleLoggerContextFactory\")\n
"},{"location":"field-guide/","title":"Field Guide","text":""},{"location":"field-guide/#field-guide","title":"Field Guide","text":"

The tables below provide an indication of which fields are populated when files of different types are read using MPXJ The tables are not hand-crafted: they have been generated from test data and are therefore may be missing some details.

"},{"location":"field-guide/#project","title":"Project","text":""},{"location":"field-guide/#core-fields","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) AM Text \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Increment \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Increment Based On Selected Activity \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Prefix \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Suffix \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 Actual Duration \u2713 Actual Start \u2713 Actual Work \u2713 Actuals In Sync \u2713 Application Version \u2713 \u2713 \u2713 \u2713 Author \u2713 \u2713 \u2713 \u2713 \u2713 Auto Add New Resources and Tasks \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Auto Filter \u2713 Auto Link \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Bar Text Date Format \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Calculate Float on Finish Date of Each Project \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Calculate Multiple Float Paths \u2713 \u2713 \u2713 Calculate Multiple Float Paths Ending With Activity Unique ID \u2713 \u2713 Calculate Multiple Paths Using Total Float \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Category \u2713 \u2713 Comments \u2713 \u2713 \u2713 Company \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Compute Start to Start Lag From Early Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Consider Assignments In Other Project With Priority Equal or Higher Than \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Content Status \u2713 Content Type \u2713 Cost \u2713 Creation Date \u2713 \u2713 \u2713 \u2713 \u2713 Critical Activity Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Critical Slack Limit \u2713 \u2713 Currency Code \u2713 \u2713 Currency Digits \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Currency Symbol \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Currency Symbol Position \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Current Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Custom Properties \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Date Format \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Date Order \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Date Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Days per Month \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Decimal Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Calendar Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Duration Is Fixed \u2713 Default End Time \u2713 \u2713 \u2713 \u2713 \u2713 Default Overtime Rate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Standard Rate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Start Time \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Work Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Document Version \u2713 Duration \u2713 \u2713 Earned Value Method \u2713 Editable Actual Costs \u2713 \u2713 Editing Time \u2713 Export Flag \u2713 \u2713 Extended Creation Date \u2713 File Application \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 File Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Fiscal Year Start \u2713 Fiscal Year Start Month \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Full Application Name \u2713 GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Honor Constraints \u2713 \u2713 \u2713 Hyperlink Base \u2713 Ignore Relationships To And From Other Projects \u2713 Inserted Projects Like Summary \u2713 Keywords \u2713 \u2713 \u2713 Language \u2713 Last Author \u2713 Last Printed \u2713 Last Saved \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Level All Resources \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Level Resources Only Within Activity Total Float \u2713 \u2713 Leveling Priorities \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Limit Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Location Unique ID \u2713 MPP File Type \u2713 MPX Code Page \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 MPX Delimiter \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 MPX File Version \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 MPX Program Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Manager \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Maximum Percentage to Overallocate Resources \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Microsoft Project Server URL \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Day \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Month \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Week \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Year \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Multiple Critical Paths \u2713 \u2713 Must Finish By \u2713 \u2713 Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 New Task Start Is Project Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 New Tasks Are Effort Driven \u2713 \u2713 New Tasks Are Manual \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 New Tasks Estimated \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 PM Text \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Percentage Complete \u2713 Planned Start \u2713 \u2713 \u2713 Presentation Format \u2713 Preserve Minimum Float When Leveling \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Preserve Scheduled Early and Late Dates \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Project Externally Edited \u2713 Project File Path \u2713 Project ID \u2713 \u2713 \u2713 Project Title \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Project Website URL \u2713 \u2713 Relationship Lag Calendar \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Resource Pool File \u2713 Revision \u2713 \u2713 Schedule From \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Scheduled Finish \u2713 \u2713 \u2713 Short Application Name \u2713 Show Project Summary Task \u2713 Split In Progress Tasks \u2713 \u2713 \u2713 \u2713 Start Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 Status Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Subject \u2713 \u2713 \u2713 \u2713 Template \u2713 Thousands Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Time Format \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Time Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Total Slack Calculation Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 Updating Task Status Updates Resource Status \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Use Expected Finish Dates \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 WBS Code Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Week Start Day \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 When Scheduling Progressed Activities Use \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work \u2713 Work 2 \u2713"},{"location":"field-guide/#baseline-fields","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Date \u2713 Baseline2 Date \u2713 Baseline3 Date \u2713 Baseline4 Date \u2713 Baseline5 Date \u2713 Baseline6 Date \u2713 Baseline7 Date \u2713 Baseline8 Date \u2713 Baseline9 Date \u2713 Baseline10 Date \u2713 Baseline Calendar Name \u2713 \u2713 Baseline Cost \u2713 Baseline Date \u2713 \u2713 Baseline Duration \u2713 Baseline Finish \u2713 \u2713 Baseline Project Unique ID \u2713 \u2713 \u2713 Baseline Start \u2713 \u2713 Baseline Type Name \u2713 Baseline Work \u2713 Last Baseline Update Date \u2713 Project Is Baseline \u2713"},{"location":"field-guide/#task","title":"Task","text":""},{"location":"field-guide/#core-fields_1","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) % Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 % Work Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 ACWP \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity Codes \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity Percent Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity Status \u2713 \u2713 \u2713 Activity Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Duration Units \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work (Labor) \u2713 \u2713 \u2713 Actual Work (Nonlabor) \u2713 \u2713 \u2713 Actual Work Protected \u2713 Bar Name \u2713 Bid Item \u2713 Board Status ID \u2713 Budget Cost \u2713 Budget Work \u2713 CV \u2713 Calendar Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Category of Work \u2713 Complete Through \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Constraint Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Constraint Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Contact \u2713 \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Critical \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Deadline \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Department \u2713 Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Duration Units \u2713 Duration Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Early Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Early Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Earned Value Method \u2713 Effort Driven \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Estimated \u2713 \u2713 \u2713 \u2713 Expanded \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Expected Finish \u2713 \u2713 Expense Items \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 External Early Start \u2713 \u2713 External Late Finish \u2713 \u2713 External Project \u2713 \u2713 External Task \u2713 \u2713 Feature of Work \u2713 Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Fixed Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Fixed Cost Accrual \u2713 \u2713 \u2713 Free Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Hammock Code \u2713 Hide Bar \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 Hyperlink Data \u2713 Hyperlink Screen Tip \u2713 Hyperlink SubAddress \u2713 ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Ignore Resource Calendar \u2713 \u2713 \u2713 \u2713 \u2713 Late Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Late Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Level Assignments \u2713 \u2713 \u2713 Leveling Can Split \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 \u2713 Leveling Delay Units \u2713 \u2713 \u2713 Longest Path \u2713 \u2713 Mail \u2713 Manager \u2713 Manual Duration \u2713 \u2713 Manual Duration Units \u2713 Marked \u2713 \u2713 Milestone \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Null \u2713 \u2713 \u2713 Outline Level \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Outline Number \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Overall Percent Complete \u2713 Overallocated \u2713 Overtime Cost \u2713 \u2713 \u2713 Overtime Work \u2713 Parent Task Unique ID \u2713 Percent Complete Type \u2713 \u2713 \u2713 Phase of Work \u2713 Physical % Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Planned Cost \u2713 \u2713 \u2713 Planned Duration \u2713 \u2713 \u2713 \u2713 Planned Finish \u2713 \u2713 \u2713 \u2713 Planned Start \u2713 \u2713 \u2713 \u2713 Planned Work \u2713 \u2713 \u2713 Planned Work (Labor) \u2713 \u2713 \u2713 Planned Work (Nonlabor) \u2713 \u2713 \u2713 Preleveled Finish \u2713 \u2713 \u2713 Preleveled Start \u2713 \u2713 \u2713 Primary Resource Unique ID \u2713 \u2713 \u2713 Priority \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Project \u2713 \u2713 \u2713 \u2713 \u2713 Recalc Outline Codes \u2713 Recurring \u2713 \u2713 \u2713 Recurring Data \u2713 Regular Work \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Early Finish \u2713 \u2713 \u2713 Remaining Early Start \u2713 \u2713 \u2713 Remaining Late Finish \u2713 \u2713 \u2713 Remaining Late Start \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Work (Labor) \u2713 \u2713 \u2713 Remaining Work (Nonlabor) \u2713 \u2713 \u2713 Resource Names \u2713 \u2713 Responsibility Code \u2713 Resume \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Resume No Earlier Than \u2713 Resume Valid \u2713 Rollup \u2713 \u2713 \u2713 \u2713 Scheduled Duration \u2713 Scheduled Finish \u2713 Scheduled Start \u2713 Secondary Constraint Date \u2713 \u2713 Secondary Constraint Type \u2713 \u2713 Section \u2713 Sequence Number \u2713 \u2713 \u2713 Show Duration Text \u2713 Show Finish Text \u2713 Show Start Text \u2713 Splits \u2713 \u2713 Sprint ID \u2713 Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Steps \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 \u2713 Subproject File \u2713 \u2713 \u2713 Subproject GUID \u2713 Subproject Task ID \u2713 \u2713 Subproject Task Unique ID \u2713 Subproject Tasks Unique ID Offset \u2713 Summary \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Summary Progress \u2713 Suspend Date \u2713 \u2713 Task Calendar GUID \u2713 Task Mode \u2713 \u2713 Task Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Total Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID Successors \u2713 WBS \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713"},{"location":"field-guide/#baseline-fields_1","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Duration \u2713 \u2713 \u2713 \u2713 Baseline1 Duration Units \u2713 Baseline1 Estimated Duration \u2713 Baseline1 Estimated Finish \u2713 Baseline1 Estimated Start \u2713 Baseline1 Finish \u2713 \u2713 \u2713 \u2713 Baseline1 Fixed Cost \u2713 Baseline1 Fixed Cost Accrual \u2713 Baseline1 Start \u2713 \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Duration \u2713 \u2713 \u2713 Baseline2 Duration Units \u2713 Baseline2 Estimated Duration \u2713 Baseline2 Estimated Finish \u2713 Baseline2 Estimated Start \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Fixed Cost \u2713 Baseline2 Fixed Cost Accrual \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Duration \u2713 \u2713 \u2713 Baseline3 Duration Units \u2713 Baseline3 Estimated Duration \u2713 Baseline3 Estimated Finish \u2713 Baseline3 Estimated Start \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Fixed Cost \u2713 Baseline3 Fixed Cost Accrual \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Duration \u2713 \u2713 \u2713 Baseline4 Duration Units \u2713 Baseline4 Estimated Duration \u2713 Baseline4 Estimated Finish \u2713 Baseline4 Estimated Start \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Fixed Cost \u2713 Baseline4 Fixed Cost Accrual \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Duration \u2713 \u2713 \u2713 Baseline5 Duration Units \u2713 Baseline5 Estimated Duration \u2713 Baseline5 Estimated Finish \u2713 Baseline5 Estimated Start \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Fixed Cost \u2713 Baseline5 Fixed Cost Accrual \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Duration \u2713 \u2713 \u2713 Baseline6 Duration Units \u2713 Baseline6 Estimated Duration \u2713 Baseline6 Estimated Finish \u2713 Baseline6 Estimated Start \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Fixed Cost \u2713 Baseline6 Fixed Cost Accrual \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Duration \u2713 \u2713 \u2713 Baseline7 Duration Units \u2713 Baseline7 Estimated Duration \u2713 Baseline7 Estimated Finish \u2713 Baseline7 Estimated Start \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Fixed Cost \u2713 Baseline7 Fixed Cost Accrual \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Duration \u2713 \u2713 \u2713 Baseline8 Duration Units \u2713 Baseline8 Estimated Duration \u2713 Baseline8 Estimated Finish \u2713 Baseline8 Estimated Start \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Fixed Cost \u2713 Baseline8 Fixed Cost Accrual \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Duration \u2713 \u2713 \u2713 Baseline9 Duration Units \u2713 Baseline9 Estimated Duration \u2713 Baseline9 Estimated Finish \u2713 Baseline9 Estimated Start \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Fixed Cost \u2713 Baseline9 Fixed Cost Accrual \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Cost \u2713 \u2713 \u2713 \u2713 Baseline10 Deliverable Finish \u2713 Baseline10 Duration \u2713 \u2713 \u2713 \u2713 Baseline10 Duration Units \u2713 Baseline10 Estimated Duration \u2713 Baseline10 Estimated Finish \u2713 Baseline10 Estimated Start \u2713 Baseline10 Finish \u2713 \u2713 \u2713 \u2713 Baseline10 Fixed Cost \u2713 Baseline10 Fixed Cost Accrual \u2713 Baseline10 Start \u2713 \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Deliverable Finish \u2713 Baseline Deliverable Start \u2713 Baseline Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Duration Units \u2713 Baseline Estimated Duration \u2713 Baseline Estimated Finish \u2713 Baseline Estimated Start \u2713 Baseline Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Fixed Cost \u2713 \u2713 \u2713 Baseline Fixed Cost Accrual \u2713 Baseline Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713"},{"location":"field-guide/#custom-fields","title":"Custom Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Cost1 \u2713 \u2713 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 \u2713 Duration1 Units \u2713 Duration2 \u2713 \u2713 \u2713 \u2713 Duration2 Units \u2713 Duration3 \u2713 \u2713 \u2713 \u2713 Duration3 Units \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 Finish1 \u2713 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 Start1 \u2713 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"field-guide/#enterprise-fields","title":"Enterprise Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Enterprise Data \u2713 Enterprise Duration1 Units \u2713 Enterprise Duration2 Units \u2713 Enterprise Duration3 Units \u2713 Enterprise Duration4 Units \u2713 Enterprise Duration5 Units \u2713 Enterprise Duration6 Units \u2713 Enterprise Duration7 Units \u2713 Enterprise Duration8 Units \u2713 Enterprise Duration9 Units \u2713 Enterprise Duration10 Units \u2713 Enterprise Project Date1 \u2713 Enterprise Project Date2 \u2713 Enterprise Project Date3 \u2713 Enterprise Project Date4 \u2713 Enterprise Project Number2 \u2713 Enterprise Project Number4 \u2713 Enterprise Project Number5 \u2713 Enterprise Project Number22 \u2713 Enterprise Project Text1 \u2713 \u2713 Enterprise Project Text2 \u2713 Enterprise Project Text3 \u2713 Enterprise Project Text4 \u2713 Enterprise Project Text5 \u2713 Enterprise Project Text6 \u2713 Enterprise Project Text8 \u2713 Enterprise Project Text9 \u2713 Enterprise Project Text10 \u2713 Enterprise Project Text11 \u2713 Enterprise Project Text12 \u2713 Enterprise Project Text13 \u2713 Enterprise Project Text14 \u2713 Enterprise Project Text15 \u2713 Enterprise Project Text16 \u2713 Enterprise Project Text17 \u2713 Enterprise Project Text18 \u2713 Enterprise Project Text19 \u2713 Enterprise Project Text21 \u2713 Enterprise Project Text40 \u2713 \u2713"},{"location":"field-guide/#resource","title":"Resource","text":""},{"location":"field-guide/#core-fields_2","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) % Work Complete \u2713 ACWP \u2713 \u2713 Accrue At \u2713 \u2713 \u2713 \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Availability Data \u2713 Available From \u2713 Available To \u2713 BCWS \u2713 Base Calendar \u2713 Booking Type \u2713 \u2713 Budget \u2713 \u2713 Budget Cost \u2713 Budget Work \u2713 CV \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Calendar GUID \u2713 Calendar Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Can Level \u2713 \u2713 Code \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Center \u2713 \u2713 Cost Per Use \u2713 Cost Rate A \u2713 Cost Rate B \u2713 Cost Rate C \u2713 Cost Rate D \u2713 Cost Rate E \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 Default Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Description \u2713 Email Address \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Generic \u2713 \u2713 Group \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 Hyperlink Address \u2713 Hyperlink Data \u2713 Hyperlink Screen Tip \u2713 Hyperlink SubAddress \u2713 ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Initials \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Material Label \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Max Units \u2713 Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Overallocated \u2713 \u2713 \u2713 \u2713 Overtime Cost \u2713 \u2713 \u2713 Overtime Rate \u2713 Overtime Rate Units \u2713 Overtime Work \u2713 \u2713 \u2713 Parent ID \u2713 \u2713 \u2713 \u2713 \u2713 Peak \u2713 \u2713 \u2713 \u2713 \u2713 Per Day \u2713 Phone \u2713 Phonetics \u2713 Pool \u2713 Primary Role Unique ID \u2713 \u2713 \u2713 Rate \u2713 Regular Work \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Resource ID \u2713 \u2713 \u2713 \u2713 Role \u2713 \u2713 \u2713 SV \u2713 Sequence Number \u2713 \u2713 \u2713 Shift Unique ID \u2713 \u2713 Standard Rate \u2713 Standard Rate Units \u2713 Subproject Unique Resource ID \u2713 Supply Reference \u2713 Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unit \u2713 Unit of Measure Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Windows User Account \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713 Workgroup \u2713 \u2713 \u2713"},{"location":"field-guide/#baseline-fields_2","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Budget Cost \u2713 Baseline1 Budget Work \u2713 Baseline1 Cost \u2713 \u2713 Baseline1 Work \u2713 \u2713 Baseline2 Budget Cost \u2713 Baseline2 Budget Work \u2713 Baseline2 Cost \u2713 \u2713 Baseline2 Work \u2713 \u2713 Baseline3 Budget Cost \u2713 Baseline3 Budget Work \u2713 Baseline3 Cost \u2713 \u2713 Baseline3 Work \u2713 \u2713 Baseline4 Budget Cost \u2713 Baseline4 Budget Work \u2713 Baseline4 Cost \u2713 \u2713 Baseline4 Work \u2713 \u2713 Baseline5 Budget Cost \u2713 Baseline5 Budget Work \u2713 Baseline5 Cost \u2713 \u2713 Baseline5 Work \u2713 \u2713 Baseline6 Budget Cost \u2713 Baseline6 Budget Work \u2713 Baseline6 Cost \u2713 \u2713 Baseline6 Work \u2713 \u2713 Baseline7 Budget Cost \u2713 Baseline7 Budget Work \u2713 Baseline7 Cost \u2713 \u2713 Baseline7 Work \u2713 \u2713 Baseline8 Budget Cost \u2713 Baseline8 Budget Work \u2713 Baseline8 Cost \u2713 \u2713 Baseline8 Work \u2713 \u2713 Baseline9 Budget Cost \u2713 Baseline9 Budget Work \u2713 Baseline9 Cost \u2713 \u2713 Baseline9 Work \u2713 \u2713 Baseline10 Budget Cost \u2713 Baseline10 Budget Work \u2713 Baseline10 Cost \u2713 \u2713 Baseline10 Work \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713"},{"location":"field-guide/#custom-fields_1","title":"Custom Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"field-guide/#enterprise-fields_1","title":"Enterprise Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Enterprise \u2713 \u2713 Enterprise Data \u2713 Enterprise Duration1 Units \u2713 Enterprise Duration2 Units \u2713 Enterprise Duration3 Units \u2713 Enterprise Duration4 Units \u2713 Enterprise Duration5 Units \u2713 Enterprise Duration6 Units \u2713 Enterprise Duration7 Units \u2713 Enterprise Duration8 Units \u2713 Enterprise Duration9 Units \u2713 Enterprise Duration10 Units \u2713 Enterprise Unique ID \u2713"},{"location":"field-guide/#resource-assignment","title":"Resource Assignment","text":""},{"location":"field-guide/#core-fields_3","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) ACWP \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Assignment Delay \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Assignment GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Assignment Resource GUID \u2713 Assignment Task GUID \u2713 Assignment Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 BCWS \u2713 Budget Cost \u2713 \u2713 Budget Work \u2713 \u2713 CV \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Confirmed \u2713 Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Cost Account ID \u2713 \u2713 \u2713 Cost Rate Table \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 Created \u2713 \u2713 Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 Hyperlink Data \u2713 Hyperlink Screen Tip \u2713 Hyperlink Subaddress \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 Leveling Delay Units \u2713 Linked Fields \u2713 Notes \u2713 \u2713 \u2713 Override Rate \u2713 \u2713 \u2713 Overtime Work \u2713 \u2713 \u2713 Owner \u2713 Percent Work Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Planned Cost \u2713 \u2713 \u2713 Planned Finish \u2713 \u2713 \u2713 Planned Start \u2713 \u2713 \u2713 Planned Work \u2713 \u2713 \u2713 Rate Index \u2713 \u2713 Rate Source \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Regular Work \u2713 \u2713 \u2713 Remaining Assignment Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Early Finish \u2713 \u2713 \u2713 Remaining Early Start \u2713 \u2713 \u2713 Remaining Late Finish \u2713 \u2713 Remaining Late Start \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Resource Request Type \u2713 Resource Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Response Pending \u2713 \u2713 Resume \u2713 \u2713 \u2713 Role Unique ID \u2713 \u2713 \u2713 SV \u2713 Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 Task Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Team Status Pending \u2713 \u2713 Timephased Actual Overtime Work \u2713 Timephased Actual Work \u2713 Timephased Work \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Variable Rate Units \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work Contour \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713"},{"location":"field-guide/#baseline-fields_3","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Budget Cost \u2713 Baseline1 Budget Work \u2713 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Finish \u2713 \u2713 \u2713 Baseline1 Start \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Budget Cost \u2713 Baseline2 Budget Work \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Budget Cost \u2713 Baseline3 Budget Work \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Budget Cost \u2713 Baseline4 Budget Work \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Budget Cost \u2713 Baseline5 Budget Work \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Budget Cost \u2713 Baseline6 Budget Work \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Budget Cost \u2713 Baseline7 Budget Work \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Budget Cost \u2713 Baseline8 Budget Work \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Budget Cost \u2713 Baseline9 Budget Work \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Budget Cost \u2713 Baseline10 Budget Work \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Finish \u2713 \u2713 \u2713 Baseline10 Start \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 \u2713 Baseline Finish \u2713 \u2713 \u2713 Baseline Start \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713 Timephased Baseline1 Cost \u2713 Timephased Baseline1 Work \u2713 Timephased Baseline2 Cost \u2713 Timephased Baseline2 Work \u2713 Timephased Baseline3 Cost \u2713 Timephased Baseline3 Work \u2713 Timephased Baseline4 Cost \u2713 Timephased Baseline4 Work \u2713 Timephased Baseline5 Cost \u2713 Timephased Baseline5 Work \u2713 Timephased Baseline6 Cost \u2713 Timephased Baseline6 Work \u2713 Timephased Baseline7 Cost \u2713 Timephased Baseline7 Work \u2713 Timephased Baseline8 Cost \u2713 Timephased Baseline8 Work \u2713 Timephased Baseline9 Cost \u2713 Timephased Baseline9 Work \u2713 Timephased Baseline10 Cost \u2713 Timephased Baseline10 Work \u2713 Timephased Baseline Cost \u2713 Timephased Baseline Work \u2713"},{"location":"field-guide/#custom-fields_2","title":"Custom Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"howto-build/","title":"Building MPXJ","text":"

Although MPXJ can be downloaded as a complete package from Maven, GitHub and SourceForge, the development of the library continues between releases and is driven by user requests for new functionality and bug fixes being applied to existing features. Many MPXJ users will work with and ship software based on intermediate versions of MPXJ built from the code on GitHub in order to take advantage of these enhancements before they become available in an official release. This approach is supported by the fact that code is only pushed to the master branch on GitHub if the suite of regression tests have been completed successfully: therefore the quality of the code taken from GitHub at any point can normally be guaranteed to be as good as that in an official release.

In order to take advantage of MPXJ functionality from GitHub, you will need to understand how to build the library, whether you are using it in the form of a Java JAR or a .NET DLL. The following sections explain how to do this.

"},{"location":"howto-build/#obtaining-the-source","title":"Obtaining the source","text":"

The first step in the process of building your own version of MPXJ is to obtain the latest source from GitHub. Instructions for cloning the repository can be found on this page.

"},{"location":"howto-build/#building-the-java-jar","title":"Building the Java JAR","text":"

MPXJ is built using Maven. Once you have a cloned copy of the MPXJ repository, you may wish to update the groupId, artifactId or version attributes in pom.xml. This will ensure that there is no confusion between the version of MPXJ you build and the official distributions.

If you have a copy of Maven installed, you can issue the following command to build MPXJ:

mvn -DskipTests=true -Dmaven.javadoc.skip=true -Dsource.skip=true package\n

This will generate the mpxj.jar for you in the Maven target directory, and copies MPXJ's dependencies to the lib directory. Note that for convenience this skips running the unit tests, javadoc generation and source packaging.

If you are using Maven to manage dependencies for your own project, you can install your newly built version of MPXJ in a local Maven repository:

mvn -DskipTests=true -Dmaven.javadoc.skip=true -Dsource.skip=true install\n
"},{"location":"howto-build/#building-for-net-python-and-ruby","title":"Building for .Net, Python and Ruby","text":"

Aside from using Maven to build the MPXJ jar file, building the other release artifacts for MPXJ is a somewhat involved process. To assist with this I have created a script which will configure a freshly installed Windows 10 machine ready to be used to build all the components of an MPXJ release.

The script and its instructions can be found here.

"},{"location":"howto-build/#generating-the-jaxb-code","title":"Generating the JAXB code","text":"

In order to read and write various XML file formats, MPXJ relies on code generated by the JAXB tool xjc from the XML schema for each file format. Normally you will not need to regenerate this source, but if you are changing the JAXB implementation, or modifying the use of JAXB in some way, then you may need to regenerate this code.

Where I have created an XML schema to support a particular file format, I have included it in the MPXJ distribution in the jaxb directory. For XML schemas published by product vendors, I have included a note on the home page indicating where these can be located.

If you obtain a copy of the XML schema file you want to work with, you can update the JAXB source using the xjc target found in the ant build.xml file. Note that the xjc target is platform specific, you will need to change the name of xjc tool to be xjc.bat, xjc.exe, or xjc.sh depending on your operating system. You will also need to set the properties indicated in build.xml to tell it where to find xjc and the XML schema file. If you are only regenerating source for one of the XML schemas, you can comment out the others in the Ant script to avoid unnecessary work.

"},{"location":"howto-com/","title":"Getting Started with COM","text":"

Deprecated. Only supported until MPXJ version 14.

The .Net Framework assemblies provided in the DLLs described here are accessible from COM. This should allow you to, for example, write VBA code which utilises MPXJ functionality. To assist with this, for each of the DLLs distributed with MPXJ type libraries in the form of TLB files are provided in the src.net\\lib\\net45 directory. You will also need to register the MPXJ assemblies in order to use them from COM, using the regasm assembly registration tool.

For your convenience two batch files have been provided in the src.net\\lib\\net45 directory: mpxj-register-assemblies.bat and mpxj-unregister-assemblies.bat. These batch files will register and unregister the MPXJ assemblies respectively. These batch files assume that regasm is available on the path.

"},{"location":"howto-convert/","title":"Converting Files","text":"

To convert project data between different formats you read the source data using an appropriate Reader class, then write the data using a Writer class which matches the format you want to convert to.

MPXJ can do a lot of the work for you, as the example below illustrates. The UniversalProjectReader will detect the type of schedule being read and handle it accordingly. The UniversalProjectWriter class manages the individual writer classes for you, taking an argument representing the type of file you want to write.

JavaC#Python
package org.mpxj.howto.convert;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class ConvertUniversal\n{\n   public void convert(String inputFile, FileFormat format, String outputFile) throws Exception\n   {\n      ProjectFile projectFile = new UniversalProjectReader().read(inputFile);\n      new UniversalProjectWriter(format).write(projectFile, outputFile);\n   }\n}\n
using MPXJ.Net;\n\npublic class ConvertUniversal\n{\n    public void Convert(string inputFile, FileFormat format, string outputFile)\n    {\n        var projectFile = new UniversalProjectReader().Read(inputFile);\n        new UniversalProjectWriter(format).Write(projectFile, outputFile);\n    }\n}\n
import jpype\nimport mpxj\n\njpype.startJVM()\n\nfrom net.sf.mpxj.reader import UniversalProjectReader\nfrom net.sf.mpxj.writer import FileFormat\nfrom net.sf.mpxj.writer import UniversalProjectWriter\n\ndef convert(input_file, format, output_file):\n    project_file = UniversalProjectReader().read(input_file);\n    UniversalProjectWriter(format).write(project_file, output_file);\n\njpype.shutdownJVM()\n

If you already know the file types you are converting between, you can use the specific Reader and Writer classes, as shown below.

JavaC#Python
package org.mpxj.howto.convert;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\nimport net.sf.mpxj.mpx.MPXWriter;\nimport net.sf.mpxj.reader.ProjectReader;\nimport net.sf.mpxj.writer.ProjectWriter;\n\npublic class ConvertMppToMpx\n{\n   public void convert(String inputFile, String outputFile) throws Exception\n   {\n      ProjectReader reader = new MPPReader();\n      ProjectFile projectFile = reader.read(inputFile);\n\n      ProjectWriter writer = new MPXWriter();\n      writer.write(projectFile, outputFile);\n   }\n}\n
using MPXJ.Net;\n\npublic class ConvertMppToMpx\n{\n    public void Convert(string inputFile, string outputFile)\n    {\n        var reader = new MPPReader();\n        var projectFile = reader.Read(inputFile);\n\n        var writer = new MPXWriter();\n        writer.Write(projectFile, outputFile);\n    }\n}\n
import jpype\nimport mpxj\n\njpype.startJVM()\n\nfrom net.sf.mpxj.mpp import MPPReader\nfrom net.sf.mpxj.mpx import MPXWriter\n\ndef convert(input_file, output_file):\n    reader = MPPReader()\n    project_file = reader.read(input_file)\n    writer = MPXWriter()\n    writer.write(project_file, output_file)\n\njpype.shutdownJVM()\n
"},{"location":"howto-dotnet/","title":"Getting Started with .Net","text":"

There are three different ways of adding MPXJ to your .Net project. In each case tool called IKVM is being used to convert the original Java version of MPXJ into .Net assemblies.

"},{"location":"howto-dotnet/#mpxjnet","title":"MPXJ.Net","text":"

This is the recommended approach.

The MPXJ.Net NuGet package provides a .Net wrapper around MPXJ's Java API. You will work with objects which use standard C# naming conventions, and expose native .Net types and data structures. The original Java nature of MPXJ is completely hidden from you. This is the preferred way to work with MPXJ. Just add the MPXJ.Net NuGet package to your project as a dependency and you can get started.

Note that your project will take longer than normal to build when first built using the MPXJ.Net package. As part of the build process the Java version of MPXJ is being dynamically translated into .Net assemblies. The results of this translation will be reused, so subsequent build times will return to normal. You may also see various transient warning messages as the first build completes. These can be ignored and will disappear once your project has finished building.

"},{"location":"howto-dotnet/#ikvmmavensdk","title":"IKVM.Maven.Sdk","text":"

Documented for completeness. Use the MPXJ.Net package instead..

IKVM provides an extension to SDK-style .Net projects called IKVM.Maven.SDK which allows you to refer to a Java library using Maven (the most common dependency management solution for Java projects). This means that your .Net project will be working directly with the original Java version of the library, which will automatically be translated into .Net assemblies for you as you build your project.

To include MPXJ in your project using this approach, edit your project file and include the following lines:

<ItemGroup>\n  <PackageReference Include=\"IKVM.Maven.Sdk\" Version=\"1.6.9\" />\n  <MavenReference Include=\"net.sf.mpxj:mpxj\" Version=\"13.0.0\"/>\n</ItemGroup>\n

The <PackageReference> tag enables IKVM's Maven integration functionality. The <MavenReference> tag uses this integration to request from Maven the version of MPXJ you'd like to use.

By using this approach you are working with MPXJ's Java API \"as is\", so you will need to deal with Java types, data structures, and naming conventions. In most cases you will find it more productive to work with the MPXJ.Net package described above. This approach is documented for completeness, but is not recommended.

Note that your project will take longer than normal to build when first built using IKVM.Maven.Sdk. As part of the build process the Java version of MPXJ is being dynamically translated into .Net assemblies. The results of this translation will be reused, so subsequent build times will return to normal. You may also see various transient warning messages as the first build completes. These can be ignored and will disappear once your project has finished building.

"},{"location":"howto-dotnet/#legacy-ikvm","title":"Legacy IKVM","text":"

Deprecated. Do Not Use. Only supported until MPXJ version 14.

The original .Net version of MPXJ was created using a legacy version of IKVM. The assemblies for this version are shipped as part of the MPXJ distribution and are available from NuGet as the following packages:

  • net.sf.mpxj direct translation of MPXJ
  • net.sf.mpxj-for-csharp translation of MPXJ with properties and methods following C# naming conventions
  • net.sf.mpxj-for-vb translation of MPXJ with properties and methods following C# naming conventions with some adjustments to accommodate VB's lack of case sensitivity
"},{"location":"howto-dotnet/#sample-code","title":"Sample Code","text":"

There is a repository containing sample .Net code for MPXJ covering use of the library in more depth. This repository can be found here.

"},{"location":"howto-read-asta/","title":"How To: Read Asta Powerproject and Easyproject files","text":"

Asta Powerproject and Asta Easyproject both use PP files.

"},{"location":"howto-read-asta/#reading-pp-files","title":"Reading PP files","text":"

The simplest way to read a PP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Asta\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Asta\n{\n     public void Read()\n     {\n          var reader = new UniversalProjectReader();\n          var project = reader.Read(\"my-sample.pp\");\n     }\n}\n

You can work directly with the AstaFileReader by replacing UniversalProjectReader with AstaFileReader, although this offers no particular advantage as there are no additional configuration settings available on the AstaFileReader class.

A note on password protected files: Powerproject offers the option of saving schedules with a username and password, which results in the file being encrypted. MPXJ doesn't support these files, and unfortunately I haven't come up with a way of reliably identifying that these are password protected PP files. If you pass a file like this to one of the the UniversalProjectReader read methods, it will simply return null, indicating an unsupported file type.

"},{"location":"howto-read-conceptdraw/","title":"How To: Read ConceptDraw PROJECT files","text":"

ConceptDraw PROJECT writes CDPX, CPDZ and CPDTZ files.

"},{"location":"howto-read-conceptdraw/#reading-cdpx-cpdz-and-cpdtz-files","title":"Reading CDPX, CPDZ and CPDTZ files","text":"

The simplest way to read a CDPX, CPDZ or CPDTZ file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ConceptDraw\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.cdpx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ConceptDraw\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.cdpx\");\n    }\n}\n

You can work directly with the ConceptDrawProjectReader by replacing UniversalProjectReader with ConceptDrawProjectReader, although this offers no particular advantage as there are no additional configuration settings available on the ConceptDrawProjectReader class.

"},{"location":"howto-read-fasttrack/","title":"How To: Read FastTrack Schedule files","text":"

FastTrack Schedule writes schedule data to FTS files. Note that MPXJ has only been tested with FTS files produced by FastTrack 10.

"},{"location":"howto-read-fasttrack/#reading-fts-files","title":"Reading FTS files","text":"

The simplest way to read an FTS file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class FastTrack\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.fts\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class FastTrack\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.fts\");\n    }\n}\n

You can work directly with the FastTrackReader by replacing UniversalProjectReader with FastTrackReader, although this offers no particular advantage as there are no additional configuration settings available on the FastTrackReader class.

"},{"location":"howto-read-ganttdesigner/","title":"How To: Read Gantt Designer files","text":"

Gantt Designer writes schedule data to GNT files.

"},{"location":"howto-read-ganttdesigner/#reading-gnt-files","title":"Reading GNT files","text":"

The simplest way to read a GNT file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class GanttDesigner\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.gnt\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class GanttDesigner\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.gnt\");\n    }\n}\n

You can work directly with the GanttDesignerReader by replacing UniversalProjectReader with GanttDesignerReader, although this offers no particular advantage as there are no additional configuration settings available on the GanttDesignerReader class.

"},{"location":"howto-read-ganttproject/","title":"How To: Read GanttProject files","text":"

GanttProject writes schedule data to GAN files (which are actually just XML files).

"},{"location":"howto-read-ganttproject/#reading-gan-files","title":"Reading GAN files","text":"

The simplest way to read a GAN file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class GanttProject\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.gan\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class GanttProject\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.gan\");\n    }\n}\n

You can work directly with the GanttProjectReader by replacing UniversalProjectReader with GanttProjectReader, although this offers no particular advantage as there are no additional configuration settings available on the GanttProjectReader class.

"},{"location":"howto-read-merlin/","title":"How To: Read Merlin files","text":"

Merlin Project is a Mac application. MPXJ provides experimental support for reading some Merlin Project files. The Merlin file format does not necessarily contain a full set of start and finish dates for each task. Merlin calculates these dates when it displays a schedule. At the moment MPXJ lacks this functionality, so you may not find start and finish dates for each task.

"},{"location":"howto-read-merlin/#reading-merlin-files","title":"Reading Merlin files","text":"

The simplest way to read a Merlin file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Merlin\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample-merlin-project\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Merlin\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample-merlin-project\");\n    }\n}\n

Note that on a Mac Merlin projects are not single files, but rather they are directories containing multiple files (the Mac Finder normally hides this from you). When using MPXJ to read a Merlin project you pass the directory name to the UniversalProjectReader class.

You can work directly with the MerlinReader by replacing UniversalProjectReader with MerlinReader, although this offers no particular advantage as there are no additional configuration settings available on the MerlinReader class.

"},{"location":"howto-read-mpd-database/","title":"How To: Read MPD Databases","text":"

Microsoft Project from Project 98 until Project 2003 could read and write schedules as Microsoft Access database files with the extension MPD. Versions of Microsoft Project after 2003 can import projects from MPD databases but cannot create or write to them. Project 98 creates a database with a schema known as MPD8, which MPXJ does not currently support reading. Project 2000 onward uses a schema called MPD9 which MPXJ can read.

Microsoft Project Server originally shared the same database schema as the MPD9 file format. This means that the MPDDatabaseReader class described below may also be used to read data from a Project Server SQL Server database.

"},{"location":"howto-read-mpd-database/#reading-mpd-databases","title":"Reading MPD databases","text":"

The preferred way to read MPD files is using UniversalProjectReader or the MPDFileReader reader. as described in the How To Read MPD files section.

You can if you wish read an MPD file via a database connection. Typically you will need the JDBC-ODBC bridge driver, or an equivalent JDBC driver which can work with a Microsoft Access database.

"},{"location":"howto-read-mpd-database/#setting-the-database-connection","title":"Setting the database connection","text":"

The MPDDatabaseReader class provides two methods: setConnection and setDataSource which allows you to supply a JDBC Connection instance or a JDBC DataSource instance.

"},{"location":"howto-read-mpd-database/#selecting-a-project","title":"Selecting a project","text":"

If the MPD file contains multiple projects, you can retrieve details of the available projects using the listProjects method. This returns a map of project IDs and project names. The sample code below illustrates how to retrieve this list of projects, and select the specific project that you want to read. In this case we read each project in the file in turn.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.mpd.MPDDatabaseReader;\nimport java.sql.Connection;\nimport java.util.Map;\n\npublic class MPDDatabase\n{\n   public void read(Connection connection) throws Exception\n   {\n      MPDDatabaseReader reader = new MPDDatabaseReader();\n      reader.setConnection(connection);\n      Map<Integer, String> projects = reader.listProjects();\n      for (Map.Entry<Integer, String> entry : projects.entrySet())\n      {\n         System.out.println(\"Project name: \" + entry.getValue());\n         reader.setProjectID(entry.getKey());\n         reader.read();\n      }\n   }\n}\n
"},{"location":"howto-read-mpd/","title":"How To: Read MPD files","text":"

Microsoft Project from Project 98 until Project 2003 could read and write schedules as Microsoft Access database files with the extension MPD. Versions of Microsoft Project after 2003 can import projects from MPD databases but cannot create or write to them. Project 98 creates a database with a schema known as MPD8, which MPXJ does not currently support reading. Project 2000 onward uses a schema called MPD9 which MPXJ can read.

"},{"location":"howto-read-mpd/#reading-mpd-files","title":"Reading MPD files","text":"

The simplest way to read an MPD file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MPDFile\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.mpd\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPDFile\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.mpd\");\n    }\n}\n

Note that the UniversalProjectReader.Read() method assumes that you are reading a project with ID of 1 from the MPD file. This is the default when a single project is written to an MPD file. Calling the ReadAll method will return all of the projects in the MPD file.

"},{"location":"howto-read-mpd/#using-mpdfilereader","title":"Using MPDFileReader","text":"

You can work directly with the MPDFileReader by replacing UniversalProjectReader with MPDFileReader. The sample code below illustrates how the reader can be used to retrieve a list of the projects in the file via the listProjects method. We can then select the ID of the project we want to read and use the setProjecID method to pass this to the reader. Finally, calling the read method reads the required project.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpd.MPDFileReader;\n\nimport java.io.File;\nimport java.util.Map;\n\npublic class MPDFileWithReader\n{\n    public void read() throws Exception\n    {\n        File file = new File(\"my-sample.mpd\");\n        MPDFileReader reader = new MPDFileReader();\n\n        // Retrieve the project details\n        Map<Integer, String> projects = reader.listProjects(file);\n\n        // Look up the project we want to read from the map.\n        // For this example we'll just use a hard-coded value.\n        Integer projectID = Integer.valueOf(1);\n\n        // Set the ID f the project we want to read\n        reader.setProjectID(projectID);\n\n        // Read the project\n        ProjectFile project = reader.read(file);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPDFileWithReader\n{\n    public void Read()\n    {\n        var reader = new MPDFileReader();\n\n        // Retrieve the project details\n        var projects = reader.ListProjects(\"my-sample.mpd\");\n\n        // Look up the project we want to read from the map.\n        // For this example we'll just use a hard-coded value.\n        var projectID = 1;\n\n        // Set the ID f the project we want to read\n        reader.ProjectID = projectID;\n\n        // Read the project\n        var project = reader.Read(\"my-sample.mpd\");\n    }\n}\n
"},{"location":"howto-read-mpp/","title":"How To: Read MPP files","text":"

The native Microsoft Project file format is typically has the extension MPP (or MPT for a template file). Although a common file extension uis used, there are actually a number if different variants of the file format. The list below shows the different variants, and the versions of Microsoft Project which produce them:

  • MPP8 - Project 98
  • MPP9 - Project 2000 and Project 2002
  • MPP12 - Project 2003, Project 2007
  • MPP14 - Project 2010 and all later versions
"},{"location":"howto-read-mpp/#reading-mpp-files","title":"Reading MPP files","text":"

The simplest way to read an MPP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MPP\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPP\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#using-mppreader","title":"Using MPPReader","text":"

You can work directly with the MPPReader class by replacing UniversalProjectReader with MPPReader. This provides access to additional options, as described below.

"},{"location":"howto-read-mpp/#password-protected-files","title":"Password Protected Files","text":"

When a read password has been set for an MPP file, the contents of the file are partially encrypted. If you attempt to read an MPP file which has been password protected an MPXJException will be raised, with the message File is password protected.

MPXJ only supports decryption of password protected MPP9 files. The code below illustrates how you would supply the password:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPWithPassword\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setReadPassword(\"my secret password\");\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPWithPassword\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.ReadPassword = \"my secret password\";\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n

The encryption used by MPP9 files doesn't actually require the password in order to read the contents of the file. If you wish you can set a flag to ignore the MPP9 password protection.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPIgnorePassword\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setRespectPasswordProtection(false);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPIgnorePassword\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.RespectPasswordProtection = false;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#presentation-data","title":"Presentation Data","text":"

Alongside the schedule data itself, MPXJ also extracts much of the presentation data available in an MPP file, for example table layouts, filters, graphical indicators and so on. If you are not interested in this type of data, you can tell MPXJ not to read it. This will speed up reading MPP files, and slightly reduce memory consumption. To do this you will use the setReadPresentationData method, as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPPresentationData\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setReadPresentationData(false);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPPresentationData\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.ReadPresentationData = false;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#properties-only","title":"Properties Only","text":"

Should you wish to simply \"peek\" at the contents of the MPP file by just reading the summary properties from the file, you can use the setReadPropertiesOnly method as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPPropertiesOnly\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setReadPropertiesOnly(true);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPPropertiesOnly\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.ReadPropertiesOnly = true;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#raw-timephased-data","title":"Raw timephased data","text":"

When MPXJ reads timephased data from an MPP file it \"normalises\" the data, converting it from the compact format Microsoft Project uses internally into a representation which shows the timephased values day-by-day. This is generally easier to understand, and can be further processed using the methods in the TimephasedUtility class to show the data over the required timescale.

If you do not want MPXJ to normalise the data, and would prefer instead to work with the raw data directly from the MPP file, you can use the setUseRawTimephasedData to do this, as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPRawTimephased\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setUseRawTimephasedData(true);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPRawTimephased\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.UseRawTimephasedData = true;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpx/","title":"How To: Read MPX files","text":"

Versions of Microsoft Project up to Project 98 could read and write MPX files as a data interchange format. Versions of Project after Project 98 until Project 2010 can only read MPX files. Versions of Microsoft Project after 2010 cannot read MPX files. Other third party project planning applications continue to use MPX as a data interchange format.

"},{"location":"howto-read-mpx/#reading-mpx-files","title":"Reading MPX files","text":"

The simplest way to read an MPX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MPX\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.mpx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPX\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.mpx\");\n    }\n}\n
"},{"location":"howto-read-mpx/#using-mpxreader","title":"Using MPXReader","text":"

You can work directly with the MPXReader class by replacing UniversalProjectReader with MPXReader. This provides access to additional options, as described below.

"},{"location":"howto-read-mpx/#locale","title":"Locale","text":"

It appears that very early in the life of the MPX file format, Microsoft Project was internationalised to allow versions of the application to be used in languages other than English. One unfortunate side effect of this was that the text used in the MPX file format was also internationalised. Thus rather than having a single file format which could be exchanged globally between any applications, you now need to know which internationalised version of Microsoft Project was used to create the MPX file in order to read it successfully.

Fortunately in most cases MPX files have been generated using the English language version of Microsoft Project, or an application which generates this variant, so the default settings for MPXReader will work.

If you encounter an MPX file generated by something other than an English version of Microsoft Project, you'll need to explicitly set the locale in order to read the file. The sample below shows how this is done:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXReader;\n\nimport java.util.Locale;\n\npublic class MPXWithLocale\n{\n    public void read() throws Exception\n    {\n        MPXReader reader = new MPXReader();\n        reader.setLocale(Locale.GERMAN);\n        ProjectFile project = reader.read(\"my-sample.mpx\");\n    }\n}\n
using System.Globalization;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPXWithLocale\n{\n    public void Read()\n    {\n        var reader = new MPXReader();\n        reader.Culture = CultureInfo.GetCultureInfo(\"de\");\n        var project = reader.Read(\"my-sample.mpx\");\n    }\n}\n

The following locales are supported by MPXReader:

  • English
  • German
  • Spanish
  • French
  • Italian
  • Portuguese
  • Russian
  • Swedish
  • Chinese

You can retrieve a list of supported locales programmatically using the code shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.mpx.MPXReader;\n\nimport java.util.Locale;\n\npublic class MPXSupportedLocales\n{\n    public void read() throws Exception\n    {\n        Locale[] locales = MPXReader.getSupportedLocales();\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPXSupportedLocales\n{\n    public void Read()\n    {\n        var cultures = MPXReader.SupportedCultures;\n    }\n}\n
"},{"location":"howto-read-mpx/#ignore-text-models","title":"Ignore Text Models","text":"

You should not normally need to modify this option.

An MPX file consists of a series of sections with each section representing a specific entity, for example tasks, resources, and so on. The set of attributes written for each entity is not fixed, instead at the start of each section the attributes which appear in the file are listed in two forms: as a series of numeric values, and as a series on human-readable attribute names.

Originally MPXJ used to read both of these lists, however it was found that the human-readable attribute names were often not consistent and caused problems when attempting to read MPX files. The default now is that these attributes are ignored. If for some reason you should wish to enable MPXJ's original behaviour and read these files, you would call setIgnoreTextModels as shown in the example below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXReader;\n\npublic class MPXIgnoreTextModels\n{\n    public void read() throws Exception\n    {\n        MPXReader reader = new MPXReader();\n        reader.setIgnoreTextModels(false);\n        ProjectFile project = reader.read(\"my-sample.mpx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPXIgnoreTextModels\n{\n    public void Read()\n    {\n        var reader = new MPXReader();\n        reader.IgnoreTextModels = false;\n        var project = reader.Read(\"my-sample.mpx\");\n    }\n}\n
"},{"location":"howto-read-mspdi/","title":"How To: Read MSPDI files","text":"

The Microsoft Project Data Interchange (MSPDI) format is an XML file format which Microsoft Project has been able to read and write since Project 2002.

"},{"location":"howto-read-mspdi/#reading-mspdi-files","title":"Reading MSPDI files","text":"

The simplest way to read an MSPDI file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MSDPI\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDI\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-mspdi/#using-mspdireader","title":"Using MSPDIReader","text":"

You can work directly with the MSPDIReader class by replacing UniversalProjectReader with MSPDIReader. This provides access to additional options, as described below.

"},{"location":"howto-read-mspdi/#charset","title":"Charset","text":"

By default MPXJ assumes that MSPDI files are encoded as UTF-8. The UniversalProjectReader understands Unicode Byte Order Marks (BOM) and will adjust the encoding appropriately if a BOM is present. If you have an MSPDI file with an unusual encoding, you can manually set the encoding used by the reader, as illustrated below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIReader;\n\nimport java.nio.charset.Charset;\n\npublic class MSPDIWithCharset\n{\n    public void read() throws Exception\n    {\n        MSPDIReader reader = new MSPDIReader();\n\n        reader.setCharset(Charset.forName(\"GB2312\"));\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using System.Text;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDIWithLocale\n{\n    public void Read()\n    {\n        var reader = new MSPDIReader();\n        reader.Encoding = Encoding.GetEncoding(\"GB2312\");\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-mspdi/#microsoft-project-compatibility","title":"Microsoft Project Compatibility","text":"

Microsoft Project will read MSPDI files which are not valid XML according to the MSPDI schema. By default MPXJ has been configured to take the same approach. If for some reason you wish to apply strict validation when reading an MSPDI file, you can do this using the setMicrosoftProjectCompatibleInput method, as shown below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIReader;\n\npublic class MSPDICompatibleInput\n{\n    public void read() throws Exception\n    {\n        MSPDIReader reader = new MSPDIReader();\n        reader.setMicrosoftProjectCompatibleInput(false);\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDICompatibleInput\n{\n    public void Read()\n    {\n        var reader = new MSPDIReader();\n        reader.MicrosoftProjectCompatibleInput = false;\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-mspdi/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from an MSPDI file. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the MSPDIReader to report errors encountered when reading a file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIReader;\n\npublic class MSPDIIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        MSPDIReader reader = new MSPDIReader();\n\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDIIgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new MSPDIReader();\n        reader.IgnoreErrors = false;\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-openplan/","title":"How To: Deltek Open Plan BK3 files","text":"

Deltek Open Plan is a planning tool for Windows which can store schedule data in a variety of databases, and export schedules to BK3 files.

"},{"location":"howto-read-openplan/#reading-open-plan-files","title":"Reading Open Plan files","text":"

The simplest way to read an Open Plan file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class OpenPlan\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.bk3\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class OpenPlan\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.bk3\");\n    }\n}\n

You can work directly with the OpenPlanReader by replacing UniversalProjectReader with OpenPlanReader, although this offers no particular advantage as there are no additional configuration settings available on the OpenPlanReader class.

"},{"location":"howto-read-p3/","title":"How To: Read P3 files","text":"

A Primavera P3 installation stores project data as a database consisting of a number of individual files. In a typical P3 installation files for a number of different projects live in a single projects directory. A P3 user can back up an individual project to create a PRX file, which is a compressed archive containing all of the files from a single project.

"},{"location":"howto-read-p3/#reading-prx-files","title":"Reading PRX files","text":"

The simplest way to read a PRX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class P3\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.prx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P3\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.prx\");\n    }\n}\n

You can work directly with the P3PRXFileReader by replacing UniversalProjectReader with P3PRXFileReader, although this offers no particular advantage as there are no additional configuration settings available on the P3PRXFileReader class.

"},{"location":"howto-read-p3/#reading-a-p3-directory","title":"Reading a P3 directory","text":"

If you are working with a directory containing P3 project data you have two options. If you know that the directory only contains a single project, you can use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class P3Directory\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-p3-directory\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P3Directory\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-p3-directory\");\n    }\n}\n

If the directory happens to contain multiple projects the UniversalProjectReader will simply read the first one it finds, in alphabetic order.

If you know that the directory you are working with contains multiple projects, you will need to use the P3DatabaseReader class.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.p3.P3DatabaseReader;\n\nimport java.util.List;\n\npublic class P3NamedProject\n{\n    public void read() throws Exception\n    {\n        // Find a list of the project names\n        String directory = \"my-p3-directory\";\n        List<String> projectNames = P3DatabaseReader.listProjectNames(directory);\n\n        // Tell the reader which project to work with\n        P3DatabaseReader reader = new P3DatabaseReader();\n        reader.setProjectName(projectNames.get(0));\n\n        // Read the project\n        ProjectFile project = reader.read(directory);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P3NamedProject\n{\n    public void Read()\n    {\n        // Find a list of the project names\n        var directory = \"my-p3-directory\";\n        var projectNames = P3DatabaseReader.ListProjectNames(directory);\n\n        // Tell the reader which project to work with\n        var reader = new P3DatabaseReader();\n        reader.ProjectName = projectNames[0];\n\n        // Read the project\n        var project = reader.Read(directory);\n    }\n}\n

As the example above shows, the P3DatabaseReader class provides a method which lists the names of the P3 projects it finds in a directory. You can then select which project you want to load, and call the setProjectName method of the reader to make this selection. You can then call the read method passing in the name of the directory, and the reader will extract data for the selected project.

"},{"location":"howto-read-phoenix/","title":"How To: Read Phoenix Project Manager files","text":"

Phoenix Project Manager uses PPX files.

"},{"location":"howto-read-phoenix/#reading-ppx-files","title":"Reading PPX files","text":"

The simplest way to read a PPX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Phoenix\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.ppx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Phoenix\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.ppx\");\n    }\n}\n

You can work directly with the PhoenixReader by replacing UniversalProjectReader with PhoenixReader, although this offers no particular advantage as there are no additional configuration settings available on the PhoenixReader class.

"},{"location":"howto-read-planner/","title":"How To: Read Planner files","text":"

Gnome Planner is a popular open source planning tool which writes its own XML files.

"},{"location":"howto-read-planner/#reading-planner-files","title":"Reading Planner files","text":"

The simplest way to read a Planner file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Planner\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Planner\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-samplexml\");\n    }\n}\n

You can work directly with the PlannerReader by replacing UniversalProjectReader with PlannerReader, although this offers no particular advantage as there are no additional configuration settings available on the PlannerReader class.

"},{"location":"howto-read-plf/","title":"How To: Read Primavera PLF files","text":"

Primavera P6 can export layout information as PLF files. These files define the visual appearance of the P6 user interface, and can be imported and exported by P6. Although MPXJ doesn't currently offer any facilities to interpret the contents of these files, the data they contain can be read.

"},{"location":"howto-read-plf/#reading-plf-files","title":"Reading PLF files","text":"

A PLF file contains \"structured text\" and can be read using StructuredTextParser:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.StructuredTextParser;\nimport net.sf.mpxj.primavera.StructuredTextRecord;\n\nimport java.io.FileInputStream;\n\npublic class PLF\n{\n   public void read() throws Exception\n   {\n      StructuredTextParser parser = new StructuredTextParser();\n      StructuredTextRecord record = parser.parse(new FileInputStream(\"test.plf\"));\n   }\n}\n
"},{"location":"howto-read-plf/#attributes","title":"Attributes","text":"

The resulting StructuredTextRecord contains attributes which can be accesed individually by name, as shown below:

record.getAttribute(\"attribute_name\");\n

The attributes can also be retrieved in the form of a Map containing all attributes for this record:

Map<String,String> attributes = record.getAttributes();\nattributes.get(\"attribute_name\");\n

Each record has two special attributes: a record number, and optionally a record name. These appear as part of the identifying information for each record, not as part of the general set of attributes for the record. These can be retrieved as shown below:

String recordNumber = record.getRecordNumber();\nString recordName = record.getRecordName();\n

These attributes will also be found in the attributes Map with the keys _record_number and _record_name.

"},{"location":"howto-read-plf/#child-records","title":"Child records","text":"

Along with a set of attributes, each StructuredTextRecord may have child StructuredTextRecord instances. These be retrieved as a list, as shown below:

List<StructuredTextRecord> childRecords = record.getChildren();\n

Certain record types are named, and where this is the case a child record can be retrieved individually by name:

StructuredTextRecord child = record.getChild(\"child_name\");\n
"},{"location":"howto-read-pmxml/","title":"How To: Read Primavera PMXML files","text":"

Primavera P6 can export data in an XML format known as PMXML.

"},{"location":"howto-read-pmxml/#reading-pmxml-files","title":"Reading PMXML files","text":"

The simplest way to read a PMXML file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class PMXML\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXML\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-pmxml/#using-primaverapmfilereader","title":"Using PrimaveraPMFileReader","text":"

You can work directly with the PrimaveraPMFileReader by replacing UniversalProjectReader with PrimaveraPMFileReader. This provides access to additional options, as described below.

"},{"location":"howto-read-pmxml/#multiple-projects","title":"Multiple Projects","text":"

A PMXML file can contain multiple projects. By default, MPXJ reads the first non-external project it finds in the file, otherwise it defaults to the first project it finds. You can however use MPXJ to list the projects contained in a PMXML file, as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\nimport java.io.FileInputStream;\nimport java.util.Map;\n\npublic class PMXMLListProjects\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        FileInputStream is = new FileInputStream(\"my-sample.xml\");\n        Map<Integer, String> projects = reader.listProjects(is);\n        System.out.println(\"ID\\tName\");\n        for (Map.Entry<Integer, String> entry : projects.entrySet())\n        {\n            System.out.println(entry.getKey()+\"\\t\"+entry.getValue());\n        }\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXMLListProjects\n{\n    public void Read()\n    {\n        var reader = new PrimaveraPMFileReader();\n        var stream = new FileStream(\"my-sample.xml\",\n            FileMode.Open, FileAccess.Read, FileShare.None);\n        var projects = reader.ListProjects(stream);\n        System.Console.WriteLine(\"ID\\tName\");\n        foreach (var entry in projects)\n        {\n                System.Console.WriteLine($\"{entry.Key}\\t{entry.Value}\");\n        }\n    }\n}\n

The call to listProjects returns a Map whose key is the project ID, and the values are project short names.

Once you have decided which of these projects you want to work with, you can call setProjectID to tell the reader which project to open, as shown below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\npublic class PMXMLProjectID\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        reader.setProjectID(123);\n        ProjectFile file = reader.read(\"my-sample.xml\");\n    }\n}\n

Alternatively you can ask MPXJ to read all the projects contained in the file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\nimport java.util.List;\n\npublic class PMXMLReadAll\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        List<ProjectFile> files = reader.readAll(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXMLReadAll\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.ReadAll(\"my-sample.xml\");\n    }\n}\n

The call to the readAll method returns a list of ProjectFile instances corresponding to the projects in the PMXML file.

Note that when calling the readAll method for a PMXML file, the list of projects returned will include baseline projects. You can determine which projects are baseline projects by calling the ProjectProperties method getProjectIsBaseline(), which will return true for baseline projects.

"},{"location":"howto-read-pmxml/#link-cross-project-relations","title":"Link Cross-Project Relations","text":"

A PMXML file can contain multiple projects with relations between activities which span those projects. By default, these cross-project relations are ignored. However, if you set the linkCrossProjectRelations reader attribute to true, MPXJ will attempt to link these relations across projects:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\nimport java.util.List;\n\npublic class PMXMLLinkCrossProject\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        reader.setLinkCrossProjectRelations(true);\n        List<ProjectFile> files = reader.readAll(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXMLLinkCrossProject\n{\n    public void Read()\n    {\n        var reader = new PrimaveraPMFileReader();\n        reader.LinkCrossProjectRelations = true;\n        var files = reader.ReadAll(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-pmxml/#baselines","title":"Baselines","text":"

Users can export PMXML files from P6 which contain the baseline project along with the main project being exported. When the readAll method is used to read a PMXML file, MPXJ will attempt to populate the baseline fields of the main project if it can locate the baseline project in the PMXML file.

By default the \"Planned Dates\" strategy is used to populate baseline fields, which is the approach P6 uses when the \"Earned Value Calculation\" method is set to \"Budgeted values with planned dates\".

PrimaveraPMFileReader provides a method allowing the strategy to be changed, thus allowing you to select the \"Current Dates\" strategy, which is the approach used by P6 when the Earned Value Calculation method is set to \"At Completion values with current dates\" or \"Budgeted values with current dates\". The example below illustrates how this method is used:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\nimport net.sf.mpxj.primavera.PrimaveraBaselineStrategy;\n\nimport java.util.List;\n\npublic class PMXMLBaselines\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        reader.setBaselineStrategy(PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES);\n        List<ProjectFile> files = reader.readAll(\"my-sample.xml\");\n    }\n}\n

See the How To Use Baselines section for more information on how MPXJ works with baselines.

"},{"location":"howto-read-primavera/","title":"How To: Read a Primavera P6 database","text":"

Primavera P6 supports the use of SQLite, SQL Server and Oracle databases. SQLite is a single file database, and in common with the other file-based schedule formats MPXJ provides a reader class. To read schedules from SQL Server and Oracle databases you will need to use a JDBC connection with MPXJ. These approaches are described in the sections below.

"},{"location":"howto-read-primavera/#sqlite","title":"SQLite","text":"

The PrimaveraDatabaseFileReader provides convenient access to P6 schedules stored as a SQLite database. By default P6 will create a database called PPMDBSQLite.db in the Windows user's My Documents folder. The example code below illustrates how we'd list the schedules in this file, and reda one of those schedules using it ID.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseFileReader;\n\nimport java.io.File;\nimport java.util.Map;\n\npublic class P6Sqlite\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseFileReader reader = new PrimaveraDatabaseFileReader();\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        File file = new File(\"PPMDBSQLite.db\");\n        Map<Integer,String> projects = reader.listProjects(file);\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.setProjectID(selectedProjectID);\n        ProjectFile projectFile = reader.read(file);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6Sqlite\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseFileReader();\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        var file = \"PPMDBSQLite.db\";\n        var projects = reader.ListProjects(file);\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.ProjectID = selectedProjectID;\n        var projectFile = reader.Read(file);\n    }\n}\n
"},{"location":"howto-read-primavera/#jdbc-in-java","title":"JDBC in Java","text":"

For P6 schedules hosted in either a SQL Server databases or an Oracle database, we must use a JDBC driver with the PrimaveraDatabaseReader reader in order to access this data. In this example we're reading a schedule from a SQL Server database using Microsoft's JDBC driver. This code assumes that you have added the JDBC driver as a dependency to your Java project.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.util.Map;\n\npublic class P6JDBC\n{\n    public void read() throws Exception\n    {\n        //\n        // Load the JDBC driver\n        //\n        String driverClass=\"com.microsoft.sqlserver.jdbc.SQLServerDriver\";\n        Class.forName(driverClass);\n\n        //\n        // Open a database connection. You will need to change\n        // these details to match the name of your server, database, user and password.\n        //\n        String connectionString=\"jdbc:sqlserver://localhost:1433;databaseName=my-database-name;user=my-user-name;password=my-password;\";\n        Connection c = DriverManager.getConnection(connectionString);\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setConnection(c);\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        Map<Integer,String> projects = reader.listProjects();\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.setProjectID(selectedProjectID);\n        ProjectFile projectFile = reader.read();\n    }\n}\n
"},{"location":"howto-read-primavera/#jdbc-in-net","title":"JDBC in .Net","text":"

The approach for reading schedule data from a SQL Server or Orcale database is very similar to that used with the Java version. The main difference is how we add the JDBC driver to our project as a dependency. To do this we add a MavenReference to our project. The example below show how I have added this just after the reference to the MPXJ.Net package:

<ItemGroup>\n    <PackageReference Include=\"MPXJ.Net\" Version=\"13.0.0\" />\n    <MavenReference Include=\"com.microsoft.sqlserver:mssql-jdbc\" Version=\"12.6.2.jre8\" />\n</ItemGroup>\n

Note that the IKVM's conversion of Java code to .Net being works by implementing a Java 8 (sometimes also known as a Java 1.8) virtual machine. If you have a choice of Java packages to use which are targeted at different Java versions, select the Java 8 version - as illustrated in the example above.

Now we can use the JDBC driver to create a connection to our database, as the sample code below illustrates.

using com.microsoft.sqlserver.jdbc;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6JDBC\n{\n    public void Read()\n    {\n        //\n        // Load the JDBC driver\n        //\n        var driver = new SQLServerDriver();\n\n        //\n        // Open a database connection. You will need to change\n        // these details to match the name of your server, database, user and password.\n        //\n        var connectionString = \"jdbc:sqlserver://localhost:1433;databaseName=my-database-name;user=my-user-name;password=my-password;\";\n        var connection = driver.connect(connectionString, null);\n        var reader = new PrimaveraDatabaseReader();\n        reader.Connection = connection;\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        var projects = reader.ListProjects();\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.ProjectID = selectedProjectID;\n        var projectFile = reader.Read();\n    }\n}\n
"},{"location":"howto-read-primavera/#options","title":"Options","text":"

This section documents the additional options provided by the PrimaveraDatabaseReader.

"},{"location":"howto-read-primavera/#activity-wbs","title":"Activity WBS","text":"

In the original implementation of the database handling code, MPXJ would assign each task representing a Primavera Activity its own distinct WBS value. This does not match Primavera's behaviour where all of a WBS element's child activities will have the same WBS value as the parent WBS element. MPXJ's default behaviour now matches Primavera, but should you wish to you can revert to the original behaviour by calling the setMatchPrimaveraWBS as shown below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\npublic class P6ActivityWbs\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setMatchPrimaveraWBS(false);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6ActivityWbs\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseReader();\n        reader.MatchPrimaveraWBS = false;\n    }\n}\n
"},{"location":"howto-read-primavera/#wbs-is-full-path","title":"WBS is Full Path","text":"

Currently, the WBS attribute of summary tasks (WBS entities in P6) will be a dot separated hierarchy of all the parent WBS attributes. In this example, root.wbs1.wbs2 is the WBS attribute for wbs2 which has the parents root and wbs1. To disable this behaviour, and simply record the code for the current WBS entry (in the example above wbs2) call the setWbsIsFullPath method, passing in false, as illustrated below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\npublic class P6WbsFullPath\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setWbsIsFullPath(false);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6WbsFullPath\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseReader();\n        reader.WbsIsFullPath = false;\n    }\n}\n
"},{"location":"howto-read-primavera/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from a Primavera database. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the PrimaveraDatabaseReader to report errors encountered when reading from a Primavera database:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\npublic class P6IgnoreErrors\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setIgnoreErrors(false);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6IgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseReader();\n        reader.IgnoreErrors = false;\n    }\n}\n

Note that if errors are ignored when reading from a Primavera database, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-primavera/#reading-additional-attributes","title":"Reading Additional Attributes","text":"

A data-driven approach is used to extract the attributes used by MPXJ from the database. You can if you wish change the way attributes are read from the file, or add support for additional attributes. This assumes that you know the column name of the attributes you want to work with in the database. To make changes you will need to retrieve the maps which define which MPXJ attributes are used to store which columns from the database:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\nimport java.util.Map;\n\npublic class P6AttributeMaps\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        Map<FieldType, String> resourceFieldMap = reader.getResourceFieldMap();\n        Map<FieldType, String> wbsFieldMap = reader.getWbsFieldMap();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n        Map<FieldType, String> assignmentFieldMap = reader.getAssignmentFieldMap();\n    }\n}\n

These maps will contain the default mapping between columns and MPXJ attributes. You can modify these existing mappings, or add new ones, for example:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.TaskField;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\nimport java.util.Map;\n\npublic class P6AttributeConfig\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n\n        //\n        // Store rsrc_id in NUMBER1\n        //\n        activityFieldMap.put(TaskField.NUMBER1, \"rsrc_id\");\n\n        //\n        // Read an Activity column called an_example_field and store it in TEXT10\n        //\n        activityFieldMap.put(TaskField.TEXT10, \"an_example_field\");\n    }\n}\n
"},{"location":"howto-read-projectcommander/","title":"How To: Read Project Commander files","text":"

Project Commander is a planning tool for Windows which writes its own PC file format.

"},{"location":"howto-read-projectcommander/#reading-project-commander-files","title":"Reading Project Commander files","text":"

The simplest way to read a Project Commander file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ProjectCommander\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pc\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ProjectCommander\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.pc\");\n    }\n}\n

You can work directly with the ProjectCommanderReader by replacing UniversalProjectReader with ProjectCommanderReader, although this offers no particular advantage as there are no additional configuration settings available on the ProjectCommanderReader class.

"},{"location":"howto-read-projectlibre/","title":"How To: Read ProjectLibre files","text":"

ProjectLibre writes schedule data to POD files. MPXJ can read POD files written by ProjectLibre version 1.5.5 and later versions.

"},{"location":"howto-read-projectlibre/#reading-pod-files","title":"Reading POD files","text":"

The simplest way to read a POD file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ProjectLibre\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pod\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ProjectLibre\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.pod\");\n    }\n}\n

You can work directly with the ProjectLibreReader by replacing UniversalProjectReader with ProjectLibreReader, although this offers no particular advantage as there are no additional configuration settings available on the ProjectLibreReader class.

"},{"location":"howto-read-schedule-grid/","title":"How To: Read Schedule Grid files","text":"

Schedule grid files are produced when a schedule is exported from Sage 100 Contractor.

"},{"location":"howto-read-schedule-grid/#reading-schedule-grid-files","title":"Reading Schedule Grid files","text":"

The simplest way to read a schedule grid file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ScheduleGrid\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.schedule_grid\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ScheduleGrid\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.schedule_grid\");\n    }\n}\n
"},{"location":"howto-read-schedule-grid/#using-sagereader","title":"Using SageReader","text":"

You can work directly with the SageReader class by replacing UniversalProjectReader with SageReader. This provides access to additional options, as described below.

"},{"location":"howto-read-schedule-grid/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from a Schedule Grid file. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the SageReader to report errors encountered when reading a file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.sage.SageReader;\n\npublic class ScheduleGridIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        SageReader reader = new SageReader();\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.schedule_grid\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ScheduleGridIgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new SageReader();\n        reader.IgnoreErrors = false;\n        var project = reader.Read(\"my-sample.schedule_grid\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-sdef/","title":"How To: Read SDEF files","text":"

The Standard Data Exchange Format (SDEF) is the US Army Corps of Engineers standard format for exchanging schedule data between systems. The definition of this format can be found here.

"},{"location":"howto-read-sdef/#reading-sdef-files","title":"Reading SDEF files","text":"

The simplest way to read an SDEF file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SDEF\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.sdef\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SDEF\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.sdef\");\n    }\n}\n
"},{"location":"howto-read-sdef/#using-sdefreader","title":"Using SDEFReader","text":"

You can work directly with the SDEFReader class by replacing UniversalProjectReader with SDEFReader. This provides access to additional options, as described below.

"},{"location":"howto-read-sdef/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from an SDEF file. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the SDEFReader to report errors encountered when reading a file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.sdef.SDEFReader;\n\npublic class SDEFIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        SDEFReader reader = new SDEFReader();\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.sdef\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SDEFIgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new SDEFReader();\n        reader.IgnoreErrors = false;\n        var project = reader.Read(\"my-sample.sdef\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-suretrak/","title":"How To: Read SureTrak files","text":"

A Primavera SureTrak installation stores project data as a database consisting of a number of individual files. In a typical SureTrak installation files for a number of different projects live in a single projects directory. A SureTrak user can back up an individual project to create an STX file, which is a compressed archive containing all of the files from a single project.

"},{"location":"howto-read-suretrak/#reading-stx-files","title":"Reading STX files","text":"

The simplest way to read an STX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SureTrak\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.stx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SureTrak\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.stx\");\n    }\n}\n

You can work directly with the SureTrakSTXFileReader by replacing UniversalProjectReader with SureTrakSTXFileReader, although this offers no particular advantage as there are no additional configuration settings available on the SureTrakSTXFileReader class.

"},{"location":"howto-read-suretrak/#reading-a-suretrak-directory","title":"Reading a SureTrak directory","text":"

If you are working with a directory containing SureTrak project data you have two options. If you know that the directory only contains a single project, you can use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SureTrakDirectory\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-suretrak-directory\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SureTrakDirectory\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-suretrak-directory\");\n    }\n}\n

If the directory happens to contain multiple projects the UniversalProjectReader will simply read the first one it finds, in alphabetic order.

If you know that the directory you are working with contains multiple projects, you will need to use the SureTrakDatabaseReader class.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.suretrak.SureTrakDatabaseReader;\n\nimport java.util.List;\n\npublic class SureTrakListProjects\n{\n    public void read() throws Exception\n    {\n        // Find a list of the project names\n        String directory = \"my-suretrak-directory\";\n        List<String> projectNames = SureTrakDatabaseReader.listProjectNames(directory);\n\n        // Tell the reader which project to work with\n        SureTrakDatabaseReader reader = new SureTrakDatabaseReader();\n        reader.setProjectName(projectNames.get(0));\n\n        // Read the project\n        ProjectFile project = reader.read(directory);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SureTrakListProjects\n{\n    public void Read()\n    {\n        // Find a list of the project names\n        var directory = \"my-suretrak-directory\";\n        var projectNames = SureTrakDatabaseReader.ListProjectNames(directory);\n\n        // Tell the reader which project to work with\n        var reader = new SureTrakDatabaseReader();\n        reader.ProjectName = projectNames[0];\n\n        // Read the project\n        var project = reader.Read(directory);\n    }\n}\n

As the example above shows, the SureTrakDatabaseReader class provides a method which lists the names of the SureTrak projects it finds in a directory. You can then select which project you want to load, and call the setProjectName method of the reader to make this selection. You can then call the read method passing in the name of the directory, and the reader will extract data for the selected project.

"},{"location":"howto-read-synchro/","title":"How To: Read Synchro Scheduler files","text":"

Synchro Scheduler writes SP files.

"},{"location":"howto-read-synchro/#reading-sp-files","title":"Reading SP files","text":"

The simplest way to read an SP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Synchro\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.sp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Synchro\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.sp\");\n    }\n}\n

You can work directly with the SynchroReader by replacing UniversalProjectReader with SynchroReader, although this offers no particular advantage as there are no additional configuration settings available on the SynchroReader class.

"},{"location":"howto-read-turboproject/","title":"How To: Read TurboProject files","text":"

TurboProject writes schedule data to PEP files.

"},{"location":"howto-read-turboproject/#reading-pep-files","title":"Reading PEP files","text":"

The simplest way to read a PEP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class TurboProject\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pep\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class TurboProject\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.pep\");\n    }\n}\n

You can work directly with the TurboProjectReader by replacing UniversalProjectReader with TurboProjectReader, although this offers no particular advantage as there are no additional configuration settings available on the TurboProjectReader class.

"},{"location":"howto-read-xer/","title":"How To: Read XER files","text":"

The XER file format has long been read and written by Primavera P6. Although an XML file format (PMXML) is now also supported, the XER file format is still widely used.

"},{"location":"howto-read-xer/#reading-xer-files","title":"Reading XER files","text":"

The simplest way to read an XER file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class XER\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xer\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class XER\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#using-primaveraxerfilereader","title":"Using PrimaveraXERFileReader","text":"

You can work directly with the PrimaveraXERFileReader class by replacing UniversalProjectReader with PrimaveraXERFileReader. This provides access to additional options, as described below.

"},{"location":"howto-read-xer/#ignore-errors","title":"Ignore Errors","text":"

By default P6 ignores records it can't successfully read from an XER file. MPXJ takes the same approach, and in most cases if it doesn't receive the data it expects for a particular record it will ignore the problematic item.

This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the PrimaveraXERFileReader to report errors encountered when reading a file:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.xer\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-xer/#charset","title":"Charset","text":"

By default MPXJ assumes that XER files use the Windows-1252 Charset. The UniversalProjectReader understands Unicode Byte Order Marks (BOM) and will adjust the Charset appropriately if a BOM is present. If you have an XER file with an unusual encoding, you can manually set the Charset used by the reader.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.nio.charset.Charset;\n\npublic class XERCharset\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setCharset(Charset.forName(\"GB2312\"));\n        ProjectFile project = reader.read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#multiple-projects","title":"Multiple Projects","text":"

An XER file can contain multiple projects. By default MPXJ reads the first project it finds in the file which has been marked as the \"exported\" project, otherwise it will simply read the first project it finds. You can however use MPXJ to list the projects contained in an XER file, as shown below:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.io.FileInputStream;\nimport java.util.Map;\n\npublic class XERListProjects\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        FileInputStream is = new FileInputStream(\"my-sample.xer\");\n        Map<Integer, String> projects = reader.listProjects(is);\n        System.out.println(\"ID\\tName\");\n        for (Map.Entry<Integer, String> entry : projects.entrySet())\n        {\n            System.out.println(entry.getKey()+\"\\t\"+entry.getValue());\n        }\n    }\n}\n
The call to listProjects returns a Map whose key is the project ID, and the values are project short names.

Once you have decided which of these projects you want to work with, you can call setProjectID to tell the reader which project to open, as shown below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERProjectID\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setProjectID(123);\n        ProjectFile file = reader.read(\"my-sample.xer\");\n    }\n}\n

Alternatively you can ask MPXJ to read all of the projects contained in the file:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.List;\n\npublic class XERReadAll\n{\n   public void read() throws Exception\n   {\n      PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n      List<ProjectFile> files = reader.readAll(\"my-sample.xer\");\n   }\n}\n

The call to the readAll method returns a list of ProjectFile instances corresponding to the projects in the XER file.

"},{"location":"howto-read-xer/#link-cross-project-relations","title":"Link Cross-Project Relations","text":"

An XER file can contain multiple projects with relations between activities which span those projects. By default these cross-project relations are ignored. However, if you set the linkCrossProjectRelations reader attribute to true, MPXJ will attempt to link these relations across projects:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.List;\n\npublic class XERLinkCrossProject\n{\n   public void read() throws Exception\n   {\n      PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n      reader.setLinkCrossProjectRelations(true);\n      List<ProjectFile> files = reader.readAll(\"my-sample.xer\");\n   }\n}\n
"},{"location":"howto-read-xer/#activity-wbs","title":"Activity WBS","text":"

In the original implementation of the XER file handling code, MPXJ would assign each task representing a Primavera Activity its own distinct WBS value. This does not match Primavera's behaviour where all of a WBS element's child activities will have the same WBS value as the parent WBS element. MPXJ's default behaviour now matches Primavera, but should you wish to you can revert to the original behaviour by calling the setMatchPrimaveraWBS as shown below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERMatchWbs\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setMatchPrimaveraWBS(false);\n        ProjectFile file = reader.read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#wbs-is-full-path","title":"WBS is Full Path","text":"

Currently the WBS attribute of summary tasks (WBS entities in P6) will be a dot separated hierarchy of all of the parent WBS attributes. In this example, root.wbs1.wbs2 is the WBS attribute for wbs2 which has the parents root and wbs1. To disable this behaviour, and simply record the code for the current WBS entry (in the example above wbs2) call the setWbsIsFullPath method, passing in false, as illustrated below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERWbsFullPath\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setWbsIsFullPath(false);\n        ProjectFile file = reader.read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#reading-additional-attributes","title":"Reading Additional Attributes","text":"

A data-driven approach is used to extract the attributes used by MPXJ from the XER file. You can if you wish change the way attributes are read from the file, or add support for additional attributes. This assumes that you know the column name of the attributes you want to work with in the XER file. To make changes you will need to retrieve the maps which define which MPXJ attributes are used to store which columns from the XER file:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.Map;\n\npublic class XERAttributeMaps\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        Map<FieldType, String> resourceFieldMap = reader.getResourceFieldMap();\n        Map<FieldType, String> wbsFieldMap = reader.getWbsFieldMap();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n        Map<FieldType, String> assignmentFieldMap = reader.getAssignmentFieldMap();\n    }\n}\n

These maps will contain the default mapping between columns and MPXJ attributes. You can modify these existing mappings, or add new ones, for example:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.TaskField;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.Map;\n\npublic class XERAttributeConfig\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n\n        //\n        // Store rsrc_id in NUMBER1\n        //\n        activityFieldMap.put(TaskField.NUMBER1, \"rsrc_id\");\n\n        //\n        // Read an Activity column called an_example_field and store it in TEXT10\n        //\n        activityFieldMap.put(TaskField.TEXT10, \"an_example_field\");\n    }\n}\n

When reading new columns from the XER file, if these columns have a type other than String, it is important to register the type of the column to ensure that it is converted correctly. You will also need to ensure that the MPXJ attribute you are writing this new value to can receive the data type you are assigning to it (for example, you must store a date in a date attribute, you can't store a date in an integer attribute).

For example, if we are reading an integer column called an_example_id and store it in the NUMBER2 attribute, we will need to take the following steps:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.DataType;\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.TaskField;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.Map;\n\npublic class XERRegisterType\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        Map<String, DataType> fieldTypeMap = reader.getFieldTypeMap();\n        fieldTypeMap.put(\"an_example_id\", DataType.INTEGER);\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n        activityFieldMap.put(TaskField.NUMBER2, \"an_example_id\");\n    }\n}\n
"},{"location":"howto-start-java/","title":"Getting Started with Java","text":"

MPXJ is built to work with versions of Java from 1.8 onwards. For many people, the easiest way to get started with MPXJ and its dependencies is to use Maven. Just include the following in your POM to register MPXJ as a dependency of your project:

<dependency>\n  <groupId>net.sf.mpxj</groupId>\n  <artifactId>mpxj</artifactId>\n  <version>13.0.0</version>\n</dependency>\n

The traditional method of downloading the MPXJ distribution as a zip file can also be used. Distributions can be found at GitHub and SourceForge.

The zip files contain all of the source, the MPXJ JAR file in the root of the zip file, with the libraries on which MPXJ depends being found in the lib directory of the zip file. These libraries will need to be available on your classpath in order to use all of the MPXJ functionality. The script directory in the zip file contains a batch file and a shell script which show how this can be done.

You'll find a general introduction to MPXJ's functionality here.

"},{"location":"howto-start-python/","title":"Getting Started with Python","text":"

MPXJ is available as a Python Package, which can be installed using pip:

pip install mpxj\n

You can find some documentation for the Package here. You'll need Java installed to make use of this package.

You'll find a general introduction to MPXJ's functionality here.

"},{"location":"howto-start-ruby/","title":"Getting Started with Ruby","text":"

MPXJ is available as a RubyGem, which can be installed using gem:

gem install mpxj\n

or included in you Gemfile and installed using bundler.

Note that the Ruby version of MPXJ is just a wrapper around the Java library, and provides read-only access to schedule data. You will need Java installed to make use of this Gem. You can find some documentation for the Gem here

You'll find a general introduction to MPXJ's functionality here.

"},{"location":"howto-start/","title":"MPXJ Basics","text":"

The MPXJ library allows various formats of Microsoft Project file formats, and file formats from other project planning applications to be read and written using a single consistent API in Java, .Net, Python or any other related languages, and provides read-only access as a Ruby gem.

MPXJ is based around a \"neutral\" data structure which is used to represent project data, coupled with a set of format-specific reader and writer classes which understand how to read from and write to the various supported file formats.

The diagram below illustrates the key entities represented by the MPXJ data structure.

MPXJ currently allows project data to be read from a wide variety of schedule file formats and databases. You can find details of the individual file formats supported elsewhere in the documentation. By far the easiest way to read schedule data is to use the \"universal project reader\" which can determine for itself the type of file you have passed to it.

ProjectReader reader = new UniversalProjectReader ();\nProjectFile project = reader.read(\"example.mpp\");\n

A similar arrangement exists for the writer classes, although there is not a \"universal project writer\" as such:

  • net.sf.mpxj.mpx.MPXWriter: writes Microsoft MPX files
  • net.sf.mpxj.mspdi.MSPDIWriter: writes Microsoft MSPDI (XML) files
  • net.sf.mpxj.planner.PlannerWriter: writes Planner (XML) files
  • net.sf.mpxj.sdef.SDEFWriter: writes SDEF files
  • net.sf.mpxj.primavera.PrimaveraPMFileWriter: writes Primavera PMXML (XML) files
  • net.sf.mpxj.json.JsonWriter: writes JSON files (primarily used to support the Ruby version of MPXJ)

All of these classes implement the ProjectWriter interface. If you know which type of file you are working with, you can use these writers directly, for example:

ProjectWriter writer = new MPXWriter();\nwriter.write(project, \"example.mpx\");\n
"},{"location":"howto-start/#tasks-and-resources","title":"Tasks and Resources","text":"

Once you've read your project file, what next? The first things of interest are the tasks and resources which are present in the file.

ProjectReader reader = new UniversalProjectReader ();\nProjectFile project = reader.read(\"example.mpp\");\nfor (Resource resource : project.getAllResources())\n{\n   System.out.println(\"Resource: \" + resource.getName()\n      + \" (Unique ID=\" + resource.getUniqueID() + \")\");\n}\n

The code fragment above shows how we can retrieve a collection containing all of the resources present in the file, and iterate through them printing the resource name, ID and unique ID.

Many of the entities represented in MPXJ have some concept of a unique ID. Tasks and resources have two ID fields, the unique ID, which as its name suggests never changes and uniquely identifies a task or a resource, and the ID. The ID of a task or a resource is the sequential number which typically appears next to the task or resource when displayed in Microsoft Project. If the task or resource is moved up or down the list, this number will change depending on the position in the list. The unique ID never changes.

ProjectReader reader = new UniversalProjectReader ();\nProjectFile project = reader.read(\"example.mpp\");\nfor (Task task : project.getAllTasks())\n{\n   System.out.println(\"Task: \" + task.getName() + \" ID=\" + task.getID()\n      + \" Unique ID=\" + task.getUniqueID());\n}\n

The code fragment above retrieves all tasks present in the file and prints details of their names, IDs, and unique IDs.

Methods are provided on the project to locate both tasks and resource using either their ID or their Unique ID, as the examples below illustrate.

Resource r = project.getResourceByUniqueID(Integer.valueOf(99));\nTask t = project.getTaskByUniqueID(Integer.valueOf(99));\n

The methods shown above for retrieving all tasks present in a project file ignores the hierarchical task structure which Microsoft Project allows users to create. To understand the hierarchical task structure, the following methods are used to descend through the hierarchy, starting from the top.

List<Task> tasks = project.getChildTasks();\nTask task = tasks.get(0);\ntasks = task.getChildTasks();\n

These methods are used in the following code fragment to print out an indented list representing the task hierarchy in the file.

public void listHierarchy(ProjectFile file)\n{\n   for (Task task : file.getChildTasks())\n   {\n      System.out.println(\"Task: \" + task.getName());\n      listHierarchy(task, \" \");\n   }\n\n   System.out.println();\n}\n\nprivate void listHierarchy(Task task, String indent)\n{\n   for (Task child : task.getChildTasks())\n   {\n      System.out.println(indent + \"Task: \" + child.getName());\n      listHierarchy(child, indent + \" \");\n   }\n}\n

As well as the hierarchical relationships between tasks, there is also a temporal relationship between them: this is typically used to indicate when a task can start in relation to the completion of an earlier task. The code fragment below shows the predecessor relationships between tasks.

for (Task task : file.getAllTasks())\n{\n   List<Relation> predecessors = task.getPredecessors();\n   if (predecessors != null && !predecessors.isEmpty())\n   {\n      System.out.println(task.getName() + \" predecessors:\");\n      for (Relation relation : predecessors)\n      {\n         System.out.println(\"   Task: \" + file.getTaskByUniqueID(relation.getTaskUniqueID()).getName());\n         System.out.println(\"   Type: \" + relation.getType());\n         System.out.println(\"   Lag: \" + relation.getDuration());\n      }\n   }\n}\n
"},{"location":"howto-start/#resource-assignments","title":"Resource Assignments","text":"

Tasks and resources are related by resource assignments. There is a method available on the ProjectFile class which will retrieve all resource assignments in the file. This is used by the code fragment below to provide an overview of all assignments.

for (ResourceAssignment assignment : file.getAllResourceAssignments())\n{\n   Task task = assignment.getTask();\n   String taskName;\n   if (task == null)\n   {\n      taskName = \"(null task)\";\n   }\n   else\n   {\n      taskName = task.getName();\n   }\n\n   Resource resource = assignment.getResource();\n   String resourceName;\n   if (resource == null)\n   {\n      resourceName = \"(null resource)\";\n   }\n   else\n   {\n      resourceName = resource.getName();\n   }\n\n   System.out.println(\"Assignment: Task=\" + taskName + \" Resource=\" + resourceName);\n}\n

Resource assignments can also be retrieved on a task-by-task basis, as the code fragment below illustrates.

for (Task task : file.getAllTasks())\n{\n  System.out.println(\"Assignments for task \" + task.getName() + \":\");\n\n  for (ResourceAssignment assignment : task.getResourceAssignments())\n  {\n     Resource resource = assignment.getResource();\n     String resourceName;\n\n     if (resource == null)\n     {\n        resourceName = \"(null resource)\";\n     }\n     else\n     {\n        resourceName = resource.getName();\n     }\n\n     System.out.println(\"   \" + resourceName);\n  }\n}\n

Finally, resource assignments can be viewed on a resource-by-resource basis, as the following code fragment shows.

for (Resource resource : file.getAllResources())\n{\n   System.out.println(\"Assignments for resource \" + resource.getName() + \":\");\n\n   for (ResourceAssignment assignment : resource.getTaskAssignments())\n   {\n      Task task = assignment.getTask();\n      System.out.println(\"   \" + task.getName());\n   }\n}\n
"},{"location":"howto-start/#calendars","title":"Calendars","text":"

Calendars are used to define working and non-working time, and are one of the more complex structures defined as part of a project. They are in turn used to define the time period over which a task is scheduled. There are two types of calendar: base calendars and resource calendars. Each base calendar provides a complete definition of the working and non working time for each day of the week. Resource calendars are associated with individual resources. Each resource calendar is derived from a base calendar; resource calendars may be unmodified in which case it will appear to be identical to the underlying base calendar, or the resource calendar may modify the working and non-working days. In this case these changes are \"overlaid\" on top of the working and non-working times defined by the base calendar. The calendars defined in a project can be retrieved using the method call shown below.

List<ProjectCalendar> calendars = file.getCalendars();\n

Normally a task without resource assignments will be scheduled with reference to the \"Standard\" (default) calendar defined as part of the project. This is retrieved using the method calls shown below.

ProjectCalendar defaultCalendar = file.getDefaultCalendar();\n

It is also possible to associate a specific calendar with an individual task. The method call below shows the calendar associated with a task being retrieved.

ProjectCalendar taskCalendar = task.getCalendar();\n

Bearing in mind that one calendar may be derived from another, care must be taken when choosing the methods called on a calendar instance: some methods are used to retrieve attributes defined as part of that specific calendar only, while others are used to descend through the hierarchy of calendars until an \"actual\" value is retrieved. For example the getDays method will retrieve an array of flags indicating the working/non-working/default state of each day of the week as defined by the current calendar. The getDay method however will test the current calendar to see if it is a working or non-working day. If the flag in the current calendar is set to \"default\", the method will use the base calendar from which the current calendar is derived to determine if the day is working or non-working.

As noted above a calendar contains a set of flags which represent each day of the week, these indicate the day of the week is working non-working, or \"default\". Where a day is set as \"default\", the working time for that day is taken from the underlying base calendar, if it is a resource calendar, or uses the default values provided by Microsoft Project if it is a base calendar.

If a particular day is defined as a working day, then the calendar will also contain a set of working hours for that day. The working hours for a day are defined by an instance of the ProjectCalendarHours class. This contains a collection of LocalTimeRange instances which defined the start and end times of each working period during the day.

Alongside the flags which control whether a day is working or non-working, and the working hours for each day, each calendar defines a set of exceptions which are used to \"override\" the default working or non-working hours for individual days or entire date ranges. Methods are provided to allow a list of all exceptions defined by a calendar can be retrieved, or to retrieve the exception which covers an individual date. Calendar exceptions are represented by instances of the ProjectCalendarException class.

"},{"location":"howto-start/#timephased-data","title":"Timephased Data","text":"

Although resource assignments on their own describe which resources are assigned to which tasks, and how much work they are going to do, this does not necessarily tell us how much work a resource will be doing on any particular date. In order to find this information, you will need to consult the timephased resource assignment data.

Each resource assignment has a pair of methods allowing you to retrieve timephased data, as shown by the example code below.

List<TimephasedResourceAssignment> planned = assignment.getTimephasedPlanned();\nList<TimephasedResourceAssignment> complete = assignment.getTimephasedComplete();\n

Timephased resource assignment data is represented by instances of the TimephasedResourceAssignment class. This class is designed to provide a compact representation of the work carried out over ranges of days, rather than having to represent the work carried out on each individual day using a single class instance per day. Each TimephasedResourceAssignment defines four attributes: a start date, an end date, a total amount of work, and an amount of work per day.

For example, you may retrieve an instance of the TimephasedResourceAssignment class whose start and end date defines a five day period. The total work for the period is 40 hours, and the work per day is defined as 8 hours. This indicates that for the period in question, on each working day within the date range, 8 hours of work will be carried out. It is important to remember that non-working days are ignored, so for example if we have a 7 day period which spans a weekend, the total work could still be 40 hours, and the work per day 8 hours: only the 5 working days are allocated work, the non-working weekend days have zero hours of work performed.

The two lists defined above will contain multiple TimephasedResourceAssignment instances where different numbers of hours are worked on different days. Each contiguous range of dates where the same number of hours are worked in a day will be represented by one TimephasedResourceAssignment instance.

The two lists of timephased data represent completed (actual) work, and planned work respectively. These lists may overlap by a single day if they are being used to show a partially completed day's work. For example, during a normal 8 hour working day, if 4 hours of work has been completed, and 4 hours remains, then the list of completed timephased data will end with 4 hours of work which have been completed, and the planned work list will start with the 4 hours remaining on the same day.

"},{"location":"howto-use-baselines/","title":"How To: Use Baselines","text":"

One tool to assist measuring how a schedule has changed over time is to create a baseline. A baseline is a snapshot of a schedule taken at a point in time: in the future you can compare the current state of your schedule to this snapshot to help understand what has changed.

"},{"location":"howto-use-baselines/#baselines","title":"Baselines","text":""},{"location":"howto-use-baselines/#microsoft-project","title":"Microsoft Project","text":"

Microsoft Project captures a baseline by taking copies of a small set of attributes for tasks, resources and resource assignments. The main attributes captured for each of these entities are Work, Cost, Duration, Start and Finish. These attributes can be stored as one of 11 distinct baselines: one called simply \"Baseline\", and the rest labelled \"Baseline 1\" through to \"Baseline 10\". If we pick Duration as an example attribute, the baseline value for this attribute might appear as \"Baseline Duration\", \"Baseline 1 Duration\", \"Baseline 2 Duration\" and so on, depending on which set of baseline attributes you had chosen to capture your snapshot.

Capturing a baseline in Microsoft Project is as simple as selecting the \"Set Baseline\" menu option for the current project you are working with to take a new baseline.

You'll be prompted to select which baseline you'd like to populate (\"Baseline\", \"Baseline 1\", \"Baseline 2\" and so on), and whether you'd like to baseline the whole project or just selected tasks.

When you click OK, the attributes captured for a baseline by Microsoft Project will be copied to the equivalent baseline attributes.

Note that the baseline attributes you have captured as part of this process have no special properties: they can be edited once they have been captured, and no recalculation takes place if they are edited (for example, if you change a baseline duration of a task, the baseline finish date of the task won't change).

"},{"location":"howto-use-baselines/#primavera-p6","title":"Primavera P6","text":"

The approach taken by Microsoft Project to managing baselines is unusual: most other scheduling applications take an approach similar to that used by Primavera P6, which is to take a complete copy of the schedule at the point a baseline is made, and thus any part of the baseline schedule is available in future to be compared with the current schedule. Let's look at baselines in P6 in a little more detail.

Baselines are managed in P6 in two stages. The first stage is actually to capture a baseline, which is achieved by selecting the \"Maintain Baselines...\" menu option.

The dialog which opens allows you to create, update, or delete a baseline.

When a baseline is taken, although it is simply a copy of an existing project, the baseline itself is not visible as a normal project in P6 so you can't view or, and more importantly for us, export it. The Maintain Baselines dialog includes the option of \"restoring\" a baseline, which turns the baseline back into a normal project which you can view or export.

Once you have a baseline, you then need to \"assign\" it in order to tell P6 what you want to do with it by selecting the \"Assign Baselines...\" menu option we saw earlier. This menu option will open a dialog similar to the one shown below.

As you can see from the dialog, P6 recognizes four distinct baseline types: the Project Baseline, and the Primary, Secondary and Tertiary User Baselines.

Note that the User Baselines are not visible outside of P6, i.e. information about which baselines are assigned as user baselines does not appear in either PMXML or XER files exported from P6.

In a similar way to Microsoft Project, P6 allows attributes from these baselines to be shown alongside information from the current schedule.

The dialog shown above is being used to select the columns to display in the tabular part of the Gantt chart in P6. As you can see there four start and finish attributes shown here, corresponding to the Project Baseline (for example BL Project Start) and the User Baselines (for example, BL1 Start, BL2 Start and BL3 Start).

There is a \"special case\" baseline, and a slightly obscure setting in P6 which determines exactly which values are shown in these columns. The \"special case\" baseline is where \"<Current Project>\" is selected as the baseline. This value doesn't represent a baseline which has been taken from the current project, but instead tells P6 that it should display the \"planned\" attributes from the current schedule in any baseline columns the user adds to the Gantt chart. So for example, if \"<Current Project>\" has been selected as the Project Baseline, then the values in the \"BL Project Start\" column on the Gantt chart will be the same as the values in the \"Planned Start\" column.

Where an actual baseline taken from the project has been assigned, then the values which will be shown in the baseline columns will depend on the \"Earned Value Calculation\" setting from the P6 Admin Preference dialog.

If the \"Earned value calculation\" setting is \"Budgeted values with planned dates\", then the Planned dates from the selected baseline schedule are used to populate the baseline attributes in the current schedule (for example, BL Project Start in the current schedule will be populated by the Planned Start value from the baseline schedule). If the \"Earned value calculation\" setting is NOT \"Budgeted values with planned dates\", then the current dates from the selected baseline schedule are used to populate the baseline attributes (for example, BL Project Start in the current schedule will be populated by the Start value from the baseline schedule).

It's important to note that the \"Earned Value Calculation\" setting is NOT available in either PMXML or XER files exported from P6, so when presenting schedule data from these files types to an end user outside of P6, there is no way to automatically determine which are the correct baseline values to be displayed.

"},{"location":"howto-use-baselines/#asta-powerproject","title":"Asta Powerproject","text":"

Powerproject takes the same approach as P6 to capturing a baseline - an entire copy of the schedule is made. This copy can either be held as a separate file, or can be embedded within the main schedule file (note the \"Embed the baseline in the file\" option in the dialog shown below).

MPXJ can read baselines which have been embedded within the main schedule file, although as you will see in a later section, with a little more work you can attach a baseline from a separate file to the main schedule.

"},{"location":"howto-use-baselines/#mpxj","title":"MPXJ","text":""},{"location":"howto-use-baselines/#microsoft-project_1","title":"Microsoft Project","text":"

Using MPXJ to work with baseline data from an MPP or MSPDI file is straightforward as any baseline values are available directly from the task, resource and resource assignment classes. The example below illustrates this by retrieving the Start attribute of a task, and some of the Baseline Start attributes.

ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\nTask task = file.getTaskByID(Integer.valueOf(1));\n\nSystem.out.println(\"Start: \" + task.getStart());\nSystem.out.println(\"Baseline Start: \" + task.getBaselineStart());\nSystem.out.println(\"Baseline1 Start: \" + task.getBaselineStart(1));\nSystem.out.println(\"Baseline2 Start: \" + task.getBaselineStart(2));\n\n// ...\n\nSystem.out.println(\"Baseline10 Start: \" + task.getBaselineStart(10));\n

When a baseline is taken in Microsoft Project, the date on which the baseline was taken is recorded. This can be used to indicate which baselines are set, and when they were set, although this data is only available from MPP file, not MSPDI files. The example code below illustrates how baseline dates can be used:

ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\nProjectProperties props = file.getProjectProperties();\n\nfor (int baselineNumber=0; baselineNumber <= 10; baselineNumber++)\n{\n   LocalDateTime baselineDate;\n   String baselineLabel;\n\n   if (baselineNumber == 0)\n   {\n      baselineDate = props.getBaselineDate();\n      baselineLabel = \"Baseline\";\n   }\n   else\n   {\n      baselineDate = props.getBaselineDate(baselineNumber);\n      baselineLabel = \"Baseline \" + baselineNumber;\n   }\n\n   if (baselineDate == null)\n   {\n      System.out.println(baselineLabel + \" not set\");\n   }\n   else\n   {\n      System.out.println(baselineLabel + \" set on \" + baselineDate);\n   }\n}\n
"},{"location":"howto-use-baselines/#primavera-p6_1","title":"Primavera P6","text":"

Getting baseline data for a P6 schedule is slightly more complex than for a Microsoft Project schedule.

The first thing to note is that XER files do not contain baseline data. XER files do include the ID of the Project Baseline schedule (via the ProjectProperties.getBaselineProjectUniqueID() method) but nothing more. Note that if the Project Baseline ID value is zero, this indicates that the Project Baseline selected in P6 is \"<Current Project>\". If this is the case, MPXJ will populate the attributes for the default baseline from the planned attributes (for example a task's Baseline Start will be set to the task's Planned Start attribute). This matches the behavior of P6 when \"<Current Project>\" is selected as the Project Baseline, and it the only time any form of baseline data will be available when reading an XER file.

The easiest way to get baseline data other than \"<Current Project>\" for a P6 schedule is to export a PMXML file. As part of the export process, the export dialog shows a column allowing baselines to be selected for export:

This opens a dialog for you to make the selection. Note that multiple baselines may be selected for export:

When a PMXML file is read all of the projects exported including any baselines will be available as ProjectFile instances from the readAll method.

List<ProjectFile> projects = new UniversalProjectReader().readAll(\"sample-pmxml.xml\");\nSystem.out.println(\"The file contains \" + projects.size() + \" projects\");\n

Alongside providing access to the current schedules and any baselines in the file, MPXJ will also apply the same \"<Current Project>\" logic to PMXML files as to XER files: so if the ProjectProperties.getBaselineProjectUniqueID() method returns zero, MPXJ will automatically populate the attributes of the default baseline using values from the equivalent planned attributes (for example a task's Baseline Start will be set to the task's Planned Start attribute).

Where PMXML files differ from XER files is that if the unique ID of one of the exported baselines matches the ID of the Project Baseline attribute from another project, MPXJ will link the two projects, populate the attributes of the default baseline in the main project using the equivalent planned attributes from the baseline project, and will set the default baseline date in the main project to the baseline project's create date.

To link the baseline MPXJ has actually attached the baseline ProjectFile instance to the main schedule using the ProjectFile.setBaseline() method. As well as begin able to work the populated baseline attributes in the main schedule, you also have direct access to the baseline ProjectFile instance, as illustrated by the sample code below:

ProjectFile project = new UniversalProjectReader().read(\"sample-pmxml.xml\");\nProjectFile baseline = project.getBaseline();\n\nSystem.out.println(\"Current project name: \" + project.getProjectProperties().getName());\nSystem.out.println(\"Baseline project name: \" + baseline.getProjectProperties().getName());\n

MPXJ's default behavior when attaching a baseline to a project follows what P6 does when the the \"Earned value calculation\" configuration is set to \"Budgeted values with planned dates\". As noted earlier this setting is not available in XER or PMXML files, so there is currently no way to automatically select the correct approach. You can however change MPXJ's default behavior by using the ProjectFile.setBaselineStrategy() method. BaselineStrategy is an interface implemented by classes which will implement the mechanism used to match equivalent tasks from the main ProjectFile instance with tasks from a baseline ProjectFile instance, and then populate the baseline attributes of the tasks in the main schedule with attributes from the matching tasks in the baseline schedule.

MPXJ provides baseline strategy implementations matching the two approaches taken by P6, depending on the \"Earned value calculation\". The default strategy is represented by the constant PrimaveraBaselineStrategy.PLANNED_ATTRIBUTES, with the alternative approach represented by the constant PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES. The sample code below illustrates how this constant is used to alter MPXJ's behavior to match P6 when the earned value setting is not \"Budgeted values with planned dates\".

PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\nreader.setBaselineStrategy(PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES);\nProjectFile file = reader.read(\"sample-pmxml.xml\");\n
"},{"location":"howto-use-baselines/#asta-powerproject_1","title":"Asta Powerproject","text":"

When reading an Asta Powerproject schedule MPXJ will read the main schedule, and if defined and embedded in the main schedule file, the current baseline schedule. MPXJ will populate the attributes of the default baseline in the main project using the equivalent attributes from the baseline project, and will set the default baseline date in the main project to the baseline project's create date.

Note that at present MPXJ does not read all available baselines from a Powerproject schedule. Feedback welcomed if the ability to read all baselines is desirable.

ProjectFile project = new UniversalProjectReader().read(\"sample.pp\");\nProjectFile baseline = project.getBaseline();\n\nSystem.out.println(\"Current project name: \" + project.getProjectProperties().getName());\nSystem.out.println(\"Baseline project name: \" + baseline.getProjectProperties().getName());\n
"},{"location":"howto-use-baselines/#manually-attached","title":"Manually Attached","text":"

As we saw in the previous section, MPXJ can attach a baseline ProjectFile instance to the main project, and populate the relevant baseline attributes in the main project. MPXJ will actually allow you to explicitly attach up to 11 baseline projects to a main project. Each project attached in this way will be used to populate the relevant baseline attributes (for example, Baseline Start, Baseline 1 Start, Baseline 2 Start, ... Baseline 10 Start). The limit of 11 attached baselines follows Microsoft Project's data model which allows up to 11 baselines to be recorded.

In this first example we can see that we are reading a main project and a single baseline file, and attaching the baseline as the \"default\" baseline. This means that attributes like Baseline Start, Baseline Finish and so on will be populated in the main schedule.

ProjectFile main = new UniversalProjectReader().read(\"main.pp\");\nProjectFile baseline = new UniversalProjectReader().read(\"baseline.pp\");\nmain.setBaseline(baseline);\n

This next example shows two baseline files being attached as Baseline 1 and Baseline 2, which means that the attributes Baseline 1 Start, Baseline 2 Start, Baseline 1 Finish, Baseline 2 Finish and so on will be populated.

ProjectFile main = new UniversalProjectReader().read(\"main.pp\");\nProjectFile baseline1 = new UniversalProjectReader().read(\"baseline1.pp\");\nProjectFile baseline2 = new UniversalProjectReader().read(\"baseline2.pp\");\nmain.setBaseline(baseline1, 1);\nmain.setBaseline(baseline2, 2);\n

You can retrieve a list of all attached baselines using the ProjectFile.getBaselines() method. Note that the returned list will always contain 11 items, some of which may be null if the corresponding baseline has not been set. You can also remove a baseline from the current schedule using one of the ProjectFile.clearBaseline() methods.

"},{"location":"howto-use-baselines/#baseline-tasks","title":"Baseline Tasks","text":"

As described above, when working with applications which store baselines as separate copies of the main schedule, MPXJ populates a set of baseline attributes on the Task class. For example Baseline Duration, Baseline Cost and so on will be populated from tasks in the linked baseline schedule. This aligns with how Microsoft Project works, and although in many cases these attributes provide enough information to be useful, there are still occasions when it would be best to have direct access to the baseline task from the original task. You are not then restricted by the baseline attributes provided by MPXJ, instead you can compare the two tasks in any way you choose.

Providing your ProjectFile instance has come from a file or database which includes a copy of the baseline schedule, or you have manually attached a baseline schedule to the ProjectFile instance, you can use the Task.getBaselineTask() methods to retrieve the baseline task for the current Task instance, as illustrated below.

ProjectFile project = new UniversalProjectReader().read(\"project-with-baseline.xml\");\nTask task = project.getTaskByUniqueID(1);\nTask baselineTask = task.getBaselineTask();\n

Note that if no baseline task is present for the task you are working with, the Task.getBaselineTask() methods will return null. This will always be the case for MPP files as Microsoft Project doesn't keep a separate copy of the baseline schedule.

"},{"location":"howto-use-baselines/#strategies","title":"Strategies","text":"

In an earlier section the use of baseline strategies was noted. Classes which implement the BaselineStrategy interface are used to control how tasks in the main and baseline schedule are matched, and which attributes are used to populate the relevant baseline attributes.

MPXJ provides three implementations of the BaselineStrategy interface:

  • DefaultBaselineStrategy
  • AstaBaselineStrategy
  • PrimaveraBaselineStrategy

The DefaultBaselineStrategy matches tasks based on their GUID attribute, and populates the main schedule's baseline attributes from their equivalent attributes in the baseline schedule, for example, Baseline Duration will be populated using the Duration attribute in the baseline schedule and so on. You don't need to create new instances of this strategy as static instance is provided as DefaultBaselineStrategy.INSTANCE.

The AstaBaselineStrategy matches tasks based on their Unique ID attribute, and populates the main schedule's baseline attributes from their equivalent attributes in the baseline schedule, for example, Baseline Duration will be populated using the Duration attribute in the baseline schedule and so on. You can't create new instances of this strategy, instead use the static instance provided by AstaBaselineStrategy.INSTANCE.

Finally the PrimaveraBaselineStrategy matches tasks based on their Activity ID. Two variants of the strategy are provided as PrimaveraBaselineStrategy.PLANNED_ATTRIBUTES and PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES. The PLANNED_ATTRIBUTES instance, as the name suggests, uses the planned attributes from the baseline schedule to populate the baseline attributes in the main schedule, and the CURRENT_ATTRIBUTES instance uses the current attributes from the baseline schedule to populate the baseline attributes in the main schedule (for example, Baseline Duration in the main schedule is populated using the Duration attribute in the baseline schedule).

When using the MPXJ reader classes, the correct strategy for the specific schedule type you are reading is selected for you. If you need behavior which differs from one of the defaults you can provide your own BaselineStrategy implementation. Where the reader class is automatically attaching baselines to the main schedule, you can pass an instance of your strategy class to the reader:

BaselineStrategy myStrategy = new MyBaselineStrategy();\nPrimaveraPMFileReader reader = new PrimaveraPMFileReader();\nreader.setBaselineStrategy(myStrategy);\nProjectFile file = reader.read(\"sample-pmxml.xml\");\n

If you are reading the main and baseline schedules separately, you can set the baseline strategy on the main schedule, and this will be used when each baseline schedule is attached:

BaselineStrategy myStrategy = new MyBaselineStrategy();\nProjectFile main = new UniversalProjectReader().read(\"main.pp\");\nmain.getProjectConfig().setBaselineStrategy(myStrategy);\n\nProjectFile baseline1 = new UniversalProjectReader().read(\"baseline1.pp\");\nProjectFile baseline2 = new UniversalProjectReader().read(\"baseline2.pp\");\nmain.setBaseline(baseline1, 1);\nmain.setBaseline(baseline2, 2);\n
"},{"location":"howto-use-calendars/","title":"How To: Use Calendars","text":"

Calendars are the foundation on which schedules are built. They determine when work can be carried out, and when work is not possible. Given some tasks we need to plan, and knowing how much work each task will require, a calendar can be used to decide when work on each task could start and how much elapsed time will be required to complete the tasks.

"},{"location":"howto-use-calendars/#calendars-in-mpxj","title":"Calendars in MPXJ","text":"

Let's see how calendars work in MPXJ. First let's try creating one. As it happens, the ProjectFile class provides a convenience method addDefaultBaseCalendar to create a default calendar. The calendar it creates is modelled on the Standard calendar you'd see in Microsoft Project if you created a new project. This default calendar defines Monday to Friday as working days, with 8 working hours each day (8am to noon, then 1pm to 5pm).

ProjectFile file = new ProjectFile();\nProjectCalendar calendar = file.addDefaultBaseCalendar();\nSystem.out.println(\"The calendar name is \" + calendar.getName());\n

As you can see from the code above, the calendar also has a name which we can set to distinguish between different calendars.

"},{"location":"howto-use-calendars/#working-days","title":"Working Days","text":"

Let's see what the calendar can tell us. First we'll use the DayOfWeek enumeration to retrieve the working/non-working state for each day.

for (DayOfWeek day : DayOfWeek.values()) {\n   String dayType = calendar.getCalendarDayType(day).toString();\n   System.out.println(day + \" is a \" + dayType + \" day\");\n}\n

Running the code shown above will produce output like this:

MONDAY is a WORKING day\nTUESDAY is a WORKING day\nWEDNESDAY is a WORKING day\nTHURSDAY is a WORKING day\nFRIDAY is a WORKING day\nSATURDAY is a NON_WORKING day\nSUNDAY is a NON_WORKING day\n

We can use the setWorkingDay method to change our pattern of working day. Let's make Saturday a working day for our team, and make Monday a non-working day to compensate.

calendar.setWorkingDay(DayOfWeek.SATURDAY, true);\ncalendar.setWorkingDay(DayOfWeek.MONDAY, false);\n

Now if we use the loop we saw previously to inspect the week days, we'll see this output:

MONDAY is a NON_WORKING day\nTUESDAY is a WORKING day\nWEDNESDAY is a WORKING day\nTHURSDAY is a WORKING day\nFRIDAY is a WORKING day\nSATURDAY is a WORKING day\nSUNDAY is a NON_WORKING day\n
"},{"location":"howto-use-calendars/#working-hours","title":"Working Hours","text":"

So far, all we have done is set a flag which tells us whether a day is working or non-working. How do we know the working times on those days? We can use the getCalendarHours method to find that information.

The getCalendarHours method returns a List of LocalTimeRange instances. LocalTimeRange is a simple immutable class which represents a span of time between a start time and an end time as an inclusive range. Let's try printing these LocalTimeRange instances to our output to see what we get:

List<LocalTimeRange> hours = calendar.getCalendarHours(DayOfWeek.TUESDAY);\nhours.forEach(System.out::println);\n

Here's the output:

[LocalTimeRange start=08:00 end=12:00]\n[LocalTimeRange start=13:00 end=17:00]\n

Let's add a method to format the hours of a day a little more concisely for display:

private String formatLocalTimeRanges(List<LocalTimeRange> hours) {\n   return hours.stream()\n      .map(h -> h.getStart() + \"-\" + h.getEnd())\n      .collect(Collectors.joining(\", \"));\n}\n

So now our output looks like this:

08:00-12:00, 13:00-17:00\n

Let's use this method to take a look at the whole week again:

for (DayOfWeek day : DayOfWeek.values()) {\n   String dayType = calendar.getCalendarDayType(day).toString();\n   System.out.println(day\n      + \" is a \" + dayType + \" day (\"\n      + formatLocalTimeRanges(calendar.getCalendarHours(day)) + \")\");\n}\n

Here's the output:

MONDAY is a NON_WORKING day ()\nTUESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nWEDNESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nTHURSDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nFRIDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nSATURDAY is a WORKING day ()\nSUNDAY is a NON_WORKING day ()\n

The one thing we're missing now is that although we have set Saturday to be a working day, it doesn't have any working hours. MPXJ has some constants which can be used to help us add some working hours:

hours = calendar.getCalendarHours(DayOfWeek.SATURDAY);\nhours.add(ProjectCalendarDays.DEFAULT_WORKING_MORNING);\nhours.add(ProjectCalendarDays.DEFAULT_WORKING_AFTERNOON);\n

Now when we examine our week this is what we see:

MONDAY is a NON_WORKING day ()\nTUESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nWEDNESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nTHURSDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nFRIDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nSATURDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nSUNDAY is a NON_WORKING day ()\n

The version of MPXJ at the time of writing (12.0.0) has a limitation that if setCalendarDayType is used to make a day into a working day, we don't automatically add working hours for it. This behaviour is likely to change with the next major version of MPXJ.

What if we want to supply some working hours different from the defaults we've used so far? To set our own working hours we just need to create as many LocalTimeRange instances as we need using a pair of LocalTime instances for each one to represent the start and end times.

LocalTime startTime = LocalTime.of(9, 0);\nLocalTime finishTime = LocalTime.of(14, 30);\nhours = calendar.getCalendarHours(DayOfWeek.SATURDAY);\nhours.clear();\nhours.add(new LocalTimeRange(startTime, finishTime));\n

Now when we look at the working hours for Saturday, this is what we see:

SATURDAY is a WORKING day (09:00-14:30)\n

Now we've seen how we can create our own ranges of working time for a day, let's tackle a slightly more challenging case: dealing with midnight. Our first step is to take a look at the actual amount of working time we've set up on Saturday. To do this we call the getWork method, as shown below.

Duration duration = calendar.getWork(DayOfWeek.SATURDAY, TimeUnit.HOURS);\nSystem.out.println(duration);\n

This getWork method determines the total amount of work on the given day, and returns this in the format we specify. In this case we've asked for hours, and we'll be receiving the result as a Duration object. Duration simply combines the duration amount with an instance of the TimeUnit enumeration so we always know the units of the duration amount.

Running the code above give us this output:

5.5h\n

As you can see, the toString method of Duration give us a nicely formatted result, complete with an abbreviation for the units.

Let's try to change Saturday to be 24 hour working. First we'll configure a midnight to midnight date range:

startTime = LocalTime.MIDNIGHT;\nfinishTime = LocalTime.MIDNIGHT;\nhours.clear();\nhours.add(new LocalTimeRange(startTime, finishTime));\nSystem.out.println(formatLocalTimeRanges(calendar.getCalendarHours(DayOfWeek.SATURDAY)));\n

This looks reasonable:

00:00-00:00\n

Now let's see how much work this represents:

duration = calendar.getWork(DayOfWeek.SATURDAY, TimeUnit.HOURS);\nSystem.out.println(duration);\n
24.0h\n

So we have our 24 hours of work on Saturday!

"},{"location":"howto-use-calendars/#exceptions","title":"Exceptions","text":"

After working a few of these 24 hour days on Saturdays, we might be in need of a vacation! How can we add this to our calendar?

So far we've been working with the DayOfWeek class to make changes to days of the week, rather than any specific date. Now we'll need to work with a specific date, and add an \"exception\" for this date. The terminology here can be slightly confusing when coming from a programming background, but the term exception is often used by scheduling applications in the context of making ad-hoc adjustments to a calendar.

LocalDate exceptionDate = LocalDate.of(2022, 5, 10);\n\nboolean workingDate = calendar.isWorkingDate(exceptionDate);\nSystem.out.println(exceptionDate + \" is a \"\n   + (workingDate ? \"working\" : \"non-working\") + \" day\");\n

In the code above we're creating a LocalDate instance to represent the date we want to add an exception for. The code uses the isWorkingDate method to determine whether or not the given date is a working day. Before we add the exception, here's the output we get:

2022-05-10 is a working day\n

Now we can create our exception.

ProjectCalendarException exception = calendar.addCalendarException(exceptionDate);\nexception.setName(\"A day off\");\n

The code above illustrates adding an exception for a single day. The code above also shows that optionally an exception can be named, this can make it easier to understand the purpose of each exception. Now if we re-run our code which displays whether our chosen date is a working day, this is what we see:

2022-05-10 is a non-working day\n

We have successfully added an exception to turn this date into a day off!

Perhaps we were being a little too generous in giving ourselves the entire day off, perhaps in this case we should make this a half day instead. To do that, we just need to add a time range to the exception:

startTime = LocalTime.of(8, 0);\nfinishTime = LocalTime.of(12, 0);\nexception.add(new LocalTimeRange(startTime, finishTime));\n

Now if we look at our chosen date, this is what we see:

2022-05-10 is a working day\n

Let's take a closer look at what's happening on that day:

System.out.println(\"Working time on Tuesdays is normally \"\n   + calendar.getWork(DayOfWeek.TUESDAY, TimeUnit.HOURS) + \" but on \"\n   + exceptionDate + \" it is \"\n   + calendar.getWork(exceptionDate, TimeUnit.HOURS));\n

The code above shows how we use the getWork method which takes a DayOfWeek as an argument to look at what the default working hours are on a Tuesday, then we use the getWork method which takes a LocalDate instance as an argument to see what's happening on the specific Tuesday of our exception. Here's the output we get:

Working time on Tuesdays is normally 8.0h but on 2022-05-10 it is 4.0h\n

We can see the effect of adding a LocalTimeRange to our exception: we've gone from an exception which changes a working day into a non-working day to an exception which just changes the number of working hours in the day. This same approach can be used to change a date which falls on a day that's typically non-working (for example a Sunday) into a working day, just by adding an exception with some working hours.

We can also use a single exception to affect a number of days. First let's write a little code to see the number of working hours over a range of days:

private void dateDump(ProjectCalendar calendar, LocalDate startDate, LocalDate endDate)\n{\n   for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1)) {\n      System.out.println(date + \"\\t\" + calendar.getWork(date, TimeUnit.HOURS));\n   }\n   System.out.println();\n}\n

Running this code with our calendar as its stands produces this output for the example week we're using:

2022-05-23  0.0h\n2022-05-24  8.0h\n2022-05-25  8.0h\n2022-05-26  8.0h\n2022-05-27  8.0h\n

Let's add an exception which covers Tuesday to Thursday that week (24th to 26th), and changes the working hours, so there are now only four hours of work per day (9am to 12pm):

LocalDate exceptionStartDate = LocalDate.of(2022, 5, 24);\nLocalDate exceptionEndDate = LocalDate.of(2022, 5, 26);\nexception = calendar.addCalendarException(exceptionStartDate, exceptionEndDate);\nstartTime = LocalTime.of(9, 0);\nfinishTime = LocalTime.of(13, 0);\nexception.add(new LocalTimeRange(startTime, finishTime));\n

Here we can see that we're using a different version of the addCalendarException method which takes a start and an end date, rather that just a single date. Running our code again to print out the working hours for each day now gives us this output:

2022-05-23  0.0h\n2022-05-24  4.0h\n2022-05-25  4.0h\n2022-05-26  4.0h\n2022-05-27  8.0h\n

As we can see, we've changed multiple days with this single exception.

"},{"location":"howto-use-calendars/#working-weeks","title":"Working Weeks","text":"

So far we've looked at using ProjectCalendarException, which can make one change (add working hours, change working hours, or make days non-working) and apply that change to one day or a contiguous range of days. What if we want to make more complex changes to the working pattern of a calendar?

Let's imagine that our project has a three week \"crunch\" period at the beginning of October where we will need to work 16 hour days, Monday through Friday, and 8 hour days at weekends. (I hope this is a fictional example and you'd don't have to work at such a high intensity in real life!). We could construct this work pattern using exceptions: we'd need six in total, one for each of the three sets of weekend days, and one for each of the three sets of week days.

An alternative way to do this is to set up a new working week, using the ProjectCalendarWeek class. \"Working Week\" is perhaps a slightly misleading name, as a ProjectCalendarWeek can be set up for an arbitrary range of dates, from a few days to many weeks. What it represents is the pattern of working an non-working time over the seven days of a week, and this pattern is applied from the start to the end of the date range we configure.

The ProjectCalendar we've been working with so far is actually already a form of working week (they share a common parent class). The main differences between the two are that a ProjectCalendarWeek allows us to specify the range of dates over which it is effective, and a ProjectCalendarWeek does not have exceptions: exceptions are only added to a ProjectCalendar.

For a fresh start, we'll create a new ProjectCalendar instance. With this we'll add a new working week definition and give it a name, to make it easily identifiable. Now we'll set the dates for which this work pattern is valid (in this case the first three weeks of October). Finally we mark every day as a working day. Here's how our example looks in code:

LocalDate weekStart = LocalDate.of(2022, 10, 1);\nLocalDate weekEnd = LocalDate.of(2022, 10, 21);\ncalendar = file.addDefaultBaseCalendar();\nProjectCalendarWeek week = calendar.addWorkWeek();\nweek.setName(\"Crunch Time!\");\nweek.setDateRange(new LocalDateRange(weekStart, weekEnd));\nArrays.stream(DayOfWeek.values()).forEach(d -> week.setWorkingDay(d, true));\n

Next we can set up our weekend 9am to 5pm working pattern:

startTime = LocalTime.of(9, 0);\nfinishTime = LocalTime.of(17, 0);\nLocalTimeRange weekendHours = new LocalTimeRange(startTime, finishTime);\nStream.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)\n   .forEach(d -> week.addCalendarHours(d).add(weekendHours));\n

Finally we can set up our weekday 5am to 9pm pattern:

startTime = LocalTime.of(5, 0);\nfinishTime = LocalTime.of(21, 0);\nLocalTimeRange weekdayHours = new LocalTimeRange(startTime, finishTime);\nStream.of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY,\n      DayOfWeek.THURSDAY, DayOfWeek.FRIDAY)\n   .forEach(d -> week.addCalendarHours(d).add(weekdayHours));\n

As ProjectCalendar and ProjectCalendarWeek are both derived from the same parent class, we can use the same code we did previously to examine how our new ProjectCalendarWeek instance looks:

MONDAY is a WORKING day (05:00-21:00)\nTUESDAY is a WORKING day (05:00-21:00)\nWEDNESDAY is a WORKING day (05:00-21:00)\nTHURSDAY is a WORKING day (05:00-21:00)\nFRIDAY is a WORKING day (05:00-21:00)\nSATURDAY is a WORKING day (09:00-17:00)\nSUNDAY is a WORKING day (09:00-17:00)\n

To see the effect that our new working week has had on the calendar, let's first take a look at the week running up to the start of our crunch period. Using the same code we worked with previously to present working hours for a range of dates we see this output:

2022-09-24  0.0h\n2022-09-25  0.0h\n2022-09-26  8.0h\n2022-09-27  8.0h\n2022-09-28  8.0h\n2022-09-29  8.0h\n2022-09-30  8.0h\n

So starting from Saturday 24th we can see that we have that standard working pattern: weekends are non-working (zero working hours), and week days have 8 hours of working time.

Now let's look at the first week of our crunch period:

2022-10-01  8.0h\n2022-10-02  8.0h\n2022-10-03  16.0h\n2022-10-04  16.0h\n2022-10-05  16.0h\n2022-10-06  16.0h\n2022-10-07  16.0h\n

We can see that the crunch is in full effect, we're working 8 hour days at the weekend, and 16 hour days for the rest of the week - not something I'd like to try for any length of time!

To summarise: the ProjectCalendar instance itself defines the default working and non-working pattern for the seven week days. Additional working weeks can be added to the calendar which override this pattern for specific date ranges.

"},{"location":"howto-use-calendars/#recurring-exceptions","title":"Recurring Exceptions","text":"

So far we've seen how exceptions can be used to override the default working pattern established by a calendar for either a single day, or for a contiguous range of days. We've also seen how an entirely new seven-day working pattern can be applied across a range of dates by using working weeks. But what if we want to represent a regularly occurring exception which will change our default working pattern such as, for example, Christmas Day or Thanksgiving? To deal with this we can use recurring exceptions.

A recurring exception can be created simply by passing an instance of RecurringData to the addCalendarException method.

RecurringData recurringData = new RecurringData();\nexception = calendar.addCalendarException(recurringData);\n

Let's create a simple recurence for 1st January for five years:

recurringData.setRecurrenceType(RecurrenceType.YEARLY);\nrecurringData.setOccurrences(5);\nrecurringData.setDayNumber(Integer.valueOf(1));\nrecurringData.setMonthNumber(Integer.valueOf(1));\nrecurringData.setStartDate(LocalDate.of(2023, 1, 1));\nSystem.out.println(recurringData);\n

The toString method on the RecurringData class tries to describe the recurrence as best it can, here's the output we'll see from the code above:

[RecurringData Yearly on the 1 January From 2023-01-01 For 5 occurrences]\n

The example above shows a very simple configuration. Full details of how to use RecurringData are provided elsewhere as they are beyond the scope of this section.

Before we move on from recurring exceptions, one useful feature of the ProjectCalendarException class is the getExpandedExceptions method. This will convert a recurring exception into a list of individual exceptions representing each date or range of dates the recurring exception will affect the calendar. You may find this useful if you need to display or pass this data on for consumption elsewhere.

"},{"location":"howto-use-calendars/#calendar-hierarchies","title":"Calendar Hierarchies","text":"

Now we've seen how to set up an individual calendar, perhaps we could go ahead and create calendars for all of the people who will be working on our project? What we'd quickly find is that a considerable amount of the information in each calendar will be the same: the same working week pattern, the same public holidays and so on. We could set all of this up programmatically of course, but wouldn't it be great if we could change this kind of detail in just one place, and have all of our other calendars inherit it?

"},{"location":"howto-use-calendars/#creating-a-calendar-hierarchy","title":"Creating a Calendar Hierarchy","text":"

As it happens, we can do this as our calendars can be organised into a hierarchy, with each \"child\" calendar inheriting its configuration from a \"parent\" calendar and overriding that configuration as required rather like a class hierarchy in a programing language). This will allow us to have one shared \"base\" calendar for everyone, with derived calendars used for individuals on our team where we need to add variation, for example personal vacation time and so on.

ProjectFile file = new ProjectFile();\nProjectCalendar parentCalendar = file.addDefaultBaseCalendar();\nLocalDate christmasDay = LocalDate.of(2023, 12, 25);\nparentCalendar.addCalendarException(christmasDay);\n

In the example above we've used the familiar addDefaultBaseCalendar method to create a simple calendar, and called addCalendarException to add an exception for Christmas Day 2023.

ProjectCalendar childCalendar = file.addDefaultDerivedCalendar();\nchildCalendar.setParent(parentCalendar);\nSystem.out.println(christmasDay + \" is a working day: \"\n   + childCalendar.isWorkingDate(christmasDay));\n

Now we've created childCalendar, using a method we've not seen before, addDefaultBaseCalendar (we'll talk about this method in more detail in a minute), and we've used the new calendar's setParent method to attach parentCalendar as its parent. We can see the effect of this when we check to see if Christmas Day 2023 is a working day. This is a Monday so by default it will be a working day, but as childCalendar is inheriting from parentCalendar it picks up the exception defined in parentCalendar and makes Christmas Day a non-working day.

Here's the output when our code is executed:

2023-12-25 is a working day: false\n

We can also do the same thing with day types:

parentCalendar.setCalendarDayType(DayOfWeek.TUESDAY, DayType.NON_WORKING);\nSystem.out.println(\"Is \" + DayOfWeek.TUESDAY + \" a working day: \"\n   + childCalendar.isWorkingDay(DayOfWeek.TUESDAY));\n

In the example above we've set Tuesday to be a non-working day in the parent calendar, and we can see that this is inherited by the child calendar. Here's the output we see when we execute our code:

Is TUESDAY a working day: false\n

So what's special about the \"derived calendar\" we've just created (childCalendar), why is it different to the normal calendar, and what's the difference between the addDefaultBaseCalendar and addDefaultDerivedCalendar methods?

The answer to this question lies in the DayType enumeration. Let's take a look at the day types for parentCalendar.

SUNDAY is a NON_WORKING day\nMONDAY is a WORKING day\nTUESDAY is a NON_WORKING day\nWEDNESDAY is a WORKING day\nTHURSDAY is a WORKING day\nFRIDAY is a WORKING day\nSATURDAY is a NON_WORKING day\n

So far so good, we have a mixture of working an non-working days, and we can see that as part of our last example we set Tuesday to be a non-working day. Now let's take a look at childCalendar:

SUNDAY is a DEFAULT day\nMONDAY is a DEFAULT day\nTUESDAY is a DEFAULT day\nWEDNESDAY is a DEFAULT day\nTHURSDAY is a DEFAULT day\nFRIDAY is a DEFAULT day\nSATURDAY is a DEFAULT day\n

Ah-ha! Here we can see that the DayType enumeration actually has a third value alongside WORKING and NON_WORKING: DEFAULT. The DEFAULT value simply means that we should inherit the parent calendar's settings for this particular day: so whether the day is working, non-working, what the working hours are, and so on.

We can override the day type we're inheriting from the base calendar:

childCalendar.setCalendarDayType(DayOfWeek.TUESDAY, DayType.WORKING);\nLocalTime startTime = LocalTime.of(9, 0);\nLocalTime finishTime = LocalTime.of(12, 30);\nchildCalendar.addCalendarHours(DayOfWeek.TUESDAY)\n   .add(new LocalTimeRange(startTime, finishTime));\n

In the code above we're explicitly setting Tuesday to be a working day, rather than inheriting the settings for Tuesday from the parent calendar, then we're adding the working hours we want for Tuesday.

Earlier we said we come back and look at the addDefaultDerivedCalendar method in a little more detail. The main difference between addDefaultDerivedCalendar and addDefaultBaseCalendar is that the calendar created by addDefaultDerivedCalendar has no working hours defined, and all day types are set to DEFAULT so everything is inherited from the parent calendar.

"},{"location":"howto-use-calendars/#working-with-a-calendar-hierarchy","title":"Working with a Calendar Hierarchy","text":"

In general when working with a calendar hierarchy, if we use a calendar to determine working/non-working time, working hours, and so on for a given date, anything configured in a child calendar will always override what we find in the parent calendar. So for example if we have exceptions or working weeks configured in a child calendar, these will override anything found in a parent calendar.

If we're asking the calendar a question about a particular day (rather than a date), for example Monday, Tuesday and so on, we'll use information from the child calendar if the day type is WORKING or NON_WORKING, otherwise we'll work our way up the calendar hierarchy until we find the first ancestor calendar which does not specify the day type as DEFAULT, and we'll use the configuration for the day in question from that calendar.

This brings us on to an interesting question: how do we know if we ask the calendar for a piece of information, whether that's come from the calendar whose method we've just called, or if the response we've received has come from another calendar somewhere further up the calendar hierarchy?

As it happens there are only a small number of attributes for which this is relevant. These are summarised by the table below.

Attribute Set Get Get with Hierarchy Day Type setCalendarDayType getCalendarDayType getDayType Hours addCalendarHours getCalendarHours getHours Minutes Per Day setCalendarMinutesPerDay getCalendarMinutesPerDay getMinutesPerDay Minutes Per Week setCalendarMinutesPerWeek getCalendarMinutesPerWeek getMinutesPerWeek Minutes Per Month setCalendarMinutesPerMonth getCalendarMinutesPerMonth getMinutesPerWeek Minutes Per Year setCalendarMinutesPerYear getCalendarMinutesPerYear getMinutesPerYear

The first column give us the name of the attribute, and the second column give the name of the method we'd call to set that attribute for the current calendar. The third column gives us the name of the method we'd use to retrieve the attribute from the current calendar only (i.e this will ignore any parent calendars). Finally the last column gives us the name of the method we'd call to retrieve the attribute from the current calendar, or inherit that attribute from a parent calendar if it is not present in the current calendar.

We haven't looked at the Minutes Per X attributes so far. The values they contain are used when calculating working time. One interesting point to note is that if no calendars in a hierarchy define these values the default values will be retrieved from from the ProjectFile configuration, which is represented by the ProjectConfig class.

"},{"location":"howto-use-calendars/#how-deep-is-your-hierarchy","title":"How deep is your Hierarchy?","text":"

MPXJ will allow you to create an arbitrarily deep hierarchy of calendars if you wish by establishing parent-child relationships between the calendars you create. Most schedule application file formats will only support a limited hierarchy of calendars, which you will see when you read files of this type when using MPXJ. The notes below briefly outlines how calendar hierarchies operate in some of the applications MPXJ can work with.

If you are using MPXJ to create or modify schedule data, when you write the results to a file MPXJ will attempt to ensure that the calendars it writes to the file format you have chosen reflect what the target application is expecting. This means that MPXJ may end up \"flattening\" or otherwise simplifying a set of calendars and their hierarchy to ensure that they are read correctly by the target application and are \"functionally equivalent\" in use.

"},{"location":"howto-use-calendars/#microsoft-project","title":"Microsoft Project","text":"

Microsoft Project uses two tiers of calendars. The first tier of calendars are referred to as \"base calendars\", one of which is marked as the default calendar for the project. Work is scheduled based on the default calendar, unless a task explicitly selects a different base calendar to use when being scheduled, or resources with their own calendars have been assigned to the task. Each resource will have its own calendar, which is always derived from a base calendar.

Note that, as you might expect, material resources don't have a calendar!

"},{"location":"howto-use-calendars/#primavera-p6","title":"Primavera P6","text":"

The situation with P6 is a little more complicated, although it's still a two tier arrangement. P6 has the concept of Global calendars (broadly similar to base calendars in Microsoft Project). These can be assigned to activities in any project. Global calendars are never derived from other calendars.

You can also have Project calendars which, as their name suggests, can only be assigned to activities in the project to which they belong. Project calendars can be derived from a Global Calendar, or they can have no parent calendar.

Finally you can have two types of resource calendar: Shared, or Personal. These can either be derived from a Global calendar, or can have no parent. A Shared resource calendar can be assigned to multiple resources, but a Personal resource calendar can only be assigned to a single resource.

When reading a P6 schedule, the ProjectCalendar method getType can be used to retrieve the calendar type (Global, Shared, or Personal), while the getPersonal method returns a Boolean flag indicating if the calendar is a Personal resource calendar.

"},{"location":"howto-use-calendars/#others","title":"Others","text":"

ConceptDraw, Planner, SureTrak and TurboProject all support some form of calendar hierarchy, although Planner is the only one which definitely supports an arbitrarily deep nested calendar structure.

"},{"location":"howto-use-calendars/#calendar-container","title":"Calendar Container","text":"

So far we've looked at creating and configuring calendars, and lining them together in a hierarchy. If we've just read a schedule in from a file, how can we examine the calendars it contains? Let's set up some calendars and take a look:

ProjectFile file = new ProjectFile();\nProjectCalendar calendar1 = file.addCalendar();\ncalendar1.setName(\"Calendar 1\");\n\nProjectCalendar calendar2 = file.addCalendar();\ncalendar2.setName(\"Calendar 2\");\n\nProjectCalendar calendar3 = file.addCalendar();\ncalendar3.setName(\"Calendar 3\");\n

Our sample code above creates three calendars, each with a distinct name. To see what calendars our file contains we can use the ProjectFile method getCalendars:

file.getCalendars().forEach(c -> System.out.println(c.getName()));\n

Which gives us the following output, as we'd expect:

Calendar 1\nCalendar 2\nCalendar 3\n

The getCalendars method returns an object which implements the List<ProjectCalendar> interface, but it also does more for us than just that. The actual object being returned is a ProjectCalendarContainer, which is in charge of managing the calendars in the file and making it easy to access them.

The typical way this is done is through the use of the calendar's Unique ID attribute. Each calendar has an Integer Unique ID, typically this is read as part of the calendar information from a schedule file, or if you are creating a schedule yourself, the default is for the Unique ID to be automatically populated. Let's see:

file.getCalendars().forEach(c -> System.out.println(c.getName()\n   + \" (Unique ID: \" + c.getUniqueID() + \")\"));\n

Here's what we get:

Calendar 1 (Unique ID: 1)\nCalendar 2 (Unique ID: 2)\nCalendar 3 (Unique ID: 3)\n

Let's use a Unique ID to retrieve a calendar:

ProjectCalendar calendar = file.getCalendars().getByUniqueID(2);\nSystem.out.println(calendar.getName());\n

Here's the result of running this code:

Calendar 2\n

The ProjectCalendarContainer class also allows us to retrieve calendars by name, although that's not recommended as MPXJ doesn't enforce presence or uniqueness constraints on calendar names.

Most of the time accessing a calendar from some other part of MPXJ is handled for you, for example to retrieve a resource's calendar you just need to call the Resource method getCalendar rather than having to use ProjectCalendarContainer to retrieve it by Unique ID.

"},{"location":"howto-use-calendars/#calendar-relationships","title":"Calendar Relationships","text":"

The ProjectCalendar class provides a variety of methods to allow us to explore how it relates to other calendars and the rest of the schedule.

As we've been discussing the hierarchy of calendars, the first method we can try is isDerived, which will return true if this calendar has been derived from a parent calendar. Alongside this we can also use the getParent method to retrieve this calendar's parent. We can traverse a hierarchy of calendars using this method until getParent returns null at which point we know we have reached a \"base\" calendar and can go no further.

Calendars can also be assigned to both Tasks and Resources. The getTasks and getResources methods will each retrieve a list of the tasks and resources which explicitly use this calendar.

Finally, earlier in this section we mentioned the idea of the default calendar for a project. We can set or retrieve the default calendar using the ProjectFile methods setDefaultCalendar and getDefaultCalendar, as illustrated below.

ProjectFile file = new ProjectFile();\nProjectCalendar calendar = file.addDefaultBaseCalendar();\nfile.setDefaultCalendar(calendar);\nSystem.out.println(\"The default calendar name is \"\n   + file.getDefaultCalendar().getName());\n

As the name suggests, the default calendar will be used for all date, time, duration and work calculations if no other calendar has been assigned explicitly.

"},{"location":"howto-use-external-projects/","title":"How To: Use External Projects","text":"

From a schedule in Microsoft Project you can work with data from other project files in three ways: Subprojects, External Predecessors, and Resource Pools.

"},{"location":"howto-use-external-projects/#subprojects","title":"Subprojects","text":"

Microsoft Project allows you to manage larger projects by breaking them down into Subprojects. From one MPP file, a link can be added to another MPP file forming a parent-child relationship. The child MPP file will appear as a summary task in the location you've selected within the parent file. When this summary task is expanded the tasks from the child MPP file will appear seamlessly as tasks in the parent file.

"},{"location":"howto-use-external-projects/#identifying-subproject-tasks","title":"Identifying Subproject Tasks","text":"

If you use MPXJ to read an MPP file that contains a Subproject, initially you won't see anything different to a file which just contains ordinary tasks: the Subproject will just appear as a normal summary task whose attributes will roll up the details from the Subproject. If you want you can just work with the task as-is, you only need to so something different if you want to work with the contents of the Subproject.

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class IdentifySubprojectTasks\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      for (Task task : file.getTasks())\n      {\n         if (task.getExternalProject())\n         {\n            System.out.println(task.getName() + \" is a subproject\");\n            System.out.println(\"The path to the file is: \"\n               + task.getSubprojectFile());\n            System.out.println(\"The GUID of this project is: \"\n               + task.getSubprojectGUID());\n            System.out.println(\"The offset used when displaying Unique ID values is: \"\n               + task.getSubprojectTasksUniqueIDOffset());\n         }\n      }\n   }\n}\n

The example above illustrates how we can identify a Subproject by using a task's External Project attribute. Once we have identified that we have a Subproject we can determine where the file is located, using the Subproject File attribute, and the GUID of this project, using the Subproject GUID attribute.

The last attribute we're looking at in this example is the Subproject Tasks Unique ID Offset. When Microsoft Project provides a combined view of two or more MPP files using Subprojects, one issue is that the Unique ID values in each project will no longer be unique. To get around this problem Microsoft Project adds an offset to the Unique ID values of the tasks it displays from each Subproject to ensure that each one has a distinct value. This offset is the value we're retrieving using the getSubprojectTasksUniqueIDOffset method.

"},{"location":"howto-use-external-projects/#reading-subproject-data","title":"Reading Subproject Data","text":"

If you wish, you can use UniversalProjectReader directly to load the external project, as the example below illustrates:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ReadSubprojectData\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      Task externalProject = file.getTaskByID(Integer.valueOf(1));\n      String filePath = externalProject.getSubprojectFile();\n      ProjectFile externalProjectFile = new UniversalProjectReader().read(filePath);\n   }\n}\n

The code above assumes that the file is located on a readable filesystem at the exact path specified by the Subproject File attribute.

Note that these examples assume that the file is on a filesystem which is directly readable. For MPP files exported from Project Server, it is likely that the path to an external project will be in the form <>\\FileName which represents a project hosted by Project Server. MPXJ cannot open this type of external project.

An alternative to writing your own code to do this would be to use the method provided by MPXJ, as illustrated below:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ReadSubprojectDataMpxj\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      Task externalProjectTask = file.getTaskByID(Integer.valueOf(1));\n      ProjectFile externalProjectFile = externalProjectTask.getSubprojectObject();\n   }\n}\n

The advantage of this approach, apart from using less code, is that MPXJ will attempt to find the file in locations other than the full path provided in Subproject File. By default the other place MPXJ will look is in the working directory of the current process, however this behaviour can be configured as the example below illustrates:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\nimport java.io.File;\n\npublic class ReadSubprojectDataDirectory\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      file.getProjectConfig().setSubprojectWorkingDirectory(new File(\"/path/to/directory\"));\n      Task externalProjectTask = file.getTaskByID(Integer.valueOf(1));\n      ProjectFile externalProjectFile = externalProjectTask.getSubprojectObject();\n   }\n}\n

In the code above we're calling the setSubprojectWorkingDirectory method to give MPXJ details of a directory to look in when attempting to read an external project.

Note that if MPXJ can't load the external project for any reason, the getSubprojectObject method will return null.

"},{"location":"howto-use-external-projects/#expanding-subproject-data","title":"Expanding Subproject Data","text":"

In Microsoft Project, when a Subproject task is expanded it behaves just like any other summary task by revealing the child tasks it contains. We can reproduce this behavior using the code shown in the sample below:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ExpandSubprojects\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      Task externalProjectTask = file.getTaskByID(Integer.valueOf(1));\n      System.out.println(\"Task has child tasks: \" + externalProjectTask.hasChildTasks());\n      externalProjectTask.expandSubproject();\n      System.out.println(\"Task has child tasks: \" + externalProjectTask.hasChildTasks());\n   }\n}\n

The expandSubproject method attempts to open the external project, and if successful attaches the tasks from the external project as children of the external project task. You are then able to access the tasks from the parent project along with the tasks from the external project as part of the same MPXJ ProjectFile instance.

Note that when using the expandSubproject method, the setSubprojectWorkingDirectory method on ProjectConfig can be used to tell MPXJ where to find the external projects in the same way we did when using the getSubprojectObject method.

You can also do this globally and expand all Subproject tasks in a project by using the expandSubprojects method on the project file itself (we'll cover the false argument we're passing into this method in the section below on External Predecessors):

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ExpandSubprojectsGlobally\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      file.expandSubprojects(false);\n   }\n}\n

Remember that all the \"expand subproject\" functionality described in the notes above is doing is attaching the tasks from one ProjectFile instance as child tasks of a task in another ProjectFile instance. This will allow you to recursively descend through the tasks in a project and any subprojects. However, these tasks still belong to separate ProjectFile instances, so calling the getTasks() method on the top level ProjectFile instance will only return the tasks from that project, and will not include tasks from any subprojects.

"},{"location":"howto-use-external-projects/#external-predecessors","title":"External Predecessors","text":"

The second way an external project can be referenced in a Microsoft Project schedule is through the use of an external predecessor task. Project allows you to enter the task ID for a predecessor in the form myproject.mpp\\123 which selects the task with ID 123 in myproject.mpp as the predecessor of the task in the schedule you are working on.

When you use an external predecessor task like this, Project includes a \"placeholder\" task in your current schedule which represents the task in the external project and has a copy of all of the relevant attributes of the task from the external project. In many cases this placeholder task is all you need to work with the schedule.

When you are working with MPXJ, how can you identify that you are looking at a placeholder task representing an external predecessor? The sample code below illustrates this:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ExternalPredecessors\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      for (Task task : file.getTasks())\n      {\n         if (task.getExternalTask())\n         {\n            System.out.println(task.getName() + \" is an external predecessor\");\n            System.out.println(\"The path to the file containing this task is: \"\n               + task.getSubprojectFile());\n            System.out.println(\"The ID of the task in this file is: \"\n               + task.getSubprojectTaskID());\n            System.out.println(\"The Unique ID of the task in this file is: \"\n               + task.getSubprojectTaskUniqueID());\n         }\n      }\n   }\n}\n

As the code above illustrates, if the getExternalTask method return true, the task is an external predecessor. As illustrated by the code there are three relevant attributes: Subproject File (the location of the external project this predecessor belongs to), and the Subproject Task ID and Subproject Task Unique ID which are the ID and Unique ID of the task in the schedule it comes from.

As with a task representing an external project, you can retrieve the project for an external predecessor task using the getSubprojectObject method. Note however that the expandSubproject method will have no effect as the external predecessor task does not represent an entire project!

"},{"location":"howto-use-external-projects/#predecessors-and-successors-from-subprojects","title":"Predecessors and Successors from Subprojects","text":"

As we saw in a previous section, when working with Microsoft Project you can configure a project with a number of subprojects. When this is the case you can also create predecessor or successor relationships between tasks in any of these projects. When you open your MPP file in Microsoft Project, and all of the subprojects can also be opened, then Microsoft Project will present you with a unified view of the tasks and their relationships, even though the relationships cross different files. However, if you open your project but do not have the subproject files available, you will see placeholder external tasks representing the predecessor or successor tasks from the missing subproject files.

When reading the file using MPXJ, you will encounter the same situation: opening your MPP file without any of the subprojects being available you will see placeholder external tasks for predecessor and successor tasks from the subproject files. As we have already seen, the expandSubprojects method can be used to expand all subprojects, if the files they represent are available, allowing you to traverse the hierarchy of tasks. The expandSubprojects method also offers some additional functionality: when you pass true to this method, MPXJ will attempt to replace any predecessor or successor relationships which include placeholder external tasks with relationships which refer to the original task from a subproject, and those placeholder external tasks will be removed from the project entirely. This functionality is intended to replicate what you would see if you opened your file in Microsoft Project and all subprojects were successfully loaded.

As noted previously, the expandSubprojects method is only stitching together a set of individual ProjectFile instances so the tasks they contain can be traversed seamlessly, and in this case the predecessor and successor relationships between those tasks no longer use placeholder external tasks. This is still not a single unified ProjectFile instance so care should be taken when working with this data to bear in mind that it comes from a number of separate files.

"},{"location":"howto-use-external-projects/#resource-pools","title":"Resource Pools","text":"

The final way an external project can be used from a Microsoft Project schedule is as a resource pool. A resource pool schedule allows you to capture details of all of your organisation's resources in one place, then refer to them from multiple schedules. Setting up a resource pool like this should ensure that your resource utilisation across different projects is accurately captured as the utilisation detail in the resource pool is updated by the projects using those resources.

The full path for a project's resource pool can be retrieved using the getResourcePoolFile method as illustrated below:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ResourcePool\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      String path = file.getProjectProperties().getResourcePoolFile();\n   }\n}\n

In a similar manner to the other external project examples given in previous sections, MPXJ can also open and read the resource pool file for you:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ResourcePoolObject\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      ProjectFile resourcePool = file.getProjectProperties().getResourcePoolObject();\n   }\n}\n
"},{"location":"howto-use-external-projects/#mspdi-files","title":"MSPDI Files","text":"

Much of the detail noted above is also applicable to MSPDI files, but with the following exceptions:

  • Where the MSPDI file contains a Subproject, only the Subproject File attribute will be populated, the Subproject GUID add Subproject Tasks Unique ID Offset will not be available.
  • If an MSPDI file has been saved in Microsoft Project from an MPP file which contains Subprojects, and those Subprojects were expanded at the point the file was exported, the MSPDI file will actually contain the data for the Subproject as well as the main project. MPXJ will automatically read this data, which you can access using the getSubprojectObject method on the task, or you can call the expandSubproject or expandSubprojects methods documented in the previous sections to show the tasks contained in the Subproject as part of the main project.
  • Where the original MPP file contained an external task predecessor, the equivalent MSPDI file will not contain a placeholder task for the predecessor. MPXJ will generate one for you, but this will contain none of the attributes you would find if you read the MPP file using MPXJ.
  • MSPDI files do not contain any references to resource pools.

Note that although Microsoft Project will write external predecessor information to an MSPDI file, it will fail to load these correctly when the MSPDI file is reopened.

"},{"location":"howto-use-fields/","title":"How To: Use Fields","text":"

Once you've read a schedule using MPXJ, and you have a ProjectFile instance with tasks, resources and resource assignments, how do you access the data represented as fields in each of these entities? If you're creating or updating a schedule, how can you assign values to fields? This section explains the different approaches you can take in each of these cases.

"},{"location":"howto-use-fields/#setter-and-getter-methods","title":"Setter and Getter Methods","text":"

Let's start by creating a task we can use to demonstrate some of these approaches:

ProjectFile file = new ProjectFile();\nTask task = file.addTask();\n

When you already know exactly which field you need to access, you can work with the data these fields contain in a type-safe way by using the setter and getter methods provided by each class, for example:

task.setName(\"Task 1\");\n\nString name = task.getName();\nSystem.out.println(\"Task name: \" + name);\n

Here's the output from the sample code:

Task name: Task 1\n

Here we can see that we are able to set the name of the task using a String, and when we call the getter method we'll be returned the name as a String. How about working with a field that has a type other than a String?

LocalDateTime startDate = LocalDateTime.of(2022, 5, 10, 8, 0);\ntask.setStart(startDate);\n\nSystem.out.println(\"Start date: \" + task.getStart());\n

Here's the output from the sample code:

Start date: 2022-05-10T08:00\n

We're setting and retrieving the task's start date using a LocalDateTime instance. For almost all of the fields supported by tasks, resources, and resource assignments you'll find a pair of getter and setter methods allowing you to access and modify the field with a convenient type safe interface.

"},{"location":"howto-use-fields/#field-enumerations","title":"Field Enumerations","text":"

What if we don't know ahead of time which fields we need to access? For example, what if our application allows users to choose which fields to display for each task? In this case we can use a data-driven approach to read and write fields, as shown in the example below.

task = file.addTask();\ntask.set(TaskField.NAME, \"Task 2\");\n\nname = (String)task.get(TaskField.NAME);\nSystem.out.println(\"Task name: \" + name);\n\nstartDate = LocalDateTime.of(2022, 5, 11, 8, 0);\ntask.set(TaskField.START, startDate);\n\nSystem.out.println(\"Start date: \" + task.getStart());\n

Here's the output from this sample code:

Task name: Task 2\nStart date: 2022-05-11T08:00\n

What are the TaskField values in the example above? TaskField is an enumeration representing all of the fields of a Task instance. This type of enumeration is not unique to tasks, there are four main enumerations available:

  • ProjectField: fields available from ProjectProperties
  • ResourceField: fields available from a Resource
  • TaskField: fields available from a Task
  • AssignmentField: fields available from a ResourceAssignment

The ProjectProperties, Resource, Task and ResourceAssignment classes noted above actually all implement the FieldContainer interface. This is the interface that gives us the get and set methods we've seen in the examples above. FieldContainer also provides us with one more interesting method: getCachedValue. What is this, and why is it different to the get method? Let's take a step back and look at calculated values to understand where getCachedValue fits in.

"},{"location":"howto-use-fields/#calculated-fields","title":"Calculated Fields","text":"

Some of the fields available from each of these classes can actually contain a calculated value. For example: the Task field \"Start Variance\" represents the difference between the Baseline Start date and the Start date of a task. Some schedules may provide this value for us when we read the data they contain, others may not. If we don't have this value when we read our schedule data, but we do have a Baseline Start and Start date available to us, then we can perform the calculation ourselves to produce the Start Variance value. The example below illustrates this:

// Set up the sample project\nProjectFile file = new ProjectFile();\n\n// We need at least a default calendar to calculate variance\nfile.setDefaultCalendar(file.addDefaultBaseCalendar());\n\n// Create tasks\nTask task1 = file.addTask();\nTask task2 = file.addTask();\n\n// Set up example dates\nLocalDateTime baselineStart = LocalDateTime.of(2022, 5, 1, 8, 0);\nLocalDateTime startDate = LocalDateTime.of(2022,5, 10, 8, 0);\n\n// Update task1 using methods\ntask1.setStart(startDate);\ntask1.setBaselineStart(baselineStart);\n\n// Update task2 using TaskField enumeration\ntask2.set(TaskField.START, startDate);\ntask2.set(TaskField.BASELINE_START, baselineStart);\n\n// Show the variance being retrieved by method and TaskField enumeration\nSystem.out.println(\"Task 1\");\nSystem.out.println(\"Start Variance from method: \"\n   + task1.getStartVariance());\nSystem.out.println(\"Start Variance from get: \"\n   + task1.get(TaskField.START_VARIANCE));\nSystem.out.println();\n\nSystem.out.println(\"Task 2\");\nSystem.out.println(\"Start Variance from method: \"\n   + task2.getStartVariance());\nSystem.out.println(\"Start Variance from get: \"\n   + task2.get(TaskField.START_VARIANCE));\n

Here's the output from running this code:

Task 1\nStart Variance from method: 6.0d\nStart Variance from get: 6.0d\n\nTask 2\nStart Variance from method: 6.0d\nStart Variance from get: 6.0d\n

Regardless of how we set up the data, both the getStartVariance method and the call to get(TaskField.START_VARIANCE) trigger the calculation and produce the expected Start Variance value.

Rather than immediately discarding the Start Variance value we've just calculated, this value is cached as part of the data held by the task, and will be returned next time we use the getStartVariance method or we call get(TaskField.START_VARIANCE).

"},{"location":"howto-use-fields/#cached-values","title":"Cached Values","text":"

The getCachedValue method allows us to retrieve a field without attempting to calculate a value. It's not a method you'd normally expect to use, but it's worth mentioning for completeness. Let's take a look at this using a new example:

// Set up the sample project with a default calendar\nProjectFile file = new ProjectFile();\nfile.setDefaultCalendar(file.addDefaultBaseCalendar());\n\n// Set up example dates\nLocalDateTime baselineStart = LocalDateTime.of(2022, 5, 1, 8, 0);\nLocalDateTime startDate = LocalDateTime.of(2022,5, 10, 8, 0);\n\n// Create a task\nTask task = file.addTask();\ntask.setStart(startDate);\ntask.setBaselineStart(baselineStart);\n\nSystem.out.println(\"Start Variance using getCachedValue(): \" \n   + task.getCachedValue(TaskField.START_VARIANCE));\nSystem.out.println(\"Start Variance using get(): \" \n   + task.get(TaskField.START_VARIANCE));\nSystem.out.println(\"Start Variance using getCachedValue(): \" \n   + task.getCachedValue(TaskField.START_VARIANCE));\n

The output from this code is:

Start Variance using getCachedValue(): null\nStart Variance using get(): 6.0d\nStart Variance using getCachedValue(): 6.0d\n

What we can see happening here is that using the getCachedValue method initially returns null as the Start Variance is not present, and MPXJ doesn't attempt to calculate it. When we use the get method, MPXJ sees that it doesn't have a value for this field and knows how to calculate it, and returns the expected result. Finally if we use the getCachedValue method again, as we've now calculated this value and cached it, the method returns the Start Variance.

In summary, getCachedValue will never attempt to calculate values for fields which are not already present. This can be useful if you want to read a schedule using MPXJ, but retrieve only the fields which were in the original schedule, not calculated or inferred by MPXJ.

"},{"location":"howto-use-fields/#fieldtype","title":"FieldType","text":"

Earlier in this section we noted that there were four main enumerations representing the fields which particular classes can contain.

  • ProjectField
  • ResourceField
  • TaskField
  • AssignmentField

What I didn't mention then is that each of these enumerations implements the FieldType interface which defines a common set of methods for each of these enumerations. The most interesting of these methods are:

  • name()
  • getName()
  • getFieldTypeClass()
  • getDataType()

The name() method retrieves the name of the enumeration value exactly as it appears in the code. The getName() method returns a localized version of the name, suitable for display to end users (currently English is the default and only supported locale).

The getFieldTypeClass() method returns a value from the FieldTypeClass enumeration which will help you to determine which kind of object this FieldType belongs to (for example task, resource, and so on). Finally the getDataType() method will return a value from the DataType enumeration which indicates the data type you will receive from the get method when accessing this field, and the type to pass to the set method when updating the field.

Here's some example code to make this a little clearer:

FieldType type = TaskField.START_VARIANCE;\n\nSystem.out.println(\"name(): \" + type.name());\nSystem.out.println(\"getName(): \" + type.getName());\nSystem.out.println(\"getFieldTypeClass(): \" + type.getFieldTypeClass());\nSystem.out.println(\"getDataType():\" + type.getDataType());\n

In this case we're using the Task Start Variance field as an example. Here's the output:

name(): START_VARIANCE\ngetName(): Start Variance\ngetFieldTypeClass(): TASK\ngetDataType(): DURATION\n

Returning to our earlier example of how we might allow a user to select fields we will display, we can use the data type of the selected field to determine how we format the value for display.

private String getValueAsText(FieldContainer container, FieldType type)\n{\n    Object value = container.get(type);\n    if (value == null)\n    {\n        return \"\";\n    }\n\n    String result;\n    switch (type.getDataType())\n    {\n        case CURRENCY:\n        {\n            result = new DecimalFormat(\"\u00a30.00\").format(value);\n            break;\n        }\n\n        case DATE:\n        {\n            result = DateTimeFormatter.ofPattern(\"dd/MM/yyyy\").format((LocalDateTime)value);\n            break;\n        }\n\n        case BOOLEAN:\n        {\n            result = ((Boolean)value).booleanValue() ? \"Yes\" : \"No\";\n            break;\n        }\n\n        default:\n        {\n            result = value.toString();\n            break;\n        }\n    }\n\n    return result;\n}\n

The sample code above implements a generic method which can work with any class implementing the FieldContainer interface (for example, Task, Resource and so on). Given the particular field the user has asked us to display (passed in via the type argument), we retrieve the value from the container as an Object, then use the data type to decide how best to format the value for display. (This is obviously a contrived example - I wouldn't recommend creating new instances of DecimalFormat and DateTimeFormatter each time you need to format a value!)

"},{"location":"howto-use-fields/#custom-fields","title":"Custom Fields","text":"

So far we've seen how simple fields like Name and Start can be accessed and modified using both field-specific and generic methods. Name and Start are examples of standard fields which might be provided and managed by schedule applications, and have a well understood meaning. What if we have some additional data we want to capture in our schedule, but that data doesn't fit into any of these standard fields?

Microsoft Project's solution to this problem is Custom Fields. By default Microsoft Project provides a number of general purpose fields with names like \"Text 1\", \"Text 2\", \"Date 1\", \"Date 2\" and so on, which can be used to relevant vales as part of the schedule. If we look for methods like setText1 or setDate1 we won't find them, so how can we work with these fields?

The answer is quite straightforward, for each of these custom fields you'll find getter and setter methods which take an integer value, for example:

task.setText(1, \"This is Text 1\");\nString text1 = task.getText(1);\nSystem.out.println(\"Text 1 is: \" + text1);\n

If you're working with the generic get and set methods, the situation is more straightforward as each individual field has its own enumeration, as shown below:

task.set(TaskField.TEXT1, \"This is also Text 1\");\ntext1 = (String)task.get(TaskField.TEXT1);\nSystem.out.println(\"Text 1 is: \" + text1);\n

For Task, Resource and ResourceAssignment the following custom fields are available for use:

  • Cost 1-10
  • Date 1-10
  • Duration 1-10
  • Flag 1-20
  • Finish 1-10
  • Number 1-20
  • Start 1-10
  • Text 1-30
  • Outline Code 1-10 (Task and Resource only)

Microsoft Project allows users to configure custom fields. This facility can be used to do something as simple as provide an alias for the field, allowing it to be displayed with a meaningful name rather than something like \"Text 1\" or \"Date 1\". Alternatively there are more complex configurations available, for example constraining the values that can be entered for a field by using a lookup table, or providing a mask to enforce a particular format.

Information about custom field configurations can be obtained from the CustomFieldsContainer. The sample code below provides a simple illustration of how we can query this data.

ProjectFile file = new UniversalProjectReader().read(\"example.mpp\");\n\nCustomFieldContainer container = file.getCustomFields();\nfor (CustomField field : container)\n{\n    FieldType type = field.getFieldType();\n    String typeClass = type.getFieldTypeClass().toString();\n    String typeName = type.name();\n    String alias = field.getAlias();\n    System.out.println(typeClass + \".\" + typeName + \"\\t\" + alias);\n}\n

Depending on how the custom fields in your schedule are configured, you'll see output like this:

TASK.TEXT1      Change Request Reason\nTASK.NUMBER1    Number of Widgets Required\nRESOURCE.DATE1  Significant Date\n

In the source above, the first thing we're retrieving from each CustomField instance is the FieldType, which identifies the field we're configuring. The values we retrieve here will be from one of the enumerations we've touched on previously in this section, for example TaskField, ResourceField and so on.

The next thing we're doing in our sample code is to create a representation of the parent type to which this field belongs, followed by the name of the field itself (this is what's providing us with the value TASK.TEXT1 for example). Finally we're displaying the alias which has been set by the user for this field.

It's important to note that for schedules from Microsoft Project, there won't necessarily be a CustomField entry for all of the custom fields in use in a schedule. For example, if a user has added values to the \"Text 1\" field for each of the tasks in their schedule, but have not configured Text 1 in some way (for example by setting an alias or adding a lookup table) there won't be an entry for \"Text 1\" in the CustomFieldContainer.

As well as iterating through the collection of CustomField instances for the current schedule, you can directly request the CustomField instance for a specific field, as shown below:

CustomField fieldConfiguration = container.get(TaskField.TEXT1);\n

One common use-case for the configuration data help in CustomFieldContainer is to locate particular information you are expecting to find in the schedule. For example, let's say that you know that the schedule you're reading should have a field on each task which users have named \"Number of Widgets Required\", and you want to read that data. You can determine which field you need by using a method call similar to the one shown below:

FieldType fieldType = container.getFieldTypeByAlias(\n    FieldTypeClass.TASK,\n   \"Number of Widgets Required\");\n

Note that the first argument we need to pass identifies which parent entity we're expecting to find the field in. The CustomFieldContainer will have entries from all field containers (tasks, resources, resource assignments and so on) so this is used to locate the correct one - particularly useful if, for example, a task and a resource might both have a field with the same alias! Remember: this method will return null if we don't have a field with the alias you've provided.

Once we have the FieldType of the field we're looking for, we can use this to retrieve the value using the get method as we've seen earlier in this section:

Task task = file.getTaskByID(Integer.valueOf(1));\nObject value = task.get(fieldType);\n

Finally, there are a couple of convenience methods to make retrieving a field by its alias easier. The first is that each \"container\" class for the various entities also provides a getFieldTypeByAlias method. If you know ahead of time you're looking for a field in a particular entity, this will simplify your code somewhat. The example below illustrates this: as we're looking for a task field we can go straight to the TaskContainer and ask for the field with the alias we're looking for:

fieldType = file.getTasks().getFieldTypeByAlias(\"Number of Widgets Required\");\n

Lastly, you can actually retrieve the value of a field directly from the parent entity using its alias, as shown below:

value = task.getFieldByAlias(\"Number of Widgets Required\");\n

This is not recommended where you are iterating across multiple tasks to retrieve values: it's more efficient to look up the FieldType once before you start, then use that to retrieve the value you are interested in from each task.

"},{"location":"howto-use-fields/#populated-fields","title":"Populated Fields","text":"

So far we've touched on how to can read and write fields in examples where we are targeting specific fields. If we're reading a schedule whose contents are unknown to us, how can we tell which fields are actually populated? A typical use-case for this might be where we need to read a schedule, then present the user with the ability to select the columns they'd like to see in a tabular display of the schedule contents. If you look at the various enumerations we have mentioned previously in this section (TaskField, ResourceField and so on) you can see that there are a large number of possible fields a user could choose from, so ideally we only want to show a user fields which actually contain non-default values.

To solve this problem we need to use the appropriate getPopulatedFields method for each of the entities we're interested in.

ProjectFile file = new UniversalProjectReader().read(\"example.mpp\");\n\nSet<ProjectField> projectFields = file.getProjectProperties().getPopulatedFields();\nSet<TaskField> taskFields = file.getTasks().getPopulatedFields();\nSet<ResourceField> resourceFields = file.getResources().getPopulatedFields();\nSet<AssignmentField> assignmentFields = file.getResourceAssignments().getPopulatedFields();\n

In the example above we're opening a sample file, then for each of the main classes which implement the FieldContainer interface, we'll query the container which holds those classes and call its getPopulatedFields method. In each case this will return a Set containing the enumeration values representing fields which have non-default values.

If you need to you can retrieve all of this information in one go:

ProjectFile file = new UniversalProjectReader().read(\"example.mpp\");\n\nSet<FieldType> allFields = file.getPopulatedFields();\n

The set returned by the project's getPopulatedFields will contain all the populated fields from all entities which implement the FieldContainer interface. You'll need to remember to look at the FieldTypeClass value of each field in the resulting set to determine which entity the field belongs to. The following section provides more detail on this.

"},{"location":"howto-use-fields/#user-defined-fields","title":"User Defined Fields","text":"

In an earlier section we touched briefly on how Microsoft Project uses a fixed set of \"custom fields\" to allow you to store arbitrary data as part of the schedule. A more common approach in other applications is to allow you to create your own fields to represent the data you need to store - that way you can have exactly the fields you need, without needing to worry if you can fit your data into the fixed set of custom fields. In fact Microsoft Project also supports this concept, in the form of Enterprise Custom Fields, although these are only available if you are working with a schedule hosted in Project Server (Project 365).

As you can imagine MPXJ can't provide dedicated getter and setter methods for these fields as it doesn't know ahead of time what they are - they're user defined! Instead we rely on the get and set methods to work with these fields.

When a schedule is read by MPXJ, each user defined field is represented internally by an instance of the UserDefinedField class. This class implements the FieldType interface, and so can be used with the get and set methods to read and write these values.

You can see which user defined fields exist in a project using code similar to the example below:

for (UserDefinedField field : project.getUserDefinedFields())\n{\n    System.out.println(\"name(): \" + field.name());\n    System.out.println(\"getName(): \" + field.getName());\n    System.out.println(\"getFieldTypeClass(): \" + field.getFieldTypeClass());\n    System.out.println(\"getDataType():\" + field.getDataType());         \n}\n

As well as using the getUserDefinedFields method on the project to see which fields are defined, the getPopulatedFields methods discussed in an earlier section will also return UserDefinedField instances if these fields have values in the schedule. Information about UserDefinedField instances is also available in the CustomFieldContainer. This means that when you read a schedule and you are expecting certain user defined fields to be present, you can use the getFieldTypeByAlias or getFieldByAlias methods to find the fields you are interested in by name, as described in an earlier section.

If you import schedules data from an application which supports user defined fields and export to a Microsoft Project file format (MPX or MSPDI), MPXJ will automatically map any user defined fields to unused custom fields. Note that as there are only a finite number of custom field available, it is possible that not all user defined fields will be available when the resulting file is opened in Microsoft Project.

"},{"location":"howto-use-universal/","title":"How To: Use the Universal Project Reader","text":"

As you may have seen elsewhere in this documentation, the preferred way to read from most sources of schedule data is to use the UniversalProjectReader:

package org.mpxj.howto.use.universal;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.ProjectReader;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SimpleExample\n{\n   public void process() throws Exception\n   {\n      ProjectReader reader = new UniversalProjectReader();\n      ProjectFile project = reader.read(\"example.mpp\");\n   }\n}\n

This is very convenient as you don't need to know ahead of time what type of schedule file you are working with, UniversalProjectReader will figure this out for you. The drawback to this approach is that for a number of schedule types, the reader class for that type may provide additional configuration options to guide the way schedule data is read. In the example above, you can see that there is no opportunity to provide any extra configuration to the reader class selected by UniversalProjectReader.

To get around this issue, UniversalProjectReader provides access to \"project reader proxy\" classes. These proxy classes implement the UniversalProjectReader.ProjectReaderProxy interface and provide access to the reader class which UniversalProjectReader has selected to read the project data at the point just before schedule data has been read.

You can use these proxy classes to, for example, choose whether or not to continue reading the type of schedule contained in the supplied file or stream, or you can change the reader's settings before continuing to read the schedule. The example code below illustrates both these situations.

package org.mpxj.howto.use.universal;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.phoenix.PhoenixReader;\nimport net.sf.mpxj.reader.ProjectReader;\nimport net.sf.mpxj.reader.UniversalProjectReader;\nimport net.sf.mpxj.sdef.SDEFReader;\n\nimport java.io.File;\n\npublic class ProxyExample\n{\n   public void process(File file) throws Exception\n   {\n      UniversalProjectReader upr = new UniversalProjectReader();\n\n      // Retrieve the proxy\n      try (UniversalProjectReader.ProjectReaderProxy proxy\n              = upr.getProjectReaderProxy(file))\n      {\n         // Retrieve the reader class\n         ProjectReader reader = proxy.getProjectReader();\n\n         // Determine if we want to continue processing this file type.\n         // In this example we are ignoring SDEF files.\n         if (reader instanceof SDEFReader)\n         {\n            return;\n         }\n\n         // Provide configuration for specific reader types.\n         // In this example we are changing the behavior of the Phoenix reader.\n         if (reader instanceof PhoenixReader)\n         {\n            ((PhoenixReader)reader).setUseActivityCodesForTaskHierarchy(false);\n         }\n\n         // Finally, we read the schedule\n         ProjectFile project = proxy.read();\n\n         // Now we can work with the schedule data...\n      }\n   }\n}\n

The first thing to notice is that the proxy class is being used within a \"try with resources\" statement. This is important as the UniversalProjectReader may have a number of resources open (streams, temporary files, and so on) which need to be released once you have finished with the proxy class. UniversalProjectReader.ProjectReaderProxy implements the AutoCloseable interface, so you can either arrange to explicitly call the close method yourself at an appropriate point, or you can use try with resources to ensure this happens automatically.

The initial line of the try statement calls getProjectReaderProxy to retrieve the proxy. This method can be called with either a file name, a File instance, or an InputStream. Within the try block, the first thing we do is retrieve the reader class instance which the UniversalProjectReader has selected to read our schedule data.

The next two stanzas of code use instanceof to determine the type of the reader selected: in the first stanza we're choosing not to continue if we've been provided with an SDEF file. In the second stanza, if we are dealing with a Phoenix schedule, we're choosing to change the default behavior of the reader.

Finally at the end of the try block we're calling the read method of the proxy to read the schedule. The proxy also provides a readAll method: if the source data contains multiple schedules you can use this method to read them all.

Note that we're using the read or readAll methods provided by the proxy class, we're not attempting to use the methods provided on the reader class itself. This is important as the UniversalProjectReader may have located the schedule within a larger set of data, for example within a Zip file or sub-directory. The proxy class already has this context, whereas you won't necessarily have this information if you tried to use the reader class methods directly.

"},{"location":"howto-write-mpx/","title":"How To: Write MPX files","text":"

Versions of Microsoft Project up to Project 98 could read and write MPX files as a data interchange format. Versions of Project after Project 98 until Project 2010 can only read MPX files. Versions of Microsoft Project after 2010 cannot read MPX files. Other third party project planning applications continue to use MPX as a data interchange format.

"},{"location":"howto-write-mpx/#writing-mpx-files","title":"Writing MPX files","text":"

The sample code below illustrates how to write data to an MPX file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class MPX\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.MPX).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MPX\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.MPX).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mpx/#using-mpxwriter","title":"Using MPXWriter","text":"

If required, the MPXWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-mpx/#locale","title":"Locale","text":"

The MPX file format is actually locale specific, so in the example code below we can see that the writer is being asked to produce a file suitable for reading with a localized German version of Microsoft Project.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXWriter;\n\nimport java.util.Locale;\n\npublic class MPXLocale\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MPXWriter writer = new MPXWriter();\n        writer.setLocale(Locale.GERMAN);\n        writer.write(project, fileName);\n    }\n}\n
using System.Globalization;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MPXLocale\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MPXWriter();\n        writer.Culture = CultureInfo.GetCultureInfo(\"de\");\n        writer.Write(project, fileName);\n    }\n}\n

The locales supported by the MPX writer class can be retrieved using the following call:

JavaC#
MPXWriter.getSupportedLocales()\n
MPXWriter.SupportedCultures\n
"},{"location":"howto-write-mpx/#locale-defaults","title":"Locale Defaults","text":"

By default the MPX writer ignores the date, time, number and currency formats specified in the project properties and instead uses the defaults from the specified locale. Calling the setUseLocaleDefaults method and passing false ensures that the information present in the project properties is used instead of the locale defaults. This is illustrated in the sample code below:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXWriter;\n\nimport java.util.Locale;\n\npublic class MPXLocaleDefaults\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MPXWriter writer = new MPXWriter();\n        writer.setLocale(Locale.GERMAN);\n        writer.setUseLocaleDefaults(false);\n        writer.write(project, fileName);\n    }\n}\n
using System.Globalization;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MPXLocaleDefaults\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MPXWriter();\n        writer.Culture = CultureInfo.GetCultureInfo(\"de\");\n        writer.UseCultureDefaults = false;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/","title":"How To: Write MSPDI files","text":"

Since Microsoft Project 2002, Microsoft Project has been able to read and write an XML-based data interchange format called MSPDI.

"},{"location":"howto-write-mspdi/#writing-mspdi-files","title":"Writing MSPDI files","text":"

The sample code below illustrates how to write data to an MSPDI file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class MSPDI\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.MSPDI).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDI\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.MSPDI).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/#using-mspdiwriter","title":"Using MSPDIWriter","text":"

If required, the MSPDIWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-mspdi/#microsoft-project-compatible-output","title":"Microsoft Project Compatible Output","text":"

Microsoft Project has a non-standard way of representing negative duration values (it should have a minus sign as a prefix at the start of the XSD duration expression rather than embedded in it).

Originally MPXJ read and wrote correctly formatted XSD duration values, but unfortunately this meant that Project would not read these values correctly, and MPXJ would not be able to consume these values correctly from an MSPDI file written by Project. MPXJ has been updated so that it reads and writes the form of these duration values understood by Project, but this does mean that if you were previously expecting to be able to parse valid XSD duration values from output generated by MPXJ, that will no longer be the case.

To provide backward compatibility the MicrosoftProjectCompatibleOutput flag has been introduced. This defaults to true so MSPDI files containing negative durations written by MPXJ can be read by Project. If you need to produce correctly formatted XSD durations for consumption by applications other than Project you can set this flag to false:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\n\npublic class MSPDICompatibleOutput\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setMicrosoftProjectCompatibleOutput(false);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDICompatibleOutput\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.MicrosoftProjectCompatibleOutput = false;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/#save-version","title":"Save Version","text":"

The MSPDI file contains a SaveVersion attribute which indicates the version of Microsoft Project used to save the file. The value of SaveVersion is defined by the net.sf.mpxj.mspdi.SaveVersion enum, which provides the following values:

Project2002\nProject2003\nProject2007\nProject2010\nProject2013\nProject2016\n

By default MSPDIWriter sets the SaveVersion value to Project2016. The only functional difference this setting makes when writing MSPDI files is that the format of calendar exceptions changed in Project 2003 and onwards. MPXJ will always write calendar exceptions using the original Project 2002 format, and if the SaveVersion is set to Project2003 or later it will also write the new format data as well.

Here's an example of the SaveVersion attribute being set to ensure that only the older style of calendar exceptions is written to the MSPDI file:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\nimport net.sf.mpxj.mspdi.SaveVersion;\n\npublic class MSPDISaveVersion\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setSaveVersion(SaveVersion.Project2002);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDISaveVersion\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.SaveVersion = SaveVersion.Project2002;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/#timephased-data","title":"Timephased Data","text":"

By default MSPDIWriter does not write timephased data to an MSPDI file. To enable writing timephased data, you can call the setWriteTimephasedData method.

When this setting is enabled, the default behaviour is for the timephased data is broken down into days when written to the file. If it better suits your use case (or you need a more compact file) you can choose to write an aggregated form of the timephased data by calling the setSplitTimephasedAsDays method and passing false. The difference between the two formats is that if for example you have a 10 day block with 8 hours work per day, this can either be represented as 10 entries in the file each for a single day with a value of 8 hours, or a single entry for a 10 day range with a value of 80 hours. Although the latter case is more compact, if you are consuming the MSPDI timephased data yourself you will need to differentiate between working and non-working days in order to break the single block down into smaller ranges. The default day-by-day format MPXJ writes does this for you automatically.

In the first example below we're enabling timephased data, and using the default day-by-dat breakdown:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\n\npublic class MSPDITimephased\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setWriteTimephasedData(true);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDITimephased\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.WriteTimephasedData = true;\n        writer.Write(project, fileName);\n    }\n}\n

In this second example we're overriding the default behaviour as asking MPXJ to write an aggregated form of the timephased data:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\n\npublic class MSPDITimephasedAggregate\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setWriteTimephasedData(true);\n        writer.setSplitTimephasedAsDays(false);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDITimephasedAggregate\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.WriteTimephasedData = true;\n        writer.SplitTimephasedAsDays = true;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-planner/","title":"How To: Write Planner files","text":"

Gnome Planner is a simple cross platform planning tool. MPXJ can be used to write a schedule as a Planner file, which the Gnome Planner application can open.

"},{"location":"howto-write-planner/#writing-planner-files","title":"Writing Planner files","text":"

The sample code below illustrates how to write data to a Planner file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class Planner\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.PLANNER).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class Planner\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.PLANNER).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-planner/#using-plannerwriter","title":"Using PlannerWriter","text":"

If required, the PlannerWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-planner/#charset","title":"Charset","text":"

The character set used to write a Planner file can be specified using the setCharset method, as illustrated below.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.planner.PlannerWriter;\n\nimport java.nio.charset.Charset;\n\npublic class PlannerCharset\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        PlannerWriter writer = new PlannerWriter();\n        writer.setCharset(Charset.forName(\"GB2312\"));\n        writer.write(project, fileName);\n    }\n}\n
using System.Text;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class PlannerCharset\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new PlannerWriter();\n        writer.Encoding = Encoding.GetEncoding(\"GB2312\");\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-pmxml/","title":"How To: Write PMXML files","text":"

The XML file format supported by Primavera P6 for import and export is known as PMXML.

"},{"location":"howto-write-pmxml/#writing-pmxml-files","title":"Writing PMXML files","text":"

The sample code below illustrates how to write data to a PMXML file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class PMXML\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.PMXML).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class PMXML\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.PMXML).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-pmxml/#using-primaverapmfilewriter","title":"Using PrimaveraPMFileWriter","text":"

If required, the PrimaveraPMFileWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-pmxml/#baselines","title":"Baselines","text":"

By default baselines are not written to PMXML files. If the ProjectFile instance you are writing contains a baseline, this can be included in the PMXML file by calling the setWriteBaselines method as shown below.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileWriter;\n\npublic class PMXMLBaselines\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        PrimaveraPMFileWriter writer = new PrimaveraPMFileWriter();\n        writer.setWriteBaselines(true);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class PMXMLBaselines\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new PrimaveraPMFileWriter();\n        writer.WriteBaselines = true;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-sdef/","title":"How To: Write SDEF files","text":"

SDEF is the Standard Data Exchange Format, as defined by the USACE (United States Army Corps of Engineers). SDEF is a fixed column format text file, used to import a project schedule up into the QCS (Quality Control System) software from USACE. The specification for the file format can be found here.

"},{"location":"howto-write-sdef/#writing-sdef-files","title":"Writing SDEF files","text":"

The sample code below illustrates how to write data to an SDEF file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class SDEF\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.SDEF).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class SDEF\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.SDEF).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-sdef/#using-sdefwriter","title":"Using SDEFWriter","text":"

If required, the SDEFWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-sdef/#charset","title":"Charset","text":"

By default SDEF files are written using the US_ASCII charset. The setCharset method on the SDEFWriter class can be used to change this if required:

package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.sdef.SDEFWriter;\n\nimport java.nio.charset.StandardCharsets;\n\npublic class SDEFCharset\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        SDEFWriter writer = new SDEFWriter();\n        writer.setCharset(StandardCharsets.UTF_8);\n        writer.write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-xer/","title":"How To: Write XER files","text":"

XER files have been imported and exported by Primavera software since the earliest days of P6 and this format is still often the preferred way to move schedule data between instances of P6 even today.

"},{"location":"howto-write-xer/#writing-xer-files","title":"Writing XER files","text":"

The sample code below illustrates how to write data to an XER file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class XER\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.XER).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class XER\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.XER).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-xer/#using-primaveraxerfilewriter","title":"Using PrimaveraXERFileWriter","text":"

If required, the PrimaveraXERFileWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-xer/#charset","title":"Charset","text":"

By default XER files written by MPXJ are encoded using the Windows-1252 character set. If you need to use a different character set, the setCharset method can be used to achieve this, as illustrated by the code below.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileWriter;\n\nimport java.nio.charset.Charset;\n\npublic class XERCharset\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        PrimaveraXERFileWriter writer = new PrimaveraXERFileWriter();\n        writer.setCharset(Charset.forName(\"GB2312\"));\n        writer.write(project, fileName);\n    }\n}\n
using System.Text;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class XERChatset\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new PrimaveraXERFileWriter();\n        writer.Encoding = Encoding.GetEncoding(\"GB2312\");\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"mpp-field-guide/","title":"MPP Field Guide","text":""},{"location":"mpp-field-guide/#mpp-field-guide","title":"MPP Field Guide","text":"

The tables below provide an indication of which fields are populated when different MPP file versions are read using MPXJ The tables are not hand-crafted: they have been generated from test data and are therefore may be missing some details.

"},{"location":"mpp-field-guide/#project","title":"Project","text":""},{"location":"mpp-field-guide/#core-fields","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 AM Text \u2713 \u2713 \u2713 \u2713 Activity ID Increment \u2713 \u2713 \u2713 \u2713 Activity ID Increment Based On Selected Activity \u2713 \u2713 \u2713 \u2713 Activity ID Prefix \u2713 \u2713 \u2713 \u2713 Activity ID Suffix \u2713 \u2713 \u2713 \u2713 Application Version \u2713 \u2713 \u2713 \u2713 Author \u2713 \u2713 \u2713 \u2713 Auto Add New Resources and Tasks \u2713 \u2713 \u2713 \u2713 Auto Filter \u2713 \u2713 Auto Link \u2713 \u2713 \u2713 \u2713 Bar Text Date Format \u2713 \u2713 \u2713 \u2713 Calculate Float on Finish Date of Each Project \u2713 \u2713 \u2713 \u2713 Calculate Multiple Paths Using Total Float \u2713 \u2713 \u2713 \u2713 Category \u2713 \u2713 \u2713 \u2713 Comments \u2713 \u2713 \u2713 \u2713 Company \u2713 \u2713 \u2713 \u2713 Compute Start to Start Lag From Early Start \u2713 \u2713 \u2713 \u2713 Consider Assignments In Other Project With Priority Equal or Higher Than \u2713 \u2713 \u2713 \u2713 Content Status \u2713 \u2713 \u2713 Content Type \u2713 \u2713 \u2713 Creation Date \u2713 \u2713 \u2713 \u2713 Critical Activity Type \u2713 \u2713 \u2713 \u2713 Critical Slack Limit \u2713 \u2713 Currency Code \u2713 \u2713 \u2713 Currency Digits \u2713 \u2713 \u2713 \u2713 Currency Symbol \u2713 \u2713 \u2713 \u2713 Currency Symbol Position \u2713 \u2713 \u2713 \u2713 Current Date \u2713 \u2713 \u2713 \u2713 Custom Properties \u2713 \u2713 \u2713 \u2713 Date Format \u2713 \u2713 \u2713 \u2713 Date Order \u2713 \u2713 \u2713 \u2713 Date Separator \u2713 \u2713 \u2713 \u2713 Days per Month \u2713 \u2713 \u2713 \u2713 Decimal Separator \u2713 \u2713 \u2713 \u2713 Default Calendar Unique ID \u2713 \u2713 \u2713 \u2713 Default End Time \u2713 \u2713 \u2713 \u2713 Default Overtime Rate \u2713 \u2713 \u2713 Default Standard Rate \u2713 \u2713 \u2713 Default Start Time \u2713 \u2713 \u2713 \u2713 Default Work Units \u2713 \u2713 \u2713 \u2713 Document Version \u2713 \u2713 \u2713 Editable Actual Costs \u2713 \u2713 Editing Time \u2713 \u2713 \u2713 \u2713 File Application \u2713 \u2713 \u2713 \u2713 File Type \u2713 \u2713 \u2713 \u2713 Finish Date \u2713 \u2713 \u2713 \u2713 Fiscal Year Start \u2713 \u2713 \u2713 \u2713 Fiscal Year Start Month \u2713 \u2713 \u2713 \u2713 Full Application Name \u2713 \u2713 \u2713 \u2713 GUID \u2713 \u2713 \u2713 \u2713 Honor Constraints \u2713 \u2713 \u2713 \u2713 Hyperlink Base \u2713 \u2713 \u2713 \u2713 Keywords \u2713 \u2713 \u2713 \u2713 Language \u2713 \u2713 \u2713 Last Author \u2713 \u2713 \u2713 \u2713 Last Printed \u2713 \u2713 \u2713 \u2713 Last Saved \u2713 \u2713 \u2713 \u2713 Level All Resources \u2713 \u2713 \u2713 \u2713 Leveling Priorities \u2713 \u2713 \u2713 \u2713 Limit Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 MPP File Type \u2713 \u2713 \u2713 \u2713 MPX Code Page \u2713 \u2713 \u2713 \u2713 MPX Delimiter \u2713 \u2713 \u2713 \u2713 MPX File Version \u2713 \u2713 \u2713 \u2713 MPX Program Name \u2713 \u2713 \u2713 \u2713 Manager \u2713 \u2713 \u2713 \u2713 Maximum Percentage to Overallocate Resources \u2713 \u2713 \u2713 \u2713 Microsoft Project Server URL \u2713 \u2713 \u2713 \u2713 Minutes per Day \u2713 \u2713 \u2713 \u2713 Minutes per Month \u2713 \u2713 \u2713 \u2713 Minutes per Week \u2713 \u2713 \u2713 \u2713 Minutes per Year \u2713 \u2713 \u2713 \u2713 Multiple Critical Paths \u2713 \u2713 \u2713 New Task Start Is Project Start \u2713 \u2713 \u2713 \u2713 New Tasks Are Manual \u2713 \u2713 \u2713 New Tasks Estimated \u2713 \u2713 \u2713 \u2713 Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 PM Text \u2713 \u2713 \u2713 \u2713 Presentation Format \u2713 \u2713 \u2713 Preserve Minimum Float When Leveling \u2713 \u2713 \u2713 \u2713 Preserve Scheduled Early and Late Dates \u2713 \u2713 \u2713 \u2713 Project File Path \u2713 \u2713 \u2713 Project Title \u2713 \u2713 \u2713 \u2713 Relationship Lag Calendar \u2713 \u2713 \u2713 \u2713 Resource Pool File \u2713 \u2713 \u2713 Revision \u2713 \u2713 \u2713 \u2713 Schedule From \u2713 \u2713 \u2713 \u2713 Short Application Name \u2713 \u2713 \u2713 \u2713 Show Project Summary Task \u2713 \u2713 \u2713 \u2713 Split In Progress Tasks \u2713 \u2713 \u2713 \u2713 Start Date \u2713 \u2713 \u2713 \u2713 Status Date \u2713 \u2713 \u2713 Subject \u2713 \u2713 \u2713 \u2713 Template \u2713 \u2713 \u2713 \u2713 Thousands Separator \u2713 \u2713 \u2713 \u2713 Time Format \u2713 \u2713 \u2713 \u2713 Time Separator \u2713 \u2713 \u2713 \u2713 Total Slack Calculation Type \u2713 \u2713 \u2713 \u2713 Updating Task Status Updates Resource Status \u2713 \u2713 \u2713 \u2713 Use Expected Finish Dates \u2713 \u2713 \u2713 \u2713 WBS Code Separator \u2713 \u2713 \u2713 \u2713 Week Start Day \u2713 \u2713 \u2713 \u2713 When Scheduling Progressed Activities Use \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Date \u2713 \u2713 \u2713 Baseline2 Date \u2713 \u2713 Baseline3 Date \u2713 \u2713 Baseline4 Date \u2713 \u2713 Baseline5 Date \u2713 \u2713 Baseline6 Date \u2713 \u2713 Baseline7 Date \u2713 \u2713 Baseline8 Date \u2713 \u2713 Baseline9 Date \u2713 \u2713 Baseline10 Date \u2713 \u2713 Baseline Calendar Name \u2713 \u2713 \u2713 \u2713 Baseline Date \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#task","title":"Task","text":""},{"location":"mpp-field-guide/#core-fields_1","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 % Complete \u2713 \u2713 \u2713 \u2713 % Work Complete \u2713 \u2713 \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 Activity Codes \u2713 \u2713 \u2713 \u2713 Activity Percent Complete \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 Actual Duration \u2713 \u2713 \u2713 \u2713 Actual Duration Units \u2713 \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Board Status ID \u2713 Budget Cost \u2713 \u2713 \u2713 Budget Work \u2713 \u2713 \u2713 Calendar Unique ID \u2713 \u2713 \u2713 Complete Through \u2713 \u2713 \u2713 \u2713 Constraint Date \u2713 \u2713 \u2713 \u2713 Constraint Type \u2713 \u2713 \u2713 \u2713 Contact \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 \u2713 Critical \u2713 \u2713 \u2713 \u2713 Deadline \u2713 \u2713 \u2713 Duration \u2713 \u2713 \u2713 \u2713 Duration Units \u2713 \u2713 \u2713 Duration Variance \u2713 \u2713 \u2713 \u2713 Early Finish \u2713 \u2713 \u2713 \u2713 Early Start \u2713 \u2713 \u2713 \u2713 Earned Value Method \u2713 \u2713 Effort Driven \u2713 \u2713 \u2713 \u2713 Estimated \u2713 \u2713 \u2713 Expanded \u2713 \u2713 \u2713 \u2713 Expense Items \u2713 \u2713 \u2713 \u2713 External Project \u2713 \u2713 \u2713 External Task \u2713 \u2713 \u2713 Finish \u2713 \u2713 \u2713 \u2713 Finish Slack \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 \u2713 Fixed Cost \u2713 \u2713 \u2713 \u2713 Fixed Cost Accrual \u2713 \u2713 \u2713 \u2713 Free Slack \u2713 \u2713 \u2713 GUID \u2713 \u2713 Hide Bar \u2713 \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 \u2713 Hyperlink Data \u2713 \u2713 \u2713 Hyperlink Screen Tip \u2713 \u2713 \u2713 Hyperlink SubAddress \u2713 \u2713 \u2713 \u2713 ID \u2713 \u2713 \u2713 \u2713 Ignore Resource Calendar \u2713 \u2713 \u2713 Late Finish \u2713 \u2713 \u2713 \u2713 Late Start \u2713 \u2713 \u2713 \u2713 Level Assignments \u2713 \u2713 \u2713 \u2713 Leveling Can Split \u2713 \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 \u2713 \u2713 Leveling Delay Units \u2713 \u2713 \u2713 Manual Duration \u2713 Manual Duration Units \u2713 Marked \u2713 \u2713 \u2713 Milestone \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 Null \u2713 \u2713 \u2713 Outline Level \u2713 \u2713 \u2713 \u2713 Outline Number \u2713 \u2713 \u2713 \u2713 Overtime Cost \u2713 \u2713 \u2713 \u2713 Parent Task Unique ID \u2713 \u2713 \u2713 Physical % Complete \u2713 \u2713 \u2713 Preleveled Finish \u2713 \u2713 \u2713 \u2713 Preleveled Start \u2713 \u2713 \u2713 \u2713 Priority \u2713 \u2713 \u2713 \u2713 Project \u2713 \u2713 \u2713 Recalc Outline Codes \u2713 \u2713 Recurring \u2713 \u2713 \u2713 \u2713 Recurring Data \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 Remaining Duration \u2713 \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Resume \u2713 \u2713 \u2713 \u2713 Resume No Earlier Than \u2713 \u2713 \u2713 Rollup \u2713 \u2713 \u2713 \u2713 Scheduled Duration \u2713 Scheduled Finish \u2713 Scheduled Start \u2713 Show Duration Text \u2713 Show Finish Text \u2713 Show Start Text \u2713 Splits \u2713 \u2713 \u2713 Sprint ID \u2713 Start \u2713 \u2713 \u2713 \u2713 Start Slack \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 \u2713 Steps \u2713 \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 \u2713 Subproject File \u2713 \u2713 \u2713 Subproject GUID \u2713 \u2713 Subproject Task ID \u2713 \u2713 \u2713 Subproject Task Unique ID \u2713 \u2713 \u2713 Subproject Tasks Unique ID Offset \u2713 \u2713 \u2713 Summary \u2713 \u2713 \u2713 \u2713 Summary Progress \u2713 \u2713 \u2713 Task Calendar GUID \u2713 \u2713 Task Mode \u2713 Task Name \u2713 \u2713 \u2713 \u2713 Total Slack \u2713 \u2713 \u2713 \u2713 Type \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 WBS \u2713 \u2713 \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields_1","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Duration \u2713 \u2713 \u2713 Baseline1 Duration Units \u2713 \u2713 Baseline1 Estimated Duration \u2713 Baseline1 Estimated Finish \u2713 Baseline1 Estimated Start \u2713 Baseline1 Finish \u2713 \u2713 \u2713 Baseline1 Fixed Cost \u2713 \u2713 \u2713 Baseline1 Fixed Cost Accrual \u2713 \u2713 Baseline1 Start \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Duration \u2713 \u2713 \u2713 Baseline2 Duration Units \u2713 \u2713 Baseline2 Estimated Duration \u2713 Baseline2 Estimated Finish \u2713 Baseline2 Estimated Start \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Fixed Cost \u2713 \u2713 \u2713 Baseline2 Fixed Cost Accrual \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Duration \u2713 \u2713 \u2713 Baseline3 Duration Units \u2713 \u2713 Baseline3 Estimated Duration \u2713 Baseline3 Estimated Finish \u2713 Baseline3 Estimated Start \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Fixed Cost \u2713 \u2713 \u2713 Baseline3 Fixed Cost Accrual \u2713 \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Duration \u2713 \u2713 \u2713 Baseline4 Duration Units \u2713 \u2713 Baseline4 Estimated Duration \u2713 Baseline4 Estimated Finish \u2713 Baseline4 Estimated Start \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Fixed Cost \u2713 \u2713 \u2713 Baseline4 Fixed Cost Accrual \u2713 \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Duration \u2713 \u2713 \u2713 Baseline5 Duration Units \u2713 \u2713 Baseline5 Estimated Duration \u2713 Baseline5 Estimated Finish \u2713 Baseline5 Estimated Start \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Fixed Cost \u2713 \u2713 \u2713 Baseline5 Fixed Cost Accrual \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Duration \u2713 \u2713 \u2713 Baseline6 Duration Units \u2713 \u2713 Baseline6 Estimated Duration \u2713 Baseline6 Estimated Finish \u2713 Baseline6 Estimated Start \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Fixed Cost \u2713 \u2713 \u2713 Baseline6 Fixed Cost Accrual \u2713 \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Duration \u2713 \u2713 \u2713 Baseline7 Duration Units \u2713 \u2713 Baseline7 Estimated Duration \u2713 Baseline7 Estimated Finish \u2713 Baseline7 Estimated Start \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Fixed Cost \u2713 \u2713 \u2713 Baseline7 Fixed Cost Accrual \u2713 \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Duration \u2713 \u2713 \u2713 Baseline8 Duration Units \u2713 \u2713 Baseline8 Estimated Duration \u2713 Baseline8 Estimated Finish \u2713 Baseline8 Estimated Start \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Fixed Cost \u2713 \u2713 \u2713 Baseline8 Fixed Cost Accrual \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Duration \u2713 \u2713 \u2713 Baseline9 Duration Units \u2713 \u2713 Baseline9 Estimated Duration \u2713 Baseline9 Estimated Finish \u2713 Baseline9 Estimated Start \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Fixed Cost \u2713 \u2713 \u2713 Baseline9 Fixed Cost Accrual \u2713 \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Deliverable Finish \u2713 Baseline10 Duration \u2713 \u2713 \u2713 Baseline10 Duration Units \u2713 \u2713 Baseline10 Estimated Duration \u2713 Baseline10 Estimated Finish \u2713 Baseline10 Estimated Start \u2713 Baseline10 Finish \u2713 \u2713 \u2713 Baseline10 Fixed Cost \u2713 \u2713 \u2713 Baseline10 Fixed Cost Accrual \u2713 \u2713 Baseline10 Start \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 \u2713 Baseline Deliverable Finish \u2713 Baseline Deliverable Start \u2713 Baseline Duration \u2713 \u2713 \u2713 \u2713 Baseline Duration Units \u2713 \u2713 \u2713 Baseline Estimated Duration \u2713 Baseline Estimated Finish \u2713 Baseline Estimated Start \u2713 Baseline Finish \u2713 \u2713 \u2713 \u2713 Baseline Fixed Cost \u2713 \u2713 \u2713 Baseline Fixed Cost Accrual \u2713 \u2713 Baseline Start \u2713 \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#custom-fields","title":"Custom Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 \u2713 Duration1 Units \u2713 \u2713 \u2713 Duration2 \u2713 \u2713 \u2713 \u2713 Duration2 Units \u2713 \u2713 \u2713 Duration3 \u2713 \u2713 \u2713 \u2713 Duration3 Units \u2713 \u2713 \u2713 Duration4 \u2713 \u2713 \u2713 \u2713 Duration4 Units \u2713 \u2713 \u2713 Duration5 \u2713 \u2713 \u2713 \u2713 Duration5 Units \u2713 \u2713 \u2713 Duration6 \u2713 \u2713 \u2713 \u2713 Duration6 Units \u2713 \u2713 \u2713 Duration7 \u2713 \u2713 \u2713 \u2713 Duration7 Units \u2713 \u2713 \u2713 Duration8 \u2713 \u2713 \u2713 \u2713 Duration8 Units \u2713 \u2713 \u2713 Duration9 \u2713 \u2713 \u2713 \u2713 Duration9 Units \u2713 \u2713 \u2713 Duration10 \u2713 \u2713 \u2713 \u2713 Duration10 Units \u2713 \u2713 \u2713 Finish1 \u2713 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 \u2713 \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 \u2713 \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 \u2713 \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 \u2713 \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 \u2713 \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 \u2713 \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 \u2713 \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 \u2713 \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 \u2713 \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#enterprise-fields","title":"Enterprise Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Enterprise Data \u2713 Enterprise Duration1 Units \u2713 \u2713 Enterprise Duration2 Units \u2713 \u2713 Enterprise Duration3 Units \u2713 \u2713 Enterprise Duration4 Units \u2713 \u2713 Enterprise Duration5 Units \u2713 \u2713 Enterprise Duration6 Units \u2713 \u2713 Enterprise Duration7 Units \u2713 \u2713 Enterprise Duration8 Units \u2713 \u2713 Enterprise Duration9 Units \u2713 \u2713 Enterprise Duration10 Units \u2713 \u2713 Enterprise Project Date1 \u2713 Enterprise Project Date2 \u2713 Enterprise Project Date3 \u2713 Enterprise Project Date4 \u2713 Enterprise Project Number2 \u2713 Enterprise Project Number4 \u2713 Enterprise Project Number5 \u2713 Enterprise Project Number22 \u2713 Enterprise Project Text1 \u2713 \u2713 \u2713 Enterprise Project Text2 \u2713 \u2713 Enterprise Project Text3 \u2713 \u2713 Enterprise Project Text4 \u2713 \u2713 Enterprise Project Text5 \u2713 Enterprise Project Text6 \u2713 \u2713 Enterprise Project Text8 \u2713 Enterprise Project Text9 \u2713 Enterprise Project Text10 \u2713 Enterprise Project Text11 \u2713 Enterprise Project Text12 \u2713 Enterprise Project Text13 \u2713 Enterprise Project Text14 \u2713 Enterprise Project Text15 \u2713 Enterprise Project Text16 \u2713 Enterprise Project Text17 \u2713 Enterprise Project Text18 \u2713 Enterprise Project Text19 \u2713 Enterprise Project Text21 \u2713 Enterprise Project Text40 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#resource","title":"Resource","text":""},{"location":"mpp-field-guide/#core-fields_2","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Accrue At \u2713 \u2713 \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Availability Data \u2713 \u2713 \u2713 Available From \u2713 \u2713 \u2713 Available To \u2713 \u2713 \u2713 Booking Type \u2713 \u2713 Budget \u2713 \u2713 Budget Cost \u2713 \u2713 \u2713 Budget Work \u2713 \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 Calendar GUID \u2713 \u2713 Calendar Unique ID \u2713 \u2713 \u2713 \u2713 Code \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Center \u2713 Cost Per Use \u2713 \u2713 \u2713 Cost Rate A \u2713 \u2713 \u2713 Cost Rate B \u2713 \u2713 \u2713 Cost Rate C \u2713 \u2713 \u2713 Cost Rate D \u2713 \u2713 \u2713 Cost Rate E \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 Default Units \u2713 \u2713 \u2713 \u2713 Email Address \u2713 \u2713 \u2713 GUID \u2713 \u2713 Generic \u2713 \u2713 \u2713 Group \u2713 \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 Hyperlink Data \u2713 \u2713 \u2713 Hyperlink Screen Tip \u2713 \u2713 \u2713 Hyperlink SubAddress \u2713 \u2713 \u2713 ID \u2713 \u2713 \u2713 \u2713 Initials \u2713 \u2713 \u2713 \u2713 Material Label \u2713 \u2713 \u2713 Max Units \u2713 \u2713 \u2713 Name \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 Overallocated \u2713 \u2713 \u2713 \u2713 Overtime Cost \u2713 \u2713 \u2713 Overtime Rate \u2713 \u2713 \u2713 Overtime Rate Units \u2713 \u2713 \u2713 Overtime Work \u2713 \u2713 \u2713 Peak \u2713 \u2713 \u2713 \u2713 Phonetics \u2713 Regular Work \u2713 \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Standard Rate \u2713 \u2713 \u2713 Standard Rate Units \u2713 \u2713 \u2713 Subproject Unique Resource ID \u2713 \u2713 Type \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 Unit of Measure Unique ID \u2713 \u2713 \u2713 Windows User Account \u2713 \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713 Workgroup \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields_2","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Budget Cost \u2713 Baseline1 Budget Work \u2713 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Budget Cost \u2713 Baseline2 Budget Work \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Budget Cost \u2713 Baseline3 Budget Work \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Budget Cost \u2713 Baseline4 Budget Work \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Budget Cost \u2713 Baseline5 Budget Work \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Budget Cost \u2713 Baseline6 Budget Work \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Budget Cost \u2713 Baseline7 Budget Work \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Budget Cost \u2713 Baseline8 Budget Work \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Budget Cost \u2713 Baseline9 Budget Work \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Budget Cost \u2713 Baseline10 Budget Work \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#custom-fields_1","title":"Custom Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 \u2713 \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 \u2713 \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 \u2713 \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 \u2713 \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 \u2713 \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 \u2713 \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 \u2713 \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 \u2713 \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 \u2713 \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 \u2713 \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 \u2713 \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 \u2713 \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 \u2713 \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 \u2713 \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 \u2713 \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 \u2713 \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 \u2713 \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 \u2713 \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 \u2713 \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#enterprise-fields_1","title":"Enterprise Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Enterprise \u2713 \u2713 Enterprise Data \u2713 Enterprise Duration1 Units \u2713 \u2713 Enterprise Duration2 Units \u2713 \u2713 Enterprise Duration3 Units \u2713 \u2713 Enterprise Duration4 Units \u2713 \u2713 Enterprise Duration5 Units \u2713 \u2713 Enterprise Duration6 Units \u2713 \u2713 Enterprise Duration7 Units \u2713 \u2713 Enterprise Duration8 Units \u2713 \u2713 Enterprise Duration9 Units \u2713 \u2713 Enterprise Duration10 Units \u2713 \u2713 Enterprise Unique ID \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#resource-assignment","title":"Resource Assignment","text":""},{"location":"mpp-field-guide/#core-fields_3","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Actual Cost \u2713 \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Assignment Delay \u2713 \u2713 \u2713 Assignment GUID \u2713 \u2713 Assignment Resource GUID \u2713 \u2713 Assignment Task GUID \u2713 \u2713 Assignment Units \u2713 \u2713 \u2713 \u2713 Budget Cost \u2713 \u2713 Budget Work \u2713 \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 Confirmed \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Rate Table \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 Finish \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 Hyperlink Data \u2713 \u2713 \u2713 Hyperlink Screen Tip \u2713 \u2713 \u2713 Hyperlink Subaddress \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 \u2713 Leveling Delay Units \u2713 \u2713 Linked Fields \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 Overtime Work \u2713 \u2713 \u2713 Owner \u2713 \u2713 Percent Work Complete \u2713 \u2713 \u2713 \u2713 Rate Source \u2713 \u2713 \u2713 \u2713 Regular Work \u2713 \u2713 \u2713 Remaining Assignment Units \u2713 \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Resource Request Type \u2713 \u2713 Resource Unique ID \u2713 \u2713 \u2713 \u2713 Response Pending \u2713 \u2713 \u2713 Resume \u2713 \u2713 \u2713 Start \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 Task Unique ID \u2713 \u2713 \u2713 \u2713 Team Status Pending \u2713 \u2713 \u2713 Timephased Actual Overtime Work \u2713 \u2713 \u2713 Timephased Actual Work \u2713 \u2713 \u2713 Timephased Work \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 Variable Rate Units \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Contour \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields_3","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Budget Cost \u2713 \u2713 Baseline1 Budget Work \u2713 \u2713 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Finish \u2713 \u2713 \u2713 Baseline1 Start \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Budget Cost \u2713 \u2713 Baseline2 Budget Work \u2713 \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Budget Cost \u2713 \u2713 Baseline3 Budget Work \u2713 \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Budget Cost \u2713 \u2713 Baseline4 Budget Work \u2713 \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Budget Cost \u2713 \u2713 Baseline5 Budget Work \u2713 \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Budget Cost \u2713 \u2713 Baseline6 Budget Work \u2713 \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Budget Cost \u2713 \u2713 Baseline7 Budget Work \u2713 \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Budget Cost \u2713 \u2713 Baseline8 Budget Work \u2713 \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Budget Cost \u2713 \u2713 Baseline9 Budget Work \u2713 \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Budget Cost \u2713 \u2713 Baseline10 Budget Work \u2713 \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Finish \u2713 \u2713 \u2713 Baseline10 Start \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 \u2713 Baseline Budget Work \u2713 \u2713 Baseline Cost \u2713 \u2713 \u2713 Baseline Finish \u2713 \u2713 \u2713 Baseline Start \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 Timephased Baseline1 Cost \u2713 \u2713 \u2713 Timephased Baseline1 Work \u2713 \u2713 \u2713 Timephased Baseline2 Cost \u2713 \u2713 Timephased Baseline2 Work \u2713 \u2713 Timephased Baseline3 Cost \u2713 \u2713 Timephased Baseline3 Work \u2713 \u2713 Timephased Baseline4 Cost \u2713 \u2713 Timephased Baseline4 Work \u2713 \u2713 Timephased Baseline5 Cost \u2713 \u2713 Timephased Baseline5 Work \u2713 \u2713 Timephased Baseline6 Cost \u2713 \u2713 Timephased Baseline6 Work \u2713 \u2713 Timephased Baseline7 Cost \u2713 \u2713 Timephased Baseline7 Work \u2713 \u2713 Timephased Baseline8 Cost \u2713 \u2713 Timephased Baseline8 Work \u2713 \u2713 Timephased Baseline9 Cost \u2713 \u2713 Timephased Baseline9 Work \u2713 \u2713 Timephased Baseline10 Cost \u2713 \u2713 \u2713 Timephased Baseline10 Work \u2713 \u2713 \u2713 Timephased Baseline Cost \u2713 \u2713 \u2713 Timephased Baseline Work \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#custom-fields_2","title":"Custom Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 \u2713 \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 \u2713 \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 \u2713 \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 \u2713 \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 \u2713 \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 \u2713 \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 \u2713 \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 \u2713 \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 \u2713 \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 \u2713 \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"support/","title":"Support","text":"

Support and feature requests can be opened on MPXJ's issue tracker. I will respond to these as time permits.

For more pressing issues, commercial support is available via my company Timephased. I can also provide consultancy around the use of MPXJ and implementation services. Please contact me directly for further details.

"},{"location":"supported-formats/","title":"Supported Formats","text":"
  • MPX: The MPX file format can be read by versions of Microsoft Project up to and including Microsoft Project 2010, and written by versions of Microsoft Project up to Microsoft Project 98. Applications other than Microsoft Project also commonly write MPX files as a way of sharing project data. MPXJ can read and write MPX files. See this Microsoft support article for a definition of the file format.

  • MPP: Microsoft Project by default stores projects as MPP files. MPXJ supports read only access to MPP files produced by Microsoft Project from Microsoft Project 98 onwards (Microsoft Project 98, Microsoft Project 2000, Microsoft Project 2002, Microsoft Project 2003, Microsoft Project 2007, Microsoft Project 2010, Microsoft Project 2013, Microsoft Project 2016, and Microsoft Project 2019). MPP template files, with the suffix MPT can also be read by MPXJ.

  • MSPDI: The MSPDI file format is Microsoft's XML file format for sharing project data. Versions of Microsoft Project from 2002 onwards can read and write MSPDI files. Applications other than Microsoft Project also commonly write MSPDI files as a way of sharing project data. MPXJ can read and write MSPDI files. The MSDPI file format has remained broadly unchanged since it was introduced, although several versions of Microsoft Project have tweaked the file format slightly, and have their own updated documentation. Documentation is available online here. Documentation for the Project 2003 MSPDI file format can be downloaded as part of the Office 2003 XML Reference Schemas package. Documentation for the Project 2007 MSPDI file format can be downloaded as part of the Project 2007 SDK. Documentation for the Project 2010 MSPDI file format can be downloaded as part of the Project 2010 Reference: Software Development Kit. Documentation for the Project 2013 MSPDI file format can be downloaded as part of the Project 2013 SDK.

  • MPD: The Microsoft Project MPD file format is a Microsoft Access database used to store one or more projects. Versions of Microsoft Project from Microsoft Project 98 to Microsoft Project 2003 can write MPD files. Later versions of Microsoft Project can read MPD files but can't write them. MPXJ can read MPD files natively, without using a JDBC driver, or via a JDBC connection. MPXJ supports reading MPD files written by versions of Microsoft Project 2000 onwards.

  • PLANNER: Gnome Planner is a cross-platform Open Source project management tool which uses an XML file format to store project data. MPXJ can read and write Planner files.

  • PRIMAVERA P6: Primavera P6 is an industry-leading tool favoured by users with complex planning requirements. It can export project data in the form of XER or PMXML files, both of which MPXJ can read and write. It is also possible for MPXJ to connect directly to a P6 database via JDBC to read project data, or if a standalone SQLite P6 database is being used, MPXJ can read projects from this natively without using JDBC. The PMXML schema forms part of the P6 distribution media, which can be downloaded from the Oracle Software Delivery Cloud.

  • PRIMAVERA P3: Primavera P3 (Primavera Project Planner) is the forerunner of P6. It stores each project as a directory containing Btrieve database files which MPXJ can read from the directory itself or from a zip archive of the directory. MPXJ can also read P3 data from PRX backup files.

  • PRIMAVERA SURETRAK: Primavera SureTrak is an early iteration of the application which eventually became Primavera P6. SureTrak stores each project as a directory containing Btrieve database files which MPXJ can read from the directory itself or from a zip archive of the directory. MPXJ can also read SureTrak data from STX backup files.

  • POWERPROJECT: Asta Powerproject is a planning tool used in a number of industries, particularly construction. Powerproject saves data to PP files. MPXJ can read PP files produced by Powerproject version 8 onwards (although earlier versions may also be supported). Powerproject can also write one or more projects to MDB (Microsoft Access) database files which MPXJ can read natively without a JDBC driver, or via a JDBC connection.

  • PHOENIX: Phoenix Project Manager is an easy-to-use critical path method scheduling tool aimed primarily at the construction industry. Phoenix stores projects as XML files with the file extension PPX. MPXJ can read PPX files written by Phoenix from version 4 onwards.

  • FASTTRACK: Fasttrack Schedule is general purpose planning tool. FastTrack stores projects as FTX files. MPXJ can read FTX files written by Fasttrack version 10 onwards, although FTX files written by earlier versions may be supported.

  • GANTTPROJECT: GanttProject is an open source general purpose planning tool. GanttProject stores projects as GAN files, which can be read by MPXJ.

  • TURBOPROJECT: TurboProject is general purpose planning tool. TurboProject store projects as PEP files, which can be read by MPXJ.

  • CONECPTDRAW PROJECT: ConceptDraw PROJECT is general purpose planning tool. ConceptDraw PROJECT writes CDPX, CDPZ and CDPTZ files which MPXJ can read.

  • SYNCHRO SCHEDULER: Synchro Scheduler is general purpose planning tool from Bentley Systems. Synchro Scheduler stores projects as SP files. MPXJ can read SP files written by Synchro Scheduler version 6 and onwards, although SP files written by earlier versions may be supported.

  • GANTT DESIGNER: Gantt Designer is a simple Gantt chart drawing tool. Gantt Designer stores projects as GNT files, which can be read using MPXJ.

  • SDEF: SDEF is the Standard Data Exchange Format, as defined by the United States Army Corps of Engineers (USACE). SDEF is a fixed column format text file, used to export a project schedule to the QCS (Quality Control System) software from USACE. MPXJ can read and write SDEF files.

  • SCHEDULE_GRID: Sage 100 Contractor is an application for small to medium sized companies in the construction industry, providing accounting, and estimating and project management functionality. Project plans managed in Sage 100 Contractor can be exported as schedule grid files, which can be read by MPXJ.

  • PROJECT COMMANDER: Project Commander is a general purpose project planning application. Project Commander stores projects as PC files. PC files written by Project Commander version 7 and onwards can be read by MPXJ, although PC files written by earlier versions may be supported.

  • DELTEK OPEN PLAN: Deltek Open Plan Deltek Open Plan is an enterprise project management application offering resource management, critical path analysis, and customizable reporting. Projects managed in Open Plan can be exported to BK3 files, which can be read by MPXJ.

"},{"location":"users/","title":"MPXJ Users","text":"

Here is a list of organisations and projects currently using, or believed to be using MPXJ. Feel free to contact me if you would like to be featured in this list.

  • ]project-open[ www.project-open.com
  • a-dato www.a-dato.net
  • Afinion Project Viewer www.afinion.de
  • allProView www.allproview.com
  • Atlas Authority atlasauthority.com
  • Aurea Savvion BPM Studio www.aurea.com
  • Autodesk Build \u2013 Schedule construction.autodesk.com/products/autodesk-build/
  • Bosch RefinemySite www.bosch-refinemysite.com
  • Bryntum bryntum.com
  • Buildots buildots.com
  • Celoxis www.celoxis.com
  • Change Inspector www.changeinspector.com
  • Comindwork www.comindwork.com
  • Complex Data Exchange www.informatica.com
  • ConceptDraw www.conceptdraw.com/
  • Concourse concourse.tools
  • CS Project www.crestsoftware.co.uk/cs-project/planning/
  • CV Projects www.cvprojects.com
  • DHTMLX Gantt dhtmlx.com/docs/products/dhtmlxGantt
  • DTP www.parasoft.com/products/parasoft-dtp
  • eProject www.eprocorp.com
  • Exicom www.exicom.se/en
  • FastTrack Schedule www.aecsoftware.com
  • forProject www.forproject.com
  • Frontline www.frontlinec.com
  • Gantt Designer timios.net/Gantt
  • Gantter gantter.com
  • GanttPro ganttpro.com
  • GanttProject www.ganttproject.biz
  • Ganttzilla www.ganttzilla.com
  • GIS PAM www.gish.de
  • Housatonic Project Viewer Central www.projectviewercentral.com
  • HPE Project and Portfolio Management Center admhelp.microfocus.com/ppm
  • HudsonFog www.hudsonfog.com
  • i-lign www.ilign.com
  • IBM TRIRIGA www.ibm.com/uk-en/marketplace/ibm-tririga
  • Incremental www.incremental.eu.com
  • Ingantt ingantt.com
  • Intellisys www.webintellisys.com
  • Lean Station leanstation.com/
  • LibrePlan www.libreplan.dev
  • Lighthouse www.artifactsoftware.com
  • LiveProject www.kadonk.com
  • Merlin www.projectwizards.net
  • Milestones Professional kidasa.com
  • MOOS Project Viewer www.moosprojectviewer.com
  • mpower www.monitor-mpower.com
  • Mpp Viewer www.sourceforge.net/projects/mppviewer
  • MsProjecttools www.msprojecttools.com
  • OmniPlan www.omnigroup.com
  • OnePager www.onepager.com
  • Onepoint Project www.onepoint-project.com
  • Opdec www.opdec.com
  • OpenProj openproj.org
  • Pavone www.pavone.com
  • Pemari www.pemari.com
  • PIEmatrix piematrix.com
  • PlantSight www.bentley.com/en/products/brands/plantsight
  • Plexus www.plexsusplanning.com
  • Predict! www.riskdecisions.com
  • Primavera Unifier www.oracle.com/industries/construction-engineering/unifier-facilities-asset-management/
  • Procore www.procore.com
  • ProjectForge www.projectforge.org
  • PROJECT in a box projectinabox.org.uk
  • Project Kit www.methodpark.de
  • ProjectLibre www.projectlibre.org
  • Projec.to Online Microsoft Project Viewer www.onlineprojectviewer.com/
  • ProjExec www.triloggroup.com
  • RationalPlan www.rationalplan.com
  • Safran www.safran.com
  • SAP Conversion Agent by Informatica help.sap.com
  • SharedPlan www.sharedplan.com
  • Siemens COMOS www.siemens.com/global/en/products/automation/industry-software/plant-engineering-software-comos.html
  • SmartWorks www.smartworks.us/
  • StaffPM code.google.com/p/mhe3-staffpm
  • Steelray Project Viewer www.steelray.com
  • Tamara www.vosesoftware.com/products/tamara
  • Task Adapter www.taskadapter.com
  • Team Elements sourceforge.net/projects/teamelements
  • Teamwork www.twproject.com
  • ThoughtWeb www.thoughtweb.com
  • Timenow timenow.com.br
  • TrackStudio www.trackstudio.com
  • Turbo Chart - Linear Project Software turbo-chart.com
  • Virtuelle Projektverwaltung www.swissasp.ch
  • VisiLean visilean.com
  • Windchill ProjectLink www.ptc.com/products/windchill-projectlink
  • Workfront www.workfront.com
  • Xena xena.sourceforge.net
  • xPlanner www.xplanner.org
  • xProcess www.openxprocess.com
  • Zilicus www.zilicus.com
  • ZTimeView www.tuwien.ac.at
  • Zurvan Planning zurvan-planning.com
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Introduction","text":"

Welcome to MPXJ! This library enables you to read project plans (sometimes known as schedules or programmes) from a variety of file formats and databases, and can also write that information to a variety of file formats.

The library is based on data structures which follow the way schedule data is represented by Microsoft Project, extended to accommodate features and concepts from other applications.

"},{"location":"#sponsors","title":"Sponsors","text":"

Work to build and maintain MPXJ is kindly supported by my sponsors:

Head over to my sponsors page if you'd like to see your name and logo here, or if you just want to say thanks you could buy me a coffee!

"},{"location":"#file-formats","title":"File Formats","text":"

MPXJ can read file formats including MPX, MPP, MSPDI, MPD, Planner, Primavera P6 PMXML and XER, Primavera P3, SureTrak, Asta Powerproject, Asta Easyplan, Phoenix, Fasttrack, GanttProject, TurboProject, ConceptDraw PROJECT, Synchro, Gantt Designer, SDEF, Sage 100 Contractor Schedule Grid, Project Commander and Deltek Open Plan BK3.

MPXJ can also write schedule data as MPX, MSPDI, PMXML, XER, Planner and SDEF files.

More details of the supported file formats can be found here.

"},{"location":"#languages","title":"Languages","text":"

MPXJ is written and maintained in Java, however this is no barrier to using its functionality in other languages. Thanks to IKVM, MPXJ is available for .Net, allowing it to be used from any .Net language.

There is also now a Ruby Gem which provides native Ruby access to read from schedule files using MPXJ, and a Python package which wraps the Java library to provide full read/write access to schedule files.

You may be able to leverage MPXJ from other languages too, for example the PHP/Java Bridge can be used to expose the complete MPXJ API in PHP.

"},{"location":"#contact","title":"Contact","text":"

Having problems? Need support? All the details you need can be found on the support page.

Using MPXJ successfully somewhere? I'd love to hear from you about your experiences. Do tell me what's missing or what could be better - I can use this feedback to guide future development work. It would also be great to add a link to your website from the MPXJ users page.

Finally, if you're deriving value from MPXJ, please consider sponsoring me, to ensure I can continue enhancing and maintaining the library, or just buy me a coffee - thank you!

"},{"location":"#licensing","title":"Licensing","text":"

MPXJ is distributed under the terms of the GNU LGPL a copy of which can be found in the root of the distribution. Please read this license carefully! It will cost you nothing to use MPXJ commercially or non-commercially, but you must comply with the terms of the license.

Please see the legal folder within the distribution for details of the licences for the third party libraries used by MPXJ.

"},{"location":"#acknowledgements","title":"Acknowledgements","text":"

This library includes functionality provided by:

  • POI
  • IKVM
  • RTF Parser Kit
  • SQLITE-JDBC
  • ZLIB/CONTRIB
  • JWAT
  • JSOUP

This library has been built with the assistance of:

  • JProfiler
  • Araxis Merge
"},{"location":"CHANGELOG/","title":"Changelog","text":""},{"location":"CHANGELOG/#1361-unreleased","title":"13.6.1 (unreleased)","text":"
  • Update the MPXJ ruby gem to allow access to calendar data.
"},{"location":"CHANGELOG/#1360-2024-11-06","title":"13.6.0 (2024-11-06)","text":"
  • Added the Task.getBaselineTask() methods. For applications where a separate baseline schedule is present or a baseline has been manually added to the ProjectFile instance, these methods will allow you to access the underlying baseline task instance from the current task instance.
  • Added the Activity Percent Complete attribute to the Task class. The value of this attribute will be the Duration, Physical or Units percent complete value, based on the Percent Complete Type setting. This attribute is provided as a convenience to match the Activity Percent Complete type value shown in P6.
  • Improve retrieval of custom field values for certain MPP files.
  • Improve handling of PMXML files with more than 11 baselines.
  • Improve handling of unexpected data types when writing JSON files.
  • Added the Relation.getPredecessorTask() and Relation.getSuccessorTask() methods.
  • Marked the Relation.getSourceTask() and Relation.getTargetTask() methods as deprecated, use the Relation.getPredecessorTask() and Relation.getSuccessorTask() instead.
  • Ensure that with \"Link Cross Project Relations\" enabled when reading XER or PMXML files, the predecessor and successor lists for both tasks related acrosss projects are correctly populated.
"},{"location":"CHANGELOG/#1351-2024-10-28","title":"13.5.1 (2024-10-28)","text":"
  • Fix CVE-2024-49771: Potential Path Traversal Vulnerability (Contributed by yyjLF and sprinkle).
"},{"location":"CHANGELOG/#1350-2024-10-17","title":"13.5.0 (2024-10-17)","text":"
  • Added support for reading and writing Resource Role Assignments for Primavera schedules. The Resource.getRoleAssignments() method retrieves a map representing the roles a resource is assigned to, along with the skill level for each assignment. The Resource.addRoleAssignment() and Resource.removeRoleAssignment() methods allow role assignments to be added and removed.
  • Added support for the Resource Primary Role attribute, which is read from and written to Primavera schedules.
  • Improve handling Boolean attributes with default values when reading XER files.
  • Added the getShowStartText, getShowFinishText and getShowDurationText methods to the Task class. When working with manually scheduled tasks in Microsoft Project, users can potentially supply arbitrary text for the Start, Finish and Duration attributes. Microsoft Project still stores appropriate values for these attributes, which can be accessed in MPXJ as Start, Finish and Duration, but where the user has supplied text, these attributes are available as Start Text, Finish Text, and Duration Text. The methods added by this change allow the caller to determine which version of each attribute should be shown to the user in order to replicate what they see in Microsoft Project.
"},{"location":"CHANGELOG/#1342-2024-10-08","title":"13.4.2 (2024-10-08)","text":"
  • Added the ProjectCalendarDays.getCalendarHours() method to allow direct access to the ProjectCalendarHours instances for each day of the week.
"},{"location":"CHANGELOG/#1341-2024-10-07","title":"13.4.1 (2024-10-07)","text":"
  • Added the ProjectCalendarDays.getCalendarDayTypes() method to allow direct access to the DayType instances for each day of the week.
"},{"location":"CHANGELOG/#1340-2024-09-18","title":"13.4.0 (2024-09-18)","text":"
  • Added support for reading and writing resource shifts for P6 schedules.
  • Ensure the Scheduling Progressed Activities project property is populated when reading Phoenix schedules.
  • When reading milestones from an Asta schedule, ensure that the Activity Type attribute is populated to allow start milestones and finish milestones to be differentiated.
  • Fix an issue which occurred when writing MSPDI files with manually scheduled tasks starting on non-working days where their timephased data is split as days.
"},{"location":"CHANGELOG/#1331-2024-08-30","title":"13.3.1 (2024-08-30)","text":"
  • Handle duplicate custom field value unique IDs when reading MSPDI files.
  • Handle missing remaining early start date when reading timephased data from a P6 schedule.
"},{"location":"CHANGELOG/#1330-2024-08-22","title":"13.3.0 (2024-08-22)","text":"
  • When reading multiple Primavera schedules from the same source, MPXJ now ensures that instances of activity code definitions, user defined field definitions, locations, units of measure, expense categories, cost accounts, work contours, and notes topics are shared across projects. This will allow you to, for example, filter tasks from multiple projects using a Location instance. Previously each project had its own independent instances for each of these types, which could not be used across multiple projects.
  • When reading Powerproject schedules, ensure that the Activity ID attribute for WBS entries is populated using Powerproject's Unique Task ID attribute.
  • Add support for reading timephased planned work from MPP files for manually scheduled tasks (Contributed by Fabian Schmidt).
"},{"location":"CHANGELOG/#1322-2024-08-14","title":"13.2.2 (2024-08-14)","text":"
  • Add missing constructors to TimephasedCost and TimephasedWork in MPXJ.Net.
"},{"location":"CHANGELOG/#1321-2024-08-13","title":"13.2.1 (2024-08-13)","text":"
  • Make the MPXJ.Net assembly strong named.
"},{"location":"CHANGELOG/#1320-2024-08-12","title":"13.2.0 (2024-08-12)","text":"
  • Implemented the UserDefinedField.Builder class.
  • Marked the UserDefinedField constructor as deprecated. Use the builder class instead.
  • Marked the UserDefinedField.setDataType() method as deprecated. Use the builder class instead.
  • Updated to address an issue when writing XER files where a project does not have an explicit Unique ID value, and there are project UDF values.
  • Added the convenience method ActivityCode.addValue to make it easier to add a value to an activity code.
"},{"location":"CHANGELOG/#1310-2024-07-26","title":"13.1.0 (2024-07-26)","text":"
  • Updated to POI 5.3.0
  • Add support for reading and writing timephased data for activities in P6 schedules which have a \"manual\" curve. (Note: MPXJ does not currently support translating timephased data between different applications, so timephased data read from an MPP file won't be written to a P6 schedule and vice versa).
  • Add an attribute to the ResourceAssignment class to represent timephased planned work. This is read from/written to P6 as Budgeted Work.
  • Update Phoenix schemas to ensure that cost types are represented as doubles.
  • Updated to avoid reading apparently invalid resources from Project Commander files.
  • Correct the Finish attribute for resource assignments when reading PMXML files.
  • Improve accuracy of the RemainingDuration attribute for resource assignments when writing PMXML files.
  • Improve recognition of non-working days when reading calendars certain PMXML files.
  • Add support for the Resource Assignment field Remaining Units. (Note: this field defaults to the same value as Units if it is not explicitly populated).
  • Ensure the Resource Assignment field Remaining Units is read from and written to P6 schedules.
  • Improve handling of invalid calendar exception data when reading P6 schedules from XER files or a P6 database.
  • Improve the implementation of the Unique ID sequence generator used by MPXJ to avoid issues when multiple classloaders are used.
  • Deprecated the original StructuredNotes constructor. A new version of the constructor takes an additional ProjectFile argument.
  • Deprecated the original UserDefinedField constructor. A new version of the constructor takes an additional ProjectFile argument.
  • Add support for reading and writing the Project Website URL attribute for P6 schedules.
  • Add support for the Notes attribute as part of the ProjectProperties class.
  • Ensure that project notes are read from and written to PMXML files.
  • Usability improvements to the Notes class hierarchy to make it easier to update notes.
  • Improvements to notes handling when writing PMXML files to make it easier to construct structured notes using plain text.
"},{"location":"CHANGELOG/#1302-2024-07-08","title":"13.0.2 (2024-07-08)","text":"
  • When writing XER files, provide a default value for the Resource ID if it is not populated.
"},{"location":"CHANGELOG/#1301-2024-07-04","title":"13.0.1 (2024-07-04)","text":"
  • For XER files, ignore the \"null\" resource when writing resource rates.
  • When reading MPP files, ensure that Enterprise Custom Field Unique IDs are unique across entities.
"},{"location":"CHANGELOG/#1300-2024-06-20","title":"13.0.0 (2024-06-20)","text":"
  • NOTE: this is a major release containing breaking changes. When updating from a 12.x release it is recommended that you first update to the most recent 12.x release and deal with any deprecation warnings before moving to this release.
  • NOTE: the original net.sf.mpxj NuGet packages are now deprecated and will be replaced by the MPXJ.Net NuGet Package in the next major MPXJ release. The net.sf.mpxj packages will continue to be maintained until then, at which point they will no longer be distributed. Please migrate your code to use MPXJ.Net at the earliest opportunity, and open an issue in the GitHUb issue tracker if you encounter problems.
  • Updated to use JAXB3. Among other things this change ensures compatibility with Spring Boot 3. Note that this may be a breaking change for you if you own application uses JAXB2.
  • When reading P6 schedules, the custom properties (as retrieved using ProjectProperties.getCustomProperties) will no longer contain scheduling options. These are now all available as attributes of the ProjectProperties class.
  • Removed redundant setUniqueID methods from immutable objects. These previously threw UnsupportedOperationException when called.
  • The ProjectEntityWithUniqueID interface no longer contains the setUniqueID method. Entities with a mutable Unique ID attribute now implement the ProjectEntityWithMutableUniqueID interface, which inherits from the ProjectEntityWithUniqueID interface.
  • The MSPDIReader and PrimaveraXERFileReader classes no longer provide getter and setter methods for Encoding, use the Charset getter and setter methods instead.
  • Removed the XerFieldType class and replaced usages of it with the DataType class.
  • The deprecated ActivityCode() constructor and addValue method have been removed.
  • The deprecated ActivityCodeValue() constructor and setParent method have been removed.
  • The deprecated CostAccount() constructor and getDescription method have been removed.
  • The deprecated CustomFieldValueItem methods getParent and setParent have been removed.
  • The deprecated ExpenseCategory() constructor has been removed.
  • The deprecated ExpenseItem(Task) constructor and all setter methods have been removed.
  • The deprecated JsonWriter methods setEncoding and getEncoding have been removed.
  • The deprecated Location.Builder() constructor has been removed.
  • The deprecated NotesTopic() constructor has been removed.
  • The deprecated ObjectSequence method reset has been removed.
  • The deprecated PlannerWriter methods setEncoding and getEncoding have been removed.
  • The deprecated PrimaveraXERFileWriter method setEncoding has been removed.
  • The deprecated ProjectCalendar method getDate has been removed.
  • The deprecated ProjectCalendarHelper method getExpandedExceptionsWithWorkWeeks has been removed.
  • The deprecated ProjectEntityContainer methods getNextUniqueID, renumberUniqueIDs and updateUniqueIdCounter have been removed.
  • The deprecated ProjectFile methods expandSubprojects and updateUniqueIdCounters have been removed.
  • The deprecated ProjectReader method setProperties and setCharset have been removed.
  • The deprecated ProjectWriterUtility class has been removed.
  • The deprecated RateHelper methods accepting a ProjectFile argument have veen removed.
  • The deprecated Relation(Task,Task,RelationType,Duration) constructor has been removed.
  • The deprecated RelationContainer.addPredecessor(Task,Task,RelationType,Duration) method has been removed
  • The deprecated Resource methods setAvailableFrom, setAvailableTo, setMaterialLabel and setMaxUnits have been removed.
  • The deprecated ResourceAssignment method getCalendar has been removed.
  • The deprecated Step(Task) constructor and all setter methods have been removed.
  • The deprecated Task method addPredecessor(Task,RelationType,Duration) has been removed
  • The deprecated TimephasedUtility methods segmentBaselineWork(ProjectFile, ...) and segmentBaselineCost(ProjectFile, ...) methods have been removed.
  • The deprecated UnitOfMeasure.Builder() constructor has been removed.
"},{"location":"CHANGELOG/#12103-2024-06-14","title":"12.10.3 (2024-06-14)","text":"
  • Add new project property IsProjectBaseline. When using the readAll method to retrieve a set of schedules, if the data source contains both schedules and baselines this property will be true for the ProjectFile instances which represent a baseline.
"},{"location":"CHANGELOG/#12102-2024-06-03","title":"12.10.2 (2024-06-03)","text":"
  • Added a missing unique ID mapping when writing resource assignment resource unique IDs to MSPDI files (Contributed by Alex Matatov)
  • Handle null field type when reading outline code values from an MPP9 file.
"},{"location":"CHANGELOG/#12101-2024-05-22","title":"12.10.1 (2024-05-22)","text":"
  • Ignore missing PropertySets when reading MPP files (Contributed by Fabian Schmidt).
  • Corrected handling of the \"24 Hour Calendar\" Relationship Lag Calendar setting when reading and writing XER files (Based on a contribution by Alex Matatov)
"},{"location":"CHANGELOG/#12100-2024-05-13","title":"12.10.0 (2024-05-13)","text":"
  • When a baseline is added using one of the ProjectFile.setBaseline methods, ensure that the relevant baseline date is set in ProjectProperties.
  • Marked the JsonWriter methods setEncoding and getEncoding as deprecated, use setCharset and getCharset instead.
  • Marked the PlannerWriter methods setEncoding and getEncoding as deprecated, use setCharset and getCharset instead.
  • Marked the PrimaveraXERFileWriter method setEncoding as deprecated, use setCharset instead.
  • Marked the ProjectCalendarHelper method getExpandedExceptionsWithWorkWeeks as deprecated, use ProjectCalendar.getExpandedCalendarExceptionsWithWorkWeeks instead.
  • Marked the ProjectReader method setCharset as deprecated. Readers which support setting the Charset now implement the HasCharset interface, which includes Charset getter and setter methods.
  • Implemented the UniversalProjectWriter class. This complements the UniversalProjectReader class by providing a simple way for MPXJ users to write project files without having to be concerned with details of the individual ProjectWriter classes. This is intended to replace the ProjectWriterUtility class. Note that the ProjectWriterUtility has a somewhat brittle mechanism to determine the output file format from the supplied output file name. This is not replicated by UniversalProjectWriter, users are expected to provide their own code to determine the appropriate file format.
  • Marked the ProjectWriterUtility class as deprecated.
"},{"location":"CHANGELOG/#1293-2024-04-24","title":"12.9.3 (2024-04-24)","text":"
  • Improve handling of non-standard timestamp formats in XER files.
"},{"location":"CHANGELOG/#1292-2024-04-19","title":"12.9.2 (2024-04-19)","text":"
  • Ensure calendars in Asta schedules have the correct name.
  • Improve assignment of calendars to summary tasks when reading Asta schedules.
  • Preserve calendar hierarchy when reading Asta schedules.
"},{"location":"CHANGELOG/#1291-2024-04-17","title":"12.9.1 (2024-04-17)","text":"
  • Fix an issue where UniversalProjectReader would raise an exception when handling an unknown file type.
  • Ensure that resource type is included as part of the resource assignment data when writing PMXML files.
"},{"location":"CHANGELOG/#1290-2024-04-11","title":"12.9.0 (2024-04-11)","text":"
  • Updated UniversalProjectReader to add getProjectReaderProxy methods to allow access to the instance of the reader class which will be used to read a schedule, prior to the schedule being read. This will allow the reader to be configured, or schedule to be ignored without reading its content.
  • Deprecated the ProjectReader.setProperties method. This method was originally implemented to allow settings to be passed to reader classes when using UniversalProjectReader. You can now use UniversalProjectReader.getProjectReaderProxy to achieve this.
  • Add from method to all Builder classes to allow initialisation from existing objects.
  • The CostAccount.Builder class now provides two notes methods to allow formatted or unformatted notes to be added to cost accounts.
  • The CostAccount method getDescription() has been marked as deprecated. Use the getNotes() or getNotesObject() method instead.
  • The CustomFieldValueItem methods getParent and setParent have been marked as deprecated. Use the getParentUniqueID and setParentUniqueID methods instead.
  • JSON output from MPXJ now includes more detail for custom field definitions read from MPP files.
  • When reading a PMXML file, populate the Early/Late Start/Finish date attributes from the Remaining Early/Late Start/Finish date attributes.
  • Fix an issue reading WBS ID for P3 and SureTrak schedules.
"},{"location":"CHANGELOG/#1281-2024-03-11","title":"12.8.1 (2024-03-11)","text":"
  • Improve reading resource assignments from certain FastTrack FTS files.
"},{"location":"CHANGELOG/#1280-2024-03-04","title":"12.8.0 (2024-03-04)","text":"
  • Add experimental support for reading Deltek Open Plan BK3 files.
  • Implemented the Relation.Builder class.
  • Marked the Relation(Task,Task,RelationType,Duration) constructor as deprecated, use the Relation.Builder class instead.
  • Marked the RelationContainer.addPredecessor(Task,Task,RelationType,Duration) method as deprecated, use the RelationContainer.addPredecessor(Relation.Builder) method instead.
  • Marked the Task.addPredecessor(Task,RelationType,Duration) method as deprecated, use the Task.addPredecessor(Relation.Builder) method instead.
  • Add a notes attribute to the Relation class and ensure that it is read from and written to P6 schedules.
  • Read the Relationship Lag Calendar setting from Phoenix 5 files. (Contributed by Rohit Sinha)
  • Don't write a material label to an MSPDI file for a resource which isn't a material.
  • Update representation of Work Variance when writing MSPDI files to more closely match output from Microsoft Project.
  • Updated to ensure that when schedules are read from XER files or P6 databases, labor and nonlabor work amounts are combined for the Actual, Remaining and Planned work attributes. This is now consistent with the existing behavior when reading PMXML files.
  • Added support for new Task attributes Actual Work Labor, Actual Work Nonlabor, Remaining Work Labor, Remaining Work Nonlabor, Planned Work Labor, Planned Work Nonlabor, when reading and writing P6 schedules.
  • Update default readAll method on reader classes to ensure that if the reader is unable to read any schedule data, an empty list is returned rather than a list containing null.
  • Ensure that Task Start and Finish dates are both the same when reading milestones from PMXML files, and that the correct date is used depending on whether we have a Start Milestone or a Finish Milestone.
"},{"location":"CHANGELOG/#1270-2024-02-07","title":"12.7.0 (2024-02-07)","text":"
  • Added support for reading and writing the project property Baseline Calendar Name to and from MPP and MSPDI files.
  • Ensure Start Variance and Finish Variance are read from and written to MSPDI files in the correct format.
  • Improve accuracy of large Work Variance values read from MSPDI files.
  • Add support for the Calendar GUID attribute, which is read from MPP and MSPDI files, and written to MSPDI files.
  • Ensure Activity Codes are available when reading Phoenix PPX files even if they are also being used to construct the task hierarchy.
  • Ensure Activity Codes Values are populated when reading Phoenix PPX files. (Contributed by Rohit Sinha)
  • When writing an MSPDI file, derive the TimephasedData Unit attribute from the duration of the timephased data item.
  • Fixed an issue with the ProjectCalendar.getPreviousWorkFinish method when called with a time which was already at the end of a period of work.
  • Ensure that the proj_node_flag is set for the root WBS node when writing XER files.
"},{"location":"CHANGELOG/#1260-2024-01-22","title":"12.6.0 (2024-01-22)","text":"
  • Updated PMXML schema to version 23.12.
  • Ensure that baselines in PMXML files written by Oracle Primavera Cloud are read.
  • Fix an issue reading certain XER files and P6 databases where activities lost the relationship with their parent WBS entry.
  • Added ResourceAssignment.getEffectiveCalendar method.
  • Deprecated ResourceAssignment.getCalendar method, use getEffectiveCalendar method instead.
  • Improved reading timephased baseline work from MPP files.
  • Added new versions of the TimephasedUtility.segmentBaselineWork and segmentBaselineCost methods which take a ProjectCalendar instance as the first argument rather than a ProjectFile instance.
  • Deprecated the TimephasedUtility.segmentBaselineWork and segmentBaselineCost methods which take a ProjectFile instance as the first argument.
  • Added a new version of the ProjectCalendar.getDate() method which just takes a date and a duration as its arguments. This method handles both positive and negative durations.
  • Marked the original version of the ProjectCalendar.getDate() method as deprecated. Use the new version instead.
  • Improve recognition of task splits when reading MPP and MSPDI files.
"},{"location":"CHANGELOG/#1250-2023-12-18","title":"12.5.0 (2023-12-18)","text":"
  • Add support for the following Resource Assignment attributes: Remaining Early Start, Remaining Early Finish, Remaining Late Start, and Remaining Late Finish.
  • Ensure that the Resource Assignment attributes Remaining Early Start and Remaining Early Finish are read from and written to PMXML files.
  • Ensure that the Resource Assignment attributes Remaining Early Start, Remaining Early Finish, Remaining Late Start, and Remaining Late Finish are read from and written to XER files.
  • Improve accuracy of reading and writing the ProjectProperties Relationship Lag Calendar attribute for PMXML files.
  • All P6 scheduling and leveling options which were previously made available via the ProjectProperties custom properties map are now deprecated. These properties now have individual getter and setter methods available on the ProjectProperties class. Note: this may be a breaking change if you were creating schedules from scratch, populating the custom properties map, then writing PMXML or XER files. In this case you will need to update your code, for all other use cases your code will continue to work unchanged until the next major version of MPXJ.
  • Added support for reading and writing the ProjectProperties attributes Baseline Type Name, Baseline Type Unique ID, and Last Baseline Update Date for baseline projects in PMXML files.
  • When reading projects from PMXML files, if the creation date attribute is not present in the file fall back to populating the ProjectProperties creation date attribute with the PMXML date added attribute.
  • When writing PMXML files, ensure the date added attribute for projects is populated with the creation date.
  • Add the CustomFieldContainer.remove method to allow field configurations to be removed.
  • Updated the UserDefinedFieldContainer.remove method to ensure that any associated field configuration is removed from the CustomFieldContainer.
  • Ensure that Microsoft Project's \"unknown\" resource (with Unique ID zero) is not exported to XER files.
  • Ensure that resource assignments which are not associated with an Activity or a Resource are not written to XER files.
  • Durations are written to PMXML files in hours. We now round to 2 decimal places to allow minutes to be represented, and avoid unnecessary precision.
  • Currency amounts written to PMXML files are now rounded to 8 decimal places to more closely match the behavior of P6, and avoid unnecessary precision.
  • Decimal amounts other than currency and duration are written to PMXML files with 15 decimal places to more closely match the behavior of P6.
  • Fix an issue reading ConceptDraw calendars.
  • Fixed a misspelled field name in the JSON output (Contributed by Daniel Taylor).
  • Improved handling of the Resource Assignment Planned and Remaining Units and Units per Time attributes read from and written to P6 schedules.
  • Added support for the following project properties: Activity ID Prefix, Activity ID Suffix, Activity ID Increment and Activity ID Based On Selected Activity, and ensure these are read from and written to P6 schedules.
"},{"location":"CHANGELOG/#1240-2023-11-23","title":"12.4.0 (2023-11-23)","text":"
  • Added support for the WBS Code Separator attribute to ProjectProperties.
  • Avoid creating duplicate ActivityCodeValue instances when reading Asta PP files.
  • Added a new version of the ProjectFile.expandSubprojects method which takes a boolean argument indicating if external tasks should be removed. Passing true to this method will recreate predecessor and successor relationships using the original tasks rather than the placeholder external tasks, and will remove the external tasks.
  • Marked the ProjectFile.expandSubprojects() method as deprecated, use the new version which takes a boolean argument instead.
  • Ensure the ProjectProperties name attribute is set correctly when reading XER files and P6 databases.
  • The ProjectEntityContainer method renumberUniqueIDs has been marked as deprecated.
  • The ProjectEntityContainer method getNextUniqueID has been marked as deprecated. Use ProjectFile.getUniqueIdObjectSequence(class).getNext() instead.
  • The ProjectEntityContainer method updateUniqueIdCounter has been marked as deprecated as it is no longer required.
  • The ProjectFile method updateUniqueIdCounters has been marked as deprecated as it is no longer required.
  • The ObjectSequence method reset has been marked as deprecated as it is no longer required.
  • When creating a Location instance using the Builder class, a Unique ID will be generated if one is not supplied.
  • The no-arg Location.Builder constructor has been marked a deprecated. Use the constructor which requires a ProjectFile instance instead.
  • Implemented the ExpenseItem.Builder class.
  • Marked the ExpenseItem(task) constructor as deprecated, use the ExpenseItem.Builder class instead.
  • Marked all ExpenseItem setter methods a deprecated. The ExpenseItem class will be immutable in the next major release.
  • Marked no-arg UnitOfMeasure.Builder() constructor as deprecated, use the UnitOfMeasure.Builder(ProjectFile) constructor instead.
  • Implemented the Step.Builder class.
  • Marked the Step(task) constructor as deprecated, use the Step.Builder class instead.
  • Marked all Step setter methods a deprecated. The Step class will be immutable in the next major release.
  • Marked the NotesTopic constructor as deprecated, use the NotesTopic.Builder(ProjectFile) constructor instead.
  • Implemented the ExpenseCategory.Builder class.
  • Marked the ExpenseCategory constructor as deprecated, use the ExpenseCategory.Builder class instead.
  • Implemented the CostAccount.Builder class.
  • Marked the CostAccount constructor as deprecated, use the CostAccount.Builder class instead.
  • Implemented the ActivityCodeValue.Builder class.
  • Marked the ActivityCodeValue constructor as deprecated, use the ActivityCodeValue.Builder class instead.
  • Marked the ActivityCodeValue.setParent method as deprecated, use the ActivityCodeValue.Builder class instead.
  • Marked the ActivityCode.addValue method as deprecated, use the ActivityCodeValue.Builder class instead to create an ActivityCodeValue instance and add it directly to the list held by the parent ActivityCode.
  • Implemented the ActivityCode.Builder class.
  • Marked the ActivityCode constructor as deprecated, use the ActivityCode.Builder class instead.
  • Only predecessor Relation instances are now stored in RelationContainer, successors are generated dynamically. You will only notice a difference if you are iterating over the RelationContainer collection directly, in which case you will only see predecessors.
"},{"location":"CHANGELOG/#1230-2023-11-07","title":"12.3.0 (2023-11-07)","text":"
  • Retrieve role availability data when reading a schedule from a P6 database.
  • Populate the project's Name and Title attributes when exporting an MSPDI file.
  • Ensure the Project ID attribute is populated when writing an XER file.
  • Don't include null tasks (blank tasks) when writing an XER file.
  • Strip control characters from entity names written to MSPDI files and XER files.
  • Ensure resource material labels written to MSPDI files meet Microsoft Project's naming requirements.
  • Ensure the activity code value Name attribute is populated when read from an Asta PP file.
  • Don't allow multiple values for an activity code when writing XER and PMXML files.
  • The MSPDI and MPX writers now dynamically renumber Unique ID values which are too large for Microsoft Project. The original schedule is no longer modified to achieve this.
"},{"location":"CHANGELOG/#1220-2023-10-12","title":"12.2.0 (2023-10-12)","text":"
  • Add the UnitOfMeasure class to represent the unit of measure for a material resource. The unit of measure corresponds to the current \"material label\" attribute of a resource. The Resource.getMaterialLabel() method will now retrieve the label from the UnitOfMeasure instance associated with the resource. The Resource.setMaterialLabel() method is now deprecated, the Resource.setUnitOfMeasure() or Resource.setUnitOfMeasureUniqueID() methods should be used instead.
  • Unit of measure for material resources are now read from and written to Primavera schedules.
  • Improve task duration and percent completion calculation for Asta PP files.
  • Improve date parsing when reading XER files written by older versions of P6.
  • Added the setIgnoreErrors method to the Primavera database reader class, and MSPDI, Schedule Grid, and SDEF file reader classes. The current default behavior of ignoring data type parse errors is unchanged. Calling setIgnoreErrors(false) on one of these reader classes will ensure that an exception is raised when a data type parse error is encountered.
  • Added the ProjectFile.getIgnoredErrors() method. The default behavior for MPXJ reader classes is to ignore data type parse errors. If any errors have been ignored when reading a schedule, details of these errors can be retrieved by calling the ProjectFile.getIgnoredErrors() method.
  • Handle duplicate relation unique IDs when reading schedules.
  • Include resource availability table in JSON output.
  • Add the Resource field Default Units, and ensure this field is read and written for P6 Schedules.
  • Updated the Resource attribute Max Units to ensure that this is calculated from the resource's availability table. Note that the Resource.getMaxUnits() method will return the resource's Max Units attribute for the current date. To retrieve the Max Units for a different date, use the AvailabilityTable.getEntryByDate() method.
  • Marked the Resource.setMaxUnits() method as deprecated. The Max Units attribute is derived from the resource's availability table. Changes to Max Units should now be made by modifying the availability table.
  • Updated the Resource attribute Available From to ensure that this is calculated from the resource's availability table. Note that the Resource.getAvailableFrom() method will return the resource's Available From attribute for the current date. To retrieve the Available From attribute for a different date, use the AvailabilityTable.availableFrom() method.
  • Marked the Resource.setAvailableFrom() method as deprecated. The Available From attribute is derived from the resource's availability table. Changes to the Available From attribute should now be made by modifying the availability table.
  • Updated the Resource attribute Available To to ensure that this is calculated from the resource's availability table. Note that the Resource.getAvailableTo() method will return the resource's Available To attribute for the current date. To retrieve the Available To attribute for a different date, use the AvailabilityTable.availableTo() method.
  • Marked the Resource.setAvailableTo() method as deprecated. The Available To attribute is derived from the resource's availability table. Changes to the Available To attribute should now be made by modifying the availability table.
"},{"location":"CHANGELOG/#1213-2023-09-25","title":"12.1.3 (2023-09-25)","text":"
  • Added the Project Properties attribute Relationship Lag Calendar and implemented read and write support for this for P6 schedules. (Contributed by Rohit Sinha).
  • Improve compatibility of PMXML files with P6 EPPM by moving the Schedule Options tag.
  • Ensure Baseline Projects in PMXML files include Schedule Options and Location Object ID.
"},{"location":"CHANGELOG/#1212-2023-09-21","title":"12.1.2 (2023-09-21)","text":"
  • Updates to improve compatibility with versions of Java after Java 8.
  • Ensure timestamps with fractional sections are read correctly from Phoenix PPX files (Based on a contribution by Rohit Sinha).
  • Improve handling of double quotes when reading and writing XER files.
  • To allow XER files written by MPXJ to be imported correctly by P6, ensure that they have a single top level WBS entry (Based on a contribution by Alex Matatov)
  • Ensure that ProjectProperties.getCustomProperties() returns an empty Map rather than returning null if no custom properties have been configured.
  • Ensure project calendars and project activity codes are nested within the project tag of PMXML files.
"},{"location":"CHANGELOG/#1211-2023-08-23","title":"12.1.1 (2023-08-23)","text":"
  • Fix an issue preventing native SQLite library from loading when using the .Net version of MPXJ on macOS.
"},{"location":"CHANGELOG/#1210-2023-08-22","title":"12.1.0 (2023-08-22)","text":"
  • Write schedule options to PMXML and XER files.
  • Fix an arithmetic error in RateHelper when converting a rate from minutes to hours.
  • Introduced new methods to RateHelper accepting a TimeUnitDefaultsContainer argument rather than a ProjectFile for greater flexibility. Marked methods taking a ProjectFile argument as deprecated.
  • Ensure Early Finish and Late Finish are populated for Asta milestones and tasks.
  • Don't attempt to calculate total slack if start slack or finish slack are missing.
  • Ensure completed tasks are not marked as critical.
  • Improve handling of non-standard Boolean values in MPX files.
  • Improve Total Slack calculation for P6 projects.
  • Handle finish milestones with null actual start date for actual duration calculation when reading PMXML files (Contributed by Andrew Marks).
"},{"location":"CHANGELOG/#1202-2023-07-25","title":"12.0.2 (2023-07-25)","text":"
  • Ensure that the Fixed Cost attribute is rolled up from activities to WBS entries when reading P6 schedules.
"},{"location":"CHANGELOG/#1201-2023-07-21","title":"12.0.1 (2023-07-21)","text":"
  • Improve resource hierarchy handling.
  • Improve handling of external tasks read from MSPDI files.
  • Improve handling of resource assignments read from Asta PP files containing multiple baselines.
  • Improve filtering to ignore hammock tasks in Asta PP files and ensure that non-hammock items are not incorrectly ignored.
  • Improve handling of bars without additional linked data read from Asta PP files.
  • Ensure that invalid duplicate Unique ID values encountered when reading schedule data are renumbered to maintain uniqueness.
  • Improve reading certain FastTrack FTS files.
  • Roll up the expense item at completion values read from P6 schedules to the task Fixed Cost attribute.
"},{"location":"CHANGELOG/#1200-2023-06-29","title":"12.0.0 (2023-06-29)","text":"
  • NOTE: this is a major version release, breaking changes have been made to the MPXJ API as documented below.
  • Timestamps, dates, and times are now represented by java.time.LocalDateTime, java.time.LocalDate and java.time.LocalTime respectively, rather than java.util.Date as they were originally.
  • For .Net users, new ToDateTime and ToNullableDateTime extension methods have been provided to convert java.time.LocalDateTime, java.time.LocalDate, java.time.LocalTime to DateTime instances.
  • For .Net users, new ToJavaLocalDateTime, ToJavaLocalDate and ToJavaLocalTime extension methods have been provided to convert DateTime instances to java.time.LocalDateTime, java.time.LocalDate, and java.time.LocalTime.
  • The class net.sf.mpxj.Day has been replaced by java.time.DayOfWeek.
  • All code previously marked as deprecated has been removed.
  • Added support for reading and writing the Activity attribute \"Expected Finish\" for P6 schedules.
"},{"location":"CHANGELOG/#1154-2023-06-27","title":"11.5.4 (2023-06-27)","text":"
  • Improve accuracy of dates read from Synchro, Suretrak and Turboproject files.
  • By default ignore errors in individual records read from XER files. This matches P6's behavior when importing XER files. Use the PrimaveraXERFileReader.setIgnoreErrors method to change the behavior.
"},{"location":"CHANGELOG/#1153-2023-06-19","title":"11.5.3 (2023-06-19)","text":"
  • When writing an XER file, provide the necessary default values to allow non-P6 schedules to be successfully imported into P6.
  • Ensure multi-day exceptions are written to XER files correctly.
  • Ensure GanttProject exception dates are read correctly.
  • More closely match the Planner predecessor lag calculation.
  • Ensure that java.sql.Date values are correctly formatted when writing XER files.
  • When reading from a P6 database, check to ensure the location table is present before attemting to read locations.
"},{"location":"CHANGELOG/#1152-2023-06-08","title":"11.5.2 (2023-06-08)","text":"
  • Improve accuracy of calendar data read from certain Powerproject schedules.
  • Improve handling of unusual XER files with calendar time ranges expressed in 12-hour format.
  • Correctly parse midnight represented as 24:00:00 from MSPDI files written by certain non-Microsoft Project applications.
  • For MSPDI files produced by applications other than Microsoft Project which have an incorrectly nested calendar hierarchy, avoid pruning derived calendars which are referenced elsewhere in the hierarchy.
"},{"location":"CHANGELOG/#1151-2023-05-24","title":"11.5.1 (2023-05-24)","text":"
  • Improve read performance when working with large schedules.
  • Improve read and write performance of code handling resource calendars.
  • Updated to use sqlite-jdbc 3.42.0.0
"},{"location":"CHANGELOG/#1150-2023-05-19","title":"11.5.0 (2023-05-19)","text":"
  • Added the ability to read Subproject data embedded in MSPDI files.
  • Added the ability to read timephased baseline work and cost from MSPDI files.
  • Added the ability to write timephased baseline work and cost to MSPDI files.
  • Improve accuracy of timephased baseline work read from MPP files.
  • Ensure that non-recurring calendar exceptions take precedence over recurring calendar exceptions.
  • Avoid creating duplicate calendar exceptions when reading Asta PP files.
  • Added the Bar Name attribute to Task, which is accessed using the getBarName and setBarName methods. This is populated with the name of the bar to which a task belongs when reading an Asta Powerproject schedule.
  • When reading schedules from XER files and P6 databases, ensure durations without a value are returned as null rather than as a zero duration.
"},{"location":"CHANGELOG/#1140-2023-05-08","title":"11.4.0 (2023-05-08)","text":"
  • Added the \"Resource Pool File\" attribute to ProjectProperties, which represents the full path of the resource pool used by an MPP file. This attribute is accessible via the getResourcePoolFile and setResourcePoolFile methods.
  • Added the getResourcePoolObject method to allow the resource pool file to be located and read
  • Added support for reading the task attribute Subproject GUID from MPP files. This attribute can be accessed via the getSubprojectGUID and setSubprojectGUID methods.
  • Added support for the task attribute \"External Project\". When this attribute is true it indicates that the task represents a subproject. The attribute is accessed via the getExternalProject and setExternalProject methods.
  • When reading an MSPDI file with external task predecessors, MPXJ now attempts to recreate the placeholder external tasks which would be present if the equivalent MPP file was read.
  • External task predecessors are now represented when writing an MSPDI file.
  • Added the Task method getSubprojectObject which allows the caller to retrieve a ProjectFile instance representing the external project linked to a task.
  • Added the Task method expandSubproject. For task which represent an external project, this method automatically loads the external project and attaches the tasks it contains as children of the current task. This is analogous to the behavior in Microsoft Project where a subproject is expanded to reveal the tasks it contains.
  • Added the ProjectFile method expandSubprojects which identifies any tasks in the project which represent an external project and expands them, linking the tasks from the external project as children of the task in the parent project. Note that the method works recursively so multiple levels of external tasks will be expanded.
  • Updated to ensure that the internal_name attribute of a UserdefinedField is generated if not present.
  • Updated to avoid an exception when reading notebook topics from PMXML files.
  • Marked the Task method setSubprojectName as deprecated. Use the setSubProjectFile method instead.
  • Marked the Task method getSubprojectName as deprecated. Use getSubprojectFile instead.
  • Marked the Task method setExternalTaskProject as deprecated. Use the setSubprojectFile method instead.
  • Marked the Task method getExternalTaskProject as deprecated. Use the getSubprojectFile method instead.
  • Marked the ProjectFile method getSubProjects as deprecated. Use the subproject attributes on individual tasks instead.
  • Marked the Task methods getSubProject and setSubProject as deprecated. Use the subproject attributes instead.
"},{"location":"CHANGELOG/#1132-2023-04-29","title":"11.3.2 (2023-04-29)","text":"
  • Improve default values provided for P6 calendars with missing data.
  • Implement both \"planned dates\" and \"current dates\" strategies for populating P6 baselines.
  • Ensure the Project GUID is read from MPP files.
"},{"location":"CHANGELOG/#1131-2023-04-21","title":"11.3.1 (2023-04-21)","text":"
  • Improve accuracy of resource assignment Actual Start and Actual Finish dates when reading MPP files.
  • Avoid generating timephased data for zero duration tasks.
  • Improve preservation of custom timephased data start and end times.
"},{"location":"CHANGELOG/#1130-2023-04-12","title":"11.3.0 (2023-04-12)","text":"
  • Implemented PrimaveraXERFileWriter to allow MPXJ to write XER files.
  • Updated the ActivityCode class to ensure that both the scope Project ID and EPS ID can be represented when reading a P6 schedule. (Potentially breaking change if you were using this class).
  • Ensure secondary constraint date and type are written to PMXML files.
  • Ensure leveling priority is written to PMXML files.
  • Ensure WBS UDF values are written to PMXML files.
  • Ensure integer UDF values are read correctly from XER files and P6 databases.
  • Add methods to allow the project's default calendar unique ID to be set and retrieved.
  • Add method to allow a calendar's parent calendar unique ID to be retrieved.
  • Add method to allow a task's parent task unique ID to be retrieved.
  • Add methods to allow a resource assignment's role unique ID to be set and retrieved.
  • Add methods to allow a resource assignment's cost account unique ID to be set and retrieved.
  • Add method to allow a cost account's parent unique ID to be retrieved.
  • Add method to allow an expense item's cost account unique ID to be retrieved.
  • Add method to allow an expense item's category unique ID to be retrieved.
  • Added WorkContour.isDefault() method to allow \"built in\" resource curves/work contours to be distinguished from user defined curves.
  • Updated to retrieve the project's start date from Phoenix PPX files (Contributed by Rohit Sinha).
  • Provide access to notebook topics from P6 schedules via the ProjectFile.getNotesTopics() method.
  • Capture unique ID of Activity and WBS notes from P6 schedules.
  • Improve the calculation used to determine At Completion Duration of activities when reading XER files and P6 databases.
  • Improve representation of certain duration values written to MSPDI files.
  • Improve accuracy of certain work calculations where the specified time period does not start with a working day.
  • Fix an issue which caused negative timephased work values to be generated when reading certain MPP files.
  • Fix an issue reading XER files where the critical_drtn_hr_cnt field is expressed a decimal rather than an integer.
  • Fix an issue populating the WBS attribute for activities read from certain XER files.
"},{"location":"CHANGELOG/#1120-2023-03-13","title":"11.2.0 (2023-03-13)","text":"
  • The project property Critical Slack Limit is now represented as a Duration rather than as an Integer. (Potentially breaking change if you were using this property directly).
  • TaskType is now a simple enum with all Microsoft Project specific functionality moved into TaskTypeHelper. (Potentially breaking change if you were using the TaskType methods getInstance or getValue in your code)
  • When reading the task type from P6 schedule the mapping to the MPXJ TaskType enum has been updated to more closely match P6. The main changes are that the P6 type \"Fixed Units\" now maps to TaskType.FIXED_WORK and the \"Fixed Duration & Units\" type now maps to a new enumeration value TaskType.FIXED_DURATION_AND_UNITS.
  • Added support for reading project calendar exceptions from Phoenix schedules (based on a contribution by Rohit Sinha).
  • The Resource attribute Active now defaults to true if the schedule being read doesn't support or contain a value for this attribute.
  • Add support for reading and writing the Resource's Active flag for P6 schedules.
  • Add support for reading and writing the Resource's Default Units/Time value for P6 schedules.
  • Add support for reading and writing the Project's Critical Slack Limit value for P6 schedules.
  • Fixed an issue reading certain types of Enterprise Custom Fields containing date values.
  • Ensure activity code value parent can be set to null.
  • Improved existing .Net extension methods and added support for more types.
  • Added NuGet package icon
  • Simplified NuGet packaging
"},{"location":"CHANGELOG/#1110-2023-02-15","title":"11.1.0 (2023-02-15)","text":"
  • Write activity code definitions and activity code assignments to PMXML files.
  • Added support for \"secure\" and \"max length\" attributes to the ActivityCode class.
  • Added getChildCodes method to ActivityCode and ActivityCodeValue to make it easier to traverse activity code values hierarchically.
  • Added setDescription method to Step class to make it simpler to add a plan text description.
"},{"location":"CHANGELOG/#1100-2023-02-08","title":"11.0.0 (2023-02-08)","text":"
  • User defined fields read from P6, Asta and GanttProject schedules are now represented by instances of UserDefinedField. They will no longer be mapped to custom field instances.
  • Enterprise Custom Fields read from MPP and MSPDI files are now represented by instances of UserDefinedField.
  • When writing MSPDI files, UserDefinedField instances which were originally read from enterprise custom fields will be written to the MSPDI file as enterprise custom fields.
  • When writing MSPDI files, UserDefinedField instances which were from applications other than Microsoft Project will automatically be mapped to available custom fields.
  • When writing MPX files, UserDefinedField instances will automatically be mapped to available custom fields.
  • The UserDefinedField type implements the FieldType interface and so can be used with the FieldContainer get and set methods to work with the contents of the user defined fields.
  • The ProjectFile.getUserDefinedFields() method has been added to provide access to all user defined fields defined in the project.
  • The CustomFieldContainer returned by ProjectFile.getCustomFields() will contain entries for all UserDefinedField instances.
  • The various getFieldTypeByAlias and getFieldByAlias methods will retrieve user defined fields by name.
  • Added the convenience method ProjectFile.getPopulatedFields() to retrieve details of all populated fields across the project. This avoids the caller having to individually retrieve the populated fields from the tasks container, resource container and so on.
  • Updated the getPopulatedFields methods to return a Set of FieldType rather than a Set of TaskField, ResourceField etc.
  • The various getPopulatedFields methods will include instances of UserDefinedField in the returned collection if relevant.
  • All ENTERPRISE_CUSTOM_FIELDn values have been removed from the TaskField, ResourceField, AssignmentField and ProjectField enumerations.
  • The getEnterpriseCustomField and setEnterpriseCustomField methods have been removed from ProjectProperties, Task,ResourceandResourceAssignment`.
  • Project UDFs are now read from P6 schedules.
  • Project UDFs are now written to PMXML files.
  • All code previously marked as deprecated has been removed.
"},{"location":"CHANGELOG/#10162-2023-01-29","title":"10.16.2 (2023-01-29)","text":"
  • Updated to improve reading resource attributes from certain MPP14 files.
"},{"location":"CHANGELOG/#10161-2023-01-26","title":"10.16.1 (2023-01-26)","text":"
  • Updated to make resource curve definitions (work contours) available in the WorkContourContainer. This container is accessed using the ProjectFile.getWorkContours() method.
"},{"location":"CHANGELOG/#10160-2023-01-24","title":"10.16.0 (2023-01-24)","text":"
  • Improve accuracy when normalising timephased data.
  • Add support for reading activity steps from XER files, PMXML files and Primavera databases.
  • Add support for writing activity steps to PMXML files.
  • Updated PMXML schema to version 22.12.
  • Updated methods in the GanttBarCommonStyle and GanttBarStyle classes to use a FieldType instance rather than a TaskField instance to allow more flexibility. (Note: this may be a breaking change if you are currently using these classes.)
  • Optionally include some Microsoft Project layout data in JSON output.
"},{"location":"CHANGELOG/#10150-2023-01-11","title":"10.15.0 (2023-01-11)","text":"
  • Avoid writing invalid characters to PMXML, MSPDI and Planner XML files.
  • Improve handling of slack values for schedules which only contain a value for total slack.
  • Add support for reading constraint type and constraint date from Phoenix schedules (based on a contribution by Rohit Sinha).
  • Improve timephased data calculation when assignment has zero units.
  • Improve handling of very large duration values when reading and writing MSPDI files.
  • Ensure the Task attributes Active, Constraint Type, Task Mode, and Type always have a value.
  • Ensure the Resource attributes Type, Calculate Costs from Units, and Role always have a value.
  • Ensure the Resource Assignment attributes Calculate Costs from Units, Rate Index, and Rate Source always have a value.
  • Add version number constant to the Java source, accessible as MPXJ.VERSION.
  • Ensure that UDF values are read for WBS entries in PMXML files.
  • Avoid writing duplicate resource assignments to MPX files.
"},{"location":"CHANGELOG/#10141-2022-11-25","title":"10.14.1 (2022-11-25)","text":"
  • Fix CVE-2022-41954: Temporary File Information Disclosure Vulnerability (Contributed by Jonathan Leitschuh)
"},{"location":"CHANGELOG/#10140-2022-11-21","title":"10.14.0 (2022-11-21)","text":"
  • Handle missing default calendar when reading a PMXML file.
  • When reading an MPP file using a file name or File instance, ensure a more memory-efficient approach is used.
  • Improve reading certain FastTrack FTS files.
  • Improve generation of timephased data where working time ends at midnight.
  • Improve generation of timephased data for tasks with a calendar assigned.
"},{"location":"CHANGELOG/#10130-2022-11-16","title":"10.13.0 (2022-11-16)","text":"
  • Add support for reading a resource assignment's cost account from P6 schedules.
  • Add support for writing a resource assignment's cost account to PMXML files.
  • Read resource assignment custom field definitions present in MPP14 files.
  • Improve identification of deleted resources when reading MPP9 files.
  • Ensure tasks with task calendars in MPP files are handled correctly when generating timephased data.
  • Improve generation of timephased data for material resource assignments.
  • Improve accuracy of timephased data when reading certain MPP files.
"},{"location":"CHANGELOG/#10120-2022-11-01","title":"10.12.0 (2022-11-01)","text":"
  • Added the Resource Assignment attribute Calculate Costs From Units, and added read and write support for Primavera schedules.
  • Added the Resource attribute Calculate Costs From Units, and added read and write support for Primavera schedules.
  • Added the Resource and Role attribute Sequence Number, and added read and write support for Primavera schedules.
  • Added the WBS attribute Sequence Number, and added read and write support for Primavera schedules.
  • Ensure activity type is read from Phoenix schedules. (Contributed by Christopher John)
  • Deprecate the CostAccount method getSequence and replace with getSequenceNumber to improve naming consistency.
  • Deprecate the ExpenseCategory method getSequence and replace with getSequenceNumber to improve naming consistency.
  • Avoid possible ArrayIndexOutOfBoundsException when reading GUID values from MPP files (Contributed by Rohit Sinha).
"},{"location":"CHANGELOG/#10110-2022-09-27","title":"10.11.0 (2022-09-27)","text":"
  • Deprecated the Resource methods getParentID and setParentID. Replaced with getParentResourceUniqueID and setParentResourceUniqueID for clarity and consistency.
  • Added the Resource methods setParent and getParent.
  • Added the ChildResourceContainer interface and ResourceContainer.updateStructure method to ensure that resources can be accessed hierarchically when reading a schedule.
  • Added the ResourceAssignment methods getFieldByAlias and setFieldByAlias to simplify working with custom fields, and mkae the API consistent with existing methods on Task and Resource.
  • Added the TaskContainer methods getCustomFields and getFieldTypeByAlias to simplify access to task custom fields.
  • Added the ResourceContainer methods getCustomFields and getFieldTypeByAlias to simplify access to resource custom fields.
  • Added the ResourceAssignmentContainer methods getCustomFields and getFieldTypeByAlias to simplify access to resource assignment custom fields.
  • Added the getCustomFieldsByFieldTypeClass method to CustomFieldContainer to allow retrieval of custom field details by parent class.
  • Deprecated the CustomFieldContainer method getFieldByAlias to be replaced by getFieldTypeByAlias to provide a more consistent method name.
  • Don't attempt to write unknown extended attributes to MSPDI files.
  • Don't populate graphical indicator data if the graphical indicator is not enabled.
  • Don't set custom field aliases to empty strings.
  • Added the CustomFieldContainer method add.
  • Deprecated the CustomFieldContainer method getCustomField, which is replaced by the get method (which returns null if the field type is not configured) and the getOrCreate method (which will return an existing configuration or create a new one if the requested field does not yet have a configuration).
"},{"location":"CHANGELOG/#10100-2022-09-13","title":"10.10.0 (2022-09-13)","text":"
  • Add an option to import Phoenix schedules as a flat set of tasks with separate activity codes, rather than creating a hierarchy of tasks from the activity codes. Note the default is to disable this behavior so existing functionality is unchanged. (Contributed by Christopher John)
  • Add a setProperties method to reader classes to allow configuration to be supplied via a Properties instance rather than having to call setter methods. Properties passed to the UniversalProjectReader version of this method will be forwarded to the reader class UniversalProjectReader chooses to reader the supplied file. Properties for multiple reader classes can be included in the Properties instance, each reader class will ignore irrelevant properties.
  • Added the get method to Task, Resource, ResourceAssignment and ProjectProperties as a replacement for the getCurrentValue method. The new get method is paired with the existing set method to provide read and write access to attributes of these classes. This change is intended to improve the interfaces to these classes by making them more consistent, and thus easier to understand.
  • Deprecated the getCurrentValue method on the Task, Resource, ResourceAssignment and ProjectProperties classes. Use the new get method instead.
  • Add getter and setter methods for the Resource attributes Cost Center, Budget Cost, Budget Work, Baseline Budget Cost, Baseline Budget Work, Baseline Budget Cost 1-10, and Baseline Budget Work 1-10.
  • Add getter and setter methods for the Task attributes Response Pending, Scheduled Start, Scheduled Finish, Scheduled Duration, Budget Cost, Budget Work, Baseline Budget Cost, Baseline Budget Work, Baseline Budget Cost 1-10, and Baseline Budget Work 1-10.
  • Added support for the Resource Cost Centre attribute for MSPDI files.
  • Move MPP file-specific functionality for determining baseline values from the Task class into the MPP reader class.
  • Improve handling of the TaskMode attribute.
  • Don't set a Task's Critical attribute unless we have valid slack values.
  • Ensure ResourceAssignment calculated fields are returned correctly when using the getCurrentValue method.
  • Ensure ProjectProperties calculated fields are returned correctly when using the getCurrentValue method.
  • Updated to use jsoup 1.15.3
"},{"location":"CHANGELOG/#1091-2022-08-31","title":"10.9.1 (2022-08-31)","text":"
  • Ensure monthly and yearly recurrences are calculated correctly when the supplied start date is the same as the first recurrence date (Contributed by Rohit Sinha).
  • Add support for reading task calendars from Phoenix files (Contributed by Rohit Sinha).
  • Improve reliability of ProjectCleanUtility when using the replacement strategy.
"},{"location":"CHANGELOG/#1090-2022-08-23","title":"10.9.0 (2022-08-23)","text":"
  • Added the ResourceAssignment.getEffectiveRate method to allow the cost rate effective on a given date for a resource assignment to be calculated. For P6 schedules this will take account of the cost rate configuration included as part of the resource assignment.
  • For P6 schedules, the ResourceAssignment.getCostRateTable method now takes in account any cost rate configuration details from the resource assignment when determining which table to return.
  • A resource's Standard Rate, Overtime Rate and Cost per Use are now all derived from the resource's cost rate table, and not stored as attributes of the resource itself.
  • The resource methods setStandardRate, setOvertimeRate, and setCostPerUse have been deprecated. These attributes can now only be set or updated by modifying the resource's cost rate table.
  • When writing MPX files, only include attributes which have a non-empty, non-default value in at least one task or resource.
  • When writing MPX files, ensure attributes which have calculated values are used.
  • Add support for reading a resource assignment's rate type from P6 schedules. The rate type is accessed via the ResourceAssignment.getRateIndex method. The value returned by this method can be used to select the required rate using the CostRateTableEntry,getRate method.
  • Add support for writing a resource assignment's rate type to PMXML files.
  • Add support for reading a resource assignment's role from P6 schedules. The role is accessed via the ResourceAssignment.getRole and ResourceAssignment.setRole methods.
  • Add support for writing a resource assignment's role to PMXML files.
  • Add support for reading a resource assignment's override rate (Price / Unit) from P6 schedules. The rate is accessed via the ResourceAssignment.getOverrideRate and ResourceAssignment.setOverrideRate methods.
  • Add support for writing a resource assignment's override rate (Price / Unit) to PMXML files.
  • Add support for reading a resource assignment's rate source from P6 schedules. The rate source is accessed via the ResourceAssignment.getRateSource and ResourceAssignment.setRateSource methods.
  • Add support for writing a resource assignment's rate source to PMXML files.
"},{"location":"CHANGELOG/#1080-2022-08-17","title":"10.8.0 (2022-08-17)","text":"
  • When reading P6 schedules, all five cost rates for a resource are now available via the CostRateTableEntry.getRate method.
  • All five rates from each cost rate table entry can now be written to PMXML files.
  • When reading files written by Microsoft Project, resource rate values now use the same units as seen by the end user rather than defaulting to hours as was the case previously. (For example, if the user sees $8/day in the source application, you will receive a Rate instance of $8/day rather than $1/hr).
  • The values for a resource's standard rate, overtime rate, and cost per use attributes are now derived from the cost rate table. The values stored on the resource itself are only used if a cost rate table for the resource is not present.
  • The Resource methods getStandardRateUnits and getOvertimeRateUnits are deprecated. Use the getStandardRate and getOvertimeRate methods to retrieve a Rate instance which will include the units for these rates.
  • The Resource methods setStandardRateUnits and setOvertimeRateUnits are deprecated. Supply Rate instances to the setStandardRate and setOvertimeRate methods with the required units instead.
  • The CostRateTableEntry methods getStandardRateUnits and getOvertimeRateUnits are deprecated. Use the getStandardRate and getOvertimeRate methods to retrieve a Rate instance which will include the units for these rates.
  • Ensure rates are formatted \"per hour\" when writing MSPDI and PMXML files.
  • Include cost rate tables in JSON output.
"},{"location":"CHANGELOG/#1070-2022-08-09","title":"10.7.0 (2022-08-09)","text":"
  • Use Jackcess to read Asta MDB and Microsoft Project MPD files. This allows these file to be read on platforms other than Windows.
  • Improve support for reading correctly typed values for enterprise custom fields from MPP files.
  • Improve array index validation when reading GUID values from MPP files.
"},{"location":"CHANGELOG/#1062-2022-06-29","title":"10.6.2 (2022-06-29)","text":"
  • Ensure ProjectCleanUtility can load dictionary words from distribution jar.
  • Improve handling of calendars without days read from PMXML files.
"},{"location":"CHANGELOG/#1061-2022-06-14","title":"10.6.1 (2022-06-14)","text":"
  • Updated to use POI 5.2.2
  • Updated to use sqlite-jdbc 3.36.0.3
  • Updated to use jsoup 1.15.1
"},{"location":"CHANGELOG/#1060-2022-06-08","title":"10.6.0 (2022-06-08)","text":"
  • Added support for reading and writing the unique ID of P6 user defined fields via new getUniqueID and setUniqueID methods on `CustomField (based on a suggestion by Wes Lund).
  • Added support for reading and writing scope, scope ID, and sequence number attributes for activity codes (based on a suggestion by Wes Lund).
  • Added support for reading and writing sequence number and color attributes for activity code values (based on a suggestion by Wes Lund).
  • Added isWorking method to ProjectCalendarException to make it clearer how to determine if the exception changes the dates it is applied to into working or non-working days.
  • Improve reading task start from certain Planner files.
  • Improve reading predecessor lag values from Planner files.
  • Ensure calendar hierarchy is written correctly to Planner files.
  • Don't write null tasks to Planner files as Planner will not read files which contain them.
  • When writing Planner file, ignore constraint types which Planner can't represent.
  • Don't write emply predecessor lists to Planner files.
  • Improve handling of lag duration when writing Planner files.
  • Improve ProjectCalendar start date calculation when we have long runs of non-working days.
  • Performance enhancement for timephased data normalisation.
"},{"location":"CHANGELOG/#1050-2022-05-24","title":"10.5.0 (2022-05-24)","text":"
  • The ProjectCalendarWeek methods addCalendarHours(), attachHoursToDay, removeHoursFromDay have been removed. Use addCalendarHours(day), removeCalendarHours(day) instead. (Note: this will be a breaking change if you were using the original methods to create or modify a schedule)
  • The ProjectCalendar methods attachHoursToDay and removeHoursFromDay have been removed. Use the addCalendarHours and removeCalendarHours methods instead. (Note: this will be a breaking change if you were using the original methods to create or modify a schedule)
  • The class hierarchy for ProjectCalendarHours and ProjectCalendarException has been simplified, but there should be no impact for uses of these classes.
  • The ProjectCalendarHours class now implements the List interface. Methods in this class not part ofthe List interface have been deprecated in favour of the equivalent List methods.
  • Updated MPXWriter to ensure: calendar names are quoted if necessary, all calendars have names, all calendar names are unique.
  • Updated MPXReader to recognise wk as a valid time unit.
  • Updated MPXWriter, PrimaveraPMFileWriter, SDEFWriter and PlannerWriter to ensure any working weeks defined by a calendar are represented by exceptons.
  • Updated MSPDIWriter to ensure any working weeks defined by a calendar are represented in the \"legacy\" exception definition used by Microsoft Project prior to 2007.
  • Updated SDEFWriter to ensure: only relevant calendars are written, and derived calendars are flattened.
  • When reading Planner schedules MPXJ will no longer create an \"artificial\" resource calendar for each resource. Resources will be linked directly to the calendar used in the original schedule.
  • Add support for reading the P6 calendar type and personal calendar flag from P6 schedules.
  • Add support for writing the calendar type and personal calendar flag to PMXML files.
  • Updated the calendar class hierarchy: ProjectCalendar and ProjectCalendarWeek both now inherit from a new class ProjectCalendarDays. Note that ProjectCalendar is no longer a subclass of ProjectCalendarWeek.
  • The getHours and isWorkingDay methods have been moved up to ProjectCalendar from the ProjectCalendarWeek class.
  • The ProjectCalendar method copy has been deprecated, without replacement.
  • Added a getWork method to ProjectCalendar which calculates the amount of work given a Day instance.
  • Added removeWorkWeek and removeCalendarException methods to ProjectCalendar.
  • Recurring exceptions are now added to a ProjectCalendar using the addCalendarException method which takes a recurringData instance its argument.
  • The ProjectCalendarException method setRecurringData has been removed, recurring exceptions should be added using the addCalendarExcepton method described above. (Note: this will be a breaking change if you were creating recurring exceptions)
"},{"location":"CHANGELOG/#1040-2022-05-05","title":"10.4.0 (2022-05-05)","text":"
  • Remove getParent, setParent, and isDerived from ProjectCalendarWeek. (Note: this will be a breaking change if you were working with ProjectCalendarWeek directly).
  • The ProjectProperties methods getDefaultCalendarName() and setDefaultCalendarName() have been deprecated. Use getDefaultCalendar() and setDefaultCalendar() instead.
  • Ensure that percent complete values can be read from MSPDI files even if the values are decimals.
  • Improve handling of the default calendar when reading certain MSPDI files.
  • Improve reading certain Phoenix PPX files.
  • Improve reading certain FastTrack FTS files.
  • Improve formatting of time project properties when written to JSON.
  • Improve reading MPP files generated by Microsoft Project 16.0.15128.20158 and later versions.
"},{"location":"CHANGELOG/#1030-2022-04-29","title":"10.3.0 (2022-04-29)","text":"
  • General improvements to make calendar data read from different file formats more consistent.
  • When reading P6 and Powerproject schedules MPXJ will no longer create an \"artificial\" resource calendar for each resource. Resources will be linked directly to the calendars they use in the original schedule.
  • Update MPXWriter and MSPDIWriter to ensure that, when written, calendars are correctly structured in the form required by Microsoft Project.
  • JsonWriter now includes calendar data as part of its output.
  • The ProjectCalendar methods setMinutesPerDay, setMinutesPerWeek, setMinutesPerMonth and setMinutesPerYear have been deprecated, use setCalendarMinutesPerDay, setCalendarMinutesPerWeek, setCalendarMinutesPerMonth and setCalendarMinutesPerYear instead.
  • The ProjectCalendar method setResource has been deprecated and will not be replaced. Use the Resource method setCalendar or setCalendarUniqueID to link a calendar with a resource.
  • The ProjectCalendar method getResource has been deprecated. Use the getResources method instead to retrieve all resources linked with a calendar.
  • The Resource methods addResourceCalendar, setResourceCalendar, getResourceCalendar, setResourceCalendarUniqueID and getResourceCalendarUniqueID have been deprecated and replaced by addCalendar, setCalendar, getCalendar, setCalendarUniqueID and getCalendarUniqueID respectively.
"},{"location":"CHANGELOG/#1020-2022-03-06","title":"10.2.0 (2022-03-06)","text":"
  • Improvements to writing currency, rate and units amounts to MSPDI files.
  • When reading MPP and MSPDI files, calendar exceptions representing a single range of days, but defined as a recurring exception are converted to a range of days, removing the unnecessary recurring definition.
  • Added StructuredTextParser to replace original code handling calendar data, project properties and curve data read from XER files and Primavera databases. Can also be used to extract data from Primavera Layout Files (PLF).
  • Improve recognition of contoured resource assignments read from MPP files.
  • Improve retrieval of resource assignment confirmed, response pending, linked fields, and team status pending flags from certain MPP files.
"},{"location":"CHANGELOG/#1010-2022-01-29","title":"10.1.0 (2022-01-29)","text":"
  • Improve PMXML file compatibility with P6.
  • Strip any trailing invalid characters from text read from FTS files.
  • Ensure all tasks read from Powerproject and Project Commander have unique IDs.
  • Correct expansion of exceptions from a weekly recurring calendar exception.
  • Ensure that expanded calendar exceptions are written to file formats which do not support recurring exceptions.
  • Ensure that start and finish dates are set when reading milestones from GanttProject files.
"},{"location":"CHANGELOG/#1005-2022-01-11","title":"10.0.5 (2022-01-11)","text":"
  • Ensure Task.getActivityCodes() returns an empty list rather than null when no activity code values have been assigned.
  • Default to using ASCII when reading and writing SDEF files, as per the SDEF specification.
  • Provide methods to set and get the charset used when reading and writing SDEF files.
"},{"location":"CHANGELOG/#1004-2022-01-07","title":"10.0.4 (2022-01-07)","text":"
  • Added support for reading Code Library values (as Activity Codes) from Powerproject files.
  • Updated ProjectCleanUtility to provide a \"replace\" strategy alongside the original \"redact\" strategy.
"},{"location":"CHANGELOG/#1003-2021-12-22","title":"10.0.3 (2021-12-22)","text":"
  • Fix issue with null tasks from certain MPP files introduced in 10.0.2.
"},{"location":"CHANGELOG/#1002-2021-12-16","title":"10.0.2 (2021-12-16)","text":"
  • Improve identification of null tasks for certain MPP files.
"},{"location":"CHANGELOG/#1001-2021-12-10","title":"10.0.1 (2021-12-10)","text":"
  • Avoid false positives when detecting password protected MPP files.
"},{"location":"CHANGELOG/#1000-2021-12-01","title":"10.0.0 (2021-12-01)","text":"
  • Added support for .NET Core 3.1
  • Nuget packages now explicitly target .NET Framework 4.5 (net45) and .NET Core 3.1 (netcoreapp3.1)
"},{"location":"CHANGELOG/#983-2021-11-30","title":"9.8.3 (2021-11-30)","text":"
  • Improve reliability when reading certain Phoenix files.
  • Ensure multiple trailing nul characters are stripped from text when reading schedules from a Primavera database.
"},{"location":"CHANGELOG/#982-2021-11-01","title":"9.8.2 (2021-11-01)","text":"
  • Improve accuracy of identifying null tasks in certain MPP files.
  • Improve accuracy of identifying valid tasks in certain MPP files.
  • Ensure hierarchical outline code values are read correctly from MSPDI files.
  • Improve support for files produced by recent versions of FastTrack.
"},{"location":"CHANGELOG/#981-2021-10-13","title":"9.8.1 (2021-10-13)","text":"
  • Added support for Phoenix 5 schedules.
  • Improve handling of null tasks read from MPP files.
"},{"location":"CHANGELOG/#980-2021-09-30","title":"9.8.0 (2021-09-30)","text":"
  • Introduced the BaselineStrategy interface and implementing classes. (Note: this includes a breaking change if you were using the ProjectFile.setBaseline method and supplying a lambda. You will now need to implement a BaselineStrategy and set this in ProjectConfig before setting a baseline).
  • Improved accuracy of baseline attributes for Primavera schedules.
"},{"location":"CHANGELOG/#970-2021-09-28","title":"9.7.0 (2021-09-28)","text":"
  • Add Sprint ID and Board Status ID attributes to task.
  • Introduce the TimeUnitDefaultsContainer to allow constants for time unit conversions to be obtained from both project properties and calendars.
  • Duration attributes are no longer returned as Duration instances by the ruby gem, they are now returned as floating point numbers. By default, durations are expressed in seconds. A new optional argument to MPXJ::Reader.read allows you to change the units used to express durations. (Note: this is a breaking change for users of the ruby gem)
  • Update JsonWriter to use a relevant calendar when converting durations.
  • Ensure default calendar is set correctly when reading XER and PMXML files, and P6 databases.
  • Use default hours per day/week/month/year when reading P6 XER files or databases if these values are not present.
  • Ensure that the minutes per day/week/month/year attributes are copied when a calendar is copied.
  • When reading P6 schedules, roll up calendar for WBS entries when child activities all share the same calendar.
  • Generate missing minutes per day/week/month/year for calendars read from P6 schedules.
  • Inherit minutes per day/week/month/year from base calendars (Note: minor method signature changes on ProjectProperties and ProjectCalendar).
  • Allow explicit values to be set for project minutes per week and minutes per year.
  • Fall back on defaults for project minutes per day/week/month/year attributes.
"},{"location":"CHANGELOG/#960-2021-09-13","title":"9.6.0 (2021-09-13)","text":"
  • Add Planned Start and Scheduled Finish to project properties.
  • Add attribute_types method to Ruby classes.
  • Updated to use POI 5.0.0.
  • Corrected source of Must Finish By project property when reading XER files or P6 databases.
  • When reading PMXML files, ensure that the activity calendar is set before calculating slack.
  • Remove unused field TaskField.PARENT_TASK.
  • Ensure task Unique ID and task Parent Unique ID attributes are treated as mandatory when written to JSON.
  • Fix an issue with Ruby gem where a task's parent was not being retrieved correctly in some circumstances.
"},{"location":"CHANGELOG/#952-2021-08-22","title":"9.5.2 (2021-08-22)","text":"
  • Add Must Finish By date to project properties.
  • Add support for the task attributes Longest Path, External Early Start and External Early Finish, and ensure they can be read from P6 schedules.
  • Rename ProjectFile.getStartDate() and ProjectFile.getFinishDate() methods for clarity. Original method names are marked as deprecated
  • Ensure that all activities in a PMXML file have a CalendarID attribute to ensure compatibility with older versions of P6.
  • Ensure that the user's selected progress period is used to set the project's status date attribute when reading Asta PP files.
  • Ensure that a task's Complete Through attribute is not advanced to the start of the next working day (the behaviour of Microsoft Project prior to 2007 was to report Complete Through as the start of the next working day. This change ensures MPXJ matches versions of Microsoft Project from 2007 onwards. Previous behaviour can be restored using the ProjectConfig.setCompleteThroughIsNextWorkStart() method).
  • Deprecate task getSplitCompleteDuration() and setSplitCompleteDuration() in favour of getCompleteThrough() and setCompleteThrough().
  • Improved the implementation of the TaskContainer.synchronizeTaskIDToHierarchy method.
  • Update jsoup to 1.14.2.
"},{"location":"CHANGELOG/#951-2021-07-01","title":"9.5.1 (2021-07-01)","text":"
  • When applying a baseline using ProjectFile.setBaseline, gracefully handle duplicate task key values.
  • Handle missing values populating cost rate table from an MPP file.
"},{"location":"CHANGELOG/#950-2021-06-30","title":"9.5.0 (2021-06-30)","text":"
  • Added support for reading baseline data from embedded baselines in PP files.
  • Correct resource assignment percent complete values read from PP files.
  • JsonWriter no longer writes attribute type information by default. (The original behaviour can be restored by calling setWriteAttributeTypes(true) on your JsonWriter instance).
  • The MPXJ Ruby Gem now generates explicit methods to access attributes rather than relying on \"method_missing\" to intercept and act on attribute access.
  • Don't write Assignment Task GUID, Assignment Resource GUID or Resource Calendar GUID to JSON.
  • Don't write a value for Assignment Work Contour to JSON if the contour is the default value (i.e. flat).
  • Don't write a value for Assignment Resource Request Type to JSON if the type is the default value (i.e. none).
  • Don't write a value for Task Earned Value Method to JSON if the method matches the project default.
  • Don't write a value for Task Type to JSON if the type matches the project default.
  • Stop writing a default value (-1) for Parent Task ID to JSON if the task does not have a parent.
  • Stop writing a default value (-1) for Task Calendar ID to JSON if the task does not have a calendar.
  • When reading resource assignments from an MPP file, don't record Project's internal representation of a null resource ID (-65535), record the resource ID explicitly as null.
  • For MPX and Planner files, don't write resource assignments for the \"null\" resource.
  • Handle missing status date when reading P6 schedules from XER files or database.
  • When reading MPP files, treat UUIDs which are all zeros as null.
  • Deprecate the 10 Resource Outline Code get and set methods and replace with get and set methods which take an index argument.
  • Provide a helper method (PrimaveraHelper.baselineKey) to encapsulate key generation for setting Primavera baselines.
"},{"location":"CHANGELOG/#940-2021-06-11","title":"9.4.0 (2021-06-11)","text":"
  • Read custom value lists for resource custom fields from MPP files (based on a suggestion by Markus H\u00f6ger).
  • Added support for reading custom fields from Asta Powerproject files.
  • Ensure short data type values are written to JSON files as numeric values.
  • Ensure delay data type values are written to JSON files as duration values.
  • Don't write zero rates to JSON files.
  • Introduced a separator into rate values when written to a JSON file to make it clear that the value is a rate not a duration (for example: 5.00h is now 5.00/h).
  • When writing an enum value of a JSON file, ensure we write the original enum name rather than the value return by toString. This provides more meaningful output (Potentially breaking change if you use the Ruby gem or consume the JSON output directly. Affected attributes are project properties: currency symbol position, time format, date format, bar text date format, schedule from, mpx file version; resource attribute: type).
  • Ensure invalid cost rate table data is handled gracefully when reading from MSPDI files.
  • Handle missing data when reading MSPDI files (based on a contribution by Lord Helmchen).
  • Improve population of summary task names when reading from Powerproject PP files.
  • Correctly read hierarchical resource outline codes from MPP files (based on a suggestion by Markus H\u00f6ger).
"},{"location":"CHANGELOG/#931-2021-05-18","title":"9.3.1 (2021-05-18)","text":"
  • Preserve multiple assignments between an activity and a resource when reading P6 schedules.
  • Renamed WorkContour.isFlat to isContourFlat and WorkContour.isContoured to isContourManual.
  • Include an entry for 0% in the WorkContour curve definition.
  • Fix an issue where non-working days were not being treated correctly in date calculations if they happen to still have time ranges attached.
"},{"location":"CHANGELOG/#930-2021-05-06","title":"9.3.0 (2021-05-06)","text":"
  • Add support for reading roles from P6 databases, XER and PMXML files, and for writing roles to PMXML files. Roles are represented as resources. The new resource Boolean attribute \"Role\" is used to distinguish between Resource instances which represent resources and those which represent roles.
  • Add support for reading resource curves from P6 databases, XER and PMXML files, and for writing resource curves to PMXML files. The WorkContour enum is now a class, and instance of this class are used to represent resource curves. The curves are available via the work contour attribute of resource assignments.
  • Corrected the data type of the task physical percent complete attribute.
  • Improve handling of non-standard relationship type representations encountered in XER files and P6 databases.
"},{"location":"CHANGELOG/#926-2021-04-26","title":"9.2.6 (2021-04-26)","text":"
  • Handle invalid baseline numbers when reading MSPDI files.
  • Improve custom field handling when reading GanttProject files.
"},{"location":"CHANGELOG/#925-2021-04-20","title":"9.2.5 (2021-04-20)","text":"
  • Add launcher batch file and shell script.
  • Improve handling of calculated task attributes when writing a project to a different format.
  • Ensure that dates are rolled up to summary tasks when reading FastTrack files.
  • Improve support for Synchro 6.3 SP files.
"},{"location":"CHANGELOG/#924-2021-04-09","title":"9.2.4 (2021-04-09)","text":"
  • Fix an issue reading resource rate information GanttProject files.
"},{"location":"CHANGELOG/#923-2021-04-08","title":"9.2.3 (2021-04-08)","text":"
  • Fix an issue reading Planned Duration from P6 databases and XER files.
  • Ensure Duration and Actual Duration are populated for WBS entries when reading P6 schedules.
"},{"location":"CHANGELOG/#922-2021-04-07","title":"9.2.2 (2021-04-07)","text":"
  • Fix issue with WBS ordering when writing PMXML files.
"},{"location":"CHANGELOG/#921-2021-04-04","title":"9.2.1 (2021-04-04)","text":"
  • Improve Task critical flag calculation when reading PMXML files.
  • Improve support for Synchro 6.3 SP files.
"},{"location":"CHANGELOG/#920-2021-03-30","title":"9.2.0 (2021-03-30)","text":"
  • Improve accuracy when reading subprojects from MPP files.
  • Add Remaining Late Start and Remaining Late Finish attributes to Task.
  • Add Critical Activity Type attribute to Project Properties
  • Read Remaining Early Start, Remaining Late Start, Remaining Early Finish and Remaining Late finish from and write to PMXML files.
  • Read Remaining Late Start and Remaining Late finish from P6 database and XER files.
  • Ensure that WBS entries without child activities are not marked as critical.
  • Don't attempt to set the critical flag when reading XER and PMXML files where the schedule is using \"longest path\" to determine critical activities. (MPXJ currently doesn't have enough information to be able to determine the correct value for the critical flag in this situation).
  • Ensure cost, duration, date and work attributes are rolled up to WBS entries for P6 schedules read from PMXML files, XER files and P6 databases.
  • Populate baseline cost, duration, finish, start and work when reading from XER files, PMXML files and P6 databases where the \"Project Baseline\" has been set to \"Current Project\".
"},{"location":"CHANGELOG/#910-2021-03-11","title":"9.1.0 (2021-03-11)","text":"
  • Add methods to the ProjectFile class to attach a ProjectFile instance as a baseline. The baselines attached to the ProjectFile will be used to populate the relevant baseline attributes in the current schedule.
  • Added experimental support for writing baseline projects to PMXML files.
  • Added the Project GUID attribute.
  • When reading PMXML files, the list of projects returned by the readAll method will include any baseline projects present in the file.
  • When reading PMXML files which include the current baseline project, use this to populate the relevant baseline attributes in the main schedule.
  • The Project Unique ID property is now an integer rather than a string.
  • When reading Primavera schedules, populate the project properties Project ID and Baseline Project Unique ID.
  • Handle Primavera resource rates which don't have a start or finish date.
  • Handle MSPDI files with resource availability tables which don't have a start or finish date.
  • Ensure that the Activity ID field is populated consistently for WBS entries in PMXML files compared to the same schedule read from an XER file or P6 database.
  • Ensure duration of manually scheduled tasks in MPP files is represented correctly.
"},{"location":"CHANGELOG/#900-2020-02-18","title":"9.0.0 (2020-02-18)","text":"
  • NOTE: this release introduces breaking changes!
  • All fields which are non-user defined, but were previously being returned by MPXJ as custom fields are now represented as explicit field types. Custom fields now only contain values for user-defined custom fields.
  • All code previously marked as deprecated has been removed.
  • When reading an XER file or a P6 database, some custom project property names have been updated. LagCalendar is now CalendarForSchedulingRelationshipLag, RetainedLogic is now WhenSchedulingProgressedActivitiesUseRetainedLogic, ProgressOverride is now WhenSchedulingProgressedActivitiesUseProgressOverride, IgnoreOtherProjectRelationships is now WhenSchedulingProgressedActivitiesUseProgressOverride, and StartToStartLagCalculationType is now ComputeStartToStartLagFromEarlyStart.
  • Updated PMXML schema to version 20.12.
  • Fix an issue where GUID values were not being read correctly from XER files and P6 databases.
  • Percent complete type is now available as a task attribute for P6 schedules from any source.
  • Ensure that percent complete values are stored in the appropriate attributes when reading P6 schedules. (NOTE: Previously the \"reported\" percent complete value was stored as the tasks \"percent complete\" attribute. Now this holds the schedule percent complete value, and the percent work complete and physical percent complete attributes are also populated. To determine which value should be reported for a task, see the \"percent complete type\" extended field attribute.)
  • Correctly handle default calendar when reading and writing PMXML files.
  • Update the sort order of WBS entries and activities in PMXML files to match the order exported by P6.
  • Match the way P6 exports the WBS code attribute for PMXML files.
  • Update the representation of Boolean values when writing PMXML files to match the form exported by P6.
  • Set the task type attribute when reading PMXML files.
  • Improve duration and actual duration calculations when reading XER files and P6 databases.
  • Fix an issue where resource assignment costs were not being read correctly from PMXML files.
  • Read and write the suspend date and resume date attributes for PMXML files.
  • General improvements to the SDEF writer.
  • Updated to rtfparserkit 1.16.0.
"},{"location":"CHANGELOG/#851-2021-01-07","title":"8.5.1 (2021-01-07)","text":"
  • Don't write unused enterprise custom field definitions to MSPDI files. This ensures that MS Project will open these files correctly.
"},{"location":"CHANGELOG/#850-2021-01-06","title":"8.5.0 (2021-01-06)","text":"
  • Notes in their original format (HTML from P6, RTF from MS Project) can now be retrieved via the getNotesObject method on Task, Resource, and ResourceAssignment. Plain text notes can still be retrieved via the getNotes method. If you were previously using the \"preserve note formatting\" flag to retrieve the original formated version of a note, you will now need to use the getNotesObject method.
  • Write WBS and Activity notes to PMXML files.
  • PMXML compatibility improvements to ensure files can be successfully imported into P6.
"},{"location":"CHANGELOG/#840-2020-12-29","title":"8.4.0 (2020-12-29)","text":"
  • Previously when reading PMXML files, XER files, and P6 databases, a set of baseline attributes on tasks and assignments (including Start, Finish, Duration, Cost and Work) were being populated with planned values rather than baseline values. These baseline attributes are no longer being set. The values they previously contained are now available as custom fields.
  • Read activity notepad entries for XER, PMXML files and P6 databases.
  • Read schedule and leveling options from PMXML files and P6 databases.
  • Improve support for reading activity cost and work from PMXML files.
"},{"location":"CHANGELOG/#835-2020-12-15","title":"8.3.5 (2020-12-15)","text":"
  • Fix CVE-2020-35460: zip slip vulnerability (with thanks to Sangeetha Rajesh S, ZOHO Corporation)
"},{"location":"CHANGELOG/#834-2020-12-10","title":"8.3.4 (2020-12-10)","text":"
  • Updated PMXML schema to version 19.12.
  • Ensure that we always set the activity planned start and planned finish dates when writing a PMXML file.
  • Updated the getPopulatedFields methods to ignore fields with default values.
  • Made the Resource ID attribute available as a resource's TEXT1 custom field, with the alias \"Resource ID\" when reading PMXML and XER files, or from a P6 database. (Note that presently for XER files and P6 databases, the Resource ID value is also read into the initials attribute. This behaviour is deprecated and will be removed in the next major MPXJ release).
  • Populate the Resource ID with the value read from a P6 schedule when writing a PMXML file.
  • Ensure that the hours per day, week, month and year attributes are read from and written to PMXML files.
  • Fix an issue causing the hours per day calendar attribute to be read inaccurately from XER files and P6 databases.
  • Read assignment actual overtime cost and work attributes from PMXML files.
  • Update calculation of assignment work, cost and units attributes for PMXML files.
"},{"location":"CHANGELOG/#833-2020-11-24","title":"8.3.3 (2020-11-24)","text":"
  • Added cost rate table support when reading from and writing to PMXML files.
  • Added a getPopulatedFields method to the TaskContainer, ResourceContainer and ResourceAssignmentContainer classes. This will retrieve the set of fields which are populated with a non-null value across the whole project for Tasks, Resources, and ResourceAssignments respectively.
  • Add START_ON, FINISH_ON constraint types. \u00a7 MANDATORY_START, MANDATORY_FINISH constraint types. MANDATORY_START/FINISH are now represented as MUST_START/FINISH_ON. This change allows users to distinguish between START/FINISH_ON and the MANDATORY_* constraints when reading P6 schedules.
  • Improve handling of cost rate tables and availability tables when writing to an MSPDI file.
  • Handle P6 databases and XER files with user defined fields of type FT_FLOAT.
  • Align invalid XER record behaviour with P6.
  • Handle Planner files which don't contain an allocations tag.
  • Gracefully handle MPP files with missing view or table data.
"},{"location":"CHANGELOG/#832-2020-10-22","title":"8.3.2 (2020-10-22)","text":"
  • Added support for \"new tasks are manual\" project property (Contributed by Rohit Sinha)
  • Improved support for reading and writing outline codes and extended attributes for MSPDI files (Based on a contribution by Dave McKay)
  • Improved handling of enterprise custom fields when reading MPP files
  • Update Primavera database and XER readers to avoid potential type conversion errors when the caller provides their own field mappings.
  • Improve handling of some MPP12 MPP file variants.
  • Avoid error when reading timephased data from certain MPP files.
  • Gracefully handle MPP files with missing view data.
  • Update junit to 4.13.1.
"},{"location":"CHANGELOG/#831-2020-10-14","title":"8.3.1 (2020-10-14)","text":"
  • Minor updates to PlannerReader.
"},{"location":"CHANGELOG/#830-2020-10-13","title":"8.3.0 (2020-10-13)","text":"
  • Add the \"userDefined\" attribute to the CustomField class to allow caller to determine if the field has been created by a user or MPXJ.
  • Add support for reading expense items, expense categories and cost accounts from XER files, PMXML files and Primavera databases.
  • Add support for writing expense items, expense categories and cost accounts to PMXML files.
  • Updated the XER file reader to ignore invalid records rather than reporting an error, matching the behaviour of P6
  • Updated the XER file reader to ensure that activity suspend and resume dates are read correctly.
  • Updated the XER file reader to ensure that if the reader returns the project selected by the caller when the caller supplies a value for project ID.
  • Updated PMXML reader to avoid user defined field collisions.
  • Updated PMXML reader to add setProjectID and listProjects methods.
  • Update the .net extension method ToIEnumerable to work with java.lang.Iterable rather than java.util.Collection
"},{"location":"CHANGELOG/#820-2020-09-09","title":"8.2.0 (2020-09-09)","text":"
  • All readers, including the UniversalProjectReader, now support a readAll method. If a file or database contains more than one project the readAll method can be used to retrieve them all in one operation. If the file format doesn't support multiple schedules, readAll will just return a single schedule.
  • Add PrimaveraDatabaseFileReader to encapsulate access to SQLite Primavera databases.
  • Ensure that the summary flag is true for WBS items in Primavera schedules, even if they have no child activities.
  • Ensure that the critical flag is rolled up appropriately to WBS items when reading Primavera schedules.
  • Set export flag property when reading projects from a PMXML file.
  • Corrected data type of resource assignment Work Contour field.
  • Corrected data type of resource fields: BCWS, BCWP, ACWP, SV, CV, and Work Contour.
  • Corrected data type of task fields: CV, ACWP, VAC, CPI, EAC, SPI, TCPI, and Work Contour.
"},{"location":"CHANGELOG/#814-2020-08-31","title":"8.1.4 (2020-08-31)","text":"
  • Fix CVE-2020-25020: XXE vulnerability (with thanks to Sangeetha Rajesh S, ZOHO Corporation)
  • Import milestone constraints from Asta schedules (Contributed by Dave McKay)
  • Handle elapsed durations in Asta schedules (Based on a contribution by Dave McKay)
  • Correctly determine the constraint type for tasks with ALAP placement with or without predecessors when reading from Asta schedules (Contributed by Dave McKay)
  • Gracefully handle a missing table name when reading an XER file.
  • Gracefully handle an unexpected calendar data when reading an XER file.
  • Correctly handle XER files with multibyte character encoding.
  • Import all schedule and leveling options from XER files.
  • Ensure project calendars are read from PMXML files.
  • Added readAll methods to PrimaveraPMFileReader to allow all projects contained in a PMXML file to be read in a single pass.
"},{"location":"CHANGELOG/#813-2020-06-25","title":"8.1.3 (2020-06-25)","text":"
  • Improve reliability when reading custom field values from certain MPP12 files.
  • Improve accuracy of activity percent complete when reading from certain XER files or P6 databases.
  • Improve accuracy of WBS percent complete when reading from certain XER files or P6 databases.
  • Improve accuracy of task durations when reading Asta schedules.
  • Fix an issue handling the end date of calendar exceptions when reading Asta schedules.
  • Fix an issue with correctly identifying the calendar applied to summary tasks when reading Asta schedules.
  • Populate percent complete, duration, actual start, actual finish, early start, late start, early finish and late finish attributes for summary tasks when reading Asta schedules.
  • The percent complete value reported for tasks when reading Asta schedules is now Duration Percent Complete. The Overall Percent Complete value originally being returned is available in a custom field.
"},{"location":"CHANGELOG/#812-2020-06-18","title":"8.1.2 (2020-06-18)","text":"
  • Improve detection of unusual MSPDI file variants.
  • Updated to read task notes from FastTrack FTS files.
"},{"location":"CHANGELOG/#811-2020-06-17","title":"8.1.1 (2020-06-17)","text":"
  • Improve support for Synchro 6.2 SP files.
"},{"location":"CHANGELOG/#810-2020-06-11","title":"8.1.0 (2020-06-11)","text":"
  • Experimental support for reading Project Commander schedules.
  • Update to use JAXB 2.3.2.
  • Avoid failures caused by unreadable OLE compound documents when the UniversalProjectReader is trying to determine the file type.
  • Strip trailing ASCII NUL characters from text fields when reading from a Primavera database.
  • Improve accuracy of task order when reading Phoenix files.
  • Improve accuracy of task data when reading some MPP file variants.
  • Improve reliability when reading certain SureTrak files.
"},{"location":"CHANGELOG/#808-2020-04-20","title":"8.0.8 (2020-04-20)","text":"
  • Improve handling of numeric character references invalid for XML 1.0 in PMXML files.
  • Improve handling of resource calendars read from Planner files.
  • Improve handling of resource calendars read from MPX files.
  • Ignore the milestone flag when reading MPX files if the task has a non-zero duration.
  • Ensure JSON files can be written when Unique ID predecessor/successor attributes have been read from an MPX file.
"},{"location":"CHANGELOG/#807-2020-04-17","title":"8.0.7 (2020-04-17)","text":"
  • Updated to rtfparserkit 1.15.0.
  • Improve handling of PMXML files with empty calendar exception time ranges.
"},{"location":"CHANGELOG/#806-2020-03-05","title":"8.0.6 (2020-03-05)","text":"
  • Updated to use POI 4.1.2.
  • Improve handling of some XER file variants.
"},{"location":"CHANGELOG/#805-2020-02-07","title":"8.0.5 (2020-02-07)","text":"
  • Allow users to determine WBS attribute content with \"wbs is full path\" flag for Primavera readers.
  • Ensure summary task start and finish dates are populated when reading PMXML files.
  • Use baseline start and finish dates as planned start and finish dates when writing PMXML files.
  • Late start and late finish dates are now written to PMXML files.
"},{"location":"CHANGELOG/#804-2020-02-06","title":"8.0.4 (2020-02-06)","text":"
  • Update sqlite-jdbc dependency to 3.30.1
  • Improve handling of characters invalid for XML 1.0 in PMXML files generated by P6.
"},{"location":"CHANGELOG/#803-2020-01-27","title":"8.0.3 (2020-01-27)","text":"
  • Improve handling of zero value durations, costs and units from certain MPP files.
  • Improve percent complete calculation for certain XER file and P6 Database schedules.
  • Improve percent complete calculation for certain P3 schedules.
  • Improve handling of incorrectly encoded characters in PMXML files generated by P6.
  • Ensure that negative durations can be written to and read from MSPDI files in the format understood by MS Project.
"},{"location":"CHANGELOG/#802-2020-01-16","title":"8.0.2 (2020-01-16)","text":"
  • Improve handling of zero duration tasks read from Phoenix files.
"},{"location":"CHANGELOG/#801-2020-01-05","title":"8.0.1 (2020-01-05)","text":"
  • Add missing nuget dependency
"},{"location":"CHANGELOG/#800-2020-01-02","title":"8.0.0 (2020-01-02)","text":"
  • MPXJ now requires Java 8 or later.
  • Removed deprecated methods.
  • Updated to use POI 4.1.1.
  • Updated to use IKVM 8.1.5717.0.
"},{"location":"CHANGELOG/#798-2019-12-27","title":"7.9.8 (2019-12-27)","text":"
  • Added support for reading and writing outline code/custom field lookup tables for MSPDI files.
  • Added sample code to demonstrate creation of timephased work.
  • Populate project status date attribute when reading Asta schedules.
  • Populate parent attribute when reading activity code values from Primavera schedules.
  • Improve configurability of PrimaveraDatabaseReader and PrimaveraXERFileReader.
  • Made JAXB JARs an explicit dependency to avoid issues with recent Java versions which do not include them.
"},{"location":"CHANGELOG/#797-2019-11-25","title":"7.9.7 (2019-11-25)","text":"
  • Round percent complete values read from Asta files to two decimal places to avoid values like 99.9999999%.
"},{"location":"CHANGELOG/#796-2019-11-22","title":"7.9.6 (2019-11-22)","text":"
  • Improve support for FastTrack files.
"},{"location":"CHANGELOG/#795-2019-11-19","title":"7.9.5 (2019-11-19)","text":"
  • Added flag to manage compliance with password protection. (Contributed by ztravis)
  • Improve support for Synchro 6.1 SP files.
  • Fix an issue where the task hierarchy was not correctly represented when reading a PMXML file.
"},{"location":"CHANGELOG/#794-2019-11-08","title":"7.9.4 (2019-11-08)","text":"
  • Add support for reading Sage 100 Contractor schedule grid files.
  • Ensure attribute names are valid when exporting JSON.
  • Improve handling of custom field lookup values (Based on a contribution by Nick Darlington).
  • Fix an issue when copying a calendar which has exceptions defined.
"},{"location":"CHANGELOG/#793-2019-09-10","title":"7.9.3 (2019-09-10)","text":"
  • Add support for reading task early finish and late finish attributes from Asta PP files.
  • Ensure XER files containing secondary constraints can be read correctly.
  • Preserve calendar IDs when reading from XER files and P6 database (Based on a contribution by forenpm).
  • Ensure base calendars are read correctly for P6 schedules.
  • Ensure MPP files with unexpected auto filter definition data are handled gracefully.
  • Preserve leveling delay format when reading tasks from MSPDI files.
  • Ensure unexpected structure of timephased data is handled gracefully when reading MPP files.
"},{"location":"CHANGELOG/#792-2019-08-19","title":"7.9.2 (2019-08-19)","text":"
  • Add support for reading and writing secondary constraints from P6 schedules (Based on a contribution by Sruthi-Ganesh)
  • Improve support for Synchro SP files containing blank tasks.
  • Make constraint type mapping consistent when reading and writing PMXML files.
  • Improve handling of leveling delay units and actual duration units (Based in a contribution by Daniel Schmidt).
  • Improve handling of certain types of malformed MPP files.
  • Improve handling of certain types of malformed SDEF files.
  • Map P6 Equipment resource type to cost rather than work (Contributed by forenpm)
  • Improve handling of certain MPP files containing large numbers of blank tasks.
  • Improve handling of certain MPX files containing trailing delimiters.
"},{"location":"CHANGELOG/#791-2019-07-01","title":"7.9.1 (2019-07-01)","text":"
  • Set task start, finish and percent complete when reading SDEF files.
"},{"location":"CHANGELOG/#790-2019-07-01","title":"7.9.0 (2019-07-01)","text":"
  • Add support for reading SDEF files.
"},{"location":"CHANGELOG/#784-2019-06-27","title":"7.8.4 (2019-06-27)","text":"
  • Add support for reading data links (linked fields) configuration from MPP files.
  • Updated to avoid an infinite loop when processing certain corrupt files (Contributed by ninthwaveltd).
  • Update MSPDI generation to ensure MS Project correctly recognises complete tasks without resource assignments.
  • Ensure that activity codes are read for P6 schedules.
  • Improve support for reading custom field values derived from custom field lookup tables in MPP files.
  • Improve support for MPP files written with the June 2019 update of Microsoft Project.
"},{"location":"CHANGELOG/#783-2019-05-24","title":"7.8.3 (2019-05-24)","text":"
  • Improve handling of task baseline start, start, baseline finish, finish and slack fields read from FTS files.
"},{"location":"CHANGELOG/#782-2019-05-19","title":"7.8.2 (2019-05-19)","text":"
  • Improve handling of MPP files with missing Props.
  • Improve handling of custom field lookup tables for MPP12 files.
  • Correctly write activity duration type to a PMXML file (Contributed by Sebastian Stock)
  • Improve handling of Activity Type and Activity ID when writing PMXML files (Based on a contribution by Sebastian Stock)
  • Update PMXML file reader for greater consistency with XER and P6 database readers (Activity ID, Activity Type, Status, and Primary Resource ID)
  • Improve handling of certain FTS files.
  • Improve handling of task notes from MPP8 files.
  • More accurately read predecessors and successors from Asta PP files (Based on a contribution by Dave McKay)
  • When a schedule is read from P6, P3, or SureTrak, Task.getSummary will return true only if a task is part of the WBS
  • Improve support for reading the Synchro Scheduler 2018 SP files.
  • Added Task.hasChildTasks() method.
  • Fixed Issue 330: Splits data coming in as null for all tasks
"},{"location":"CHANGELOG/#781-2019-02-13","title":"7.8.1 (2019-02-13)","text":"
  • Improve support for reading the Synchro Scheduler 2018 SP files.
  • Add support for reading Gantt Designer GNT files.
  • Improve handling of non-standard MSPDI files.
  • Improve handling of non-standard GanttProject files.
  • Update MSPDI generation to ensure MS Project correctly recognises complete milestones without resource assignments.
  • Improve support for reading user defined fields from PMXML files.
  • Ignore hammock tasks when reading PP files.
"},{"location":"CHANGELOG/#780-2019-01-18","title":"7.8.0 (2019-01-18)","text":"
  • Added support for reading and writing GUIDs for Tasks, Resources, and Assignments in MSPDI files.
  • Updated Java build to use Maven
  • Updated to provide a general performance improvement (Based on a contribution by Tiago de Mello)
  • Updated to fix an issue when the Microsoft JDBC driver is used to access a P6 database in SQL Server 2005
  • Fixed Issue 332: Asta lag sign incorrect (Based on a contribution by Dave McKay)
  • Fixed Issue 333: Asta constraints lost (Contributed by Dave McKay)
  • Fixed Issue 335: MSDPI into Asta doesn't import Calendar exceptions (Contributed by Dave McKay)
"},{"location":"CHANGELOG/#771-2018-10-23","title":"7.7.1 (2018-10-23)","text":"
  • Read additional schedule options from XER files. (Contributed by forenpm)
  • Improve handling of some types of MPP file with missing resource assignment data.
  • Ensure that resource assignment flag fields are read correctly for all MPP file types (Based on a contribution by Vadim Gerya).
  • Ensure that timephased actual work is handled correctly for material resources (Contributed by Vadim Gerya).
  • Improve accuracy when reading resource type from MPP files.
  • Improve compatibility of generated MSPDI files with Asta Powerproject (Contributed by Dave McKay).
"},{"location":"CHANGELOG/#770-2018-10-12","title":"7.7.0 (2018-10-12)","text":"
  • Add support for reading the Synchro Scheduler SP files.
  • Add support for reading the activity code (ID) from Asta files.
  • When reading a Phoenix file, set the project's status date to the data date from the storepoint.
  • Handle MSPDI files with timephased assignments that don't specify a start and end date.
"},{"location":"CHANGELOG/#763-2018-10-04","title":"7.6.3 (2018-10-04)","text":"
  • Add support for reading Remaining Early Start and Remaining Early Finish task attributes from P6. (Contributed by forenpm)
  • Add support for reading Retained Logic and Progressive Override project attributes from P6. (Contributed by forenpm)
  • Fix incorrect sign when calculating start and finish slack (Contributed by Brian Leach).
  • Correctly read predecessors and successors from Phoenix files.
"},{"location":"CHANGELOG/#762-2018-08-30","title":"7.6.2 (2018-08-30)","text":"
  • Add support for nvarchar columns when reading from a P6 database.
  • Updated to correctly read percent lag durations from MSPDI files (based on a contribution by Lord Helmchen).
  • Updated the data type for the ValueGUID tag in an MSPDI file (based on a contribution by Lord Helmchen).
"},{"location":"CHANGELOG/#761-2018-08-29","title":"7.6.1 (2018-08-29)","text":"
  • Improve handling of MPP files where MPXJ is unable to read the filter definitions.
  • Improve handling of SureTrak projects without a WBS.
  • Improve handling of SureTrak and P3 WBS extraction.
  • Handle unsupported ProjectLibre POD files more gracefully.
  • Improve detection of non MS Project compound OLE documents.
  • Gracefully handle XER files which contain no projects.
"},{"location":"CHANGELOG/#760-2018-07-13","title":"7.6.0 (2018-07-13)","text":"
  • Added support for reading ConceptDraw PROJECT CDPX, CPDZ and CPDTZ files.
  • Add support for reading the export_flag attribute from XER files. (Contributed by forenpm)
  • Use correct licence details in Maven pom.xml (contributed by Mark Atwood).
  • Improve UniversalProjectReader's handling of XER files containing multiple projects.
"},{"location":"CHANGELOG/#750-2018-06-19","title":"7.5.0 (2018-06-19)","text":"
  • Added support for reading activity codes from P6 databases, XER files, and PMXML files.
  • Added support for reading user defined values from a P6 database.
  • Added support for PRX files which contain a SureTrak database.
  • Added support for reading the resource \"enterprise\" attribute from MPP12 and MPP14 files.
  • Improve performance when reading user defined values from XER files.
  • Improved support for older Primavera PMXML files.
  • Updated to rtfparserkit 1.11.0 for improved RTF parsing.
"},{"location":"CHANGELOG/#744-2018-06-06","title":"7.4.4 (2018-06-06)","text":"
  • Improve handling of calendar exceptions in MPX files.
  • Improve handling of MPP files with large numbers of null tasks.
  • Improve robustness when reading timephased data.
  • Correctly sort Primavera schedules containing WBS entries with no child activities.
"},{"location":"CHANGELOG/#743-2018-05-25","title":"7.4.3 (2018-05-25)","text":"
  • Add support for reading the resource \"generic\" attribute from MPP files.
  • Add a Unique ID attribute to the Relation class and populate for schedule types which support this concept.
  • Store the Primavera Project ID as Unique ID in the project properties.
  • Update MerlinReader to ensure support for Merlin Project Pro 5.
"},{"location":"CHANGELOG/#742-2018-04-30","title":"7.4.2 (2018-04-30)","text":"
  • Gracefully handle malformed duration values in MSPDI files.
  • Gracefully handle unexpected calendar exception data structure in certain MPP files.
  • Improve handling of certain unusual MPP12 files.
  • More work to gracefully handle POI issue 61677, allowing affected MPP files to be read successfully.
"},{"location":"CHANGELOG/#741-2018-04-16","title":"7.4.1 (2018-04-16)","text":"
  • Add methods to list projects available in P3 and SureTrak database directories.
  • Avoid NPE when a work pattern can't be located in an Asta Powerproject PP file.
  • Avoid array bounds exception when reading certain PRX files.
  • Read outline code value lists from MPP9 files.
  • Handle SureTrak projects without a WBS.
"},{"location":"CHANGELOG/#740-2018-03-23","title":"7.4.0 (2018-03-23)","text":"
  • Added support for reading Primavera SureTrak databases from directories, zip files, and STX files.
  • Added support for PP files generated by Asta Powerproject from version 13.0.0.1
"},{"location":"CHANGELOG/#730-2018-03-12","title":"7.3.0 (2018-03-12)","text":"
  • Added support for reading Primavera P3 databases from directories, zip files, and PRX files.
  • Improve robustness when reading MPP files containing apparently invalid custom field data.
  • Improve UniversalProjectReader byte order mark handling.
  • Fixed Issue 324: Fields with lookup unreadable when a field has custom name.
"},{"location":"CHANGELOG/#721-2018-01-26","title":"7.2.1 (2018-01-26)","text":"
  • More work to gracefully handle POI issue 61677, allowing affected MPP files to be read successfully.
  • Avoid divide by zero when calculating percent complete from certain Primavera PMXML files.
  • UniversalProjectReader updated to recognise MPX files with non-default separator characters.
  • Update FastTrack reader to handle invalid percentage values on resource assignments.
  • Update FastTrack reader to handle variations in UUID format.
  • Read the full project name from XER files and the Primavera database and store it in the project title attribute.
"},{"location":"CHANGELOG/#720-2018-01-18","title":"7.2.0 (2018-01-18)","text":"
  • Added support for reading TurboProject PEP files.
  • Handle numeric values with leading spaces in XER files.
  • Fix array bounds error when reading constraints from certain MPP files.
"},{"location":"CHANGELOG/#710-2018-01-03","title":"7.1.0 (2018-01-03)","text":"
  • Added support for reading GanttProject GAN files.
  • Ensure that calendar exception dates are read correctly from XER files and P6 databases regardless of the user's timezone.
  • Read working day calendar exceptions from XER files and P6 database.
  • Mark some ProjectFile methods as deprecated.
"},{"location":"CHANGELOG/#703-2017-12-21","title":"7.0.3 (2017-12-21)","text":"
  • Use the Windows-1252 character set as the default when reading XER files.
  • Gracefully handle POI issue 61677 to allow MPP affected MPP files to be read successfully.
  • Handle recurring calendar exceptions read from MSPDI files without an occurrence count.
  • Improve robustness of FastTrack schedule reader.
  • Avoid reading empty calendar exceptions from MPX files.
"},{"location":"CHANGELOG/#702-2017-11-20","title":"7.0.2 (2017-11-20)","text":"
  • Further improvements to task pruning for Asta PP files.
"},{"location":"CHANGELOG/#701-2017-11-20","title":"7.0.1 (2017-11-20)","text":"
  • Improve robustness when reading MPP files when using certain 64-bit Java runtimes.
  • Populate the project's comments property when reading an MSPDI file.
  • Ensure that tasks are not discarded when reading PP files from older Asta versions.
  • Fixed Issue 319: Wrong date ranges for split tasks
  • Fixed Issue 222: getDefaultTaskType() not returning correct default task type
"},{"location":"CHANGELOG/#700-2017-11-08","title":"7.0.0 (2017-11-08)","text":"
  • Added support for reading recurring exceptions from MPP and MSPDI files.
  • Updated RecurringTask class interface (Note: this is a breaking API change)
  • MSPDI writer now uses save version 14 by default (Note: this may affect applications which consume MSPDI files you generate)
  • Correctly handle MSPDI files with Byte Order Marks.
  • Handle MSPDI files with varying namespaces.
  • Improve robustness Merlin file reader.
  • Improve extraction of task start and finish dates from PMXML files only containing partial data.
  • Prevent POI from closing the input stream when using UniversalProjectReader
  • Fixed Issue 321: Cannot read mpp file using getProjectReader.
"},{"location":"CHANGELOG/#621-2017-10-11","title":"6.2.1 (2017-10-11)","text":"
  • Gracefully handle corrupt MPP files.
  • Improve reading and writing slack values for MSPDI files.
  • Improve activity hierarchy extraction from Phoenix files.
  • Fixed Issue 243: MSPDI Slack values not correctly set while loading.
"},{"location":"CHANGELOG/#620-2017-10-06","title":"6.2.0 (2017-10-06)","text":"
  • Added support for reading Work Weeks from MPP files.
  • Add support for calendar exception names for MPP and MSPDI files.
  • Updated to use POI 3.17.
  • Improve accuracy of calendar exception dates read from XER files and P6 database.
  • Only write non-default user-defined field values to a PMXML file.
  • Use Primavera P6 17.7 XML schema.
  • Gracefully handle corrupt document summary information in MPP files.
  • Don't duplicate exceptions when reading from an MSPDI file.
  • Fixed Issue 231: MPP DataType: Non-unique enumeration value.
  • Fixed Issue 258: Calendar Work Week missing from MPP data extraction.
  • Fixed Issue 318: TimephasedWork Negative TotalAmount.
  • Fixed Issue 320: Date conversion fails in PrimaveraReader.
"},{"location":"CHANGELOG/#612-2017-09-12","title":"6.1.2 (2017-09-12)","text":"
  • Gracefully handle incomplete records in XER files.
"},{"location":"CHANGELOG/#611-2017-08-30","title":"6.1.1 (2017-08-30)","text":"
  • Ensure all classes in the gem are required
"},{"location":"CHANGELOG/#610-2017-07-28","title":"6.1.0 (2017-07-28)","text":"
  • Provide Task.getEffectiveCalendar() method
  • Populate missing finish dates in MSPDI files
"},{"location":"CHANGELOG/#600-2017-07-22","title":"6.0.0 (2017-07-22)","text":"
  • Gracefully handle invalid calendar data in XER files.
  • Handle XER files containing blank lines.
  • Add support for reading resource rates and availability tables from P6 (Contributed by Brandon Herzog).
  • Include overtime in work and cost fields when reading from P6 (Contributed by Brandon Herzog).
  • Read default project calendar from P6 (Contributed by Brandon Herzog).
  • Read resource rate and assignment units from P6 (Contributed by Brandon Herzog).
  • Set ignore resource calendar flag for tasks from P6 (Contributed by Brandon Herzog).
  • Change P6 costs to be calculated from resource assignment to support XER files without the cost table (Contributed by Brandon Herzog).
  • Map anticipated end date to deadline for P6 (Contributed by Brandon Herzog).
  • Update task work to include actual and remaining work when reading from P6 (Contributed by Brandon Herzog).
  • Calculate summary task work fields by summing up children when reading from P6 (Contributed by Brandon Herzog).
  • Set task project name when reading from P6 (Contributed by Brandon Herzog).
  • Fix \"00:00\" calendar finish times to parse as end of day when reading from P6 (Contributed by Brandon Herzog).
  • Add default working hours if a calendar does not specify any hours when reading from P6 (Contributed by Brandon Herzog).
  • Read fiscal year start month from P6 (Contributed by Brandon Herzog).
  • Fix bug in rollup of child task dates containing null values that could set incorrect end date when reading from P6 (Contributed by Brandon Herzog).
  • Fix date offset in parse of P6 calendar exceptions (Contributed by Brandon Herzog).
  • Fix count of P6 UDFs that map to same data type (Contributed by Brandon Herzog).
  • Add support for reading Resource and Assignment UDFs from P6 (Contributed by Brandon Herzog).
  • Update P6 UDFs to fill into multiple field types to expand storage capacity, for example into TEXT and ENTERPRISE_TEXT (Contributed by Brandon Herzog).
  • Use only the WBS as activity code for WBS tasks instead of also appending name for P6 tasks (Contributed by Brandon Herzog).
  • Add the ability to link task Relations that cross project boundaries in XER files (Contributed by Brandon Herzog).
  • Add function to clear all exceptions from ProjectCalendar instances (Contributed by Brandon Herzog).
  • Reading the lag calendar scheduling option as the \"LagCalendar\" custom project property when reading from P6 (Contributed by Brandon Herzog).
  • Updated UDF parsing to handle values as booleans if the user chooses to map them to Flag fields (Contributed by Brandon Herzog).
"},{"location":"CHANGELOG/#5140-2017-07-13","title":"5.14.0 (2017-07-13)","text":"
  • Improve handling of activity codes read from Phoenix files
  • Calculate percent complete for tasks read from Phoenix files
  • Populate task duration with Original Duration attribute when reading from XER files or P6 databases.
  • Ensure that task finish dates are read correctly from Phoenix files.
  • Improve UniversalProjectReader's handling of non-MPP OLE compound documents.
  • Improve task hierarchy and ordering when reading some MPP files.
"},{"location":"CHANGELOG/#5130-2017-06-27","title":"5.13.0 (2017-06-27)","text":"
  • Further improve handling of WBS, bar, and task structure from Asta files.
"},{"location":"CHANGELOG/#5120-2017-06-26","title":"5.12.0 (2017-06-26)","text":"
  • Improve handling of WBS, bar, and task structure from Asta files.
"},{"location":"CHANGELOG/#5110-2017-06-20","title":"5.11.0 (2017-06-20)","text":"
  • Improve handling of malformed durations in MSPDI files.
  • Improve performance when reading MPP files with certain kinds of timephased data.
  • Raise a specific \"password protected\" exception type from the Ruby gem.
  • Fix an issue with the storage of the \"earned value method\" task attribute.
"},{"location":"CHANGELOG/#5100-2017-05-23","title":"5.10.0 (2017-05-23)","text":"
  • Improve handling of deleted tasks in MPP files.
  • Improve handling of invalid predecessor tasks in MPX files.
  • Improve handling of invalid saved view state in MPP files.
  • Fixed Issue 313: Empty baseline dates populated with garbage date instead of null.
"},{"location":"CHANGELOG/#590-2017-04-27","title":"5.9.0 (2017-04-27)","text":"
  • Add support for reading ProjectLibre POD files (from ProjectLibre version 1.5.5 onwards).
  • Correct getter method name for \"file application\" project property.
"},{"location":"CHANGELOG/#580-2017-04-21","title":"5.8.0 (2017-04-21)","text":"
  • Updated to use POI 3.16 (note new dependency on Apache Commons Collections required by POI).
  • Improve support for estimated durations in Merlin files.
  • Read task notes from Asta files.
  • Improve support for reading resource rates from Phoenix files.
  • Add \"file application\" and \"file type\" to project properties to determine source of schedule data.
"},{"location":"CHANGELOG/#571-2017-03-22","title":"5.7.1 (2017-03-22)","text":"
  • Improve support for Phoenix Project Manager XML files.
"},{"location":"CHANGELOG/#570-2017-03-20","title":"5.7.0 (2017-03-20)","text":"
  • Add support for FastTrack Schedule files.
  • Ensure that timephased data calculations correctly handle entry to and exit from DST.
  • Fixed Issue 306: Microsoft Project 2016: Issue with assignment 'Work Contour' attribute.
"},{"location":"CHANGELOG/#565-2017-03-07","title":"5.6.5 (2017-03-07)","text":"
  • Improve handling of invalid calendar data in MSPDI files
  • Improve handling of XER files containing multi-line records
  • Improve handling of malformed MPX files
  • Fixed Issue 308: Add support for elapsed percent to MSPDI writer
  • Fixed Issue 310: MPX percent lag incorrect
"},{"location":"CHANGELOG/#564-2017-02-16","title":"5.6.4 (2017-02-16)","text":"
  • UniversalProjectReader now recognises and handles byte order marks
  • Fixed Issue 307: TimeUnit.ELAPSED_PERCENT read incorrectly from MPP files
"},{"location":"CHANGELOG/#563-2017-02-08","title":"5.6.3 (2017-02-08)","text":"
  • Added a parameter to the Ruby gem to allow the maximum JVM memory size to be set.
  • Updated to rtfparserkit 1.10.0 for improved RTF parsing.
"},{"location":"CHANGELOG/#562-2017-02-06","title":"5.6.2 (2017-02-06)","text":"
  • Fixed Issue 305: Failed to Parse error with Primavera 15.2 or 16.1 XML files
"},{"location":"CHANGELOG/#561-2017-02-03","title":"5.6.1 (2017-02-03)","text":"
  • Correct resource assignment handling for Phoenix Project Manager schedules.
"},{"location":"CHANGELOG/#560-2017-01-29","title":"5.6.0 (2017-01-29)","text":"
  • Add support for Phoenix Project Manager schedules.
"},{"location":"CHANGELOG/#559-2017-01-27","title":"5.5.9 (2017-01-27)","text":"
  • Improve robustness of date parsing for MPX files.
"},{"location":"CHANGELOG/#558-2017-01-23","title":"5.5.8 (2017-01-23)","text":"
  • Fix NPE when reading graphical indicators with unknown field type.
"},{"location":"CHANGELOG/#557-2017-01-13","title":"5.5.7 (2017-01-13)","text":"
  • Fix percent complete NaN value for some Primavera schedules.
"},{"location":"CHANGELOG/#556-2017-01-06","title":"5.5.6 (2017-01-06)","text":"
  • Fix incorrectly set critical flag for primavera schedules.
"},{"location":"CHANGELOG/#555-2017-01-06","title":"5.5.5 (2017-01-06)","text":"
  • Updated to rtfparserkit 1.9.0 for improved RTF parsing
  • Improve calendar exception parsing for Primavera XER and database readers.
  • Ensure the task summary flag is set correctly for Primavera schedules.
  • Rollup baseline, early and late start and finish dates to WBS for Primavera schedules.
  • Rollup baseline duration, remaining duration and percent complete to WBS for Primavera schedules.
  • Use the project's critical slack limit value when setting the critical flag on a task.
  • Experimental support for reading Merlin Project schedules.
"},{"location":"CHANGELOG/#554-2016-12-01","title":"5.5.4 (2016-12-01)","text":"
  • Default to UTF-8 encoding when generating JSON files
"},{"location":"CHANGELOG/#553-2016-11-29","title":"5.5.3 (2016-11-29)","text":"
  • Correctly read text from MPP files when default charset is not UTF-8.
  • Improve accuracy when reading MPP9 files.
"},{"location":"CHANGELOG/#552-2016-11-02","title":"5.5.2 (2016-11-02)","text":"
  • Add Primavera Parent Resource ID as a specific resource attribute (Based on a contribution by Dave McKay).
  • PMXML writer generates currency record (Based on a contribution by Dave McKay).
  • PMXML writer defaults Activity PercentCompleteType to Duration (Based on a contribution by Dave McKay).
  • PMXML writer records currency and parent attributes for Resource (Based on a contribution by Dave McKay).
  • PMXML writer resource assignments include RateSource and ActualOvertimeUnits attributes(Based on a contribution by Dave McKay).
  • MSPDI reader: gracefully handle invalid calendar exceptions..
  • PMXML writer: gracefully handle missing data.
  • Planner writer: gracefully handle missing data.
"},{"location":"CHANGELOG/#551-2016-10-14","title":"5.5.1 (2016-10-14)","text":"
  • Update universal project reader to support zip files.
  • Update ruby to align error handling with universal project reader.
"},{"location":"CHANGELOG/#550-2016-10-13","title":"5.5.0 (2016-10-13)","text":"
  • Universal project reader.
  • Avoid NPE when reading PMXML files.
  • Fixed Issue 297: Missing extended attributes
  • Fixed Issue 300: CrossProject field omission causes issues when importing to P6
"},{"location":"CHANGELOG/#540-2016-10-06","title":"5.4.0 (2016-10-06)","text":"
  • Updated to use POI 3.15.
"},{"location":"CHANGELOG/#533-2016-08-31","title":"5.3.3 (2016-08-31)","text":"
  • Avoid NPE when field type is unknown.
  • Improve Ruby error reporting.
  • Improve support for non-standard time formats in MPX files
  • Improve support for MPP14 files with very large numbers of blank tasks
"},{"location":"CHANGELOG/#532-2016-08-31","title":"5.3.2 (2016-08-31)","text":"
  • When reading an XER file, treat FT_STATICTPYE user defined fields as text.
"},{"location":"CHANGELOG/#531-2016-07-01","title":"5.3.1 (2016-07-01)","text":"
  • Add data date attribute to PMXML output.
  • Update PMXML writer to avoid NPE.
  • Update PMXML writer to allow task field used for Activity ID to be chosen.
  • Updated to avoid NPE when reading an XER file where project not under EPS.
  • Generate Task IDs if missing from MSPDI file
"},{"location":"CHANGELOG/#530-2016-06-10","title":"5.3.0 (2016-06-10)","text":"
  • Add support for PP files generated by Asta Powerproject from version 13.0.0.3 onwards
  • Minor improvements to SDEF support.
  • Updated to rtfparserkit 1.8.0
  • Improve finish time handling in PMXML files (contributed by lobmeleon)
"},{"location":"CHANGELOG/#522-2016-03-11","title":"5.2.2 (2016-03-11)","text":"
  • Add support for resource assignment Stop and Resume attributes for MPP and MSPDI files
  • Fixed Issue 291: PrimaveraPMFileWriter.write fails with java.lang.IllegalArgumentException
  • Fixed Issue 292: Microsoft Project 2016 : Need to set 'Stop' and 'Resume' properties for net.sf.mpxj.ResourceAssignment
"},{"location":"CHANGELOG/#521-2016-02-11","title":"5.2.1 (2016-02-11)","text":"
  • Add support for PP files generated by Asta Powerproject up to version 13.0.0.3
"},{"location":"CHANGELOG/#520-2016-02-08","title":"5.2.0 (2016-02-08)","text":"
  • Add support for PP files generated by Asta Powerproject 11, Powerproject 12, Easyplan 2, Easyplan 3, Easyplan 4, Easyplan 5 and Easyplan 6
  • Fixed Issue 285: Unsupported encoding command ansicpg949
  • Fixed Issue 288: AvailabilityTable getEntryByDate does not work properly
"},{"location":"CHANGELOG/#5118-2016-01-25","title":"5.1.18 (2016-01-25)","text":"
  • Fixed Issue 285: Unsupported encoding command ansicpg1254
  • Fixed Issue 286: NullPointerException in CriteriaReader.getConstantValue
  • Fixed Issue 287: Allow a character encoding to be specified when reading an XER file
  • Write Primavera Primary Resource Unique ID to Task field Number1
"},{"location":"CHANGELOG/#5117-2015-12-30","title":"5.1.17 (2015-12-30)","text":"
  • Improve support for reading MPP files generated by Project 2016
  • Handle missing time component of a time stamp field when reading an MPX file.
"},{"location":"CHANGELOG/#5116-2015-12-18","title":"5.1.16 (2015-12-18)","text":"
  • Improve support for reading MPX files generated by SureTrak
"},{"location":"CHANGELOG/#5115-2015-12-16","title":"5.1.15 (2015-12-16)","text":"
  • Fix WBS and Activity ordering for tasks from Primavera.
"},{"location":"CHANGELOG/#5114-2015-12-09","title":"5.1.14 (2015-12-09)","text":"
  • Strip unescaped control characters from JSON output.
"},{"location":"CHANGELOG/#5113-2015-11-26","title":"5.1.13 (2015-11-26)","text":"
  • For schedules imported from Primavera ensure tasks representing activities are ordered by Activity ID within the WBS to match Primavera.
"},{"location":"CHANGELOG/#5112-2015-11-16","title":"5.1.12 (2015-11-16)","text":"
  • Avoid NPE when writing MSPDI files with timephased data (contributed by Bruno Gasnier)
  • Improve resource assignment constructor (based on a contribution by Bruno Gasnier)
  • Improve MPX French translations (contributed by Bruno Gasnier)
  • Add calendar specific minutes per day, week, month, and year (based on a contribution by Bruno Gasnier)
  • Add support for reading and writing GUID attribute for PMXML, XER files and Primavera database.
"},{"location":"CHANGELOG/#5111-2015-11-12","title":"5.1.11 (2015-11-12)","text":"
  • Avoid NPE when reading MPP14 custom properties.
  • Ensure calculated task attributes are present in JSON output.
  • Handle MSPDI files written by German versions of Microsoft Project (based on a contribution by Lord Helmchen)
  • Fixed Issue 277: synchronizeTaskIDToHierarchy clears list of tasks
  • Fixed Issue 273: PrimaveraPMFileWriter throws Exception at write(..)
  • Fixed Issue 281: Parent task is always null when reading a Primavera XER file
  • Ensure that Task.getSuccesors() and Task.getPredecessors() return an empty list rather than null.
"},{"location":"CHANGELOG/#5110-2015-09-09","title":"5.1.10 (2015-09-09)","text":"
  • Improve FixedMeta2 block size heuristic to improve reliability when reading MPP14 files.
"},{"location":"CHANGELOG/#519-2015-08-29","title":"5.1.9 (2015-08-29)","text":"
  • Ensure Resource BookingType is read correctly from MPP files
  • Added basic custom field attributes to JSON output
  • Added Ruby methods to work with custom field aliases
  • Fix to infinite loop condition when writing calendar (contributed by lobmeleon)
  • Fixed Issue 274: MPXJ getNotes() API returns garbled value for multibyte characters
  • Fixed Issue 268: Unsupported encoding error when reading resource notes
  • Fixed Issue 256: Incorrect resource types are read (contributed by Colin Rodriguez)
  • Symmetry between Primavera PM reader/writer (contributed by lobmeleon)
  • Added UDF support to PMXML file reader and writer(contributed by lobmeleon)
  • Updated to rtfparserkit 1.4.0
"},{"location":"CHANGELOG/#518-2015-07-13","title":"5.1.8 (2015-07-13)","text":"
  • Another attempt at getting tzinfo-data dependency working
"},{"location":"CHANGELOG/#517-2015-07-13","title":"5.1.7 (2015-07-13)","text":"
  • Updated ruby gem to make tzinfo-data dependency conditional on platform
"},{"location":"CHANGELOG/#516-2015-07-13","title":"5.1.6 (2015-07-13)","text":"
  • Updated ruby gem to allow timezone to be provided
"},{"location":"CHANGELOG/#515-2015-06-05","title":"5.1.5 (2015-06-05)","text":"
  • Updated to use IKVM 8.0.5449.1
"},{"location":"CHANGELOG/#514-2015-06-03","title":"5.1.4 (2015-06-03)","text":"
  • Updated to generate Activity ID for Primavera WBS.
  • Updated to correct Primavera duration percent complete calculation.
"},{"location":"CHANGELOG/#513-2015-05-18","title":"5.1.3 (2015-05-18)","text":"
  • Updated to ensure Ruby reads Boolean attributes correctly.
"},{"location":"CHANGELOG/#512-2015-05-18","title":"5.1.2 (2015-05-18)","text":"
  • Updated to ensure Ruby recognises short type as an integer.
"},{"location":"CHANGELOG/#511-2015-05-18","title":"5.1.1 (2015-05-18)","text":"
  • Updated to use ruby-duration gem to avoid conflict with ActiveSupport::Duration.
"},{"location":"CHANGELOG/#510-2015-05-17","title":"5.1.0 (2015-05-17)","text":"
  • Updated to ensure that PrimaveraDatabaseReader.setSchema accepts null or empty string
  • Ensure conversion to/from .Net DateTime takes account of timezone and daylight savings (based on a contribution by Timour Koupeev)
  • Updated to use POI 3.12.
  • Removed ProjectFile.getTaskFieldAliases, replaced by ProjectFile.getCustomField().getFieldByAlias
  • Removed ProjectFile.getResourceFieldAliases, replaced by ProjectFile.getCustomField().getFieldByAlias
"},{"location":"CHANGELOG/#500-2015-05-06","title":"5.0.0 (2015-05-06)","text":"
  • Added project properties to the JSON output
  • Added support for project properties to the Ruby wrapper
  • Added support for reading data from a standalone Primavera P6 SQLite database
  • Fixed Issue 267: XXE security vulnerability
  • Fixed Issue 266: Task Number fields not saved to file if the value would floor to zero
  • Fixed Issue 255: Not all project calendars are read in for Project 2013 files (based on a contribution by Colin Rodriguez)
  • Renamed TaskContainer class to ChildTaskContainer
  • Renamed ProjectHeader class to ProjectProperties
  • Introduced ProjectConfig class
  • Introduced TaskContainer class
  • Introduced ResourceContainer class
  • Introduced ResourceAssignmentContainer class
  • Introduced ProjectCalendarContainer class
  • Renamed ProjectFile.getProjectHeader to getProjectProperties
  • Renamed ProjectFile.getCalendar to getDefaultCalendar
  • Renamed ProjectFile.setCalendar to setDefaultCalendar
  • Renamed MppReader.getReadHeaderOnly to getReadPropertiesOnly
  • Renamed MppReader.setReadHeaderOnly to setReadPropertiesOnly
  • Renamed ProjectFile.getCalendarUniqueID to ProjectConfig.getNextCalendarUniqueID
  • Renamed ProjectFile.getResourceUniqueID to ProjectConfig.getNextResourceUniqueID
  • Renamed ProjectFile.getTaskUniqueID to ProjectConfig.getNextTaskUniqueID
  • Renamed ProjectFile.getAssignmentUniqueID to ProjectConfig.getNextAssignmentUniqueID
  • Renamed ProjectFile.getResourceID to ProjectConfig.getNextResourceID
  • Renamed ProjectFile.getTaskID to ProjectConfig.getNextTaskID
  • Renamed ProjectHeader.getApplicationName to getShortApplicationName
  • Renamed ProjectHeader.setApplicationName to setShortApplicationName
  • Renamed ProjectHeader.setCalendarName to setDefaultCalendarName
  • Renamed ProjectHeader.getCalendarName to getDefaultCalendarName
  • Moved ProjectFile.getProjectFilePath to ProjectHeader.getProjectFilePath
  • Moved ProjectFile.setProjectFilePath to ProjectHeader.setProjectFilePath
  • Moved ProjectFile.getApplicationName to ProjectHeader.getFullApplicationName
  • Moved ProjectFile.setApplicationName to ProjectHeader.setFullApplicationName
  • Moved FileCreationRecord.setDelimiter to ProjectHeader.setMpxDelimiter
  • Moved FileCreationRecord.getDelimiter to ProjectHeader.getMpxDelimiter
  • Moved FileCreationRecord.setProgramName to ProjectHeader.setMpxProgramName
  • Moved FileCreationRecord.getProgramName to ProjectHeader.getMpxProgramName
  • Moved FileCreationRecord.setFileVersion to ProjectHeader.setMpxFileVersion
  • Moved FileCreationRecord.getFileVersion to ProjectHeader.getMpxFileVersion
  • Moved FileCreationRecord.setCodePage to ProjectHeader.setMpxCodePage
  • Moved FileCreationRecord.getCodePage to ProjectHeader.getMpxCodePage
  • Moved ProjectFile.getMppFileType to ProjectHeader.getMppFileType
  • Moved ProjectFile.setMppFileType to ProjectHeader.setMppFileType
  • Moved ProjectFile.getApplicationVersion to ProjectHeader.getApplicationVersion
  • Moved ProjectFile.setApplicationVersion to ProjectHeader.setApplicationVersion
  • Moved ProjectFile.setAutoFilter to ProjectHeader.setAutoFilter
  • Moved ProjectFile.getAutoFilter to ProjectHeader.getAutoFilter
  • Removed ProjectFile.getAliasTaskField, replaced by ProjectFile.getTaskFieldAliases().getField()
  • Removed ProjectFile.getAliasResourceField, replaced by ProjectFile.getResourceFieldAliases().getField()
  • Removed ProjectFile.getTaskFieldAlias, replaced by ProjectFile.getTaskFieldAliases().getAlias()
  • Removed ProjectFile.setTaskFieldAlias, replaced by ProjectFile.getTaskFieldAliases().setAlias()
  • Removed ProjectFile.getResourceFieldAlias, replaced by ProjectFile.getResourceFieldAliases().getAlias()
  • Removed ProjectFile.setResourceFieldAlias, replaced by ProjectFile.getResourceFieldAliases().setAlias()
  • Removed ProjectFile.getTaskFieldAliasMap, replaced by ProjectFile.getTaskFieldAliases
  • Removed ProjectFile.getResourceFieldAliasMap, replaced by ProjectFile.getResourceFieldAliases
  • Removed ProjectFile.addTable, replaced by ProjectFile.getTables().add()
  • Removed ProjectFile.getTaskTableByName, replaced by ProjectFile.getTables().getTaskTableByName()
  • Removed ProjectFile.getResourceTableByName, replaced by ProjectFile.getTables().getResourceTableByName()
  • Removed ProjectFile.addFilter, replaced by ProjectFile.getFilters().addFilter()
  • Removed ProjectFile.removeFilter, replaced by ProjectFile.getFilters().rmoveFilter()
  • Removed ProjectFile.getAllResourceFilters, replaced by ProjectFile.getFilters().getResourceFilters()
  • Removed ProjectFile.getAllTaskFilters, replaced by ProjectFile.getFilters().getTaskFilters()
  • Removed ProjectFile.getFilterByName, replaced by ProjectFile.getFilters().getFilterByName()
  • Removed ProjectFile.getFilterByID, replaced by ProjectFile.getFilters().getFilterByID()
  • Removed ProjectFile.getAllGroups, replaced by ProjectFile.getGroups()
  • Removed ProjectFile.getGroupByName, replaced by ProjectFile.getGroups().getByName()
  • Removed ProjectFile.addGroups, replaced by ProjectFile.getGroups().add()
  • Removed ProjectFile.addView, replaced by ProjectFile.getViews().add()
  • Removed ProjectFile.setViewState, replaced by ProjectFile.getViews().setViewState()
  • Removed ProjectFile.getViewState, replaced by ProjectFile.getViews().getViewState()
  • Removed ProjectFile.getResourceSubProject, replaced by ProjectFile.getSubProjects().getResourceSubProject()
  • Removed ProjectFile.setResourceSubProject, replaced by ProjectFile.getSubProjects().setResourceSubProject()
  • Removed ProjectFile.addSubProject, replaced by ProjectFile.getSubProjects().add()
  • Removed ProjectFile.getAllSubProjects, replaced by ProjectFile.getSubProjects
  • Removed ProjectFile.fireTaskReadEvent, replaced by ProjectFile.getEventManager().fireTaskReadEvent()
  • Removed ProjectFile.fireTaskWrittenEvent, replaced by ProjectFile.getEventManager().fireTaskWrittenEvent()
  • Removed ProjectFile.fireResourceReadEvent, replaced by ProjectFile.getEventManager().fireResourceReadEvent()
  • Removed ProjectFile.fireResourceWrittenEvent, replaced by ProjectFile.getEventManager().fireResourceWrittenEvent()
  • Removed ProjectFile.fireCalendarReadEvent, replaced by ProjectFile.getEventManager().fireCalendarReadEvent()
  • Removed ProjectFile.fireAssignmentReadEvent, replaced by ProjectFile.getEventManager().fireAssignmentReadEvent()
  • Removed ProjectFile.fireAssignmentWrittenEvent, replaced by ProjectFile.getEventManager().fireAssignmentWrittenEvent()
  • Removed ProjectFile.fireRelationReadEvent, replaced by ProjectFile.getEventManager().fireRelationReadEvent()
  • Removed ProjectFile.fireRelationWrittenEvent, replaced by ProjectFile.getEventManager().fireRelationWrittenEvent()
  • Removed ProjectFile.fireCalendarWrittenEvent, replaced by ProjectFile.getEventManager().fireCalendarWrittenEvent()
  • Removed ProjectFile.addProjectListener, replaced by ProjectFile.getEventManager().addProjectListener()
  • Removed ProjectFile.addProjectListeners, replaced by ProjectFile.getEventManager().addProjectListeners()
  • Removed ProjectFile.removeProjectListener, replaced by ProjectFile.getEventManager().removeProjectListener()
  • Removed ProjectFile.addGraphicalIndicator
  • Removed ProjectFile.getGraphicalIndicator, replaced by ProjectFile.getCustomFields().getCustomField().getGraphicalIndicator()
"},{"location":"CHANGELOG/#476-2015-03-18","title":"4.7.6 (2015-03-18)","text":"
  • Added a Ruby wrapper for MPXJ
  • Added the ability to export project data as JSON, to make it easier to work with in languages other than Java
  • Added support for the Assignment attribute Resource Request Type
  • Primavera database and XER readers updated to match WBS visible in Primavera for each task. Previous behaviour of generating a unique WBS for each task can be restored using a flag set on the readers.
  • Avoid NPE when calculating Task Completed Through
  • Read Task Earned Value Method correctly from MPP files
  • Fix issue where some floating point attributes were returning NaN
"},{"location":"CHANGELOG/#475-2015-02-27","title":"4.7.5 (2015-02-27)","text":"
  • Handle invalid Primavera calendar data gracefully
"},{"location":"CHANGELOG/#474-2015-02-25","title":"4.7.4 (2015-02-25)","text":"
  • Fixed Issue 257: Failed to read project containing CodePage 1250 text.
  • Fixed Issue 259: MS Project 2010: tasks with null baseline dates
  • Incorrect task end date read from Primavera XER and database
  • Incorrect percent complete read from Primavera XER, database, and PMXML files
  • Failed to read fields held at the end of a fixed data block
  • Added support for Task Baseline Estimated Duration, Baseline Estimated Start, Baseline Estimated Finish, Baseline Fixed Cost, and Baseline Fixed Cost Accrual
  • Added the ability to customise the fields read from a Primavera database or XER file.
  • Added Task Activity Type and Task Status as additional fields read from Primavera database and XER and files
  • Changed Task physical percent complete methods for consistency to use Number rather than Integer
"},{"location":"CHANGELOG/#473-2014-12-23","title":"4.7.3 (2014-12-23)","text":"
  • Updated to use POI 3.11.
  • Updated to use rtfparserkit 1.1.0 for Java 6 compatibility.
"},{"location":"CHANGELOG/#472-2014-12-15","title":"4.7.2 (2014-12-15)","text":"
  • Updated to fix Maven dependency issue.
"},{"location":"CHANGELOG/#471-2014-12-08","title":"4.7.1 (2014-12-08)","text":"
  • Added a flag to MPPReader to indicate that only the project header should be read.
"},{"location":"CHANGELOG/#470-2014-12-04","title":"4.7.0 (2014-12-04)","text":"
  • Implemented new RTF parser for stripping RTF to improve performance and accuracy
  • Removed non-API code from the top level package
  • Improved support for reading built-in and custom project properties from MPP files.
  • Improved resilience of MPP file reading to unknown data structures
  • Fixed issue which could cause an infinite loop when ordering tasks in a file containing multiple consecutive blank tasks
  • Fixed issue where free text versions of task start, finish, and duration fields were not being read correctly from MPP14 files
"},{"location":"CHANGELOG/#462-2014-11-11","title":"4.6.2 (2014-11-11)","text":"
  • Fixed issue with custom duration field units not read correctly from MSPDI files
  • Fixed Issue 223: Problems with the lag calculated in the relation
  • Outline code not read correctly from MPP file written by Project 2013
  • Fixed Issue 239: Defensive changes to avoid exceptions when reading MPP files
  • Fixed Issue 250: Deleted tasks being read from mpp file
  • Added DotNetInputStream and DotNetOutputStream classes for ease of use under .Net.
  • Updated to automatically generate and package MpxjUtilities.dll
"},{"location":"CHANGELOG/#461-2014-10-17","title":"4.6.1 (2014-10-17)","text":"
  • Fixed NuGet metadata
"},{"location":"CHANGELOG/#460-2014-10-17","title":"4.6.0 (2014-10-17)","text":"
  • Added support for NuGet.
  • Fixed an issue where the ID and Unique ID resource attributes were being read incorrectly from MPP14 files.
  • Fixed an issue where the project's default duration format was not being used
  • Fixed Issue 248: Reading .MPP file using MPXJ 4.2 reads extra unintentional ResourceAssignment with the task which is not seen in Task Sheet in Microsoft Project
  • Fixed Issue 235: All resources have \"Material\" property
  • Fixed Issue 247: Updated Primavera PM XML file reader to capture the Project ID to align with data read from XER file/database (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to ensure task percent complete supports Physical Percent, Duration Percent and Units Percent (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to ensure task baseline values match values read from XER file/database (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to ensure task actual duration to matches value read from XER file/database (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to read the task duration (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to read task LateStart, LateFinish, EarlyStart, EarlyFinish attributes correctly (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to read task Start and End correctly (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to identify milestones (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to set the task Critical attribute (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera PM XML file reader to include costs (contributed by Nathaniel Marrin)
  • Fixed Issue 247: Updated Primavera XER/Database readers to read task Start and End correctly (contributed by Nathaniel Marrin)
  • Migrated tests to JUnit 4
"},{"location":"CHANGELOG/#450-2014-03-01","title":"4.5.0 (2014-03-01)","text":"
  • Added the ability to call the .Net version of MPXJ from COM.
  • Added support Primavera decimal database columns.
  • Added support for user defined task fields (contributed by Mario Fuentes).
  • Added POM for current Maven versions (contributed by Nick Burch)
  • Fixed Issue 213: Unable to load mpp from project-2013
  • Fixed Issue 226: Primavera currency files without currency information
  • Fixed Issue 227: PrimaveraReader cannot handle files with more than 30 user defined fields
  • Fixed Issue 224: setMilestone() issue
  • Fixed Issue 210: MPXJ 4.4 and 2013 files - invalid load of task data
  • Updated to fix an issue with Asta Powerproject PP file tokenization
  • Updated to fix an issue where valid WBS values containing .0 are corrupted
  • Updated to allow Primavera hours per day to be a decimal value
  • Updated to support Primavera PM XML files generated by Primavera versions up to P6v8.3 (contributed by Mario Fuentes)
  • Updated to set the StatusDate attribute in the project header from a Primavera database, XER file or PM XML file.
  • Updated to use (a patched version of) POI 3.10.
"},{"location":"CHANGELOG/#440-2013-03-14","title":"4.4.0 (2013-03-14)","text":"
  • Added support for writing Primavera PM XML files.
  • Added support for reading Asta Powerproject PP and MDB files.
  • Added support for writing SDEF files (Contributed by William Iverson).
  • Added support for reading Enterprise Custom Fields 1-50 for Task, Resources, and Resource Assignments.
  • Added MpxjExtensionMethods assembly to simplify working with Java types in .Net (Contributed by Kyle Patmore)
  • Provided two new .Net DLL versions in addition to the original version. These allow properties to be accessed in a \".Net style\", and for languages apart from VB, provide .Net style method names.
  • Updated to remove the distinction between base calendar and resource calendars in the ProjectFile class.
  • Updated to improve support for custom outline codes (Contributed by Gary McKenney)
  • Fixed Issue 189: getTimephasedOvertimeWork can return TimephasedWork with NaN
  • Fixed Issue 190: Support for timephased cost for cost type resources
  • Fixed Issue 195: Rolled Up tasks don't use default duration units
  • Fixed Issue 199: Extract Primavera Task ID
  • Updated to fix an issue where the resource assignment delay attribute was not being read from or written to MSPDI files correctly
  • Updated to fix an issue where derived calendars were not being read correctly from MPP files
  • Updated to use IKVM 7.2.
"},{"location":"CHANGELOG/#430-2012-02-08","title":"4.3.0 (2012-02-08)","text":"
  • Added support for reading Primavera PM XML files.
  • Added support for reading timephased cost, and timephased baseline cost and baseline work from MPP files.
  • Added support for Work Weeks in MSPDI files (SourceForge feature request 23).
  • Updated to use IKVM 7.0.
  • Updated to fix SourceForge bug 3290224: Incorrect order of tasks when writing an MSPDI file (contributed by Jonathan Besanceney).
  • Fixed Issue 161: ResourceAssignment.getTaskUniqueID() returns null.
  • Fixed Issue 169: Wrong project name in MPX file.
  • Fixed Issue 170: Wrong title in XML file when importing from XER file.
  • Fixed Issue 168: Wrong record number for resource calendar in MPX file.
  • Fixed Issue 171: In the XML file the element field SaveVersion is missing.
  • Fixed Issue 167: Loop when import task with 0% on units of works in resources.
  • Fixed Issue 163: French locale NA incorrect.
  • Fixed Issue 175: Invalid dependency between child and parent.
  • Fixed Issue 174: Missing tasks from MS Project 2010 mpp file.
  • Fixed Issue 179: Wrong WBS code and WBS when converting a Primavera XER file.
  • Fixed Issue 177: Error reading XER file with German localisation for numbers.
  • Fixed Issue 166: TimephasedResourceAssignments with negative TotalWork.
  • Fixed Issue 181: Wrong currency symbol in the exported file.
  • Fixed Issue 104: TimephasedResourceAssignment end date not correct.
  • Fixed Issue 116: Calendar hours are incorrect.
  • Fixed Issue 188: NullReferenceException with getTimephasedBaselineWork.
  • Fixed Issue 191: Outline number is null when opening Project 2003 MPP file.
  • Fixed Issue 192: Unable to parse note (unknown locale).
  • Fixed Issue 193: MPP9Reader marks all tasks after a null task as null.
  • Updated to fix an issue where the Task critical attribute was incorrectly calculated for some manually scheduled tasks.
  • Updated to fix an issue where the Task summary attribute was not set correctly when using certain methods to add or remove child tasks.
  • Updated to fix an issue where subprojects were not read correctly (Contributed by Gary McKenney).
"},{"location":"CHANGELOG/#420-2011-06-23","title":"4.2.0 (2011-06-23)","text":"
  • Added support for resource assignment fields Baseline Cost 1-n, Baseline Work 1-n, Baseline Start 1-n, Baseline Finish 1-n, Start 1-n, Finish 1-n, Date 1-n, Duration 1-n, Cost 1-n, Text 1-n, Number 1-n, Flag 1-n, for MPP, MPD, and MSPDI files.
  • Added support for task suspend date, task resume date, and task code read from Primavera, and represented in MS Project custom fields Date1, Date2, and Text1 respectively.
  • Added support for retrieving the table associated with any view.
  • Fixed Issue 158: Error converting Mpp to planner.
  • Fixed Issue 157: MSPDI Linklag for TimeUnit.Percent.
  • Fixed Issue 156: Error reading calendars for 2010 files.
  • Fixed Issue 159: Duplication of calendar id.
  • Fixed Issue 153: Wrong task start.
  • Fixed Issue 156: Wrong start and finish dates for 2010 files.
"},{"location":"CHANGELOG/#410-2011-05-30","title":"4.1.0 (2011-05-30)","text":"
  • Updated ProjectFile class to change default value for \"auto\" flags to simplify programmatic creation of project files.
  • Added support for Manual, Start Text, Finish Text, and Duration Text attributes in MSPDI files.
  • Added support cost resource type for MPP12, MPP14 and MSPDI files.
  • Added Task.removePredecessor method (contributed by Leslie Damon).
  • Added \"read presentation data\" flag to MPPReader - allows clients to save time and memory when MPP presentation data not required.
  • Added support for reading Primavera calendars (contributed by Bruno Gasnier).
  • Added support for resource assignment leveling delay for MPP, MPD, and MSPDI files.
  • Added support for \"unassigned\" resource assignments.
  • Added support for task manual duration attribute for manually scheduled tasks in MPP14 and MSPDI files.
  • Added support for resource NT account attribute for MPP9, MPP12, and MPP14 files.
  • Added support for physical % complete for MPP9, MPP12, and MPP14 files.
  • Fixed Issue 120: MPXJ API returns the incorrect start date of a manual task.
  • Fixed Issue 123: Task id incorrect after importing from MPP14 file.
  • Fixed Issue 124: MPXJ 4.0 fails to work with Project 2010 format.
  • Fixed Issue 128: Index was outside the bounds of the array.
  • Fixed Issue 131: header.getHonorConstraints() is not working in case of MPP.
  • Fixed Issue 139: Empty notes appear for all tasks when saving in XML format.
  • Fixed Issue 122: All Extended Attributes always added when using MSPDIWriter.
  • Fixed Issue 144: Baseline/Actual Work in 2010 MPP missing.
  • Fixed Issue 114: ResourceAssignment getCalendar not using IgnoreResourceCalendar flag
  • Fixed Issue 146: ExternalTaskProject value missing.
  • Fixed Issue 137: Deleted Primavera tasks handling problem.
  • Fixed Issue 143: Latest CVS version gives wrong values for inactive field.
  • Fixed Issue 125: Task ID order when creating a project file is not correct.
  • Fixed Issue 106: Invalid tasks that should not be there.
  • Updated to fix task calendars read incorrectly from MPP14 files.
  • Updated to fix incorrect month duration assumption (contributed by Frank Illenberger).
  • Updated to fix incorrect number format in MSPDI file in non-English locales (contributed by Frank Illenberger).
  • Updated to fix incorrect resource assignment actual work attribute for MPP14 files.
  • Updated to fix incorrect task leveling delay attribute for MPP9, MPP12, and MPP14 files.
  • Updated to fix leveling delay and link lag when writing an MSPDI file (contributed by Frank Illenberger).
  • Updated to fix incorrect assignment actual start date when writing an MSPDI file.
  • Updated to improve support for material resources in MSPDI files.
  • Updated to reduce overall size of MSPDI files by not writing default values.
  • Updated to use IKVM 0.46.0.1.
  • Updated to use POI 3.7.
  • Updated to make task, resource, and assignment fields read from MPP files data-driven, rather than hard coded.
"},{"location":"CHANGELOG/#400-2010-05-25","title":"4.0.0 (2010-05-25)","text":"
  • Added support for reading Microsoft Project 2010 MPP files.
  • Added support for reading Primavera P6 XER files.
  • Added support for reading Primavera P6 databases.
  • Updated to target Java 1.6.
  • Added Russian locale (Contributed by Roman Bilous).
  • Relation.getDuration() is always giving result in 'HOUR' fmt.
"},{"location":"CHANGELOG/#320-2010-01-20","title":"3.2.0 (2010-01-20)","text":"
  • Added support for Resource cost rate tables (Based on code by Andrei Missine).
  • Added support for Resource availability (Based on code by Andrei Missine).
  • Added support for successors (Based on an idea by John D. Lewis).
  • Added support for task and resource GUIDs.
  • Added a flag to allow raw timephased data to be retrieved from MPP files.
  • Updated to fix logical operator read issue in MPP auto filters (Contributed by Andrei Missine).
  • Fixed Issue 94: MPXJ Issue: Related to Project Calendar.
  • Fixed Issue 90: POI License in legal folder of download wrong.
  • Updated to fix Steelray bug 15468: Null Pointer Exception reading task constraints.
  • Fixed Issue 102: Planner writer causes Null Pointer exception.
  • Fixed Issue 100: getRecurring() task is not working
  • Fixed Issue 98: getStandardRateFormat() is returning 'null'
  • Fixed Issue 97: getWeekStartDay() is not working.
  • Fixed Issue 96: getDaysPerMonth() is not working.
  • Fixed Issue 101: Resource.getNotes() not working for MPP12 file.
  • Fixed Issue 105: MPP: getEditableActualCosts() is not behaving correctly.
  • Updated to use POI 3.6.
  • Updated to use IKVM 0.42.0.3.
  • Updated to make MPX duration parsing more lenient (Contributed by Jari Niskala).
  • Updated to make MPP Var2Data extraction more robust (Contributed by Jari Niskala).
  • Updated to implement MSPDI context caching to improve performance (Contributed by Jari Niskala).
  • Updated to improve MPP file task structure validation. (Contributed by Jari Niskala).
  • Updated to improve MPX file parsing. (Contributed by Jari Niskala).
  • Updated to automatically populate missing WBS attributes. (Contributed by Jari Niskala).
  • Updated to refactor the Relation class (note minor method name changes).
  • Updated to add default calendar to Planner output.
"},{"location":"CHANGELOG/#310-2009-05-20","title":"3.1.0 (2009-05-20)","text":"
  • Fixed Issue 73: Plan file fails to load.
  • Fixed Issue 72: Resource Assignment Normaliser rounding problem.
  • Fixed Issue 78: Column alignment values are incorrect.
  • Fixed Issue 76: NullPointerException in parseExtendedAttribute() (Contributed by Paul Pogonyshev).
  • Fixed Issue 74: .0 at the end of WBS code and outline number (Contributed by Paul Pogonyshev).
  • Fixed Issue 79: Too strict net.sf.mpxj.mpd.ResultSetRow.
  • Fixed Issue 80: Generated planner file can't be opened.
  • Fixed Issue 82: Support for loading global.mpt.
  • Fixed Issue 81: Lowercase table name won't work with db on linux machines.
  • Fixed Issue 71: Standard Calendar localization import problem.
  • Fixed Issue 83: Strange duration conversion from database
  • Fixed Issue 86: FilterCriteria not being read in properly (Contributed by James Styles)
  • Updated to fix Steelray bug 12335: Infinite loop when reading an MPP9 file.
  • Updated to fix Steelray bug 8469: Subproject flag not set correctly.
  • Updated to fix potential NPEs (Suggested by Steve Jonik).
  • Updated EncryptedDocumentInputStream to wrap rather than extend the POI DocumentInputStream to allow use with POI 3.5. (Contributed by Josh Micich)
  • Updated to provide strong names for .Net DLLs.
"},{"location":"CHANGELOG/#300-2009-01-25","title":"3.0.0 (2009-01-25)","text":"
  • Updated to the Project 2007 MSPDI schema.
  • Updated to POI 3.2.
  • Updated to use the SAX parser with JAXB rather than DOM to reduce memory consumption.
  • Updated MPX output to prevent Project 2007 complaining.
  • Fixed Issue 68: Task getNumber*() methods return inaccurate large values.
  • Fixed Issue 56: Duplicate task in file.getChildTasks() when opening MPX.
  • Fixed Issue 57: Relation.getTask returns null.
  • Fixed Issue 58: Task.getSplits() not consistent.
  • Fixed Issue 60: WBS Field not imported Mpp12.
  • Fixed Issue 63: There are some conflict in TaskField.
  • Fixed Issue 66: MSPDIReader is not setting calendarName in projectHeader.
  • Fixed Issue 67: Write resource calendar with exceptions only.
  • Fixed Issue 69: File loses predecessors.
  • Fixed Issue 70: Resources not bring read.
  • Updated to fix incorrect duration calculations where minutes per week were not being used (Contributed by Jonas Tampier).
  • Updated split task implementation to represent splits as DateRange instances rather than as hours.
  • Added .Net DLLs using IKVM.
  • Added support for reading timephased resource assignment data from MPP files.
  • Added support CurrencyCode, CreationDate, LastSaved and HyperlinkBase project header fields.
  • Added support for reading recurring task data from MPP files.
  • Added methods to MPXReader and MPXWriter to allow the caller to determine the supported locales.
  • Added Spanish locale (Contributed by Agustin Barto).
  • Added support for durations with percentage time lag (Contributed by Jonas Tampier).
  • Added support MSPDI file split tasks.
"},{"location":"CHANGELOG/#210-2008-03-23","title":"2.1.0 (2008-03-23)","text":"
  • Updated to POI 3.0.2
  • Updated to address an out of memory exception raised when processing certain MPP12 files.
  • Updated to fix a problem caused by duplicate ID values in MPP12 files.
  • Updated to fix a problem with the subproject unique ID calculation (Contributed by Jari Niskala).
  • Fixed Issue 48: Import from Project 2007 ignores some tasks.
  • Fixed Issue 52: Crash on priority not set in MSPDI-file.
  • Fixed Issue 51: Resource start/finish dates with MSP 2007.
  • Fixed Issue 51: MS Project 2007: Calendar exceptions dates are wrong.
  • Added support for Enterprise task and resource fields.
  • Added support for Baseline task and resource fields.
  • Added support for extracting non-English (i.e. character set encoded) text from note fields.
  • Added support for Chinese MPX files (contributed by Felix Tian).
  • Added support for reading project start and end dates from all MPP file types (Bug #1827633).
  • Added support for password protected MPP9 files (Contributed by Jari Niskala)
  • Added support for calendar exceptions for MPP12 files (Contributed by Jari Niskala)
  • Added support for value lists and descriptions for custom fields (Contributed by Jari Niskala)
  • Added support for timescale formats (Contributed by Jari Niskala)
  • Added support for the project file path attribute (Contributed by Jari Niskala)
  • Added support for the ignore resource calendar attribute (Contributed by Jari Niskala)
  • Added support for the resource actual overtime work attribute (Contributed by Jari Niskala)
  • Added support for the resource material label attribute (Contributed by Jari Niskala)
  • Added support for the resource NT account attribute (Contributed by Jari Niskala)
  • Improved support for hyperlinks (Contributed by Jari Niskala)
  • Improved support for custom fields in MPP12 files (Contributed by Jari Niskala)
"},{"location":"CHANGELOG/#200-2007-10-07","title":"2.0.0 (2007-10-07)","text":"
  • Migrated to Java 5
  • Introduced generics
  • Introduced enums
  • Updated to POI 3.0.1
  • Updated to JAXB 2.1.4
  • Changed company details from Tapster Rock to Packwood Software
"},{"location":"CHANGELOG/#100-2007-08-30","title":"1.0.0 (2007-08-30)","text":"
  • Added support for reading MPD files via JDBC
  • Added support for reading Planner files
  • Added support for over allocated flag to all MPP file formats.
  • Added support for calculating duration variance from MPP files.
  • Added support for calculating start and finish variance from MPP files.
  • Added support for attribute change listeners for Task and Resource classes.
  • Added support for start slack, finish slack, free slack and total slack read from MPP files.
  • Added support for external tasks.
  • Added unique ID generation for calendars read from MPX files.
  • Added support for the status date property of the project.
  • Fixed a timezone related bug when handling dates for calendar exceptions (Contributed by Todd Brannam).
  • Fixed incorrect calculation of lag times for some MPP files.
  • Fixed missing predecessor tasks in certain rare MPP9 files.
  • Fixed incorrect MPX file AM/PM text setting in certain locales.
  • Fixed an ArrayIndexOutOfBoundsException.
  • Fixed a ClassCastException.
  • Fixed a zero length string error.
  • Fixed a duration rounding error when reading MSPDI files.
  • Fixed incorrect \"as late as possible\" constraint handling.
  • Incorrect late start date read from an MPP9 file.
  • Incorrect total slack calculation.
  • Added a default for the task constraint type attribute to prevent a possible NPE when writing an MSPDI file.
  • Added a default resource calendar name where the resource name is empty.
  • Updated the Column.getTitle method to take account of user defined column aliases.
  • Updated to add another condition to the test for deleted tasks in MPP8 files.
  • Updated to significantly improve the performance of writing MSPDI files.
"},{"location":"CHANGELOG/#092-2006-03-07","title":"0.9.2 (2006-03-07)","text":"
  • Added support for split views.
  • Added support for graphical indicators.
  • Added a workaround for a bug in MS Project which is seen when calendar exceptions are exported to an MSPDI file. If the exception contained seconds and milliseconds, MS Project marked every day as being affected by the exception, not the day or range of days specified.
  • Updated to make date/time/number formats generic, and thus available to end users. For example, this allows users to format currencies in line with the settings in the project file.
  • Standardised on minutes per day and minutes per week, rather than hours per day and hours per week.
  • Provided additional time ranges for calendar exceptions.
  • Refactored Task and Resource to use TaskField and ResourceField to identify fields.
  • Updated to automatically generate WBS for tasks read from MPP files when no WBS information is present in the file.
  • Fixed a bug when reading MPP files where task finish dates appeared before the start date where a \"start no later than\" constraint was in use.
  • Fixed a bug which resulted in invalid MPX files being generated when a project either had no tasks, or it had no resources.
  • Fixed a long-standing bug where the calendar records were being written into MPX files after they were referred to in the project summary record.
  • Fixed a bug where WBS and Outline Levels were not being auto generated correctly when an MPP file contained a project summary task.
  • Fixed a bug where split tasks were not being reported correctly.
"},{"location":"CHANGELOG/#091-2006-01-26","title":"0.9.1 (2006-01-26)","text":"
  • Major API rewrite.
  • Added a flag called \"expanded\" to the Task class to represent whether a task in an MPP9 file is shown as expanded or collapsed by MS Project.
  • Fixed a bug in the relation code in MpxjQuery (contributed by Shlomo Swidler).
  • Modified MPXDateFormat, MPXTimeFormat and MPXCurrencyFormat to derive them from DateFormat and NumberFormat.
  • Added support for MPT files.
  • Fixed a bug which could case an NPE when reading certain MPP9 files.
  • Added support for the \"marked\" attribute for MPP9 files.
  • Added support for reading split task data from MPP9 files.
  • Added support for reading calculate multiple critical paths flag.
  • Fixed a bug which could case an array out of bounds exception in the Priority (contributed by Frank Illenberger).
  • Fixed bug #1346735 \"Priorities of the tasks are exported incorrectly\".
  • Added code to allow tasks, resources, resource assignments and calendars to be removed from the data structure.
  • Implemented Italian MPX file format translation (contributed by Elio Zoggia).
  • Cleaned up calendar usage.
  • Added support for retrieval of custom document summary fields from the project header (contributed by Wade Golden).
  • Updated to use checkstyle 4.0 and fixed warnings.
  • Rationalised duration conversions into a set of methods in the MPXDuration class.
  • Replaced various file format conversion utilities with the general purpose MpxjConvert utility.
  • Fixed an issue where tasks with a percent complete value, but no resource assignments, would not write correctly to an MSPDI file.
  • Added an accessor method for resource calendars.
  • Unique ID generation was not correct for tasks, resources and calendars if these entities were added to an existing project file.
  • Fixed a compatibility issue with POI3
  • Added an event listener to the project file to allow notifications of resources and tasks being read and written to and from a file.
  • Fixed a compiler warning when build with JDK5.
  • Fixed a bug where a project start date was not being set correctly in the project header.
  • Added support for reading the project header \"calendar name\", \"schedule from\" and \"revision\" values from MPP files.
  • Fixed split task support.
  • Enhanced TableFontStyle implementation.
"},{"location":"CHANGELOG/#0025-2005-08-11","title":"0.0.25 (2005-08-11)","text":"
  • Added support for reading all properties from an MPP9 file which define the visual appearance of the Gantt Chart view shown in Microsoft Project (development funding courtesy of Steelray).
  • Tidied up constructors. Added no-argument constructors to the MPPFile and MSPDIFile classes.
  • Fixed incorrect value in WorkGroup enumerated type.
  • Implemented the resource assignment work contour property (contributed by Wade Golden).
  • Implemented correct handling for MPX files using different character set encodings (suggested by Frank Illenberger).
  • Fixed task duration calculation when importing an MPP file with a \"non-standard\" hours-per-day setting (contributed by Wade Golden).
  • Updated to ensure that the MPX task fixed attribute, and the MPP/MSPDI task type attribute are correctly handled.
  • Updated to implement the remaining project header attributes supported by the MSPDI file format.
  • Updated to add support for reading the MPX 3.0 files generated by Primavera (courtesy of CapitalSoft).
  • Fixed incorrect assumptions about conversion of durations to hours when writing MPX files (contributed by Frank Illenberger).
  • Updated to calculate remaining work for resource assignments on import, to allow MSPDI export of this data to work correctly (contributed by Frank Illenberger).
  • Updated to add another condition to the test for deleted tasks in MPP8 files.
  • Updated to fix a problem with reading assignment data from MPP9 files.
  • Rationalised the location of the JUnit tests and the sample files.
  • Fixed a problem where the project start and end dates reported in the project header were incorrect.
  • Fixed an array out of bounds exception when reading an MPP9 file.
  • Updated to allow MPXCalendarHours to accept an arbitrary number of time periods.
  • Introduced the Day class to replace the use of arbitrary integers to represent days of the week.
  • Added the ability to query the task assignments for a resource using the Resource.getTaskAssignments() method.
  • Fixed a problem with number formats in MSPDI files.
  • Updated the MPP View class to extract the view type.
  • Updated to ensure that duration values read from an MSPDI file are converted into the appropriate duration units, rather than being left as hours as the durations are represented in the MSPDI file.
  • Implemented French MPX file format translation (contributed by Benoit Baranne).
  • Fixed a bug reading assignment work contour attribute.
  • Updated to make failure more graceful when a Microsoft Project 4.0 MPP file is encountered.
  • Fixed a bug where deleted constraints in an MPP9 file were not being ignored.
  • Updated to make replace the int relation type in the Relation class with instances of the RelationType class.
  • Updated to derive RelationList from AbstractList.
  • Added sample code to MpxjQuery to illustrate retrieval of information from Relation instances.
  • Updated MpqjQuery to parse MSPDI files as well as MPP and MPX files.
  • Added support for early start, early finish, late start, late finish to MPP files.
  • Updated MPP9 file support to handle start as late as possible constraints.
  • Added support for subproject file information in MPP9 files.
  • Fixed a bug where occasionally a task in MPP9 files were not being read.
  • Fixed a NegativeArrayIndexException thrown when reading certain MPP8 files.
  • Reduced the memory used by MPXJ by anything up to 60%, particularly when reading large MPP files.
  • Fixed a bug when reading MPX files where the field delimiter was not comma, and task relation lists contained more than one entry.
  • Updated to fix unreliable retrieval of project start and end dates from certain MPP files.
  • Fixed schedule from value in MSPDI files (contributed by Frank Illenberger).
  • Fixed a bug when reading durations in elapsed days from an MPP file.
  • Tasks can now have arbitrary priority values. These values are mapped to/from the fixed MPP8/MPX priority values where necessary.
"},{"location":"CHANGELOG/#0024-2005-01-10","title":"0.0.24 (2005-01-10)","text":"
  • Fixed a bug (again!) where deleted resource assignments in MPP9 files were still seen by MPXJ.
  • Updated to use class instances instead of primitives to represent some enumerated types.
  • Updated to implement support for reading and writing all the basic Resource attributes found in MSPDI files.
  • Updated to implement support for reading and writing all the basic Task attributes found in MSPDI files.
  • Updated to implement support for reading and writing all the basic Project Header attributes from MPP8 and MPP9 files.
  • Made MSPDI file parsing more robust to allow it by default to cope with non-schema-compliant XML in the same manner as MS Project. Implemented a new compatibility flag to allow this behaviour to be disabled in favour of strict parsing.
  • Merged DateTimeSettings, CurrencySettings, and DefaultSettings into the ProjectHeader class. This change makes the project header data easier to use as it is in a single place. It also makes the entities used to describe a project consistent with the contents of the MPP and MSPDI file formats.
"},{"location":"CHANGELOG/#0023-2004-11-17","title":"0.0.23 (2004-11-17)","text":"
  • Fixed a bug where MPXJ was still using the default locale of the user's machine to create localised MPX files when a normal international MPX file was expected.
  • Fixed a bug where the incorrect record delimiter was being used in by the MPX RelationList class.
  • Fixed a bug where the method Task.getText21 was not retrieving the correct text value.
  • Fixed a bug where the task unique ID values were being truncated unnecessarily.
  • Fixed a bug where calendar exceptions were not testing the range of dates between the start and end date correctly.
  • Fixed a bug where the priority of a task was being escalated when converting between an MPP9 file and an MSPDI file.
  • Fixed a bug where a deadline was incorrectly being added to a task when importing data from an MPP9 file.
  • Fixed a bug where deleted resource assignments in MPP9 files were still seen by MPXJ.
  • Fixed a bug where MPXFile attributes were not being correctly copied by the copy constructor.
  • Fixed a rounding error in MPXCalendar.getDaysInRange (contributed by Wade Golden)
  • Updated to make MPXJ more robust in the face of unexpected offsets in MPP8 file format.
  • Updated support for password-protected files to allow write-reserved files to be read.
  • Updated to use the latest version of JAXB, as shipped in Sun's Java Web Services Developer Pack (JWSDP) version 1.4.
  • Updated the distribution to include the redistributable files from the JWSDP JAXB implementation. Users will no longer need to download JWSDP separately in order to make use of MPXJ's MSPDI functionality.
  • Updated to prevent empty notes records being added to tasks and resources when reading an MSPDI file.
  • Updated to improve accuracy when converting an MPP file to an MSPDI file.
  • Added support for blank task rows in MPP8 files.
  • Added support for blank resource rows in MPP8 files.
  • Added support for Portuguese MPX files.
  • Added support reading and writing extended attributes (apart from outline codes) for MSPDI files.
  • Added support for the Resource Type attribute.
"},{"location":"CHANGELOG/#0022-2004-07-27","title":"0.0.22 (2004-07-27)","text":"
  • Fixed a bug where task data was not being read correctly from very large MPP9 files.
  • Fixed a bug where certain MPP8 files were not read correctly when no constraint data is present.
  • Fixed a bug where certain MPP9 files were not read correctly.
  • Fixed a bug where MPP9 files containing invalid resource data were not read correctly.
  • Fixed a bug where MPXJ was using the default locale of the user's machine to create localised MPX files when a normal international MPX file was expected.
  • Fixed a bug where MPXJ not correctly handling embedded line breaks when reading and writing MPX files.
  • Removed arbitrary restrictions on the number of various entities, originally taken from the MPX specification.
  • Updated MPX documentation for Task.getFixed and Task.setFixed.
  • Updated MPP9 file code to improve handling invalid offset values.
  • Updated to remove leading and trailing spaces from MPX task field names before processing.
  • Updated to detect password protected files and raise a suitable exception.
  • Implemented an enhancement to improve file loading speed by an order of magnitude for files with a large number of tasks or resources (based on a contribution by Brian Leach).
  • Implemented support for Maven.
  • Updated MpxCreate utility to allow it to create both MPX and MSPDI files.
  • Added new JUnit test for confidential customer data.
  • Added support for the resource assignment remaining work attribute for MPP8, MPP9 and MSPDI files.
"},{"location":"CHANGELOG/#0021-2004-05-06","title":"0.0.21 (2004-05-06)","text":"
  • Fixed a bug where the task start date attribute was not always correct for MPP8 files.
  • Fixed a bug causing valid tasks to be incorrectly identified as being deleted in MPP8 files.
  • Fixed a bug causing an exception when reading certain MPP9 files.
  • Updated to allow localised MPX files to be written and read.
  • Implemented support for German MPX files.
  • Implemented generic mechanism for dealing with task field aliases.
  • Implemented task field alias read/write for MSPDI files.
  • Implemented task field alias read for MPP9 files.
  • Implemented resource field alias read/write for MSPDI files.
  • Implemented resource field alias read for MPP9 files.
"},{"location":"CHANGELOG/#0020-2004-03-15","title":"0.0.20 (2004-03-15)","text":"
  • Fixed a bug where alternative decimal delimiters and thousands separators were not being handled correctly when reading and writing MPX files.
  • Fixed a bug causing a null pointer exception when writing an MSPDI file.
  • Fixed a bug in MSPDI files where default values were being written incorrectly for some task attributes.
  • Fixed a bug with MSPDI file date handling in non GMT time zones.
  • Fixed a bug in processing calendar data where data block is not a multiple of 12 bytes
  • Fixed a bug processing tables where column data is null
  • Fixed checkstyle code warnings.
  • Fixed Eclipse code warnings.
  • Updated to include version 2.5 of the POI library.
  • Added support for task calendars.
"},{"location":"CHANGELOG/#0019-2003-12-02","title":"0.0.19 (2003-12-02)","text":"
  • Fixed a bug reading table data from certain MPP8 files
  • Updated MSPDI support to use the latest version of JAXB (from JWSDP-1.3)
  • Re-implemented base and resource calendars as a single MPXCalendar class
  • Updated support for base calendars and resource calendars for all file formats
  • Improved MPXException to print details of any nested exception when a stack trace is printed.
  • Removed unnecessary use of ByteArray.java
  • Added support for the following task fields: ActualOvertimeCost, ActualOvertimeWork, FixedCostAccrual, Hyperlink, HyperlinkAddress, HyperlinkSubAddress, LevelAssignments, LevelingCanSplit, LevelingDelay, PreleveledStart, PreleveledFinish, RemainingOvertimeCost, RemainingOvertimeWork.
"},{"location":"CHANGELOG/#0018-2003-11-13","title":"0.0.18 (2003-11-13)","text":"
  • Fixed a bug with writing MS Project compatible MSPDI XML files in non-GMT timezones.
  • Fixed a bug with writing MSPDI XML files in non-GMT timezones.
  • Fixed a bug causing an exception when zero length calendar names were present
  • Fixed a bug causing MPP8 flags to be read incorrectly. Note that flag 20 is still not read correctly.
  • Fixed a bug with the \"Microsoft Project Compatible Output\" flag for MSPDI files.
  • Fixed a bug reading task text 10.
  • Added new MPXFile.setIgnoreTextModel() method to allow MPXJ to ignore faulty text version of task or resource model records in MPX files.
  • Improved invalid MPX data error handling and reporting.
  • Added BaseCalendar.getDate method to allow end dates to be calculated based on a start date and a duration of working time.
  • Made MPXDateFormat implement java.io.Serializable to allow MPXDate to serialize correctly.
  • Updated the ant build file to allow MPXJ to be built without the components that depend on JAXB
  • Rationalised setDefaultStartTime and setDefaultEndTime methods
  • Added MppXml utility
  • Added support for querying view information held in MPP files.
  • Added support for querying table information held in MPP files. (NB This allows the user to retrieve column information, including user defined column names)
  • Added support for outlinecode1-10 fields in MPP9 files.
  • Added support for resource \"available from\" and \"available to\" fields.
  • Verified that MPXJ will read MPP files written by Microsoft Project 2003 (they are still MPP9 files).
"},{"location":"CHANGELOG/#0017-2003-08-05","title":"0.0.17 (2003-08-05)","text":"
  • Fixed a bug where a decimal point was being appended to the currency format even if no decimal digits were required.
  • Fixed a bug where special characters appearing in the currency symbol were not being quoted.
  • Fixed a bug that caused resource assignments to be incorrectly read from some MPP8 files.
  • Added a new write method to MPXFile allowing the user control over the character encoding used when writing an MPX file.
"},{"location":"CHANGELOG/#0016-2003-07-04","title":"0.0.16 (2003-07-04)","text":"
  • Fixed bug causing some extended boolean attributes to be read incorrectly.
  • Fixed bug causing MPP8 file task data to be read incorrectly under certain circumstances.
  • Updated calendar duration code to account for calendar exceptions.
"},{"location":"CHANGELOG/#0015-2003-06-17","title":"0.0.15 (2003-06-17)","text":"
  • Fixed a bug causing resource assignments to be duplicated in an MPX file created programmatically.
  • Fixed a bug causing an incorrect duration value to be read from an MPP9 file.
  • Fixed a bug causing invalid MPX files to be written in locales which don't use a period as the decimal separator.
  • Fixed a bug causing embedded quote and comma characters in task and resource notes to be handled incorrectly.
  • Added simple JUnit test to demonstrate iteration through relationships.
  • Added an example of programmatically creating a partially complete task to the MPXCreate.java example.
  • Added default values to the MPX project header.
  • Added support for reading the RemainingDuration field from an MPP9 file.
  • Updated predecessor and successor method documentation.
  • Updated Task.get/set ResourceInitials and Task.get/set ResourceNames method documentation.
  • Updated to extract the following fields from resource assignment data in MPP files which were previously not imported: ActualCost, ActualWork, Cost, Finish, Start, Units, Work.
"},{"location":"CHANGELOG/#0014-2003-05-28","title":"0.0.14 (2003-05-28)","text":"
  • Updated to extract the following fields from resource data in an MPP9 file which were previously not imported: Flag1-Flag20.
  • Added the method MPPFile.getFileType to allow the type of MPP file (MPP8: 98, MPP9: 2000,2002) to be determined.
  • Updated API to make classes final and constructors package access only where appropriate.
  • Updated to use of 6 byte long int fields for cost and work values for MPP8.
  • Fixed error in reading task fixed cost for MPP8.
  • Updated to extract the following fields from task data in an MPP8 file which were previously not imported: Contact, Cost1-Cost10, Date1-Date10, Duration1-Duration10, EffortDriven, Finish1-Finish10, Flag1-Flag20, HideBar, Milestone, Number1-Number20, Rollup, Start1-Start10, Text1-Text30, Type, WBS.
  • Updated to extract the following fields from resource data in an MPP8 file which were previously not imported: Code, Cost1-Cost10, Date1-Date10, Duration1-Duration10, EmailAddress, Finish1-Finish10, Number1-Number20, Start1-Start10, Text1-Text30
  • Added support for task and resource note fields in MPP8 files.
  • Added support for the OvertimeCost task attribute for all file formats.
  • Updated to extract calendar data from MPP8 files.
  • Updated resource notes to fix end of line handling problem.
  • Added functionality to read default settings and currency settings data from MPP files.
"},{"location":"CHANGELOG/#0013-2003-05-22","title":"0.0.13 (2003-05-22)","text":"
  • Implemented support for the Microsoft Project 98 file format.
  • Fixed a bug that prevented task and resource note text from being read.
  • Updated to remove a Java 1.4 dependency introduced in 0.0.12. Will now work with Java 1.3.
  • Updated to correct handling of carriage returns embedded in note fields.
"},{"location":"CHANGELOG/#0012-2003-05-08","title":"0.0.12 (2003-05-08)","text":"
  • Fixed incorrect handling of timezones and daylight saving time.
  • Fixed incorrect task structure generated from outline levels.
  • Updated to extract the notes fields from tasks and resources read from an MPP file.
  • Added the option to remove or preserve the RTF formatting from the note fields from an MPP file.
  • Updated to extract the following fields from task data in an MPP file which were previously not imported: Text11-Text30, Number6-Number20, Duration4-Duration10, Date1-Date10, Cost4-Cost10, Start6-Start10, Finish6-Finish10
  • Updated to extract the following fields from resource data in an MPP file which were previously not imported: Text6-Text30, Start1-Start10, Finish1-Finish10, Number1-Number20, Duration1-Duration10, Date1-Date10, Cost1-Cost10
"},{"location":"CHANGELOG/#0011-2003-04-15","title":"0.0.11 (2003-04-15)","text":"
  • Fixed error in format string used in one of the example files.
  • Fixed error where double byte characters were being read incorrectly.
  • Fixed error where deleted constraints were being resurrected when read from an MPP file.
  • Updated to extract the following fields from task data in an MPP file which were previously not imported: Flag11-Flag20, Rollup, HideBar, EffortDriven.
"},{"location":"CHANGELOG/#0010-2003-04-08","title":"0.0.10 (2003-04-08)","text":"
  • Corrected Actual Start and Actual End fields from MPP file.
  • Fixed bug where time values were being broken by daylight saving time in the user's default locale.
  • Updated to extract the following fields from task data in an MPP file which were previously not imported: Actual Work, Baseline Work, Cost Variance, Deadline, Remaining Work, Work.
  • Updated to extract the following fields from resource data in an MPP file which were previously not imported: Actual Cost, Actual Overtime Cost, Actual Work, Baseline Work, Cost, Cost Variance, Max Units, Overtime Cost, Overtime Rate, Overtime Work, Peak, Regular work, Remaining Cost, Remaining Overtime Cost, Remaining Work, Standard Rate, Work, Work Variance
"},{"location":"CHANGELOG/#009-2003-04-03","title":"0.0.9 (2003-04-03)","text":"
  • Fixed bug when handling certain types of modified MPP file where resources have been updated.
  • Added sample MPP files for bugs to the JUnit tests.
  • Added support for summary flag import from MPP files.
  • Added automatic summary flag update when creating an MPX file programmatically.
  • Added new constructor to the MSPDIFile class to allow MSPDI files to be created from scratch.
"},{"location":"CHANGELOG/#008-2003-03-27","title":"0.0.8 (2003-03-27)","text":"
  • Added support for estimated durations.
  • Fixed bug in handling certain types of modified MPP file where tasks have been updated.
  • Added the facility to auto generate outline numbers.
"},{"location":"faq/","title":"Frequently Asked Questions","text":""},{"location":"faq/#general-questions","title":"General Questions","text":"

Can I use MPXJ to write MPP files?

Not at present. Although it is technically feasible to generate an MPP file, the knowledge we have of the file structure is still relatively incomplete, despite the amount of data we are able to correctly extract. It is therefore likely to take a considerable amount of development effort to make this work, and it is conceivable that we will not be able to write the full set of attributes that MPXJ supports back into the MPP file - simply because we don't understand the format well enough. You are therefore probably better off using MSPDI which does support the full range of data items present in an MPP file.

I'm generating output using MPXJ, and when my end users open the file in Microsoft Project, I want to control the appearance of the project data that they see. Can I do this with MPXJ?

In short, the answer to this question is no. The only file format which allows you to control the appearance of project data when opened in Microsoft Project is MPP. Just to clarify, visual appearance in this context refers to the view that appears when the project opens, the filtering applied to the view, the table data visible, the columns in the table, bar styles, text styles and so on. While MPXJ can read this information from an MPP file, none of the supported output file formats contain these attributes.

When I double click on an MPX file to open it in Microsoft Project, I end up with two copies of the file open. What's happening?

This isn't an issue with MPXJ - but we have an answer for you anyway! The problem is caused by an incorrect setting in Microsoft Windows which controls the way MPX files are opened. To fix the setting, open the Control Panel and click on the \"Folder Options\" icon. Select the \"File Types\" tab and scroll down the list of file types until you find an entry for MPX. Once you have found the entry for MPX, click on it to highlight it, then press the \"Advanced\" button at the bottom right hand side of the dialog. In the list of actions that you are now presented with, click on the word \"open\" to highlight it, then click the \"Edit\" button on the right hand side of the dialog. Finally, ensure that the \"Use DDE\" check box is not checked, and you can now finish by clicking OK on each of the open dialogs to dismiss them. You should now find that double clicking on an MPX file will now only open one copy of the file in Microsoft Project.

I use a version of Java older than Java 8, can I use MPXJ?

The last version of MPXJ which supports versions of Java prior to Java 8 is version 7.9.8.

I use a Java 1.4 JVM, but MPXJ is built with a later version of Java, is there anything I can do which will allow me to use it?

Yes there is. Assuming you are using a version of MPXJ prior to 8.0.0, try using Retroweaver.

"},{"location":"faq/#known-issues-with-mpxj","title":"Known Issues with MPXJ","text":"

I have an MPP file created by MS Project 98, and some Flag field values are incorrect.

The MPP8 file format is rather cryptic, and one part of it that I have yet to really understand fully is how the Flag fields are stored. I've spent a lot of time looking at this and have not made a lot of progress, so at the moment no further work is being undertaken to fix this. Contributions of insights, knowledge or fixed code for this problem are welcome. You'll find a bug for this item logged in the SourgeForge bug tracker.

When I read an MPP file I sometimes see an extra task or resource record.

What you are seeing are \"hidden\" tasks and resources which newer versions of Microsoft Project appear to use as placeholders for summary information about all of the tasks and all of the resources in a project. We're not sure exactly which versions of Project hold data like this, although we think this is only relevant for the MPP9 and MPP12 file formats. We've also noticed that the information in these hidden tasks and resources may not be reliable, so don't place too much emphasis on them in your application.

You can ignore the first resource if it has a null value as its name. The attributes of this resource should actually be a summary of all of the resource combined, e.g. utilisation, actual work, remaining work and so on for the complete set of \"real\" resources.

You can ignore the first task if it has an outline level of zero, this task will be a summary of all the \"real\" tasks in the project. You may also find that the name of this task matches the name of the project.

My localised version of MS Project won't read the MPX files created by MPXJ, or MPXJ won't read the MPX files written by my localised version of MS Project.

Localised versions of MS Project (i.e. those which have been translated for use in a non-English locale) read and write MPX files which include localised text strings. The end result of this is that an English/International version of MS Project can't read MPX files produced by a localised version of MS Project, and vice versa.

MPXJ supports a small number of non-English locales, and can read and write MPX files correctly for those locales. You can also use MPXJ to translate MPX files from one locale to another. The MPXFile.setLocale() method must be called prior to reading or writing an MPX file in order to set the required locale. By default, MPXJ will always produce MPX files for the International/English locale, regardless of the locale for which your operating system if configured.

Supported locales for MPX files currently include German, Spanish, French, Italian, Portuguese, Swedish, and Simplified Chinese. Producing a translation for your locale is very easy, please contact us for details on how you can help us to do this.

When I write an MPX file, changes to the project header settings I've made seem to be lost, what's happening?

One of the first things the MPXWriter's write method does is to determine the current locale and update various project settings (for example, currency and date formats) to match the selected locale. This behaviour can be changed so that the settings in the project are left unmodified by setting the useLocaleDefaults parameter to false when calling the write method (for versions of MPXJ up to and including 3.0.0) or by calling the method setUseLocaleDefaults on the MPXWriter instance before calling the write method (for versions of MPXJ after 3.0.0).

"},{"location":"faq/#unit-tests","title":"Unit Tests","text":"

I am trying to run the MPXJ unit tests and I'm having problems with failures in JAXB functionality. What's happening?

Older versions of JAXB were known to have issues with the JUnit classloader, so running the JUnit test runner with the -noloading command line option, other taking other steps to disable JUnit classloading was recommended. This problem is not believed to affect the more recent version of JAXB now used by MPXJ.

"},{"location":"faq/#net","title":".NET","text":"

When using MPXJ from .NET Core I get an error similar to No data is available for encoding 437. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.

By default .NET Core does not include all of the character encodings which may be used by MPXJ (and which are present by default in .NET Framework). To resolve this issue add the following to your code:

System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);\n

I have set up a simple test project using MPXJ.Net, and when I try to do anything with MPXJ, an exception is thrown

One of the libraries MPXJ depends on throws and catches one or more exceptions as part of its normal flow of control. These exceptions are handled, so you can keep pressing continue, and your code should run normally after that. Visual Studio is breaking on these exceptions even though they are handled. You can prevent this behavior by adding this condition to the \"Common Language Runtime Exceptions\" entry in the exception settings window in Visual Studio: Module Name Not Equals org.glassfish.*, as illustrated below.

I have set up a simple test project using MPXJ.Net, and when I try to do anything with MPXJ, Visual Studio crashes

This is the same problem as described above. MPXJ is catching an exception being raised in one of MPXJ's dependencies and, in the process, crashing. The solution is the same: add the condition described above to ensure that Visual Studio ignores this exception.

I have set up a simple test project using MPXJ.Net, but when I run it I get this error System.IO.FileNotFoundException: 'Could not load file or assembly 'mpxj, Version=(version number), Culture=neutral, PublicKeyToken=(token)' or one of its dependencies. The system cannot find the file specified.'

This is typically caused by MPXJ.Net being added as a dependency to a non SDK-style project. MPXJ.Net will only work with an SDK-style project. If you open your csproj file in a text editor, the first line should look something like this: <Project Sdk=\"Microsoft.NET.Sdk\">. If your csproj file is different you will need to create a new SDK-style project. Sample projects in this form can be found in this repository.

I have an application which uses MPXJ.Net and runs fine on my local machine, but fails with a Segmentation Fault when run in Docker When using Docker to host an application built with MPXJ.Net, you may find that the application crashes with a segmentation fault when invoking MPXJ.Net code. The issue is likely to be a library missing from the Docker image. Adding the following line to your Dockerfile will ensure that the most common missing library is added: RUN apt-get update && apt-get install -y libfontconfig

"},{"location":"faq/#log4j2","title":"log4j2","text":"

When you start MPXJ, you may see the following message written to the console:

ERROR StatusLogger Log4j2 could not find a logging implementation.\nPlease add log4j-core to the classpath. Using SimpleLogger to log to the console.\n

MPXJ uses Apache POI to read MPP files. Apache POI uses log4j2 to write log messages. By default the only dependency POI has on log4j2 is to its interfaces. If you're not already using log4j2 as part of your code, and you don't explicitly include the rest of the log4j2 implementation jar files, you'll see the warning message shown above. This message can safely be ignored, it's just telling you that any log messages POI produces will be written to the console. If you would like to silence this message, you can supply the following argument to the JVM:

-Dlog4j2.loggerContextFactory=org.apache.logging.log4j.simple.SimpleLoggerContextFactory\n

If you are using the Python version of MPXJ, you can provide the argument as shown below when you initialize jpype.

jpype.startJVM(\"-Dlog4j2.loggerContextFactory=org.apache.logging.log4j.simple.SimpleLoggerContextFactory\")\n
"},{"location":"field-guide/","title":"Field Guide","text":""},{"location":"field-guide/#field-guide","title":"Field Guide","text":"

The tables below provide an indication of which fields are populated when files of different types are read using MPXJ The tables are not hand-crafted: they have been generated from test data and are therefore may be missing some details.

"},{"location":"field-guide/#project","title":"Project","text":""},{"location":"field-guide/#core-fields","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) AM Text \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Increment \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Increment Based On Selected Activity \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Prefix \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID Suffix \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 Actual Duration \u2713 Actual Start \u2713 Actual Work \u2713 Actuals In Sync \u2713 Application Version \u2713 \u2713 \u2713 \u2713 Author \u2713 \u2713 \u2713 \u2713 \u2713 Auto Add New Resources and Tasks \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Auto Filter \u2713 Auto Link \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Bar Text Date Format \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Calculate Float on Finish Date of Each Project \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Calculate Multiple Float Paths \u2713 \u2713 \u2713 Calculate Multiple Float Paths Ending With Activity Unique ID \u2713 \u2713 Calculate Multiple Paths Using Total Float \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Category \u2713 \u2713 Comments \u2713 \u2713 \u2713 Company \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Compute Start to Start Lag From Early Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Consider Assignments In Other Project With Priority Equal or Higher Than \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Content Status \u2713 Content Type \u2713 Cost \u2713 Creation Date \u2713 \u2713 \u2713 \u2713 \u2713 Critical Activity Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Critical Slack Limit \u2713 \u2713 Currency Code \u2713 \u2713 Currency Digits \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Currency Symbol \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Currency Symbol Position \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Current Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Custom Properties \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Date Format \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Date Order \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Date Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Days per Month \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Decimal Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Calendar Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Duration Is Fixed \u2713 Default End Time \u2713 \u2713 \u2713 \u2713 \u2713 Default Overtime Rate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Standard Rate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Start Time \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Default Work Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Document Version \u2713 Duration \u2713 \u2713 Earned Value Method \u2713 Editable Actual Costs \u2713 \u2713 Editing Time \u2713 Export Flag \u2713 \u2713 Extended Creation Date \u2713 File Application \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 File Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Fiscal Year Start \u2713 Fiscal Year Start Month \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Full Application Name \u2713 GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Honor Constraints \u2713 \u2713 \u2713 Hyperlink Base \u2713 Ignore Relationships To And From Other Projects \u2713 Inserted Projects Like Summary \u2713 Keywords \u2713 \u2713 \u2713 Language \u2713 Last Author \u2713 Last Printed \u2713 Last Saved \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Level All Resources \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Level Resources Only Within Activity Total Float \u2713 \u2713 Leveling Priorities \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Limit Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Location Unique ID \u2713 MPP File Type \u2713 MPX Code Page \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 MPX Delimiter \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 MPX File Version \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 MPX Program Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Manager \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Maximum Percentage to Overallocate Resources \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Microsoft Project Server URL \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Day \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Month \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Week \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Minutes per Year \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Multiple Critical Paths \u2713 \u2713 Must Finish By \u2713 \u2713 Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 New Task Start Is Project Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 New Tasks Are Effort Driven \u2713 \u2713 New Tasks Are Manual \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 New Tasks Estimated \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 PM Text \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Percentage Complete \u2713 Planned Start \u2713 \u2713 \u2713 Presentation Format \u2713 Preserve Minimum Float When Leveling \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Preserve Scheduled Early and Late Dates \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Project Externally Edited \u2713 Project File Path \u2713 Project ID \u2713 \u2713 \u2713 Project Title \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Project Website URL \u2713 \u2713 Relationship Lag Calendar \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Resource Pool File \u2713 Revision \u2713 \u2713 Schedule From \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Scheduled Finish \u2713 \u2713 \u2713 Short Application Name \u2713 Show Project Summary Task \u2713 Split In Progress Tasks \u2713 \u2713 \u2713 \u2713 Start Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 Status Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Subject \u2713 \u2713 \u2713 \u2713 Template \u2713 Thousands Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Time Format \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Time Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Total Slack Calculation Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 Updating Task Status Updates Resource Status \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Use Expected Finish Dates \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 WBS Code Separator \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Week Start Day \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 When Scheduling Progressed Activities Use \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work \u2713 Work 2 \u2713"},{"location":"field-guide/#baseline-fields","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Date \u2713 Baseline2 Date \u2713 Baseline3 Date \u2713 Baseline4 Date \u2713 Baseline5 Date \u2713 Baseline6 Date \u2713 Baseline7 Date \u2713 Baseline8 Date \u2713 Baseline9 Date \u2713 Baseline10 Date \u2713 Baseline Calendar Name \u2713 \u2713 Baseline Cost \u2713 Baseline Date \u2713 \u2713 Baseline Duration \u2713 Baseline Finish \u2713 \u2713 Baseline Project Unique ID \u2713 \u2713 \u2713 Baseline Start \u2713 \u2713 Baseline Type Name \u2713 Baseline Work \u2713 Last Baseline Update Date \u2713 Project Is Baseline \u2713"},{"location":"field-guide/#task","title":"Task","text":""},{"location":"field-guide/#core-fields_1","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) % Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 % Work Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 ACWP \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity Codes \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity Percent Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Activity Status \u2713 \u2713 \u2713 Activity Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Duration Units \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work (Labor) \u2713 \u2713 \u2713 Actual Work (Nonlabor) \u2713 \u2713 \u2713 Actual Work Protected \u2713 Bar Name \u2713 Bid Item \u2713 Board Status ID \u2713 Budget Cost \u2713 Budget Work \u2713 CV \u2713 Calendar Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Category of Work \u2713 Complete Through \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Constraint Date \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Constraint Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Contact \u2713 \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Critical \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Deadline \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Department \u2713 Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Duration Units \u2713 Duration Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Early Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Early Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Earned Value Method \u2713 Effort Driven \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Estimated \u2713 \u2713 \u2713 \u2713 Expanded \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Expected Finish \u2713 \u2713 Expense Items \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 External Early Start \u2713 \u2713 External Late Finish \u2713 \u2713 External Project \u2713 \u2713 External Task \u2713 \u2713 Feature of Work \u2713 Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Fixed Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Fixed Cost Accrual \u2713 \u2713 \u2713 Free Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Hammock Code \u2713 Hide Bar \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 Hyperlink Data \u2713 Hyperlink Screen Tip \u2713 Hyperlink SubAddress \u2713 ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Ignore Resource Calendar \u2713 \u2713 \u2713 \u2713 \u2713 Late Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Late Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Level Assignments \u2713 \u2713 \u2713 Leveling Can Split \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 \u2713 Leveling Delay Units \u2713 \u2713 \u2713 Longest Path \u2713 \u2713 Mail \u2713 Manager \u2713 Manual Duration \u2713 \u2713 Manual Duration Units \u2713 Marked \u2713 \u2713 Milestone \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Null \u2713 \u2713 \u2713 Outline Level \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Outline Number \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Overall Percent Complete \u2713 Overallocated \u2713 Overtime Cost \u2713 \u2713 \u2713 Overtime Work \u2713 Parent Task Unique ID \u2713 Percent Complete Type \u2713 \u2713 \u2713 Phase of Work \u2713 Physical % Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Planned Cost \u2713 \u2713 \u2713 Planned Duration \u2713 \u2713 \u2713 \u2713 Planned Finish \u2713 \u2713 \u2713 \u2713 Planned Start \u2713 \u2713 \u2713 \u2713 Planned Work \u2713 \u2713 \u2713 Planned Work (Labor) \u2713 \u2713 \u2713 Planned Work (Nonlabor) \u2713 \u2713 \u2713 Preleveled Finish \u2713 \u2713 \u2713 Preleveled Start \u2713 \u2713 \u2713 Primary Resource Unique ID \u2713 \u2713 \u2713 Priority \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Project \u2713 \u2713 \u2713 \u2713 \u2713 Recalc Outline Codes \u2713 Recurring \u2713 \u2713 \u2713 Recurring Data \u2713 Regular Work \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Early Finish \u2713 \u2713 \u2713 Remaining Early Start \u2713 \u2713 \u2713 Remaining Late Finish \u2713 \u2713 \u2713 Remaining Late Start \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Work (Labor) \u2713 \u2713 \u2713 Remaining Work (Nonlabor) \u2713 \u2713 \u2713 Resource Names \u2713 \u2713 Responsibility Code \u2713 Resume \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Resume No Earlier Than \u2713 Resume Valid \u2713 Rollup \u2713 \u2713 \u2713 \u2713 Scheduled Duration \u2713 Scheduled Finish \u2713 Scheduled Start \u2713 Secondary Constraint Date \u2713 \u2713 Secondary Constraint Type \u2713 \u2713 Section \u2713 Sequence Number \u2713 \u2713 \u2713 Show Duration Text \u2713 Show Finish Text \u2713 Show Start Text \u2713 Splits \u2713 \u2713 Sprint ID \u2713 Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Steps \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 \u2713 Subproject File \u2713 \u2713 \u2713 Subproject GUID \u2713 Subproject Task ID \u2713 \u2713 Subproject Task Unique ID \u2713 Subproject Tasks Unique ID Offset \u2713 Summary \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Summary Progress \u2713 Suspend Date \u2713 \u2713 Task Calendar GUID \u2713 Task Mode \u2713 \u2713 Task Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Total Slack \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID Successors \u2713 WBS \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713 \u2713 \u2713"},{"location":"field-guide/#baseline-fields_1","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Duration \u2713 \u2713 \u2713 \u2713 Baseline1 Duration Units \u2713 Baseline1 Estimated Duration \u2713 Baseline1 Estimated Finish \u2713 Baseline1 Estimated Start \u2713 Baseline1 Finish \u2713 \u2713 \u2713 \u2713 Baseline1 Fixed Cost \u2713 Baseline1 Fixed Cost Accrual \u2713 Baseline1 Start \u2713 \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Duration \u2713 \u2713 \u2713 Baseline2 Duration Units \u2713 Baseline2 Estimated Duration \u2713 Baseline2 Estimated Finish \u2713 Baseline2 Estimated Start \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Fixed Cost \u2713 Baseline2 Fixed Cost Accrual \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Duration \u2713 \u2713 \u2713 Baseline3 Duration Units \u2713 Baseline3 Estimated Duration \u2713 Baseline3 Estimated Finish \u2713 Baseline3 Estimated Start \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Fixed Cost \u2713 Baseline3 Fixed Cost Accrual \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Duration \u2713 \u2713 \u2713 Baseline4 Duration Units \u2713 Baseline4 Estimated Duration \u2713 Baseline4 Estimated Finish \u2713 Baseline4 Estimated Start \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Fixed Cost \u2713 Baseline4 Fixed Cost Accrual \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Duration \u2713 \u2713 \u2713 Baseline5 Duration Units \u2713 Baseline5 Estimated Duration \u2713 Baseline5 Estimated Finish \u2713 Baseline5 Estimated Start \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Fixed Cost \u2713 Baseline5 Fixed Cost Accrual \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Duration \u2713 \u2713 \u2713 Baseline6 Duration Units \u2713 Baseline6 Estimated Duration \u2713 Baseline6 Estimated Finish \u2713 Baseline6 Estimated Start \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Fixed Cost \u2713 Baseline6 Fixed Cost Accrual \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Duration \u2713 \u2713 \u2713 Baseline7 Duration Units \u2713 Baseline7 Estimated Duration \u2713 Baseline7 Estimated Finish \u2713 Baseline7 Estimated Start \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Fixed Cost \u2713 Baseline7 Fixed Cost Accrual \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Duration \u2713 \u2713 \u2713 Baseline8 Duration Units \u2713 Baseline8 Estimated Duration \u2713 Baseline8 Estimated Finish \u2713 Baseline8 Estimated Start \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Fixed Cost \u2713 Baseline8 Fixed Cost Accrual \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Duration \u2713 \u2713 \u2713 Baseline9 Duration Units \u2713 Baseline9 Estimated Duration \u2713 Baseline9 Estimated Finish \u2713 Baseline9 Estimated Start \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Fixed Cost \u2713 Baseline9 Fixed Cost Accrual \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Cost \u2713 \u2713 \u2713 \u2713 Baseline10 Deliverable Finish \u2713 Baseline10 Duration \u2713 \u2713 \u2713 \u2713 Baseline10 Duration Units \u2713 Baseline10 Estimated Duration \u2713 Baseline10 Estimated Finish \u2713 Baseline10 Estimated Start \u2713 Baseline10 Finish \u2713 \u2713 \u2713 \u2713 Baseline10 Fixed Cost \u2713 Baseline10 Fixed Cost Accrual \u2713 Baseline10 Start \u2713 \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Deliverable Finish \u2713 Baseline Deliverable Start \u2713 Baseline Duration \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Duration Units \u2713 Baseline Estimated Duration \u2713 Baseline Estimated Finish \u2713 Baseline Estimated Start \u2713 Baseline Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Fixed Cost \u2713 \u2713 \u2713 Baseline Fixed Cost Accrual \u2713 Baseline Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713"},{"location":"field-guide/#custom-fields","title":"Custom Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Cost1 \u2713 \u2713 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 \u2713 Duration1 Units \u2713 Duration2 \u2713 \u2713 \u2713 \u2713 Duration2 Units \u2713 Duration3 \u2713 \u2713 \u2713 \u2713 Duration3 Units \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 Finish1 \u2713 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 Start1 \u2713 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"field-guide/#enterprise-fields","title":"Enterprise Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Enterprise Data \u2713 Enterprise Duration1 Units \u2713 Enterprise Duration2 Units \u2713 Enterprise Duration3 Units \u2713 Enterprise Duration4 Units \u2713 Enterprise Duration5 Units \u2713 Enterprise Duration6 Units \u2713 Enterprise Duration7 Units \u2713 Enterprise Duration8 Units \u2713 Enterprise Duration9 Units \u2713 Enterprise Duration10 Units \u2713 Enterprise Project Date1 \u2713 Enterprise Project Date2 \u2713 Enterprise Project Date3 \u2713 Enterprise Project Date4 \u2713 Enterprise Project Number2 \u2713 Enterprise Project Number4 \u2713 Enterprise Project Number5 \u2713 Enterprise Project Number22 \u2713 Enterprise Project Text1 \u2713 \u2713 Enterprise Project Text2 \u2713 Enterprise Project Text3 \u2713 Enterprise Project Text4 \u2713 Enterprise Project Text5 \u2713 Enterprise Project Text6 \u2713 Enterprise Project Text8 \u2713 Enterprise Project Text9 \u2713 Enterprise Project Text10 \u2713 Enterprise Project Text11 \u2713 Enterprise Project Text12 \u2713 Enterprise Project Text13 \u2713 Enterprise Project Text14 \u2713 Enterprise Project Text15 \u2713 Enterprise Project Text16 \u2713 Enterprise Project Text17 \u2713 Enterprise Project Text18 \u2713 Enterprise Project Text19 \u2713 Enterprise Project Text21 \u2713 Enterprise Project Text40 \u2713 \u2713"},{"location":"field-guide/#resource","title":"Resource","text":""},{"location":"field-guide/#core-fields_2","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) % Work Complete \u2713 ACWP \u2713 \u2713 Accrue At \u2713 \u2713 \u2713 \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Availability Data \u2713 Available From \u2713 Available To \u2713 BCWS \u2713 Base Calendar \u2713 Booking Type \u2713 \u2713 Budget \u2713 \u2713 Budget Cost \u2713 Budget Work \u2713 CV \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Calendar GUID \u2713 Calendar Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Can Level \u2713 \u2713 Code \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Center \u2713 \u2713 Cost Per Use \u2713 Cost Rate A \u2713 Cost Rate B \u2713 Cost Rate C \u2713 Cost Rate D \u2713 Cost Rate E \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 Default Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Description \u2713 Email Address \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Generic \u2713 \u2713 Group \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 Hyperlink Address \u2713 Hyperlink Data \u2713 Hyperlink Screen Tip \u2713 Hyperlink SubAddress \u2713 ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Initials \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Material Label \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Max Units \u2713 Name \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Overallocated \u2713 \u2713 \u2713 \u2713 Overtime Cost \u2713 \u2713 \u2713 Overtime Rate \u2713 Overtime Rate Units \u2713 Overtime Work \u2713 \u2713 \u2713 Parent ID \u2713 \u2713 \u2713 \u2713 \u2713 Peak \u2713 \u2713 \u2713 \u2713 \u2713 Per Day \u2713 Phone \u2713 Phonetics \u2713 Pool \u2713 Primary Role Unique ID \u2713 \u2713 \u2713 Rate \u2713 Regular Work \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Resource ID \u2713 \u2713 \u2713 \u2713 Role \u2713 \u2713 \u2713 SV \u2713 Sequence Number \u2713 \u2713 \u2713 Shift Unique ID \u2713 \u2713 Standard Rate \u2713 Standard Rate Units \u2713 Subproject Unique Resource ID \u2713 Supply Reference \u2713 Type \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Unit \u2713 Unit of Measure Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Windows User Account \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713 Workgroup \u2713 \u2713 \u2713"},{"location":"field-guide/#baseline-fields_2","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Budget Cost \u2713 Baseline1 Budget Work \u2713 Baseline1 Cost \u2713 \u2713 Baseline1 Work \u2713 \u2713 Baseline2 Budget Cost \u2713 Baseline2 Budget Work \u2713 Baseline2 Cost \u2713 \u2713 Baseline2 Work \u2713 \u2713 Baseline3 Budget Cost \u2713 Baseline3 Budget Work \u2713 Baseline3 Cost \u2713 \u2713 Baseline3 Work \u2713 \u2713 Baseline4 Budget Cost \u2713 Baseline4 Budget Work \u2713 Baseline4 Cost \u2713 \u2713 Baseline4 Work \u2713 \u2713 Baseline5 Budget Cost \u2713 Baseline5 Budget Work \u2713 Baseline5 Cost \u2713 \u2713 Baseline5 Work \u2713 \u2713 Baseline6 Budget Cost \u2713 Baseline6 Budget Work \u2713 Baseline6 Cost \u2713 \u2713 Baseline6 Work \u2713 \u2713 Baseline7 Budget Cost \u2713 Baseline7 Budget Work \u2713 Baseline7 Cost \u2713 \u2713 Baseline7 Work \u2713 \u2713 Baseline8 Budget Cost \u2713 Baseline8 Budget Work \u2713 Baseline8 Cost \u2713 \u2713 Baseline8 Work \u2713 \u2713 Baseline9 Budget Cost \u2713 Baseline9 Budget Work \u2713 Baseline9 Cost \u2713 \u2713 Baseline9 Work \u2713 \u2713 Baseline10 Budget Cost \u2713 Baseline10 Budget Work \u2713 Baseline10 Cost \u2713 \u2713 Baseline10 Work \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713"},{"location":"field-guide/#custom-fields_1","title":"Custom Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"field-guide/#enterprise-fields_1","title":"Enterprise Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Enterprise \u2713 \u2713 Enterprise Data \u2713 Enterprise Duration1 Units \u2713 Enterprise Duration2 Units \u2713 Enterprise Duration3 Units \u2713 Enterprise Duration4 Units \u2713 Enterprise Duration5 Units \u2713 Enterprise Duration6 Units \u2713 Enterprise Duration7 Units \u2713 Enterprise Duration8 Units \u2713 Enterprise Duration9 Units \u2713 Enterprise Duration10 Units \u2713 Enterprise Unique ID \u2713"},{"location":"field-guide/#resource-assignment","title":"Resource Assignment","text":""},{"location":"field-guide/#core-fields_3","title":"Core Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) ACWP \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Assignment Delay \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Assignment GUID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Assignment Resource GUID \u2713 Assignment Task GUID \u2713 Assignment Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 BCWS \u2713 Budget Cost \u2713 \u2713 Budget Work \u2713 \u2713 CV \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Confirmed \u2713 Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Cost Account ID \u2713 \u2713 \u2713 Cost Rate Table \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 Created \u2713 \u2713 Finish \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 Hyperlink Data \u2713 Hyperlink Screen Tip \u2713 Hyperlink Subaddress \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 Leveling Delay Units \u2713 Linked Fields \u2713 Notes \u2713 \u2713 \u2713 Override Rate \u2713 \u2713 \u2713 Overtime Work \u2713 \u2713 \u2713 Owner \u2713 Percent Work Complete \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Planned Cost \u2713 \u2713 \u2713 Planned Finish \u2713 \u2713 \u2713 Planned Start \u2713 \u2713 \u2713 Planned Work \u2713 \u2713 \u2713 Rate Index \u2713 \u2713 Rate Source \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Regular Work \u2713 \u2713 \u2713 Remaining Assignment Units \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Remaining Early Finish \u2713 \u2713 \u2713 Remaining Early Start \u2713 \u2713 \u2713 Remaining Late Finish \u2713 \u2713 Remaining Late Start \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Resource Request Type \u2713 Resource Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Response Pending \u2713 \u2713 Resume \u2713 \u2713 \u2713 Role Unique ID \u2713 \u2713 \u2713 SV \u2713 Start \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 Task Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Team Status Pending \u2713 \u2713 Timephased Actual Overtime Work \u2713 Timephased Actual Work \u2713 Timephased Work \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Variable Rate Units \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work Contour \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713"},{"location":"field-guide/#baseline-fields_3","title":"Baseline Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Baseline1 Budget Cost \u2713 Baseline1 Budget Work \u2713 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Finish \u2713 \u2713 \u2713 Baseline1 Start \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Budget Cost \u2713 Baseline2 Budget Work \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Budget Cost \u2713 Baseline3 Budget Work \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Budget Cost \u2713 Baseline4 Budget Work \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Budget Cost \u2713 Baseline5 Budget Work \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Budget Cost \u2713 Baseline6 Budget Work \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Budget Cost \u2713 Baseline7 Budget Work \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Budget Cost \u2713 Baseline8 Budget Work \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Budget Cost \u2713 Baseline9 Budget Work \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Budget Cost \u2713 Baseline10 Budget Work \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Finish \u2713 \u2713 \u2713 Baseline10 Start \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 \u2713 Baseline Finish \u2713 \u2713 \u2713 Baseline Start \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713 Timephased Baseline1 Cost \u2713 Timephased Baseline1 Work \u2713 Timephased Baseline2 Cost \u2713 Timephased Baseline2 Work \u2713 Timephased Baseline3 Cost \u2713 Timephased Baseline3 Work \u2713 Timephased Baseline4 Cost \u2713 Timephased Baseline4 Work \u2713 Timephased Baseline5 Cost \u2713 Timephased Baseline5 Work \u2713 Timephased Baseline6 Cost \u2713 Timephased Baseline6 Work \u2713 Timephased Baseline7 Cost \u2713 Timephased Baseline7 Work \u2713 Timephased Baseline8 Cost \u2713 Timephased Baseline8 Work \u2713 Timephased Baseline9 Cost \u2713 Timephased Baseline9 Work \u2713 Timephased Baseline10 Cost \u2713 Timephased Baseline10 Work \u2713 Timephased Baseline Cost \u2713 Timephased Baseline Work \u2713"},{"location":"field-guide/#custom-fields_2","title":"Custom Fields","text":"Field Asta (PP) ConceptDraw PROJECT (CDP) Deltek OpenPlan (BK3) FastTrack (FTS) GanttDesigner (GNT) GanttProject (GAN) Merlin (SQLITE) Microsoft (MPD) Microsoft (MPP) Microsoft (MPX) Microsoft (MSPDI) P3 (BTRIEVE) Phoenix (PPX) Planner (XML) Primavera (PMXML) Primavera (SQLITE) Primavera (XER) Project Commander (PC) ProjectLibre (POD) SDEF (SDEF) Sage (SCHEDULE_GRID) SureTrak (STW) Synchro (SP) TurboProject (PEP) Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"howto-build/","title":"Building MPXJ","text":"

Although MPXJ can be downloaded as a complete package from Maven, GitHub and SourceForge, the development of the library continues between releases and is driven by user requests for new functionality and bug fixes being applied to existing features. Many MPXJ users will work with and ship software based on intermediate versions of MPXJ built from the code on GitHub in order to take advantage of these enhancements before they become available in an official release. This approach is supported by the fact that code is only pushed to the master branch on GitHub if the suite of regression tests have been completed successfully: therefore the quality of the code taken from GitHub at any point can normally be guaranteed to be as good as that in an official release.

In order to take advantage of MPXJ functionality from GitHub, you will need to understand how to build the library, whether you are using it in the form of a Java JAR or a .NET DLL. The following sections explain how to do this.

"},{"location":"howto-build/#obtaining-the-source","title":"Obtaining the source","text":"

The first step in the process of building your own version of MPXJ is to obtain the latest source from GitHub. Instructions for cloning the repository can be found on this page.

"},{"location":"howto-build/#building-the-java-jar","title":"Building the Java JAR","text":"

MPXJ is built using Maven. Once you have a cloned copy of the MPXJ repository, you may wish to update the groupId, artifactId or version attributes in pom.xml. This will ensure that there is no confusion between the version of MPXJ you build and the official distributions.

If you have a copy of Maven installed, you can issue the following command to build MPXJ:

mvn -DskipTests=true -Dmaven.javadoc.skip=true -Dsource.skip=true package\n

This will generate the mpxj.jar for you in the Maven target directory, and copies MPXJ's dependencies to the lib directory. Note that for convenience this skips running the unit tests, javadoc generation and source packaging.

If you are using Maven to manage dependencies for your own project, you can install your newly built version of MPXJ in a local Maven repository:

mvn -DskipTests=true -Dmaven.javadoc.skip=true -Dsource.skip=true install\n
"},{"location":"howto-build/#building-for-net-python-and-ruby","title":"Building for .Net, Python and Ruby","text":"

Aside from using Maven to build the MPXJ jar file, building the other release artifacts for MPXJ is a somewhat involved process. To assist with this I have created a script which will configure a freshly installed Windows 10 machine ready to be used to build all the components of an MPXJ release.

The script and its instructions can be found here.

"},{"location":"howto-build/#generating-the-jaxb-code","title":"Generating the JAXB code","text":"

In order to read and write various XML file formats, MPXJ relies on code generated by the JAXB tool xjc from the XML schema for each file format. Normally you will not need to regenerate this source, but if you are changing the JAXB implementation, or modifying the use of JAXB in some way, then you may need to regenerate this code.

Where I have created an XML schema to support a particular file format, I have included it in the MPXJ distribution in the jaxb directory. For XML schemas published by product vendors, I have included a note on the home page indicating where these can be located.

If you obtain a copy of the XML schema file you want to work with, you can update the JAXB source using the xjc target found in the ant build.xml file. Note that the xjc target is platform specific, you will need to change the name of xjc tool to be xjc.bat, xjc.exe, or xjc.sh depending on your operating system. You will also need to set the properties indicated in build.xml to tell it where to find xjc and the XML schema file. If you are only regenerating source for one of the XML schemas, you can comment out the others in the Ant script to avoid unnecessary work.

"},{"location":"howto-com/","title":"Getting Started with COM","text":"

Deprecated. Only supported until MPXJ version 14.

The .Net Framework assemblies provided in the DLLs described here are accessible from COM. This should allow you to, for example, write VBA code which utilises MPXJ functionality. To assist with this, for each of the DLLs distributed with MPXJ type libraries in the form of TLB files are provided in the src.net\\lib\\net45 directory. You will also need to register the MPXJ assemblies in order to use them from COM, using the regasm assembly registration tool.

For your convenience two batch files have been provided in the src.net\\lib\\net45 directory: mpxj-register-assemblies.bat and mpxj-unregister-assemblies.bat. These batch files will register and unregister the MPXJ assemblies respectively. These batch files assume that regasm is available on the path.

"},{"location":"howto-convert/","title":"Converting Files","text":"

To convert project data between different formats you read the source data using an appropriate Reader class, then write the data using a Writer class which matches the format you want to convert to.

MPXJ can do a lot of the work for you, as the example below illustrates. The UniversalProjectReader will detect the type of schedule being read and handle it accordingly. The UniversalProjectWriter class manages the individual writer classes for you, taking an argument representing the type of file you want to write.

JavaC#Python
package org.mpxj.howto.convert;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class ConvertUniversal\n{\n   public void convert(String inputFile, FileFormat format, String outputFile) throws Exception\n   {\n      ProjectFile projectFile = new UniversalProjectReader().read(inputFile);\n      new UniversalProjectWriter(format).write(projectFile, outputFile);\n   }\n}\n
using MPXJ.Net;\n\npublic class ConvertUniversal\n{\n    public void Convert(string inputFile, FileFormat format, string outputFile)\n    {\n        var projectFile = new UniversalProjectReader().Read(inputFile);\n        new UniversalProjectWriter(format).Write(projectFile, outputFile);\n    }\n}\n
import jpype\nimport mpxj\n\njpype.startJVM()\n\nfrom net.sf.mpxj.reader import UniversalProjectReader\nfrom net.sf.mpxj.writer import FileFormat\nfrom net.sf.mpxj.writer import UniversalProjectWriter\n\ndef convert(input_file, format, output_file):\n    project_file = UniversalProjectReader().read(input_file);\n    UniversalProjectWriter(format).write(project_file, output_file);\n\njpype.shutdownJVM()\n

If you already know the file types you are converting between, you can use the specific Reader and Writer classes, as shown below.

JavaC#Python
package org.mpxj.howto.convert;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\nimport net.sf.mpxj.mpx.MPXWriter;\nimport net.sf.mpxj.reader.ProjectReader;\nimport net.sf.mpxj.writer.ProjectWriter;\n\npublic class ConvertMppToMpx\n{\n   public void convert(String inputFile, String outputFile) throws Exception\n   {\n      ProjectReader reader = new MPPReader();\n      ProjectFile projectFile = reader.read(inputFile);\n\n      ProjectWriter writer = new MPXWriter();\n      writer.write(projectFile, outputFile);\n   }\n}\n
using MPXJ.Net;\n\npublic class ConvertMppToMpx\n{\n    public void Convert(string inputFile, string outputFile)\n    {\n        var reader = new MPPReader();\n        var projectFile = reader.Read(inputFile);\n\n        var writer = new MPXWriter();\n        writer.Write(projectFile, outputFile);\n    }\n}\n
import jpype\nimport mpxj\n\njpype.startJVM()\n\nfrom net.sf.mpxj.mpp import MPPReader\nfrom net.sf.mpxj.mpx import MPXWriter\n\ndef convert(input_file, output_file):\n    reader = MPPReader()\n    project_file = reader.read(input_file)\n    writer = MPXWriter()\n    writer.write(project_file, output_file)\n\njpype.shutdownJVM()\n
"},{"location":"howto-dotnet/","title":"Getting Started with .Net","text":"

There are three different ways of adding MPXJ to your .Net project. In each case tool called IKVM is being used to convert the original Java version of MPXJ into .Net assemblies.

"},{"location":"howto-dotnet/#mpxjnet","title":"MPXJ.Net","text":"

This is the recommended approach.

The MPXJ.Net NuGet package provides a .Net wrapper around MPXJ's Java API. You will work with objects which use standard C# naming conventions, and expose native .Net types and data structures. The original Java nature of MPXJ is completely hidden from you. This is the preferred way to work with MPXJ. Just add the MPXJ.Net NuGet package to your project as a dependency and you can get started.

Note that your project will take longer than normal to build when first built using the MPXJ.Net package. As part of the build process the Java version of MPXJ is being dynamically translated into .Net assemblies. The results of this translation will be reused, so subsequent build times will return to normal. You may also see various transient warning messages as the first build completes. These can be ignored and will disappear once your project has finished building.

"},{"location":"howto-dotnet/#ikvmmavensdk","title":"IKVM.Maven.Sdk","text":"

Documented for completeness. Use the MPXJ.Net package instead..

IKVM provides an extension to SDK-style .Net projects called IKVM.Maven.SDK which allows you to refer to a Java library using Maven (the most common dependency management solution for Java projects). This means that your .Net project will be working directly with the original Java version of the library, which will automatically be translated into .Net assemblies for you as you build your project.

To include MPXJ in your project using this approach, edit your project file and include the following lines:

<ItemGroup>\n  <PackageReference Include=\"IKVM.Maven.Sdk\" Version=\"1.6.9\" />\n  <MavenReference Include=\"net.sf.mpxj:mpxj\" Version=\"13.0.0\"/>\n</ItemGroup>\n

The <PackageReference> tag enables IKVM's Maven integration functionality. The <MavenReference> tag uses this integration to request from Maven the version of MPXJ you'd like to use.

By using this approach you are working with MPXJ's Java API \"as is\", so you will need to deal with Java types, data structures, and naming conventions. In most cases you will find it more productive to work with the MPXJ.Net package described above. This approach is documented for completeness, but is not recommended.

Note that your project will take longer than normal to build when first built using IKVM.Maven.Sdk. As part of the build process the Java version of MPXJ is being dynamically translated into .Net assemblies. The results of this translation will be reused, so subsequent build times will return to normal. You may also see various transient warning messages as the first build completes. These can be ignored and will disappear once your project has finished building.

"},{"location":"howto-dotnet/#legacy-ikvm","title":"Legacy IKVM","text":"

Deprecated. Do Not Use. Only supported until MPXJ version 14.

The original .Net version of MPXJ was created using a legacy version of IKVM. The assemblies for this version are shipped as part of the MPXJ distribution and are available from NuGet as the following packages:

  • net.sf.mpxj direct translation of MPXJ
  • net.sf.mpxj-for-csharp translation of MPXJ with properties and methods following C# naming conventions
  • net.sf.mpxj-for-vb translation of MPXJ with properties and methods following C# naming conventions with some adjustments to accommodate VB's lack of case sensitivity
"},{"location":"howto-dotnet/#sample-code","title":"Sample Code","text":"

There is a repository containing sample .Net code for MPXJ covering use of the library in more depth. This repository can be found here.

"},{"location":"howto-read-asta/","title":"How To: Read Asta Powerproject and Easyproject files","text":"

Asta Powerproject and Asta Easyproject both use PP files.

"},{"location":"howto-read-asta/#reading-pp-files","title":"Reading PP files","text":"

The simplest way to read a PP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Asta\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Asta\n{\n     public void Read()\n     {\n          var reader = new UniversalProjectReader();\n          var project = reader.Read(\"my-sample.pp\");\n     }\n}\n

You can work directly with the AstaFileReader by replacing UniversalProjectReader with AstaFileReader, although this offers no particular advantage as there are no additional configuration settings available on the AstaFileReader class.

A note on password protected files: Powerproject offers the option of saving schedules with a username and password, which results in the file being encrypted. MPXJ doesn't support these files, and unfortunately I haven't come up with a way of reliably identifying that these are password protected PP files. If you pass a file like this to one of the the UniversalProjectReader read methods, it will simply return null, indicating an unsupported file type.

"},{"location":"howto-read-conceptdraw/","title":"How To: Read ConceptDraw PROJECT files","text":"

ConceptDraw PROJECT writes CDPX, CPDZ and CPDTZ files.

"},{"location":"howto-read-conceptdraw/#reading-cdpx-cpdz-and-cpdtz-files","title":"Reading CDPX, CPDZ and CPDTZ files","text":"

The simplest way to read a CDPX, CPDZ or CPDTZ file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ConceptDraw\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.cdpx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ConceptDraw\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.cdpx\");\n    }\n}\n

You can work directly with the ConceptDrawProjectReader by replacing UniversalProjectReader with ConceptDrawProjectReader, although this offers no particular advantage as there are no additional configuration settings available on the ConceptDrawProjectReader class.

"},{"location":"howto-read-fasttrack/","title":"How To: Read FastTrack Schedule files","text":"

FastTrack Schedule writes schedule data to FTS files. Note that MPXJ has only been tested with FTS files produced by FastTrack 10.

"},{"location":"howto-read-fasttrack/#reading-fts-files","title":"Reading FTS files","text":"

The simplest way to read an FTS file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class FastTrack\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.fts\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class FastTrack\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.fts\");\n    }\n}\n

You can work directly with the FastTrackReader by replacing UniversalProjectReader with FastTrackReader, although this offers no particular advantage as there are no additional configuration settings available on the FastTrackReader class.

"},{"location":"howto-read-ganttdesigner/","title":"How To: Read Gantt Designer files","text":"

Gantt Designer writes schedule data to GNT files.

"},{"location":"howto-read-ganttdesigner/#reading-gnt-files","title":"Reading GNT files","text":"

The simplest way to read a GNT file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class GanttDesigner\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.gnt\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class GanttDesigner\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.gnt\");\n    }\n}\n

You can work directly with the GanttDesignerReader by replacing UniversalProjectReader with GanttDesignerReader, although this offers no particular advantage as there are no additional configuration settings available on the GanttDesignerReader class.

"},{"location":"howto-read-ganttproject/","title":"How To: Read GanttProject files","text":"

GanttProject writes schedule data to GAN files (which are actually just XML files).

"},{"location":"howto-read-ganttproject/#reading-gan-files","title":"Reading GAN files","text":"

The simplest way to read a GAN file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class GanttProject\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.gan\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class GanttProject\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.gan\");\n    }\n}\n

You can work directly with the GanttProjectReader by replacing UniversalProjectReader with GanttProjectReader, although this offers no particular advantage as there are no additional configuration settings available on the GanttProjectReader class.

"},{"location":"howto-read-merlin/","title":"How To: Read Merlin files","text":"

Merlin Project is a Mac application. MPXJ provides experimental support for reading some Merlin Project files. The Merlin file format does not necessarily contain a full set of start and finish dates for each task. Merlin calculates these dates when it displays a schedule. At the moment MPXJ lacks this functionality, so you may not find start and finish dates for each task.

"},{"location":"howto-read-merlin/#reading-merlin-files","title":"Reading Merlin files","text":"

The simplest way to read a Merlin file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Merlin\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample-merlin-project\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Merlin\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample-merlin-project\");\n    }\n}\n

Note that on a Mac Merlin projects are not single files, but rather they are directories containing multiple files (the Mac Finder normally hides this from you). When using MPXJ to read a Merlin project you pass the directory name to the UniversalProjectReader class.

You can work directly with the MerlinReader by replacing UniversalProjectReader with MerlinReader, although this offers no particular advantage as there are no additional configuration settings available on the MerlinReader class.

"},{"location":"howto-read-mpd-database/","title":"How To: Read MPD Databases","text":"

Microsoft Project from Project 98 until Project 2003 could read and write schedules as Microsoft Access database files with the extension MPD. Versions of Microsoft Project after 2003 can import projects from MPD databases but cannot create or write to them. Project 98 creates a database with a schema known as MPD8, which MPXJ does not currently support reading. Project 2000 onward uses a schema called MPD9 which MPXJ can read.

Microsoft Project Server originally shared the same database schema as the MPD9 file format. This means that the MPDDatabaseReader class described below may also be used to read data from a Project Server SQL Server database.

"},{"location":"howto-read-mpd-database/#reading-mpd-databases","title":"Reading MPD databases","text":"

The preferred way to read MPD files is using UniversalProjectReader or the MPDFileReader reader. as described in the How To Read MPD files section.

You can if you wish read an MPD file via a database connection. Typically you will need the JDBC-ODBC bridge driver, or an equivalent JDBC driver which can work with a Microsoft Access database.

"},{"location":"howto-read-mpd-database/#setting-the-database-connection","title":"Setting the database connection","text":"

The MPDDatabaseReader class provides two methods: setConnection and setDataSource which allows you to supply a JDBC Connection instance or a JDBC DataSource instance.

"},{"location":"howto-read-mpd-database/#selecting-a-project","title":"Selecting a project","text":"

If the MPD file contains multiple projects, you can retrieve details of the available projects using the listProjects method. This returns a map of project IDs and project names. The sample code below illustrates how to retrieve this list of projects, and select the specific project that you want to read. In this case we read each project in the file in turn.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.mpd.MPDDatabaseReader;\nimport java.sql.Connection;\nimport java.util.Map;\n\npublic class MPDDatabase\n{\n   public void read(Connection connection) throws Exception\n   {\n      MPDDatabaseReader reader = new MPDDatabaseReader();\n      reader.setConnection(connection);\n      Map<Integer, String> projects = reader.listProjects();\n      for (Map.Entry<Integer, String> entry : projects.entrySet())\n      {\n         System.out.println(\"Project name: \" + entry.getValue());\n         reader.setProjectID(entry.getKey());\n         reader.read();\n      }\n   }\n}\n
"},{"location":"howto-read-mpd/","title":"How To: Read MPD files","text":"

Microsoft Project from Project 98 until Project 2003 could read and write schedules as Microsoft Access database files with the extension MPD. Versions of Microsoft Project after 2003 can import projects from MPD databases but cannot create or write to them. Project 98 creates a database with a schema known as MPD8, which MPXJ does not currently support reading. Project 2000 onward uses a schema called MPD9 which MPXJ can read.

"},{"location":"howto-read-mpd/#reading-mpd-files","title":"Reading MPD files","text":"

The simplest way to read an MPD file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MPDFile\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.mpd\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPDFile\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.mpd\");\n    }\n}\n

Note that the UniversalProjectReader.Read() method assumes that you are reading a project with ID of 1 from the MPD file. This is the default when a single project is written to an MPD file. Calling the ReadAll method will return all of the projects in the MPD file.

"},{"location":"howto-read-mpd/#using-mpdfilereader","title":"Using MPDFileReader","text":"

You can work directly with the MPDFileReader by replacing UniversalProjectReader with MPDFileReader. The sample code below illustrates how the reader can be used to retrieve a list of the projects in the file via the listProjects method. We can then select the ID of the project we want to read and use the setProjecID method to pass this to the reader. Finally, calling the read method reads the required project.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpd.MPDFileReader;\n\nimport java.io.File;\nimport java.util.Map;\n\npublic class MPDFileWithReader\n{\n    public void read() throws Exception\n    {\n        File file = new File(\"my-sample.mpd\");\n        MPDFileReader reader = new MPDFileReader();\n\n        // Retrieve the project details\n        Map<Integer, String> projects = reader.listProjects(file);\n\n        // Look up the project we want to read from the map.\n        // For this example we'll just use a hard-coded value.\n        Integer projectID = Integer.valueOf(1);\n\n        // Set the ID f the project we want to read\n        reader.setProjectID(projectID);\n\n        // Read the project\n        ProjectFile project = reader.read(file);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPDFileWithReader\n{\n    public void Read()\n    {\n        var reader = new MPDFileReader();\n\n        // Retrieve the project details\n        var projects = reader.ListProjects(\"my-sample.mpd\");\n\n        // Look up the project we want to read from the map.\n        // For this example we'll just use a hard-coded value.\n        var projectID = 1;\n\n        // Set the ID f the project we want to read\n        reader.ProjectID = projectID;\n\n        // Read the project\n        var project = reader.Read(\"my-sample.mpd\");\n    }\n}\n
"},{"location":"howto-read-mpp/","title":"How To: Read MPP files","text":"

The native Microsoft Project file format is typically has the extension MPP (or MPT for a template file). Although a common file extension uis used, there are actually a number if different variants of the file format. The list below shows the different variants, and the versions of Microsoft Project which produce them:

  • MPP8 - Project 98
  • MPP9 - Project 2000 and Project 2002
  • MPP12 - Project 2003, Project 2007
  • MPP14 - Project 2010 and all later versions
"},{"location":"howto-read-mpp/#reading-mpp-files","title":"Reading MPP files","text":"

The simplest way to read an MPP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MPP\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPP\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#using-mppreader","title":"Using MPPReader","text":"

You can work directly with the MPPReader class by replacing UniversalProjectReader with MPPReader. This provides access to additional options, as described below.

"},{"location":"howto-read-mpp/#password-protected-files","title":"Password Protected Files","text":"

When a read password has been set for an MPP file, the contents of the file are partially encrypted. If you attempt to read an MPP file which has been password protected an MPXJException will be raised, with the message File is password protected.

MPXJ only supports decryption of password protected MPP9 files. The code below illustrates how you would supply the password:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPWithPassword\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setReadPassword(\"my secret password\");\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPWithPassword\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.ReadPassword = \"my secret password\";\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n

The encryption used by MPP9 files doesn't actually require the password in order to read the contents of the file. If you wish you can set a flag to ignore the MPP9 password protection.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPIgnorePassword\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setRespectPasswordProtection(false);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPIgnorePassword\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.RespectPasswordProtection = false;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#presentation-data","title":"Presentation Data","text":"

Alongside the schedule data itself, MPXJ also extracts much of the presentation data available in an MPP file, for example table layouts, filters, graphical indicators and so on. If you are not interested in this type of data, you can tell MPXJ not to read it. This will speed up reading MPP files, and slightly reduce memory consumption. To do this you will use the setReadPresentationData method, as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPPresentationData\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setReadPresentationData(false);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPPresentationData\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.ReadPresentationData = false;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#properties-only","title":"Properties Only","text":"

Should you wish to simply \"peek\" at the contents of the MPP file by just reading the summary properties from the file, you can use the setReadPropertiesOnly method as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPPropertiesOnly\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setReadPropertiesOnly(true);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPPropertiesOnly\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.ReadPropertiesOnly = true;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpp/#raw-timephased-data","title":"Raw timephased data","text":"

When MPXJ reads timephased data from an MPP file it \"normalises\" the data, converting it from the compact format Microsoft Project uses internally into a representation which shows the timephased values day-by-day. This is generally easier to understand, and can be further processed using the methods in the TimephasedUtility class to show the data over the required timescale.

If you do not want MPXJ to normalise the data, and would prefer instead to work with the raw data directly from the MPP file, you can use the setUseRawTimephasedData to do this, as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpp.MPPReader;\n\npublic class MPPRawTimephased\n{\n    public void read() throws Exception\n    {\n        MPPReader reader = new MPPReader();\n        reader.setUseRawTimephasedData(true);\n        ProjectFile project = reader.read(\"my-sample.mpp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPPRawTimephased\n{\n    public void Read()\n    {\n        var reader = new MPPReader();\n        reader.UseRawTimephasedData = true;\n        var project = reader.Read(\"my-sample.mpp\");\n    }\n}\n
"},{"location":"howto-read-mpx/","title":"How To: Read MPX files","text":"

Versions of Microsoft Project up to Project 98 could read and write MPX files as a data interchange format. Versions of Project after Project 98 until Project 2010 can only read MPX files. Versions of Microsoft Project after 2010 cannot read MPX files. Other third party project planning applications continue to use MPX as a data interchange format.

"},{"location":"howto-read-mpx/#reading-mpx-files","title":"Reading MPX files","text":"

The simplest way to read an MPX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MPX\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.mpx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPX\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.mpx\");\n    }\n}\n
"},{"location":"howto-read-mpx/#using-mpxreader","title":"Using MPXReader","text":"

You can work directly with the MPXReader class by replacing UniversalProjectReader with MPXReader. This provides access to additional options, as described below.

"},{"location":"howto-read-mpx/#locale","title":"Locale","text":"

It appears that very early in the life of the MPX file format, Microsoft Project was internationalised to allow versions of the application to be used in languages other than English. One unfortunate side effect of this was that the text used in the MPX file format was also internationalised. Thus rather than having a single file format which could be exchanged globally between any applications, you now need to know which internationalised version of Microsoft Project was used to create the MPX file in order to read it successfully.

Fortunately in most cases MPX files have been generated using the English language version of Microsoft Project, or an application which generates this variant, so the default settings for MPXReader will work.

If you encounter an MPX file generated by something other than an English version of Microsoft Project, you'll need to explicitly set the locale in order to read the file. The sample below shows how this is done:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXReader;\n\nimport java.util.Locale;\n\npublic class MPXWithLocale\n{\n    public void read() throws Exception\n    {\n        MPXReader reader = new MPXReader();\n        reader.setLocale(Locale.GERMAN);\n        ProjectFile project = reader.read(\"my-sample.mpx\");\n    }\n}\n
using System.Globalization;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPXWithLocale\n{\n    public void Read()\n    {\n        var reader = new MPXReader();\n        reader.Culture = CultureInfo.GetCultureInfo(\"de\");\n        var project = reader.Read(\"my-sample.mpx\");\n    }\n}\n

The following locales are supported by MPXReader:

  • English
  • German
  • Spanish
  • French
  • Italian
  • Portuguese
  • Russian
  • Swedish
  • Chinese

You can retrieve a list of supported locales programmatically using the code shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.mpx.MPXReader;\n\nimport java.util.Locale;\n\npublic class MPXSupportedLocales\n{\n    public void read() throws Exception\n    {\n        Locale[] locales = MPXReader.getSupportedLocales();\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPXSupportedLocales\n{\n    public void Read()\n    {\n        var cultures = MPXReader.SupportedCultures;\n    }\n}\n
"},{"location":"howto-read-mpx/#ignore-text-models","title":"Ignore Text Models","text":"

You should not normally need to modify this option.

An MPX file consists of a series of sections with each section representing a specific entity, for example tasks, resources, and so on. The set of attributes written for each entity is not fixed, instead at the start of each section the attributes which appear in the file are listed in two forms: as a series of numeric values, and as a series on human-readable attribute names.

Originally MPXJ used to read both of these lists, however it was found that the human-readable attribute names were often not consistent and caused problems when attempting to read MPX files. The default now is that these attributes are ignored. If for some reason you should wish to enable MPXJ's original behaviour and read these files, you would call setIgnoreTextModels as shown in the example below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXReader;\n\npublic class MPXIgnoreTextModels\n{\n    public void read() throws Exception\n    {\n        MPXReader reader = new MPXReader();\n        reader.setIgnoreTextModels(false);\n        ProjectFile project = reader.read(\"my-sample.mpx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MPXIgnoreTextModels\n{\n    public void Read()\n    {\n        var reader = new MPXReader();\n        reader.IgnoreTextModels = false;\n        var project = reader.Read(\"my-sample.mpx\");\n    }\n}\n
"},{"location":"howto-read-mspdi/","title":"How To: Read MSPDI files","text":"

The Microsoft Project Data Interchange (MSPDI) format is an XML file format which Microsoft Project has been able to read and write since Project 2002.

"},{"location":"howto-read-mspdi/#reading-mspdi-files","title":"Reading MSPDI files","text":"

The simplest way to read an MSPDI file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class MSDPI\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDI\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-mspdi/#using-mspdireader","title":"Using MSPDIReader","text":"

You can work directly with the MSPDIReader class by replacing UniversalProjectReader with MSPDIReader. This provides access to additional options, as described below.

"},{"location":"howto-read-mspdi/#charset","title":"Charset","text":"

By default MPXJ assumes that MSPDI files are encoded as UTF-8. The UniversalProjectReader understands Unicode Byte Order Marks (BOM) and will adjust the encoding appropriately if a BOM is present. If you have an MSPDI file with an unusual encoding, you can manually set the encoding used by the reader, as illustrated below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIReader;\n\nimport java.nio.charset.Charset;\n\npublic class MSPDIWithCharset\n{\n    public void read() throws Exception\n    {\n        MSPDIReader reader = new MSPDIReader();\n\n        reader.setCharset(Charset.forName(\"GB2312\"));\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using System.Text;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDIWithLocale\n{\n    public void Read()\n    {\n        var reader = new MSPDIReader();\n        reader.Encoding = Encoding.GetEncoding(\"GB2312\");\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-mspdi/#microsoft-project-compatibility","title":"Microsoft Project Compatibility","text":"

Microsoft Project will read MSPDI files which are not valid XML according to the MSPDI schema. By default MPXJ has been configured to take the same approach. If for some reason you wish to apply strict validation when reading an MSPDI file, you can do this using the setMicrosoftProjectCompatibleInput method, as shown below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIReader;\n\npublic class MSPDICompatibleInput\n{\n    public void read() throws Exception\n    {\n        MSPDIReader reader = new MSPDIReader();\n        reader.setMicrosoftProjectCompatibleInput(false);\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDICompatibleInput\n{\n    public void Read()\n    {\n        var reader = new MSPDIReader();\n        reader.MicrosoftProjectCompatibleInput = false;\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-mspdi/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from an MSPDI file. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the MSPDIReader to report errors encountered when reading a file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIReader;\n\npublic class MSPDIIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        MSPDIReader reader = new MSPDIReader();\n\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class MSPDIIgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new MSPDIReader();\n        reader.IgnoreErrors = false;\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-openplan/","title":"How To: Deltek Open Plan BK3 files","text":"

Deltek Open Plan is a planning tool for Windows which can store schedule data in a variety of databases, and export schedules to BK3 files.

"},{"location":"howto-read-openplan/#reading-open-plan-files","title":"Reading Open Plan files","text":"

The simplest way to read an Open Plan file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class OpenPlan\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.bk3\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class OpenPlan\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.bk3\");\n    }\n}\n

You can work directly with the OpenPlanReader by replacing UniversalProjectReader with OpenPlanReader, although this offers no particular advantage as there are no additional configuration settings available on the OpenPlanReader class.

"},{"location":"howto-read-p3/","title":"How To: Read P3 files","text":"

A Primavera P3 installation stores project data as a database consisting of a number of individual files. In a typical P3 installation files for a number of different projects live in a single projects directory. A P3 user can back up an individual project to create a PRX file, which is a compressed archive containing all of the files from a single project.

"},{"location":"howto-read-p3/#reading-prx-files","title":"Reading PRX files","text":"

The simplest way to read a PRX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class P3\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.prx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P3\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.prx\");\n    }\n}\n

You can work directly with the P3PRXFileReader by replacing UniversalProjectReader with P3PRXFileReader, although this offers no particular advantage as there are no additional configuration settings available on the P3PRXFileReader class.

"},{"location":"howto-read-p3/#reading-a-p3-directory","title":"Reading a P3 directory","text":"

If you are working with a directory containing P3 project data you have two options. If you know that the directory only contains a single project, you can use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class P3Directory\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-p3-directory\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P3Directory\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-p3-directory\");\n    }\n}\n

If the directory happens to contain multiple projects the UniversalProjectReader will simply read the first one it finds, in alphabetic order.

If you know that the directory you are working with contains multiple projects, you will need to use the P3DatabaseReader class.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.p3.P3DatabaseReader;\n\nimport java.util.List;\n\npublic class P3NamedProject\n{\n    public void read() throws Exception\n    {\n        // Find a list of the project names\n        String directory = \"my-p3-directory\";\n        List<String> projectNames = P3DatabaseReader.listProjectNames(directory);\n\n        // Tell the reader which project to work with\n        P3DatabaseReader reader = new P3DatabaseReader();\n        reader.setProjectName(projectNames.get(0));\n\n        // Read the project\n        ProjectFile project = reader.read(directory);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P3NamedProject\n{\n    public void Read()\n    {\n        // Find a list of the project names\n        var directory = \"my-p3-directory\";\n        var projectNames = P3DatabaseReader.ListProjectNames(directory);\n\n        // Tell the reader which project to work with\n        var reader = new P3DatabaseReader();\n        reader.ProjectName = projectNames[0];\n\n        // Read the project\n        var project = reader.Read(directory);\n    }\n}\n

As the example above shows, the P3DatabaseReader class provides a method which lists the names of the P3 projects it finds in a directory. You can then select which project you want to load, and call the setProjectName method of the reader to make this selection. You can then call the read method passing in the name of the directory, and the reader will extract data for the selected project.

"},{"location":"howto-read-phoenix/","title":"How To: Read Phoenix Project Manager files","text":"

Phoenix Project Manager uses PPX files.

"},{"location":"howto-read-phoenix/#reading-ppx-files","title":"Reading PPX files","text":"

The simplest way to read a PPX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Phoenix\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.ppx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Phoenix\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.ppx\");\n    }\n}\n

You can work directly with the PhoenixReader by replacing UniversalProjectReader with PhoenixReader, although this offers no particular advantage as there are no additional configuration settings available on the PhoenixReader class.

"},{"location":"howto-read-planner/","title":"How To: Read Planner files","text":"

Gnome Planner is a popular open source planning tool which writes its own XML files.

"},{"location":"howto-read-planner/#reading-planner-files","title":"Reading Planner files","text":"

The simplest way to read a Planner file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Planner\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Planner\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-samplexml\");\n    }\n}\n

You can work directly with the PlannerReader by replacing UniversalProjectReader with PlannerReader, although this offers no particular advantage as there are no additional configuration settings available on the PlannerReader class.

"},{"location":"howto-read-plf/","title":"How To: Read Primavera PLF files","text":"

Primavera P6 can export layout information as PLF files. These files define the visual appearance of the P6 user interface, and can be imported and exported by P6. Although MPXJ doesn't currently offer any facilities to interpret the contents of these files, the data they contain can be read.

"},{"location":"howto-read-plf/#reading-plf-files","title":"Reading PLF files","text":"

A PLF file contains \"structured text\" and can be read using StructuredTextParser:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.StructuredTextParser;\nimport net.sf.mpxj.primavera.StructuredTextRecord;\n\nimport java.io.FileInputStream;\n\npublic class PLF\n{\n   public void read() throws Exception\n   {\n      StructuredTextParser parser = new StructuredTextParser();\n      StructuredTextRecord record = parser.parse(new FileInputStream(\"test.plf\"));\n   }\n}\n
"},{"location":"howto-read-plf/#attributes","title":"Attributes","text":"

The resulting StructuredTextRecord contains attributes which can be accesed individually by name, as shown below:

record.getAttribute(\"attribute_name\");\n

The attributes can also be retrieved in the form of a Map containing all attributes for this record:

Map<String,String> attributes = record.getAttributes();\nattributes.get(\"attribute_name\");\n

Each record has two special attributes: a record number, and optionally a record name. These appear as part of the identifying information for each record, not as part of the general set of attributes for the record. These can be retrieved as shown below:

String recordNumber = record.getRecordNumber();\nString recordName = record.getRecordName();\n

These attributes will also be found in the attributes Map with the keys _record_number and _record_name.

"},{"location":"howto-read-plf/#child-records","title":"Child records","text":"

Along with a set of attributes, each StructuredTextRecord may have child StructuredTextRecord instances. These be retrieved as a list, as shown below:

List<StructuredTextRecord> childRecords = record.getChildren();\n

Certain record types are named, and where this is the case a child record can be retrieved individually by name:

StructuredTextRecord child = record.getChild(\"child_name\");\n
"},{"location":"howto-read-pmxml/","title":"How To: Read Primavera PMXML files","text":"

Primavera P6 can export data in an XML format known as PMXML.

"},{"location":"howto-read-pmxml/#reading-pmxml-files","title":"Reading PMXML files","text":"

The simplest way to read a PMXML file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class PMXML\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXML\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-pmxml/#using-primaverapmfilereader","title":"Using PrimaveraPMFileReader","text":"

You can work directly with the PrimaveraPMFileReader by replacing UniversalProjectReader with PrimaveraPMFileReader. This provides access to additional options, as described below.

"},{"location":"howto-read-pmxml/#multiple-projects","title":"Multiple Projects","text":"

A PMXML file can contain multiple projects. By default, MPXJ reads the first non-external project it finds in the file, otherwise it defaults to the first project it finds. You can however use MPXJ to list the projects contained in a PMXML file, as shown below:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\nimport java.io.FileInputStream;\nimport java.util.Map;\n\npublic class PMXMLListProjects\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        FileInputStream is = new FileInputStream(\"my-sample.xml\");\n        Map<Integer, String> projects = reader.listProjects(is);\n        System.out.println(\"ID\\tName\");\n        for (Map.Entry<Integer, String> entry : projects.entrySet())\n        {\n            System.out.println(entry.getKey()+\"\\t\"+entry.getValue());\n        }\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXMLListProjects\n{\n    public void Read()\n    {\n        var reader = new PrimaveraPMFileReader();\n        var stream = new FileStream(\"my-sample.xml\",\n            FileMode.Open, FileAccess.Read, FileShare.None);\n        var projects = reader.ListProjects(stream);\n        System.Console.WriteLine(\"ID\\tName\");\n        foreach (var entry in projects)\n        {\n                System.Console.WriteLine($\"{entry.Key}\\t{entry.Value}\");\n        }\n    }\n}\n

The call to listProjects returns a Map whose key is the project ID, and the values are project short names.

Once you have decided which of these projects you want to work with, you can call setProjectID to tell the reader which project to open, as shown below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\npublic class PMXMLProjectID\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        reader.setProjectID(123);\n        ProjectFile file = reader.read(\"my-sample.xml\");\n    }\n}\n

Alternatively you can ask MPXJ to read all the projects contained in the file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\nimport java.util.List;\n\npublic class PMXMLReadAll\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        List<ProjectFile> files = reader.readAll(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXMLReadAll\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.ReadAll(\"my-sample.xml\");\n    }\n}\n

The call to the readAll method returns a list of ProjectFile instances corresponding to the projects in the PMXML file.

Note that when calling the readAll method for a PMXML file, the list of projects returned will include baseline projects. You can determine which projects are baseline projects by calling the ProjectProperties method getProjectIsBaseline(), which will return true for baseline projects.

"},{"location":"howto-read-pmxml/#link-cross-project-relations","title":"Link Cross-Project Relations","text":"

A PMXML file can contain multiple projects with relations between activities which span those projects. By default, these cross-project relations are ignored. However, if you set the linkCrossProjectRelations reader attribute to true, MPXJ will attempt to link these relations across projects:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\n\nimport java.util.List;\n\npublic class PMXMLLinkCrossProject\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        reader.setLinkCrossProjectRelations(true);\n        List<ProjectFile> files = reader.readAll(\"my-sample.xml\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class PMXMLLinkCrossProject\n{\n    public void Read()\n    {\n        var reader = new PrimaveraPMFileReader();\n        reader.LinkCrossProjectRelations = true;\n        var files = reader.ReadAll(\"my-sample.xml\");\n    }\n}\n
"},{"location":"howto-read-pmxml/#baselines","title":"Baselines","text":"

Users can export PMXML files from P6 which contain the baseline project along with the main project being exported. When the readAll method is used to read a PMXML file, MPXJ will attempt to populate the baseline fields of the main project if it can locate the baseline project in the PMXML file.

By default the \"Planned Dates\" strategy is used to populate baseline fields, which is the approach P6 uses when the \"Earned Value Calculation\" method is set to \"Budgeted values with planned dates\".

PrimaveraPMFileReader provides a method allowing the strategy to be changed, thus allowing you to select the \"Current Dates\" strategy, which is the approach used by P6 when the Earned Value Calculation method is set to \"At Completion values with current dates\" or \"Budgeted values with current dates\". The example below illustrates how this method is used:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileReader;\nimport net.sf.mpxj.primavera.PrimaveraBaselineStrategy;\n\nimport java.util.List;\n\npublic class PMXMLBaselines\n{\n    public void read() throws Exception\n    {\n        PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\n        reader.setBaselineStrategy(PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES);\n        List<ProjectFile> files = reader.readAll(\"my-sample.xml\");\n    }\n}\n

See the How To Use Baselines section for more information on how MPXJ works with baselines.

"},{"location":"howto-read-primavera/","title":"How To: Read a Primavera P6 database","text":"

Primavera P6 supports the use of SQLite, SQL Server and Oracle databases. SQLite is a single file database, and in common with the other file-based schedule formats MPXJ provides a reader class. To read schedules from SQL Server and Oracle databases you will need to use a JDBC connection with MPXJ. These approaches are described in the sections below.

"},{"location":"howto-read-primavera/#sqlite","title":"SQLite","text":"

The PrimaveraDatabaseFileReader provides convenient access to P6 schedules stored as a SQLite database. By default P6 will create a database called PPMDBSQLite.db in the Windows user's My Documents folder. The example code below illustrates how we'd list the schedules in this file, and reda one of those schedules using it ID.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseFileReader;\n\nimport java.io.File;\nimport java.util.Map;\n\npublic class P6Sqlite\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseFileReader reader = new PrimaveraDatabaseFileReader();\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        File file = new File(\"PPMDBSQLite.db\");\n        Map<Integer,String> projects = reader.listProjects(file);\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.setProjectID(selectedProjectID);\n        ProjectFile projectFile = reader.read(file);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6Sqlite\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseFileReader();\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        var file = \"PPMDBSQLite.db\";\n        var projects = reader.ListProjects(file);\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.ProjectID = selectedProjectID;\n        var projectFile = reader.Read(file);\n    }\n}\n
"},{"location":"howto-read-primavera/#jdbc-in-java","title":"JDBC in Java","text":"

For P6 schedules hosted in either a SQL Server databases or an Oracle database, we must use a JDBC driver with the PrimaveraDatabaseReader reader in order to access this data. In this example we're reading a schedule from a SQL Server database using Microsoft's JDBC driver. This code assumes that you have added the JDBC driver as a dependency to your Java project.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.util.Map;\n\npublic class P6JDBC\n{\n    public void read() throws Exception\n    {\n        //\n        // Load the JDBC driver\n        //\n        String driverClass=\"com.microsoft.sqlserver.jdbc.SQLServerDriver\";\n        Class.forName(driverClass);\n\n        //\n        // Open a database connection. You will need to change\n        // these details to match the name of your server, database, user and password.\n        //\n        String connectionString=\"jdbc:sqlserver://localhost:1433;databaseName=my-database-name;user=my-user-name;password=my-password;\";\n        Connection c = DriverManager.getConnection(connectionString);\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setConnection(c);\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        Map<Integer,String> projects = reader.listProjects();\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.setProjectID(selectedProjectID);\n        ProjectFile projectFile = reader.read();\n    }\n}\n
"},{"location":"howto-read-primavera/#jdbc-in-net","title":"JDBC in .Net","text":"

The approach for reading schedule data from a SQL Server or Orcale database is very similar to that used with the Java version. The main difference is how we add the JDBC driver to our project as a dependency. To do this we add a MavenReference to our project. The example below show how I have added this just after the reference to the MPXJ.Net package:

<ItemGroup>\n    <PackageReference Include=\"MPXJ.Net\" Version=\"13.0.0\" />\n    <MavenReference Include=\"com.microsoft.sqlserver:mssql-jdbc\" Version=\"12.6.2.jre8\" />\n</ItemGroup>\n

Note that the IKVM's conversion of Java code to .Net being works by implementing a Java 8 (sometimes also known as a Java 1.8) virtual machine. If you have a choice of Java packages to use which are targeted at different Java versions, select the Java 8 version - as illustrated in the example above.

Now we can use the JDBC driver to create a connection to our database, as the sample code below illustrates.

using com.microsoft.sqlserver.jdbc;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6JDBC\n{\n    public void Read()\n    {\n        //\n        // Load the JDBC driver\n        //\n        var driver = new SQLServerDriver();\n\n        //\n        // Open a database connection. You will need to change\n        // these details to match the name of your server, database, user and password.\n        //\n        var connectionString = \"jdbc:sqlserver://localhost:1433;databaseName=my-database-name;user=my-user-name;password=my-password;\";\n        var connection = driver.connect(connectionString, null);\n        var reader = new PrimaveraDatabaseReader();\n        reader.Connection = connection;\n\n        //\n        // Retrieve a list of the projects available in the database\n        //\n        var projects = reader.ListProjects();\n\n        //\n        // At this point you'll select the project\n        // you want to work with.\n        //\n\n        //\n        // Now open the selected project using its ID\n        //\n        int selectedProjectID = 1;\n        reader.ProjectID = selectedProjectID;\n        var projectFile = reader.Read();\n    }\n}\n
"},{"location":"howto-read-primavera/#options","title":"Options","text":"

This section documents the additional options provided by the PrimaveraDatabaseReader.

"},{"location":"howto-read-primavera/#activity-wbs","title":"Activity WBS","text":"

In the original implementation of the database handling code, MPXJ would assign each task representing a Primavera Activity its own distinct WBS value. This does not match Primavera's behaviour where all of a WBS element's child activities will have the same WBS value as the parent WBS element. MPXJ's default behaviour now matches Primavera, but should you wish to you can revert to the original behaviour by calling the setMatchPrimaveraWBS as shown below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\npublic class P6ActivityWbs\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setMatchPrimaveraWBS(false);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6ActivityWbs\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseReader();\n        reader.MatchPrimaveraWBS = false;\n    }\n}\n
"},{"location":"howto-read-primavera/#wbs-is-full-path","title":"WBS is Full Path","text":"

Currently, the WBS attribute of summary tasks (WBS entities in P6) will be a dot separated hierarchy of all the parent WBS attributes. In this example, root.wbs1.wbs2 is the WBS attribute for wbs2 which has the parents root and wbs1. To disable this behaviour, and simply record the code for the current WBS entry (in the example above wbs2) call the setWbsIsFullPath method, passing in false, as illustrated below.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\npublic class P6WbsFullPath\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setWbsIsFullPath(false);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6WbsFullPath\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseReader();\n        reader.WbsIsFullPath = false;\n    }\n}\n
"},{"location":"howto-read-primavera/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from a Primavera database. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the PrimaveraDatabaseReader to report errors encountered when reading from a Primavera database:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\npublic class P6IgnoreErrors\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        reader.setIgnoreErrors(false);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class P6IgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new PrimaveraDatabaseReader();\n        reader.IgnoreErrors = false;\n    }\n}\n

Note that if errors are ignored when reading from a Primavera database, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-primavera/#reading-additional-attributes","title":"Reading Additional Attributes","text":"

A data-driven approach is used to extract the attributes used by MPXJ from the database. You can if you wish change the way attributes are read from the file, or add support for additional attributes. This assumes that you know the column name of the attributes you want to work with in the database. To make changes you will need to retrieve the maps which define which MPXJ attributes are used to store which columns from the database:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\nimport java.util.Map;\n\npublic class P6AttributeMaps\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        Map<FieldType, String> resourceFieldMap = reader.getResourceFieldMap();\n        Map<FieldType, String> wbsFieldMap = reader.getWbsFieldMap();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n        Map<FieldType, String> assignmentFieldMap = reader.getAssignmentFieldMap();\n    }\n}\n

These maps will contain the default mapping between columns and MPXJ attributes. You can modify these existing mappings, or add new ones, for example:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.TaskField;\nimport net.sf.mpxj.primavera.PrimaveraDatabaseReader;\n\nimport java.util.Map;\n\npublic class P6AttributeConfig\n{\n    public void read() throws Exception\n    {\n        PrimaveraDatabaseReader reader = new PrimaveraDatabaseReader();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n\n        //\n        // Store rsrc_id in NUMBER1\n        //\n        activityFieldMap.put(TaskField.NUMBER1, \"rsrc_id\");\n\n        //\n        // Read an Activity column called an_example_field and store it in TEXT10\n        //\n        activityFieldMap.put(TaskField.TEXT10, \"an_example_field\");\n    }\n}\n
"},{"location":"howto-read-projectcommander/","title":"How To: Read Project Commander files","text":"

Project Commander is a planning tool for Windows which writes its own PC file format.

"},{"location":"howto-read-projectcommander/#reading-project-commander-files","title":"Reading Project Commander files","text":"

The simplest way to read a Project Commander file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ProjectCommander\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pc\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ProjectCommander\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.pc\");\n    }\n}\n

You can work directly with the ProjectCommanderReader by replacing UniversalProjectReader with ProjectCommanderReader, although this offers no particular advantage as there are no additional configuration settings available on the ProjectCommanderReader class.

"},{"location":"howto-read-projectlibre/","title":"How To: Read ProjectLibre files","text":"

ProjectLibre writes schedule data to POD files. MPXJ can read POD files written by ProjectLibre version 1.5.5 and later versions.

"},{"location":"howto-read-projectlibre/#reading-pod-files","title":"Reading POD files","text":"

The simplest way to read a POD file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ProjectLibre\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pod\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ProjectLibre\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.pod\");\n    }\n}\n

You can work directly with the ProjectLibreReader by replacing UniversalProjectReader with ProjectLibreReader, although this offers no particular advantage as there are no additional configuration settings available on the ProjectLibreReader class.

"},{"location":"howto-read-schedule-grid/","title":"How To: Read Schedule Grid files","text":"

Schedule grid files are produced when a schedule is exported from Sage 100 Contractor.

"},{"location":"howto-read-schedule-grid/#reading-schedule-grid-files","title":"Reading Schedule Grid files","text":"

The simplest way to read a schedule grid file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ScheduleGrid\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.schedule_grid\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ScheduleGrid\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.schedule_grid\");\n    }\n}\n
"},{"location":"howto-read-schedule-grid/#using-sagereader","title":"Using SageReader","text":"

You can work directly with the SageReader class by replacing UniversalProjectReader with SageReader. This provides access to additional options, as described below.

"},{"location":"howto-read-schedule-grid/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from a Schedule Grid file. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the SageReader to report errors encountered when reading a file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.sage.SageReader;\n\npublic class ScheduleGridIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        SageReader reader = new SageReader();\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.schedule_grid\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class ScheduleGridIgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new SageReader();\n        reader.IgnoreErrors = false;\n        var project = reader.Read(\"my-sample.schedule_grid\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-sdef/","title":"How To: Read SDEF files","text":"

The Standard Data Exchange Format (SDEF) is the US Army Corps of Engineers standard format for exchanging schedule data between systems. The definition of this format can be found here.

"},{"location":"howto-read-sdef/#reading-sdef-files","title":"Reading SDEF files","text":"

The simplest way to read an SDEF file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SDEF\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.sdef\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SDEF\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.sdef\");\n    }\n}\n
"},{"location":"howto-read-sdef/#using-sdefreader","title":"Using SDEFReader","text":"

You can work directly with the SDEFReader class by replacing UniversalProjectReader with SDEFReader. This provides access to additional options, as described below.

"},{"location":"howto-read-sdef/#ignore-errors","title":"Ignore Errors","text":"

By default MPXJ will ignore errors when parsing attributes from an SDEF file. This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the SDEFReader to report errors encountered when reading a file:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.sdef.SDEFReader;\n\npublic class SDEFIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        SDEFReader reader = new SDEFReader();\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.sdef\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SDEFIgnoreErrors\n{\n    public void Read()\n    {\n        var reader = new SDEFReader();\n        reader.IgnoreErrors = false;\n        var project = reader.Read(\"my-sample.sdef\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-suretrak/","title":"How To: Read SureTrak files","text":"

A Primavera SureTrak installation stores project data as a database consisting of a number of individual files. In a typical SureTrak installation files for a number of different projects live in a single projects directory. A SureTrak user can back up an individual project to create an STX file, which is a compressed archive containing all of the files from a single project.

"},{"location":"howto-read-suretrak/#reading-stx-files","title":"Reading STX files","text":"

The simplest way to read an STX file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SureTrak\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.stx\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SureTrak\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.stx\");\n    }\n}\n

You can work directly with the SureTrakSTXFileReader by replacing UniversalProjectReader with SureTrakSTXFileReader, although this offers no particular advantage as there are no additional configuration settings available on the SureTrakSTXFileReader class.

"},{"location":"howto-read-suretrak/#reading-a-suretrak-directory","title":"Reading a SureTrak directory","text":"

If you are working with a directory containing SureTrak project data you have two options. If you know that the directory only contains a single project, you can use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SureTrakDirectory\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-suretrak-directory\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SureTrakDirectory\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-suretrak-directory\");\n    }\n}\n

If the directory happens to contain multiple projects the UniversalProjectReader will simply read the first one it finds, in alphabetic order.

If you know that the directory you are working with contains multiple projects, you will need to use the SureTrakDatabaseReader class.

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.suretrak.SureTrakDatabaseReader;\n\nimport java.util.List;\n\npublic class SureTrakListProjects\n{\n    public void read() throws Exception\n    {\n        // Find a list of the project names\n        String directory = \"my-suretrak-directory\";\n        List<String> projectNames = SureTrakDatabaseReader.listProjectNames(directory);\n\n        // Tell the reader which project to work with\n        SureTrakDatabaseReader reader = new SureTrakDatabaseReader();\n        reader.setProjectName(projectNames.get(0));\n\n        // Read the project\n        ProjectFile project = reader.read(directory);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class SureTrakListProjects\n{\n    public void Read()\n    {\n        // Find a list of the project names\n        var directory = \"my-suretrak-directory\";\n        var projectNames = SureTrakDatabaseReader.ListProjectNames(directory);\n\n        // Tell the reader which project to work with\n        var reader = new SureTrakDatabaseReader();\n        reader.ProjectName = projectNames[0];\n\n        // Read the project\n        var project = reader.Read(directory);\n    }\n}\n

As the example above shows, the SureTrakDatabaseReader class provides a method which lists the names of the SureTrak projects it finds in a directory. You can then select which project you want to load, and call the setProjectName method of the reader to make this selection. You can then call the read method passing in the name of the directory, and the reader will extract data for the selected project.

"},{"location":"howto-read-synchro/","title":"How To: Read Synchro Scheduler files","text":"

Synchro Scheduler writes SP files.

"},{"location":"howto-read-synchro/#reading-sp-files","title":"Reading SP files","text":"

The simplest way to read an SP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class Synchro\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.sp\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class Synchro\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.sp\");\n    }\n}\n

You can work directly with the SynchroReader by replacing UniversalProjectReader with SynchroReader, although this offers no particular advantage as there are no additional configuration settings available on the SynchroReader class.

"},{"location":"howto-read-turboproject/","title":"How To: Read TurboProject files","text":"

TurboProject writes schedule data to PEP files.

"},{"location":"howto-read-turboproject/#reading-pep-files","title":"Reading PEP files","text":"

The simplest way to read a PEP file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class TurboProject\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.pep\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class TurboProject\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.pep\");\n    }\n}\n

You can work directly with the TurboProjectReader by replacing UniversalProjectReader with TurboProjectReader, although this offers no particular advantage as there are no additional configuration settings available on the TurboProjectReader class.

"},{"location":"howto-read-xer/","title":"How To: Read XER files","text":"

The XER file format has long been read and written by Primavera P6. Although an XML file format (PMXML) is now also supported, the XER file format is still widely used.

"},{"location":"howto-read-xer/#reading-xer-files","title":"Reading XER files","text":"

The simplest way to read an XER file is to use the UniversalProjectReader:

JavaC#
package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class XER\n{\n    public void read() throws Exception\n    {\n        UniversalProjectReader reader = new UniversalProjectReader();\n        ProjectFile project = reader.read(\"my-sample.xer\");\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToRead;\n\npublic class XER\n{\n    public void Read()\n    {\n        var reader = new UniversalProjectReader();\n        var project = reader.Read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#using-primaveraxerfilereader","title":"Using PrimaveraXERFileReader","text":"

You can work directly with the PrimaveraXERFileReader class by replacing UniversalProjectReader with PrimaveraXERFileReader. This provides access to additional options, as described below.

"},{"location":"howto-read-xer/#ignore-errors","title":"Ignore Errors","text":"

By default P6 ignores records it can't successfully read from an XER file. MPXJ takes the same approach, and in most cases if it doesn't receive the data it expects for a particular record it will ignore the problematic item.

This behavior is controlled using the setIgnoreErrors method. The example below illustrates how we can force the PrimaveraXERFileReader to report errors encountered when reading a file:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERIgnoreErrors\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setIgnoreErrors(false);\n        ProjectFile project = reader.read(\"my-sample.xer\");\n    }\n}\n

Note that if errors are ignored when reading a file, the ignored errors are available by using the ProjectFile.getIgnoredErrors() method.

"},{"location":"howto-read-xer/#charset","title":"Charset","text":"

By default MPXJ assumes that XER files use the Windows-1252 Charset. The UniversalProjectReader understands Unicode Byte Order Marks (BOM) and will adjust the Charset appropriately if a BOM is present. If you have an XER file with an unusual encoding, you can manually set the Charset used by the reader.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.nio.charset.Charset;\n\npublic class XERCharset\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setCharset(Charset.forName(\"GB2312\"));\n        ProjectFile project = reader.read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#multiple-projects","title":"Multiple Projects","text":"

An XER file can contain multiple projects. By default MPXJ reads the first project it finds in the file which has been marked as the \"exported\" project, otherwise it will simply read the first project it finds. You can however use MPXJ to list the projects contained in an XER file, as shown below:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.io.FileInputStream;\nimport java.util.Map;\n\npublic class XERListProjects\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        FileInputStream is = new FileInputStream(\"my-sample.xer\");\n        Map<Integer, String> projects = reader.listProjects(is);\n        System.out.println(\"ID\\tName\");\n        for (Map.Entry<Integer, String> entry : projects.entrySet())\n        {\n            System.out.println(entry.getKey()+\"\\t\"+entry.getValue());\n        }\n    }\n}\n
The call to listProjects returns a Map whose key is the project ID, and the values are project short names.

Once you have decided which of these projects you want to work with, you can call setProjectID to tell the reader which project to open, as shown below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERProjectID\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setProjectID(123);\n        ProjectFile file = reader.read(\"my-sample.xer\");\n    }\n}\n

Alternatively you can ask MPXJ to read all of the projects contained in the file:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.List;\n\npublic class XERReadAll\n{\n   public void read() throws Exception\n   {\n      PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n      List<ProjectFile> files = reader.readAll(\"my-sample.xer\");\n   }\n}\n

The call to the readAll method returns a list of ProjectFile instances corresponding to the projects in the XER file.

"},{"location":"howto-read-xer/#link-cross-project-relations","title":"Link Cross-Project Relations","text":"

An XER file can contain multiple projects with relations between activities which span those projects. By default these cross-project relations are ignored. However, if you set the linkCrossProjectRelations reader attribute to true, MPXJ will attempt to link these relations across projects:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.List;\n\npublic class XERLinkCrossProject\n{\n   public void read() throws Exception\n   {\n      PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n      reader.setLinkCrossProjectRelations(true);\n      List<ProjectFile> files = reader.readAll(\"my-sample.xer\");\n   }\n}\n
"},{"location":"howto-read-xer/#activity-wbs","title":"Activity WBS","text":"

In the original implementation of the XER file handling code, MPXJ would assign each task representing a Primavera Activity its own distinct WBS value. This does not match Primavera's behaviour where all of a WBS element's child activities will have the same WBS value as the parent WBS element. MPXJ's default behaviour now matches Primavera, but should you wish to you can revert to the original behaviour by calling the setMatchPrimaveraWBS as shown below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERMatchWbs\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setMatchPrimaveraWBS(false);\n        ProjectFile file = reader.read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#wbs-is-full-path","title":"WBS is Full Path","text":"

Currently the WBS attribute of summary tasks (WBS entities in P6) will be a dot separated hierarchy of all of the parent WBS attributes. In this example, root.wbs1.wbs2 is the WBS attribute for wbs2 which has the parents root and wbs1. To disable this behaviour, and simply record the code for the current WBS entry (in the example above wbs2) call the setWbsIsFullPath method, passing in false, as illustrated below.

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\npublic class XERWbsFullPath\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        reader.setWbsIsFullPath(false);\n        ProjectFile file = reader.read(\"my-sample.xer\");\n    }\n}\n
"},{"location":"howto-read-xer/#reading-additional-attributes","title":"Reading Additional Attributes","text":"

A data-driven approach is used to extract the attributes used by MPXJ from the XER file. You can if you wish change the way attributes are read from the file, or add support for additional attributes. This assumes that you know the column name of the attributes you want to work with in the XER file. To make changes you will need to retrieve the maps which define which MPXJ attributes are used to store which columns from the XER file:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.Map;\n\npublic class XERAttributeMaps\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        Map<FieldType, String> resourceFieldMap = reader.getResourceFieldMap();\n        Map<FieldType, String> wbsFieldMap = reader.getWbsFieldMap();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n        Map<FieldType, String> assignmentFieldMap = reader.getAssignmentFieldMap();\n    }\n}\n

These maps will contain the default mapping between columns and MPXJ attributes. You can modify these existing mappings, or add new ones, for example:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.TaskField;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.Map;\n\npublic class XERAttributeConfig\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n\n        //\n        // Store rsrc_id in NUMBER1\n        //\n        activityFieldMap.put(TaskField.NUMBER1, \"rsrc_id\");\n\n        //\n        // Read an Activity column called an_example_field and store it in TEXT10\n        //\n        activityFieldMap.put(TaskField.TEXT10, \"an_example_field\");\n    }\n}\n

When reading new columns from the XER file, if these columns have a type other than String, it is important to register the type of the column to ensure that it is converted correctly. You will also need to ensure that the MPXJ attribute you are writing this new value to can receive the data type you are assigning to it (for example, you must store a date in a date attribute, you can't store a date in an integer attribute).

For example, if we are reading an integer column called an_example_id and store it in the NUMBER2 attribute, we will need to take the following steps:

package org.mpxj.howto.read;\n\nimport net.sf.mpxj.DataType;\nimport net.sf.mpxj.FieldType;\nimport net.sf.mpxj.TaskField;\nimport net.sf.mpxj.primavera.PrimaveraXERFileReader;\n\nimport java.util.Map;\n\npublic class XERRegisterType\n{\n    public void read() throws Exception\n    {\n        PrimaveraXERFileReader reader = new PrimaveraXERFileReader();\n        Map<String, DataType> fieldTypeMap = reader.getFieldTypeMap();\n        fieldTypeMap.put(\"an_example_id\", DataType.INTEGER);\n        Map<FieldType, String> activityFieldMap = reader.getActivityFieldMap();\n        activityFieldMap.put(TaskField.NUMBER2, \"an_example_id\");\n    }\n}\n
"},{"location":"howto-start-java/","title":"Getting Started with Java","text":"

MPXJ is built to work with versions of Java from 1.8 onwards. For many people, the easiest way to get started with MPXJ and its dependencies is to use Maven. Just include the following in your POM to register MPXJ as a dependency of your project:

<dependency>\n  <groupId>net.sf.mpxj</groupId>\n  <artifactId>mpxj</artifactId>\n  <version>13.0.0</version>\n</dependency>\n

The traditional method of downloading the MPXJ distribution as a zip file can also be used. Distributions can be found at GitHub and SourceForge.

The zip files contain all of the source, the MPXJ JAR file in the root of the zip file, with the libraries on which MPXJ depends being found in the lib directory of the zip file. These libraries will need to be available on your classpath in order to use all of the MPXJ functionality. The script directory in the zip file contains a batch file and a shell script which show how this can be done.

You'll find a general introduction to MPXJ's functionality here.

"},{"location":"howto-start-python/","title":"Getting Started with Python","text":"

MPXJ is available as a Python Package, which can be installed using pip:

pip install mpxj\n

You can find some documentation for the Package here. You'll need Java installed to make use of this package.

You'll find a general introduction to MPXJ's functionality here.

"},{"location":"howto-start-ruby/","title":"Getting Started with Ruby","text":"

MPXJ is available as a RubyGem, which can be installed using gem:

gem install mpxj\n

or included in you Gemfile and installed using bundler.

Note that the Ruby version of MPXJ is just a wrapper around the Java library, and provides read-only access to schedule data. You will need Java installed to make use of this Gem. You can find some documentation for the Gem here

You'll find a general introduction to MPXJ's functionality here.

"},{"location":"howto-start/","title":"MPXJ Basics","text":"

The MPXJ library allows various formats of Microsoft Project file formats, and file formats from other project planning applications to be read and written using a single consistent API in Java, .Net, Python or any other related languages, and provides read-only access as a Ruby gem.

MPXJ is based around a \"neutral\" data structure which is used to represent project data, coupled with a set of format-specific reader and writer classes which understand how to read from and write to the various supported file formats.

The diagram below illustrates the key entities represented by the MPXJ data structure.

MPXJ currently allows project data to be read from a wide variety of schedule file formats and databases. You can find details of the individual file formats supported elsewhere in the documentation. By far the easiest way to read schedule data is to use the \"universal project reader\" which can determine for itself the type of file you have passed to it.

ProjectReader reader = new UniversalProjectReader ();\nProjectFile project = reader.read(\"example.mpp\");\n

A similar arrangement exists for the writer classes, although there is not a \"universal project writer\" as such:

  • net.sf.mpxj.mpx.MPXWriter: writes Microsoft MPX files
  • net.sf.mpxj.mspdi.MSPDIWriter: writes Microsoft MSPDI (XML) files
  • net.sf.mpxj.planner.PlannerWriter: writes Planner (XML) files
  • net.sf.mpxj.sdef.SDEFWriter: writes SDEF files
  • net.sf.mpxj.primavera.PrimaveraPMFileWriter: writes Primavera PMXML (XML) files
  • net.sf.mpxj.json.JsonWriter: writes JSON files (primarily used to support the Ruby version of MPXJ)

All of these classes implement the ProjectWriter interface. If you know which type of file you are working with, you can use these writers directly, for example:

ProjectWriter writer = new MPXWriter();\nwriter.write(project, \"example.mpx\");\n
"},{"location":"howto-start/#tasks-and-resources","title":"Tasks and Resources","text":"

Once you've read your project file, what next? The first things of interest are the tasks and resources which are present in the file.

ProjectReader reader = new UniversalProjectReader ();\nProjectFile project = reader.read(\"example.mpp\");\nfor (Resource resource : project.getAllResources())\n{\n   System.out.println(\"Resource: \" + resource.getName()\n      + \" (Unique ID=\" + resource.getUniqueID() + \")\");\n}\n

The code fragment above shows how we can retrieve a collection containing all of the resources present in the file, and iterate through them printing the resource name, ID and unique ID.

Many of the entities represented in MPXJ have some concept of a unique ID. Tasks and resources have two ID fields, the unique ID, which as its name suggests never changes and uniquely identifies a task or a resource, and the ID. The ID of a task or a resource is the sequential number which typically appears next to the task or resource when displayed in Microsoft Project. If the task or resource is moved up or down the list, this number will change depending on the position in the list. The unique ID never changes.

ProjectReader reader = new UniversalProjectReader ();\nProjectFile project = reader.read(\"example.mpp\");\nfor (Task task : project.getAllTasks())\n{\n   System.out.println(\"Task: \" + task.getName() + \" ID=\" + task.getID()\n      + \" Unique ID=\" + task.getUniqueID());\n}\n

The code fragment above retrieves all tasks present in the file and prints details of their names, IDs, and unique IDs.

Methods are provided on the project to locate both tasks and resource using either their ID or their Unique ID, as the examples below illustrate.

Resource r = project.getResourceByUniqueID(Integer.valueOf(99));\nTask t = project.getTaskByUniqueID(Integer.valueOf(99));\n

The methods shown above for retrieving all tasks present in a project file ignores the hierarchical task structure which Microsoft Project allows users to create. To understand the hierarchical task structure, the following methods are used to descend through the hierarchy, starting from the top.

List<Task> tasks = project.getChildTasks();\nTask task = tasks.get(0);\ntasks = task.getChildTasks();\n

These methods are used in the following code fragment to print out an indented list representing the task hierarchy in the file.

public void listHierarchy(ProjectFile file)\n{\n   for (Task task : file.getChildTasks())\n   {\n      System.out.println(\"Task: \" + task.getName());\n      listHierarchy(task, \" \");\n   }\n\n   System.out.println();\n}\n\nprivate void listHierarchy(Task task, String indent)\n{\n   for (Task child : task.getChildTasks())\n   {\n      System.out.println(indent + \"Task: \" + child.getName());\n      listHierarchy(child, indent + \" \");\n   }\n}\n

As well as the hierarchical relationships between tasks, there is also a temporal relationship between them: this is typically used to indicate when a task can start in relation to the completion of an earlier task. The code fragment below shows the predecessor relationships between tasks.

for (Task task : file.getAllTasks())\n{\n   List<Relation> predecessors = task.getPredecessors();\n   if (predecessors != null && !predecessors.isEmpty())\n   {\n      System.out.println(task.getName() + \" predecessors:\");\n      for (Relation relation : predecessors)\n      {\n         System.out.println(\"   Task: \" + file.getTaskByUniqueID(relation.getTaskUniqueID()).getName());\n         System.out.println(\"   Type: \" + relation.getType());\n         System.out.println(\"   Lag: \" + relation.getDuration());\n      }\n   }\n}\n
"},{"location":"howto-start/#resource-assignments","title":"Resource Assignments","text":"

Tasks and resources are related by resource assignments. There is a method available on the ProjectFile class which will retrieve all resource assignments in the file. This is used by the code fragment below to provide an overview of all assignments.

for (ResourceAssignment assignment : file.getAllResourceAssignments())\n{\n   Task task = assignment.getTask();\n   String taskName;\n   if (task == null)\n   {\n      taskName = \"(null task)\";\n   }\n   else\n   {\n      taskName = task.getName();\n   }\n\n   Resource resource = assignment.getResource();\n   String resourceName;\n   if (resource == null)\n   {\n      resourceName = \"(null resource)\";\n   }\n   else\n   {\n      resourceName = resource.getName();\n   }\n\n   System.out.println(\"Assignment: Task=\" + taskName + \" Resource=\" + resourceName);\n}\n

Resource assignments can also be retrieved on a task-by-task basis, as the code fragment below illustrates.

for (Task task : file.getAllTasks())\n{\n  System.out.println(\"Assignments for task \" + task.getName() + \":\");\n\n  for (ResourceAssignment assignment : task.getResourceAssignments())\n  {\n     Resource resource = assignment.getResource();\n     String resourceName;\n\n     if (resource == null)\n     {\n        resourceName = \"(null resource)\";\n     }\n     else\n     {\n        resourceName = resource.getName();\n     }\n\n     System.out.println(\"   \" + resourceName);\n  }\n}\n

Finally, resource assignments can be viewed on a resource-by-resource basis, as the following code fragment shows.

for (Resource resource : file.getAllResources())\n{\n   System.out.println(\"Assignments for resource \" + resource.getName() + \":\");\n\n   for (ResourceAssignment assignment : resource.getTaskAssignments())\n   {\n      Task task = assignment.getTask();\n      System.out.println(\"   \" + task.getName());\n   }\n}\n
"},{"location":"howto-start/#calendars","title":"Calendars","text":"

Calendars are used to define working and non-working time, and are one of the more complex structures defined as part of a project. They are in turn used to define the time period over which a task is scheduled. There are two types of calendar: base calendars and resource calendars. Each base calendar provides a complete definition of the working and non working time for each day of the week. Resource calendars are associated with individual resources. Each resource calendar is derived from a base calendar; resource calendars may be unmodified in which case it will appear to be identical to the underlying base calendar, or the resource calendar may modify the working and non-working days. In this case these changes are \"overlaid\" on top of the working and non-working times defined by the base calendar. The calendars defined in a project can be retrieved using the method call shown below.

List<ProjectCalendar> calendars = file.getCalendars();\n

Normally a task without resource assignments will be scheduled with reference to the \"Standard\" (default) calendar defined as part of the project. This is retrieved using the method calls shown below.

ProjectCalendar defaultCalendar = file.getDefaultCalendar();\n

It is also possible to associate a specific calendar with an individual task. The method call below shows the calendar associated with a task being retrieved.

ProjectCalendar taskCalendar = task.getCalendar();\n

Bearing in mind that one calendar may be derived from another, care must be taken when choosing the methods called on a calendar instance: some methods are used to retrieve attributes defined as part of that specific calendar only, while others are used to descend through the hierarchy of calendars until an \"actual\" value is retrieved. For example the getDays method will retrieve an array of flags indicating the working/non-working/default state of each day of the week as defined by the current calendar. The getDay method however will test the current calendar to see if it is a working or non-working day. If the flag in the current calendar is set to \"default\", the method will use the base calendar from which the current calendar is derived to determine if the day is working or non-working.

As noted above a calendar contains a set of flags which represent each day of the week, these indicate the day of the week is working non-working, or \"default\". Where a day is set as \"default\", the working time for that day is taken from the underlying base calendar, if it is a resource calendar, or uses the default values provided by Microsoft Project if it is a base calendar.

If a particular day is defined as a working day, then the calendar will also contain a set of working hours for that day. The working hours for a day are defined by an instance of the ProjectCalendarHours class. This contains a collection of LocalTimeRange instances which defined the start and end times of each working period during the day.

Alongside the flags which control whether a day is working or non-working, and the working hours for each day, each calendar defines a set of exceptions which are used to \"override\" the default working or non-working hours for individual days or entire date ranges. Methods are provided to allow a list of all exceptions defined by a calendar can be retrieved, or to retrieve the exception which covers an individual date. Calendar exceptions are represented by instances of the ProjectCalendarException class.

"},{"location":"howto-start/#timephased-data","title":"Timephased Data","text":"

Although resource assignments on their own describe which resources are assigned to which tasks, and how much work they are going to do, this does not necessarily tell us how much work a resource will be doing on any particular date. In order to find this information, you will need to consult the timephased resource assignment data.

Each resource assignment has a pair of methods allowing you to retrieve timephased data, as shown by the example code below.

List<TimephasedResourceAssignment> planned = assignment.getTimephasedPlanned();\nList<TimephasedResourceAssignment> complete = assignment.getTimephasedComplete();\n

Timephased resource assignment data is represented by instances of the TimephasedResourceAssignment class. This class is designed to provide a compact representation of the work carried out over ranges of days, rather than having to represent the work carried out on each individual day using a single class instance per day. Each TimephasedResourceAssignment defines four attributes: a start date, an end date, a total amount of work, and an amount of work per day.

For example, you may retrieve an instance of the TimephasedResourceAssignment class whose start and end date defines a five day period. The total work for the period is 40 hours, and the work per day is defined as 8 hours. This indicates that for the period in question, on each working day within the date range, 8 hours of work will be carried out. It is important to remember that non-working days are ignored, so for example if we have a 7 day period which spans a weekend, the total work could still be 40 hours, and the work per day 8 hours: only the 5 working days are allocated work, the non-working weekend days have zero hours of work performed.

The two lists defined above will contain multiple TimephasedResourceAssignment instances where different numbers of hours are worked on different days. Each contiguous range of dates where the same number of hours are worked in a day will be represented by one TimephasedResourceAssignment instance.

The two lists of timephased data represent completed (actual) work, and planned work respectively. These lists may overlap by a single day if they are being used to show a partially completed day's work. For example, during a normal 8 hour working day, if 4 hours of work has been completed, and 4 hours remains, then the list of completed timephased data will end with 4 hours of work which have been completed, and the planned work list will start with the 4 hours remaining on the same day.

"},{"location":"howto-use-baselines/","title":"How To: Use Baselines","text":"

One tool to assist measuring how a schedule has changed over time is to create a baseline. A baseline is a snapshot of a schedule taken at a point in time: in the future you can compare the current state of your schedule to this snapshot to help understand what has changed.

"},{"location":"howto-use-baselines/#baselines","title":"Baselines","text":""},{"location":"howto-use-baselines/#microsoft-project","title":"Microsoft Project","text":"

Microsoft Project captures a baseline by taking copies of a small set of attributes for tasks, resources and resource assignments. The main attributes captured for each of these entities are Work, Cost, Duration, Start and Finish. These attributes can be stored as one of 11 distinct baselines: one called simply \"Baseline\", and the rest labelled \"Baseline 1\" through to \"Baseline 10\". If we pick Duration as an example attribute, the baseline value for this attribute might appear as \"Baseline Duration\", \"Baseline 1 Duration\", \"Baseline 2 Duration\" and so on, depending on which set of baseline attributes you had chosen to capture your snapshot.

Capturing a baseline in Microsoft Project is as simple as selecting the \"Set Baseline\" menu option for the current project you are working with to take a new baseline.

You'll be prompted to select which baseline you'd like to populate (\"Baseline\", \"Baseline 1\", \"Baseline 2\" and so on), and whether you'd like to baseline the whole project or just selected tasks.

When you click OK, the attributes captured for a baseline by Microsoft Project will be copied to the equivalent baseline attributes.

Note that the baseline attributes you have captured as part of this process have no special properties: they can be edited once they have been captured, and no recalculation takes place if they are edited (for example, if you change a baseline duration of a task, the baseline finish date of the task won't change).

"},{"location":"howto-use-baselines/#primavera-p6","title":"Primavera P6","text":"

The approach taken by Microsoft Project to managing baselines is unusual: most other scheduling applications take an approach similar to that used by Primavera P6, which is to take a complete copy of the schedule at the point a baseline is made, and thus any part of the baseline schedule is available in future to be compared with the current schedule. Let's look at baselines in P6 in a little more detail.

Baselines are managed in P6 in two stages. The first stage is actually to capture a baseline, which is achieved by selecting the \"Maintain Baselines...\" menu option.

The dialog which opens allows you to create, update, or delete a baseline.

When a baseline is taken, although it is simply a copy of an existing project, the baseline itself is not visible as a normal project in P6 so you can't view or, and more importantly for us, export it. The Maintain Baselines dialog includes the option of \"restoring\" a baseline, which turns the baseline back into a normal project which you can view or export.

Once you have a baseline, you then need to \"assign\" it in order to tell P6 what you want to do with it by selecting the \"Assign Baselines...\" menu option we saw earlier. This menu option will open a dialog similar to the one shown below.

As you can see from the dialog, P6 recognizes four distinct baseline types: the Project Baseline, and the Primary, Secondary and Tertiary User Baselines.

Note that the User Baselines are not visible outside of P6, i.e. information about which baselines are assigned as user baselines does not appear in either PMXML or XER files exported from P6.

In a similar way to Microsoft Project, P6 allows attributes from these baselines to be shown alongside information from the current schedule.

The dialog shown above is being used to select the columns to display in the tabular part of the Gantt chart in P6. As you can see there four start and finish attributes shown here, corresponding to the Project Baseline (for example BL Project Start) and the User Baselines (for example, BL1 Start, BL2 Start and BL3 Start).

There is a \"special case\" baseline, and a slightly obscure setting in P6 which determines exactly which values are shown in these columns. The \"special case\" baseline is where \"<Current Project>\" is selected as the baseline. This value doesn't represent a baseline which has been taken from the current project, but instead tells P6 that it should display the \"planned\" attributes from the current schedule in any baseline columns the user adds to the Gantt chart. So for example, if \"<Current Project>\" has been selected as the Project Baseline, then the values in the \"BL Project Start\" column on the Gantt chart will be the same as the values in the \"Planned Start\" column.

Where an actual baseline taken from the project has been assigned, then the values which will be shown in the baseline columns will depend on the \"Earned Value Calculation\" setting from the P6 Admin Preference dialog.

If the \"Earned value calculation\" setting is \"Budgeted values with planned dates\", then the Planned dates from the selected baseline schedule are used to populate the baseline attributes in the current schedule (for example, BL Project Start in the current schedule will be populated by the Planned Start value from the baseline schedule). If the \"Earned value calculation\" setting is NOT \"Budgeted values with planned dates\", then the current dates from the selected baseline schedule are used to populate the baseline attributes (for example, BL Project Start in the current schedule will be populated by the Start value from the baseline schedule).

It's important to note that the \"Earned Value Calculation\" setting is NOT available in either PMXML or XER files exported from P6, so when presenting schedule data from these files types to an end user outside of P6, there is no way to automatically determine which are the correct baseline values to be displayed.

"},{"location":"howto-use-baselines/#asta-powerproject","title":"Asta Powerproject","text":"

Powerproject takes the same approach as P6 to capturing a baseline - an entire copy of the schedule is made. This copy can either be held as a separate file, or can be embedded within the main schedule file (note the \"Embed the baseline in the file\" option in the dialog shown below).

MPXJ can read baselines which have been embedded within the main schedule file, although as you will see in a later section, with a little more work you can attach a baseline from a separate file to the main schedule.

"},{"location":"howto-use-baselines/#mpxj","title":"MPXJ","text":""},{"location":"howto-use-baselines/#microsoft-project_1","title":"Microsoft Project","text":"

Using MPXJ to work with baseline data from an MPP or MSPDI file is straightforward as any baseline values are available directly from the task, resource and resource assignment classes. The example below illustrates this by retrieving the Start attribute of a task, and some of the Baseline Start attributes.

ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\nTask task = file.getTaskByID(Integer.valueOf(1));\n\nSystem.out.println(\"Start: \" + task.getStart());\nSystem.out.println(\"Baseline Start: \" + task.getBaselineStart());\nSystem.out.println(\"Baseline1 Start: \" + task.getBaselineStart(1));\nSystem.out.println(\"Baseline2 Start: \" + task.getBaselineStart(2));\n\n// ...\n\nSystem.out.println(\"Baseline10 Start: \" + task.getBaselineStart(10));\n

When a baseline is taken in Microsoft Project, the date on which the baseline was taken is recorded. This can be used to indicate which baselines are set, and when they were set, although this data is only available from MPP file, not MSPDI files. The example code below illustrates how baseline dates can be used:

ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\nProjectProperties props = file.getProjectProperties();\n\nfor (int baselineNumber=0; baselineNumber <= 10; baselineNumber++)\n{\n   LocalDateTime baselineDate;\n   String baselineLabel;\n\n   if (baselineNumber == 0)\n   {\n      baselineDate = props.getBaselineDate();\n      baselineLabel = \"Baseline\";\n   }\n   else\n   {\n      baselineDate = props.getBaselineDate(baselineNumber);\n      baselineLabel = \"Baseline \" + baselineNumber;\n   }\n\n   if (baselineDate == null)\n   {\n      System.out.println(baselineLabel + \" not set\");\n   }\n   else\n   {\n      System.out.println(baselineLabel + \" set on \" + baselineDate);\n   }\n}\n
"},{"location":"howto-use-baselines/#primavera-p6_1","title":"Primavera P6","text":"

Getting baseline data for a P6 schedule is slightly more complex than for a Microsoft Project schedule.

The first thing to note is that XER files do not contain baseline data. XER files do include the ID of the Project Baseline schedule (via the ProjectProperties.getBaselineProjectUniqueID() method) but nothing more. Note that if the Project Baseline ID value is zero, this indicates that the Project Baseline selected in P6 is \"<Current Project>\". If this is the case, MPXJ will populate the attributes for the default baseline from the planned attributes (for example a task's Baseline Start will be set to the task's Planned Start attribute). This matches the behavior of P6 when \"<Current Project>\" is selected as the Project Baseline, and it the only time any form of baseline data will be available when reading an XER file.

The easiest way to get baseline data other than \"<Current Project>\" for a P6 schedule is to export a PMXML file. As part of the export process, the export dialog shows a column allowing baselines to be selected for export:

This opens a dialog for you to make the selection. Note that multiple baselines may be selected for export:

When a PMXML file is read all of the projects exported including any baselines will be available as ProjectFile instances from the readAll method.

List<ProjectFile> projects = new UniversalProjectReader().readAll(\"sample-pmxml.xml\");\nSystem.out.println(\"The file contains \" + projects.size() + \" projects\");\n

Alongside providing access to the current schedules and any baselines in the file, MPXJ will also apply the same \"<Current Project>\" logic to PMXML files as to XER files: so if the ProjectProperties.getBaselineProjectUniqueID() method returns zero, MPXJ will automatically populate the attributes of the default baseline using values from the equivalent planned attributes (for example a task's Baseline Start will be set to the task's Planned Start attribute).

Where PMXML files differ from XER files is that if the unique ID of one of the exported baselines matches the ID of the Project Baseline attribute from another project, MPXJ will link the two projects, populate the attributes of the default baseline in the main project using the equivalent planned attributes from the baseline project, and will set the default baseline date in the main project to the baseline project's create date.

To link the baseline MPXJ has actually attached the baseline ProjectFile instance to the main schedule using the ProjectFile.setBaseline() method. As well as begin able to work the populated baseline attributes in the main schedule, you also have direct access to the baseline ProjectFile instance, as illustrated by the sample code below:

ProjectFile project = new UniversalProjectReader().read(\"sample-pmxml.xml\");\nProjectFile baseline = project.getBaseline();\n\nSystem.out.println(\"Current project name: \" + project.getProjectProperties().getName());\nSystem.out.println(\"Baseline project name: \" + baseline.getProjectProperties().getName());\n

MPXJ's default behavior when attaching a baseline to a project follows what P6 does when the the \"Earned value calculation\" configuration is set to \"Budgeted values with planned dates\". As noted earlier this setting is not available in XER or PMXML files, so there is currently no way to automatically select the correct approach. You can however change MPXJ's default behavior by using the ProjectFile.setBaselineStrategy() method. BaselineStrategy is an interface implemented by classes which will implement the mechanism used to match equivalent tasks from the main ProjectFile instance with tasks from a baseline ProjectFile instance, and then populate the baseline attributes of the tasks in the main schedule with attributes from the matching tasks in the baseline schedule.

MPXJ provides baseline strategy implementations matching the two approaches taken by P6, depending on the \"Earned value calculation\". The default strategy is represented by the constant PrimaveraBaselineStrategy.PLANNED_ATTRIBUTES, with the alternative approach represented by the constant PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES. The sample code below illustrates how this constant is used to alter MPXJ's behavior to match P6 when the earned value setting is not \"Budgeted values with planned dates\".

PrimaveraPMFileReader reader = new PrimaveraPMFileReader();\nreader.setBaselineStrategy(PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES);\nProjectFile file = reader.read(\"sample-pmxml.xml\");\n
"},{"location":"howto-use-baselines/#asta-powerproject_1","title":"Asta Powerproject","text":"

When reading an Asta Powerproject schedule MPXJ will read the main schedule, and if defined and embedded in the main schedule file, the current baseline schedule. MPXJ will populate the attributes of the default baseline in the main project using the equivalent attributes from the baseline project, and will set the default baseline date in the main project to the baseline project's create date.

Note that at present MPXJ does not read all available baselines from a Powerproject schedule. Feedback welcomed if the ability to read all baselines is desirable.

ProjectFile project = new UniversalProjectReader().read(\"sample.pp\");\nProjectFile baseline = project.getBaseline();\n\nSystem.out.println(\"Current project name: \" + project.getProjectProperties().getName());\nSystem.out.println(\"Baseline project name: \" + baseline.getProjectProperties().getName());\n
"},{"location":"howto-use-baselines/#manually-attached","title":"Manually Attached","text":"

As we saw in the previous section, MPXJ can attach a baseline ProjectFile instance to the main project, and populate the relevant baseline attributes in the main project. MPXJ will actually allow you to explicitly attach up to 11 baseline projects to a main project. Each project attached in this way will be used to populate the relevant baseline attributes (for example, Baseline Start, Baseline 1 Start, Baseline 2 Start, ... Baseline 10 Start). The limit of 11 attached baselines follows Microsoft Project's data model which allows up to 11 baselines to be recorded.

In this first example we can see that we are reading a main project and a single baseline file, and attaching the baseline as the \"default\" baseline. This means that attributes like Baseline Start, Baseline Finish and so on will be populated in the main schedule.

ProjectFile main = new UniversalProjectReader().read(\"main.pp\");\nProjectFile baseline = new UniversalProjectReader().read(\"baseline.pp\");\nmain.setBaseline(baseline);\n

This next example shows two baseline files being attached as Baseline 1 and Baseline 2, which means that the attributes Baseline 1 Start, Baseline 2 Start, Baseline 1 Finish, Baseline 2 Finish and so on will be populated.

ProjectFile main = new UniversalProjectReader().read(\"main.pp\");\nProjectFile baseline1 = new UniversalProjectReader().read(\"baseline1.pp\");\nProjectFile baseline2 = new UniversalProjectReader().read(\"baseline2.pp\");\nmain.setBaseline(baseline1, 1);\nmain.setBaseline(baseline2, 2);\n

You can retrieve a list of all attached baselines using the ProjectFile.getBaselines() method. Note that the returned list will always contain 11 items, some of which may be null if the corresponding baseline has not been set. You can also remove a baseline from the current schedule using one of the ProjectFile.clearBaseline() methods.

"},{"location":"howto-use-baselines/#baseline-tasks","title":"Baseline Tasks","text":"

As described above, when working with applications which store baselines as separate copies of the main schedule, MPXJ populates a set of baseline attributes on the Task class. For example Baseline Duration, Baseline Cost and so on will be populated from tasks in the linked baseline schedule. This aligns with how Microsoft Project works, and although in many cases these attributes provide enough information to be useful, there are still occasions when it would be best to have direct access to the baseline task from the original task. You are not then restricted by the baseline attributes provided by MPXJ, instead you can compare the two tasks in any way you choose.

Providing your ProjectFile instance has come from a file or database which includes a copy of the baseline schedule, or you have manually attached a baseline schedule to the ProjectFile instance, you can use the Task.getBaselineTask() methods to retrieve the baseline task for the current Task instance, as illustrated below.

ProjectFile project = new UniversalProjectReader().read(\"project-with-baseline.xml\");\nTask task = project.getTaskByUniqueID(1);\nTask baselineTask = task.getBaselineTask();\n

Note that if no baseline task is present for the task you are working with, the Task.getBaselineTask() methods will return null. This will always be the case for MPP files as Microsoft Project doesn't keep a separate copy of the baseline schedule.

"},{"location":"howto-use-baselines/#strategies","title":"Strategies","text":"

In an earlier section the use of baseline strategies was noted. Classes which implement the BaselineStrategy interface are used to control how tasks in the main and baseline schedule are matched, and which attributes are used to populate the relevant baseline attributes.

MPXJ provides three implementations of the BaselineStrategy interface:

  • DefaultBaselineStrategy
  • AstaBaselineStrategy
  • PrimaveraBaselineStrategy

The DefaultBaselineStrategy matches tasks based on their GUID attribute, and populates the main schedule's baseline attributes from their equivalent attributes in the baseline schedule, for example, Baseline Duration will be populated using the Duration attribute in the baseline schedule and so on. You don't need to create new instances of this strategy as static instance is provided as DefaultBaselineStrategy.INSTANCE.

The AstaBaselineStrategy matches tasks based on their Unique ID attribute, and populates the main schedule's baseline attributes from their equivalent attributes in the baseline schedule, for example, Baseline Duration will be populated using the Duration attribute in the baseline schedule and so on. You can't create new instances of this strategy, instead use the static instance provided by AstaBaselineStrategy.INSTANCE.

Finally the PrimaveraBaselineStrategy matches tasks based on their Activity ID. Two variants of the strategy are provided as PrimaveraBaselineStrategy.PLANNED_ATTRIBUTES and PrimaveraBaselineStrategy.CURRENT_ATTRIBUTES. The PLANNED_ATTRIBUTES instance, as the name suggests, uses the planned attributes from the baseline schedule to populate the baseline attributes in the main schedule, and the CURRENT_ATTRIBUTES instance uses the current attributes from the baseline schedule to populate the baseline attributes in the main schedule (for example, Baseline Duration in the main schedule is populated using the Duration attribute in the baseline schedule).

When using the MPXJ reader classes, the correct strategy for the specific schedule type you are reading is selected for you. If you need behavior which differs from one of the defaults you can provide your own BaselineStrategy implementation. Where the reader class is automatically attaching baselines to the main schedule, you can pass an instance of your strategy class to the reader:

BaselineStrategy myStrategy = new MyBaselineStrategy();\nPrimaveraPMFileReader reader = new PrimaveraPMFileReader();\nreader.setBaselineStrategy(myStrategy);\nProjectFile file = reader.read(\"sample-pmxml.xml\");\n

If you are reading the main and baseline schedules separately, you can set the baseline strategy on the main schedule, and this will be used when each baseline schedule is attached:

BaselineStrategy myStrategy = new MyBaselineStrategy();\nProjectFile main = new UniversalProjectReader().read(\"main.pp\");\nmain.getProjectConfig().setBaselineStrategy(myStrategy);\n\nProjectFile baseline1 = new UniversalProjectReader().read(\"baseline1.pp\");\nProjectFile baseline2 = new UniversalProjectReader().read(\"baseline2.pp\");\nmain.setBaseline(baseline1, 1);\nmain.setBaseline(baseline2, 2);\n
"},{"location":"howto-use-calendars/","title":"How To: Use Calendars","text":"

Calendars are the foundation on which schedules are built. They determine when work can be carried out, and when work is not possible. Given some tasks we need to plan, and knowing how much work each task will require, a calendar can be used to decide when work on each task could start and how much elapsed time will be required to complete the tasks.

"},{"location":"howto-use-calendars/#calendars-in-mpxj","title":"Calendars in MPXJ","text":"

Let's see how calendars work in MPXJ. First let's try creating one. As it happens, the ProjectFile class provides a convenience method addDefaultBaseCalendar to create a default calendar. The calendar it creates is modelled on the Standard calendar you'd see in Microsoft Project if you created a new project. This default calendar defines Monday to Friday as working days, with 8 working hours each day (8am to noon, then 1pm to 5pm).

ProjectFile file = new ProjectFile();\nProjectCalendar calendar = file.addDefaultBaseCalendar();\nSystem.out.println(\"The calendar name is \" + calendar.getName());\n

As you can see from the code above, the calendar also has a name which we can set to distinguish between different calendars.

"},{"location":"howto-use-calendars/#working-days","title":"Working Days","text":"

Let's see what the calendar can tell us. First we'll use the DayOfWeek enumeration to retrieve the working/non-working state for each day.

for (DayOfWeek day : DayOfWeek.values()) {\n   String dayType = calendar.getCalendarDayType(day).toString();\n   System.out.println(day + \" is a \" + dayType + \" day\");\n}\n

Running the code shown above will produce output like this:

MONDAY is a WORKING day\nTUESDAY is a WORKING day\nWEDNESDAY is a WORKING day\nTHURSDAY is a WORKING day\nFRIDAY is a WORKING day\nSATURDAY is a NON_WORKING day\nSUNDAY is a NON_WORKING day\n

We can use the setWorkingDay method to change our pattern of working day. Let's make Saturday a working day for our team, and make Monday a non-working day to compensate.

calendar.setWorkingDay(DayOfWeek.SATURDAY, true);\ncalendar.setWorkingDay(DayOfWeek.MONDAY, false);\n

Now if we use the loop we saw previously to inspect the week days, we'll see this output:

MONDAY is a NON_WORKING day\nTUESDAY is a WORKING day\nWEDNESDAY is a WORKING day\nTHURSDAY is a WORKING day\nFRIDAY is a WORKING day\nSATURDAY is a WORKING day\nSUNDAY is a NON_WORKING day\n
"},{"location":"howto-use-calendars/#working-hours","title":"Working Hours","text":"

So far, all we have done is set a flag which tells us whether a day is working or non-working. How do we know the working times on those days? We can use the getCalendarHours method to find that information.

The getCalendarHours method returns a List of LocalTimeRange instances. LocalTimeRange is a simple immutable class which represents a span of time between a start time and an end time as an inclusive range. Let's try printing these LocalTimeRange instances to our output to see what we get:

List<LocalTimeRange> hours = calendar.getCalendarHours(DayOfWeek.TUESDAY);\nhours.forEach(System.out::println);\n

Here's the output:

[LocalTimeRange start=08:00 end=12:00]\n[LocalTimeRange start=13:00 end=17:00]\n

Let's add a method to format the hours of a day a little more concisely for display:

private String formatLocalTimeRanges(List<LocalTimeRange> hours) {\n   return hours.stream()\n      .map(h -> h.getStart() + \"-\" + h.getEnd())\n      .collect(Collectors.joining(\", \"));\n}\n

So now our output looks like this:

08:00-12:00, 13:00-17:00\n

Let's use this method to take a look at the whole week again:

for (DayOfWeek day : DayOfWeek.values()) {\n   String dayType = calendar.getCalendarDayType(day).toString();\n   System.out.println(day\n      + \" is a \" + dayType + \" day (\"\n      + formatLocalTimeRanges(calendar.getCalendarHours(day)) + \")\");\n}\n

Here's the output:

MONDAY is a NON_WORKING day ()\nTUESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nWEDNESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nTHURSDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nFRIDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nSATURDAY is a WORKING day ()\nSUNDAY is a NON_WORKING day ()\n

The one thing we're missing now is that although we have set Saturday to be a working day, it doesn't have any working hours. MPXJ has some constants which can be used to help us add some working hours:

hours = calendar.getCalendarHours(DayOfWeek.SATURDAY);\nhours.add(ProjectCalendarDays.DEFAULT_WORKING_MORNING);\nhours.add(ProjectCalendarDays.DEFAULT_WORKING_AFTERNOON);\n

Now when we examine our week this is what we see:

MONDAY is a NON_WORKING day ()\nTUESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nWEDNESDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nTHURSDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nFRIDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nSATURDAY is a WORKING day (08:00-12:00, 13:00-17:00)\nSUNDAY is a NON_WORKING day ()\n

The version of MPXJ at the time of writing (12.0.0) has a limitation that if setCalendarDayType is used to make a day into a working day, we don't automatically add working hours for it. This behaviour is likely to change with the next major version of MPXJ.

What if we want to supply some working hours different from the defaults we've used so far? To set our own working hours we just need to create as many LocalTimeRange instances as we need using a pair of LocalTime instances for each one to represent the start and end times.

LocalTime startTime = LocalTime.of(9, 0);\nLocalTime finishTime = LocalTime.of(14, 30);\nhours = calendar.getCalendarHours(DayOfWeek.SATURDAY);\nhours.clear();\nhours.add(new LocalTimeRange(startTime, finishTime));\n

Now when we look at the working hours for Saturday, this is what we see:

SATURDAY is a WORKING day (09:00-14:30)\n

Now we've seen how we can create our own ranges of working time for a day, let's tackle a slightly more challenging case: dealing with midnight. Our first step is to take a look at the actual amount of working time we've set up on Saturday. To do this we call the getWork method, as shown below.

Duration duration = calendar.getWork(DayOfWeek.SATURDAY, TimeUnit.HOURS);\nSystem.out.println(duration);\n

This getWork method determines the total amount of work on the given day, and returns this in the format we specify. In this case we've asked for hours, and we'll be receiving the result as a Duration object. Duration simply combines the duration amount with an instance of the TimeUnit enumeration so we always know the units of the duration amount.

Running the code above give us this output:

5.5h\n

As you can see, the toString method of Duration give us a nicely formatted result, complete with an abbreviation for the units.

Let's try to change Saturday to be 24 hour working. First we'll configure a midnight to midnight date range:

startTime = LocalTime.MIDNIGHT;\nfinishTime = LocalTime.MIDNIGHT;\nhours.clear();\nhours.add(new LocalTimeRange(startTime, finishTime));\nSystem.out.println(formatLocalTimeRanges(calendar.getCalendarHours(DayOfWeek.SATURDAY)));\n

This looks reasonable:

00:00-00:00\n

Now let's see how much work this represents:

duration = calendar.getWork(DayOfWeek.SATURDAY, TimeUnit.HOURS);\nSystem.out.println(duration);\n
24.0h\n

So we have our 24 hours of work on Saturday!

"},{"location":"howto-use-calendars/#exceptions","title":"Exceptions","text":"

After working a few of these 24 hour days on Saturdays, we might be in need of a vacation! How can we add this to our calendar?

So far we've been working with the DayOfWeek class to make changes to days of the week, rather than any specific date. Now we'll need to work with a specific date, and add an \"exception\" for this date. The terminology here can be slightly confusing when coming from a programming background, but the term exception is often used by scheduling applications in the context of making ad-hoc adjustments to a calendar.

LocalDate exceptionDate = LocalDate.of(2022, 5, 10);\n\nboolean workingDate = calendar.isWorkingDate(exceptionDate);\nSystem.out.println(exceptionDate + \" is a \"\n   + (workingDate ? \"working\" : \"non-working\") + \" day\");\n

In the code above we're creating a LocalDate instance to represent the date we want to add an exception for. The code uses the isWorkingDate method to determine whether or not the given date is a working day. Before we add the exception, here's the output we get:

2022-05-10 is a working day\n

Now we can create our exception.

ProjectCalendarException exception = calendar.addCalendarException(exceptionDate);\nexception.setName(\"A day off\");\n

The code above illustrates adding an exception for a single day. The code above also shows that optionally an exception can be named, this can make it easier to understand the purpose of each exception. Now if we re-run our code which displays whether our chosen date is a working day, this is what we see:

2022-05-10 is a non-working day\n

We have successfully added an exception to turn this date into a day off!

Perhaps we were being a little too generous in giving ourselves the entire day off, perhaps in this case we should make this a half day instead. To do that, we just need to add a time range to the exception:

startTime = LocalTime.of(8, 0);\nfinishTime = LocalTime.of(12, 0);\nexception.add(new LocalTimeRange(startTime, finishTime));\n

Now if we look at our chosen date, this is what we see:

2022-05-10 is a working day\n

Let's take a closer look at what's happening on that day:

System.out.println(\"Working time on Tuesdays is normally \"\n   + calendar.getWork(DayOfWeek.TUESDAY, TimeUnit.HOURS) + \" but on \"\n   + exceptionDate + \" it is \"\n   + calendar.getWork(exceptionDate, TimeUnit.HOURS));\n

The code above shows how we use the getWork method which takes a DayOfWeek as an argument to look at what the default working hours are on a Tuesday, then we use the getWork method which takes a LocalDate instance as an argument to see what's happening on the specific Tuesday of our exception. Here's the output we get:

Working time on Tuesdays is normally 8.0h but on 2022-05-10 it is 4.0h\n

We can see the effect of adding a LocalTimeRange to our exception: we've gone from an exception which changes a working day into a non-working day to an exception which just changes the number of working hours in the day. This same approach can be used to change a date which falls on a day that's typically non-working (for example a Sunday) into a working day, just by adding an exception with some working hours.

We can also use a single exception to affect a number of days. First let's write a little code to see the number of working hours over a range of days:

private void dateDump(ProjectCalendar calendar, LocalDate startDate, LocalDate endDate)\n{\n   for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1)) {\n      System.out.println(date + \"\\t\" + calendar.getWork(date, TimeUnit.HOURS));\n   }\n   System.out.println();\n}\n

Running this code with our calendar as its stands produces this output for the example week we're using:

2022-05-23  0.0h\n2022-05-24  8.0h\n2022-05-25  8.0h\n2022-05-26  8.0h\n2022-05-27  8.0h\n

Let's add an exception which covers Tuesday to Thursday that week (24th to 26th), and changes the working hours, so there are now only four hours of work per day (9am to 12pm):

LocalDate exceptionStartDate = LocalDate.of(2022, 5, 24);\nLocalDate exceptionEndDate = LocalDate.of(2022, 5, 26);\nexception = calendar.addCalendarException(exceptionStartDate, exceptionEndDate);\nstartTime = LocalTime.of(9, 0);\nfinishTime = LocalTime.of(13, 0);\nexception.add(new LocalTimeRange(startTime, finishTime));\n

Here we can see that we're using a different version of the addCalendarException method which takes a start and an end date, rather that just a single date. Running our code again to print out the working hours for each day now gives us this output:

2022-05-23  0.0h\n2022-05-24  4.0h\n2022-05-25  4.0h\n2022-05-26  4.0h\n2022-05-27  8.0h\n

As we can see, we've changed multiple days with this single exception.

"},{"location":"howto-use-calendars/#working-weeks","title":"Working Weeks","text":"

So far we've looked at using ProjectCalendarException, which can make one change (add working hours, change working hours, or make days non-working) and apply that change to one day or a contiguous range of days. What if we want to make more complex changes to the working pattern of a calendar?

Let's imagine that our project has a three week \"crunch\" period at the beginning of October where we will need to work 16 hour days, Monday through Friday, and 8 hour days at weekends. (I hope this is a fictional example and you'd don't have to work at such a high intensity in real life!). We could construct this work pattern using exceptions: we'd need six in total, one for each of the three sets of weekend days, and one for each of the three sets of week days.

An alternative way to do this is to set up a new working week, using the ProjectCalendarWeek class. \"Working Week\" is perhaps a slightly misleading name, as a ProjectCalendarWeek can be set up for an arbitrary range of dates, from a few days to many weeks. What it represents is the pattern of working an non-working time over the seven days of a week, and this pattern is applied from the start to the end of the date range we configure.

The ProjectCalendar we've been working with so far is actually already a form of working week (they share a common parent class). The main differences between the two are that a ProjectCalendarWeek allows us to specify the range of dates over which it is effective, and a ProjectCalendarWeek does not have exceptions: exceptions are only added to a ProjectCalendar.

For a fresh start, we'll create a new ProjectCalendar instance. With this we'll add a new working week definition and give it a name, to make it easily identifiable. Now we'll set the dates for which this work pattern is valid (in this case the first three weeks of October). Finally we mark every day as a working day. Here's how our example looks in code:

LocalDate weekStart = LocalDate.of(2022, 10, 1);\nLocalDate weekEnd = LocalDate.of(2022, 10, 21);\ncalendar = file.addDefaultBaseCalendar();\nProjectCalendarWeek week = calendar.addWorkWeek();\nweek.setName(\"Crunch Time!\");\nweek.setDateRange(new LocalDateRange(weekStart, weekEnd));\nArrays.stream(DayOfWeek.values()).forEach(d -> week.setWorkingDay(d, true));\n

Next we can set up our weekend 9am to 5pm working pattern:

startTime = LocalTime.of(9, 0);\nfinishTime = LocalTime.of(17, 0);\nLocalTimeRange weekendHours = new LocalTimeRange(startTime, finishTime);\nStream.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)\n   .forEach(d -> week.addCalendarHours(d).add(weekendHours));\n

Finally we can set up our weekday 5am to 9pm pattern:

startTime = LocalTime.of(5, 0);\nfinishTime = LocalTime.of(21, 0);\nLocalTimeRange weekdayHours = new LocalTimeRange(startTime, finishTime);\nStream.of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY,\n      DayOfWeek.THURSDAY, DayOfWeek.FRIDAY)\n   .forEach(d -> week.addCalendarHours(d).add(weekdayHours));\n

As ProjectCalendar and ProjectCalendarWeek are both derived from the same parent class, we can use the same code we did previously to examine how our new ProjectCalendarWeek instance looks:

MONDAY is a WORKING day (05:00-21:00)\nTUESDAY is a WORKING day (05:00-21:00)\nWEDNESDAY is a WORKING day (05:00-21:00)\nTHURSDAY is a WORKING day (05:00-21:00)\nFRIDAY is a WORKING day (05:00-21:00)\nSATURDAY is a WORKING day (09:00-17:00)\nSUNDAY is a WORKING day (09:00-17:00)\n

To see the effect that our new working week has had on the calendar, let's first take a look at the week running up to the start of our crunch period. Using the same code we worked with previously to present working hours for a range of dates we see this output:

2022-09-24  0.0h\n2022-09-25  0.0h\n2022-09-26  8.0h\n2022-09-27  8.0h\n2022-09-28  8.0h\n2022-09-29  8.0h\n2022-09-30  8.0h\n

So starting from Saturday 24th we can see that we have that standard working pattern: weekends are non-working (zero working hours), and week days have 8 hours of working time.

Now let's look at the first week of our crunch period:

2022-10-01  8.0h\n2022-10-02  8.0h\n2022-10-03  16.0h\n2022-10-04  16.0h\n2022-10-05  16.0h\n2022-10-06  16.0h\n2022-10-07  16.0h\n

We can see that the crunch is in full effect, we're working 8 hour days at the weekend, and 16 hour days for the rest of the week - not something I'd like to try for any length of time!

To summarise: the ProjectCalendar instance itself defines the default working and non-working pattern for the seven week days. Additional working weeks can be added to the calendar which override this pattern for specific date ranges.

"},{"location":"howto-use-calendars/#recurring-exceptions","title":"Recurring Exceptions","text":"

So far we've seen how exceptions can be used to override the default working pattern established by a calendar for either a single day, or for a contiguous range of days. We've also seen how an entirely new seven-day working pattern can be applied across a range of dates by using working weeks. But what if we want to represent a regularly occurring exception which will change our default working pattern such as, for example, Christmas Day or Thanksgiving? To deal with this we can use recurring exceptions.

A recurring exception can be created simply by passing an instance of RecurringData to the addCalendarException method.

RecurringData recurringData = new RecurringData();\nexception = calendar.addCalendarException(recurringData);\n

Let's create a simple recurence for 1st January for five years:

recurringData.setRecurrenceType(RecurrenceType.YEARLY);\nrecurringData.setOccurrences(5);\nrecurringData.setDayNumber(Integer.valueOf(1));\nrecurringData.setMonthNumber(Integer.valueOf(1));\nrecurringData.setStartDate(LocalDate.of(2023, 1, 1));\nSystem.out.println(recurringData);\n

The toString method on the RecurringData class tries to describe the recurrence as best it can, here's the output we'll see from the code above:

[RecurringData Yearly on the 1 January From 2023-01-01 For 5 occurrences]\n

The example above shows a very simple configuration. Full details of how to use RecurringData are provided elsewhere as they are beyond the scope of this section.

Before we move on from recurring exceptions, one useful feature of the ProjectCalendarException class is the getExpandedExceptions method. This will convert a recurring exception into a list of individual exceptions representing each date or range of dates the recurring exception will affect the calendar. You may find this useful if you need to display or pass this data on for consumption elsewhere.

"},{"location":"howto-use-calendars/#calendar-hierarchies","title":"Calendar Hierarchies","text":"

Now we've seen how to set up an individual calendar, perhaps we could go ahead and create calendars for all of the people who will be working on our project? What we'd quickly find is that a considerable amount of the information in each calendar will be the same: the same working week pattern, the same public holidays and so on. We could set all of this up programmatically of course, but wouldn't it be great if we could change this kind of detail in just one place, and have all of our other calendars inherit it?

"},{"location":"howto-use-calendars/#creating-a-calendar-hierarchy","title":"Creating a Calendar Hierarchy","text":"

As it happens, we can do this as our calendars can be organised into a hierarchy, with each \"child\" calendar inheriting its configuration from a \"parent\" calendar and overriding that configuration as required rather like a class hierarchy in a programing language). This will allow us to have one shared \"base\" calendar for everyone, with derived calendars used for individuals on our team where we need to add variation, for example personal vacation time and so on.

ProjectFile file = new ProjectFile();\nProjectCalendar parentCalendar = file.addDefaultBaseCalendar();\nLocalDate christmasDay = LocalDate.of(2023, 12, 25);\nparentCalendar.addCalendarException(christmasDay);\n

In the example above we've used the familiar addDefaultBaseCalendar method to create a simple calendar, and called addCalendarException to add an exception for Christmas Day 2023.

ProjectCalendar childCalendar = file.addDefaultDerivedCalendar();\nchildCalendar.setParent(parentCalendar);\nSystem.out.println(christmasDay + \" is a working day: \"\n   + childCalendar.isWorkingDate(christmasDay));\n

Now we've created childCalendar, using a method we've not seen before, addDefaultBaseCalendar (we'll talk about this method in more detail in a minute), and we've used the new calendar's setParent method to attach parentCalendar as its parent. We can see the effect of this when we check to see if Christmas Day 2023 is a working day. This is a Monday so by default it will be a working day, but as childCalendar is inheriting from parentCalendar it picks up the exception defined in parentCalendar and makes Christmas Day a non-working day.

Here's the output when our code is executed:

2023-12-25 is a working day: false\n

We can also do the same thing with day types:

parentCalendar.setCalendarDayType(DayOfWeek.TUESDAY, DayType.NON_WORKING);\nSystem.out.println(\"Is \" + DayOfWeek.TUESDAY + \" a working day: \"\n   + childCalendar.isWorkingDay(DayOfWeek.TUESDAY));\n

In the example above we've set Tuesday to be a non-working day in the parent calendar, and we can see that this is inherited by the child calendar. Here's the output we see when we execute our code:

Is TUESDAY a working day: false\n

So what's special about the \"derived calendar\" we've just created (childCalendar), why is it different to the normal calendar, and what's the difference between the addDefaultBaseCalendar and addDefaultDerivedCalendar methods?

The answer to this question lies in the DayType enumeration. Let's take a look at the day types for parentCalendar.

SUNDAY is a NON_WORKING day\nMONDAY is a WORKING day\nTUESDAY is a NON_WORKING day\nWEDNESDAY is a WORKING day\nTHURSDAY is a WORKING day\nFRIDAY is a WORKING day\nSATURDAY is a NON_WORKING day\n

So far so good, we have a mixture of working an non-working days, and we can see that as part of our last example we set Tuesday to be a non-working day. Now let's take a look at childCalendar:

SUNDAY is a DEFAULT day\nMONDAY is a DEFAULT day\nTUESDAY is a DEFAULT day\nWEDNESDAY is a DEFAULT day\nTHURSDAY is a DEFAULT day\nFRIDAY is a DEFAULT day\nSATURDAY is a DEFAULT day\n

Ah-ha! Here we can see that the DayType enumeration actually has a third value alongside WORKING and NON_WORKING: DEFAULT. The DEFAULT value simply means that we should inherit the parent calendar's settings for this particular day: so whether the day is working, non-working, what the working hours are, and so on.

We can override the day type we're inheriting from the base calendar:

childCalendar.setCalendarDayType(DayOfWeek.TUESDAY, DayType.WORKING);\nLocalTime startTime = LocalTime.of(9, 0);\nLocalTime finishTime = LocalTime.of(12, 30);\nchildCalendar.addCalendarHours(DayOfWeek.TUESDAY)\n   .add(new LocalTimeRange(startTime, finishTime));\n

In the code above we're explicitly setting Tuesday to be a working day, rather than inheriting the settings for Tuesday from the parent calendar, then we're adding the working hours we want for Tuesday.

Earlier we said we come back and look at the addDefaultDerivedCalendar method in a little more detail. The main difference between addDefaultDerivedCalendar and addDefaultBaseCalendar is that the calendar created by addDefaultDerivedCalendar has no working hours defined, and all day types are set to DEFAULT so everything is inherited from the parent calendar.

"},{"location":"howto-use-calendars/#working-with-a-calendar-hierarchy","title":"Working with a Calendar Hierarchy","text":"

In general when working with a calendar hierarchy, if we use a calendar to determine working/non-working time, working hours, and so on for a given date, anything configured in a child calendar will always override what we find in the parent calendar. So for example if we have exceptions or working weeks configured in a child calendar, these will override anything found in a parent calendar.

If we're asking the calendar a question about a particular day (rather than a date), for example Monday, Tuesday and so on, we'll use information from the child calendar if the day type is WORKING or NON_WORKING, otherwise we'll work our way up the calendar hierarchy until we find the first ancestor calendar which does not specify the day type as DEFAULT, and we'll use the configuration for the day in question from that calendar.

This brings us on to an interesting question: how do we know if we ask the calendar for a piece of information, whether that's come from the calendar whose method we've just called, or if the response we've received has come from another calendar somewhere further up the calendar hierarchy?

As it happens there are only a small number of attributes for which this is relevant. These are summarised by the table below.

Attribute Set Get Get with Hierarchy Day Type setCalendarDayType getCalendarDayType getDayType Hours addCalendarHours getCalendarHours getHours Minutes Per Day setCalendarMinutesPerDay getCalendarMinutesPerDay getMinutesPerDay Minutes Per Week setCalendarMinutesPerWeek getCalendarMinutesPerWeek getMinutesPerWeek Minutes Per Month setCalendarMinutesPerMonth getCalendarMinutesPerMonth getMinutesPerWeek Minutes Per Year setCalendarMinutesPerYear getCalendarMinutesPerYear getMinutesPerYear

The first column give us the name of the attribute, and the second column give the name of the method we'd call to set that attribute for the current calendar. The third column gives us the name of the method we'd use to retrieve the attribute from the current calendar only (i.e this will ignore any parent calendars). Finally the last column gives us the name of the method we'd call to retrieve the attribute from the current calendar, or inherit that attribute from a parent calendar if it is not present in the current calendar.

We haven't looked at the Minutes Per X attributes so far. The values they contain are used when calculating working time. One interesting point to note is that if no calendars in a hierarchy define these values the default values will be retrieved from from the ProjectFile configuration, which is represented by the ProjectConfig class.

"},{"location":"howto-use-calendars/#how-deep-is-your-hierarchy","title":"How deep is your Hierarchy?","text":"

MPXJ will allow you to create an arbitrarily deep hierarchy of calendars if you wish by establishing parent-child relationships between the calendars you create. Most schedule application file formats will only support a limited hierarchy of calendars, which you will see when you read files of this type when using MPXJ. The notes below briefly outlines how calendar hierarchies operate in some of the applications MPXJ can work with.

If you are using MPXJ to create or modify schedule data, when you write the results to a file MPXJ will attempt to ensure that the calendars it writes to the file format you have chosen reflect what the target application is expecting. This means that MPXJ may end up \"flattening\" or otherwise simplifying a set of calendars and their hierarchy to ensure that they are read correctly by the target application and are \"functionally equivalent\" in use.

"},{"location":"howto-use-calendars/#microsoft-project","title":"Microsoft Project","text":"

Microsoft Project uses two tiers of calendars. The first tier of calendars are referred to as \"base calendars\", one of which is marked as the default calendar for the project. Work is scheduled based on the default calendar, unless a task explicitly selects a different base calendar to use when being scheduled, or resources with their own calendars have been assigned to the task. Each resource will have its own calendar, which is always derived from a base calendar.

Note that, as you might expect, material resources don't have a calendar!

"},{"location":"howto-use-calendars/#primavera-p6","title":"Primavera P6","text":"

The situation with P6 is a little more complicated, although it's still a two tier arrangement. P6 has the concept of Global calendars (broadly similar to base calendars in Microsoft Project). These can be assigned to activities in any project. Global calendars are never derived from other calendars.

You can also have Project calendars which, as their name suggests, can only be assigned to activities in the project to which they belong. Project calendars can be derived from a Global Calendar, or they can have no parent calendar.

Finally you can have two types of resource calendar: Shared, or Personal. These can either be derived from a Global calendar, or can have no parent. A Shared resource calendar can be assigned to multiple resources, but a Personal resource calendar can only be assigned to a single resource.

When reading a P6 schedule, the ProjectCalendar method getType can be used to retrieve the calendar type (Global, Shared, or Personal), while the getPersonal method returns a Boolean flag indicating if the calendar is a Personal resource calendar.

"},{"location":"howto-use-calendars/#others","title":"Others","text":"

ConceptDraw, Planner, SureTrak and TurboProject all support some form of calendar hierarchy, although Planner is the only one which definitely supports an arbitrarily deep nested calendar structure.

"},{"location":"howto-use-calendars/#calendar-container","title":"Calendar Container","text":"

So far we've looked at creating and configuring calendars, and lining them together in a hierarchy. If we've just read a schedule in from a file, how can we examine the calendars it contains? Let's set up some calendars and take a look:

ProjectFile file = new ProjectFile();\nProjectCalendar calendar1 = file.addCalendar();\ncalendar1.setName(\"Calendar 1\");\n\nProjectCalendar calendar2 = file.addCalendar();\ncalendar2.setName(\"Calendar 2\");\n\nProjectCalendar calendar3 = file.addCalendar();\ncalendar3.setName(\"Calendar 3\");\n

Our sample code above creates three calendars, each with a distinct name. To see what calendars our file contains we can use the ProjectFile method getCalendars:

file.getCalendars().forEach(c -> System.out.println(c.getName()));\n

Which gives us the following output, as we'd expect:

Calendar 1\nCalendar 2\nCalendar 3\n

The getCalendars method returns an object which implements the List<ProjectCalendar> interface, but it also does more for us than just that. The actual object being returned is a ProjectCalendarContainer, which is in charge of managing the calendars in the file and making it easy to access them.

The typical way this is done is through the use of the calendar's Unique ID attribute. Each calendar has an Integer Unique ID, typically this is read as part of the calendar information from a schedule file, or if you are creating a schedule yourself, the default is for the Unique ID to be automatically populated. Let's see:

file.getCalendars().forEach(c -> System.out.println(c.getName()\n   + \" (Unique ID: \" + c.getUniqueID() + \")\"));\n

Here's what we get:

Calendar 1 (Unique ID: 1)\nCalendar 2 (Unique ID: 2)\nCalendar 3 (Unique ID: 3)\n

Let's use a Unique ID to retrieve a calendar:

ProjectCalendar calendar = file.getCalendars().getByUniqueID(2);\nSystem.out.println(calendar.getName());\n

Here's the result of running this code:

Calendar 2\n

The ProjectCalendarContainer class also allows us to retrieve calendars by name, although that's not recommended as MPXJ doesn't enforce presence or uniqueness constraints on calendar names.

Most of the time accessing a calendar from some other part of MPXJ is handled for you, for example to retrieve a resource's calendar you just need to call the Resource method getCalendar rather than having to use ProjectCalendarContainer to retrieve it by Unique ID.

"},{"location":"howto-use-calendars/#calendar-relationships","title":"Calendar Relationships","text":"

The ProjectCalendar class provides a variety of methods to allow us to explore how it relates to other calendars and the rest of the schedule.

As we've been discussing the hierarchy of calendars, the first method we can try is isDerived, which will return true if this calendar has been derived from a parent calendar. Alongside this we can also use the getParent method to retrieve this calendar's parent. We can traverse a hierarchy of calendars using this method until getParent returns null at which point we know we have reached a \"base\" calendar and can go no further.

Calendars can also be assigned to both Tasks and Resources. The getTasks and getResources methods will each retrieve a list of the tasks and resources which explicitly use this calendar.

Finally, earlier in this section we mentioned the idea of the default calendar for a project. We can set or retrieve the default calendar using the ProjectFile methods setDefaultCalendar and getDefaultCalendar, as illustrated below.

ProjectFile file = new ProjectFile();\nProjectCalendar calendar = file.addDefaultBaseCalendar();\nfile.setDefaultCalendar(calendar);\nSystem.out.println(\"The default calendar name is \"\n   + file.getDefaultCalendar().getName());\n

As the name suggests, the default calendar will be used for all date, time, duration and work calculations if no other calendar has been assigned explicitly.

"},{"location":"howto-use-external-projects/","title":"How To: Use External Projects","text":"

From a schedule in Microsoft Project you can work with data from other project files in three ways: Subprojects, External Predecessors, and Resource Pools.

"},{"location":"howto-use-external-projects/#subprojects","title":"Subprojects","text":"

Microsoft Project allows you to manage larger projects by breaking them down into Subprojects. From one MPP file, a link can be added to another MPP file forming a parent-child relationship. The child MPP file will appear as a summary task in the location you've selected within the parent file. When this summary task is expanded the tasks from the child MPP file will appear seamlessly as tasks in the parent file.

"},{"location":"howto-use-external-projects/#identifying-subproject-tasks","title":"Identifying Subproject Tasks","text":"

If you use MPXJ to read an MPP file that contains a Subproject, initially you won't see anything different to a file which just contains ordinary tasks: the Subproject will just appear as a normal summary task whose attributes will roll up the details from the Subproject. If you want you can just work with the task as-is, you only need to so something different if you want to work with the contents of the Subproject.

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class IdentifySubprojectTasks\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      for (Task task : file.getTasks())\n      {\n         if (task.getExternalProject())\n         {\n            System.out.println(task.getName() + \" is a subproject\");\n            System.out.println(\"The path to the file is: \"\n               + task.getSubprojectFile());\n            System.out.println(\"The GUID of this project is: \"\n               + task.getSubprojectGUID());\n            System.out.println(\"The offset used when displaying Unique ID values is: \"\n               + task.getSubprojectTasksUniqueIDOffset());\n         }\n      }\n   }\n}\n

The example above illustrates how we can identify a Subproject by using a task's External Project attribute. Once we have identified that we have a Subproject we can determine where the file is located, using the Subproject File attribute, and the GUID of this project, using the Subproject GUID attribute.

The last attribute we're looking at in this example is the Subproject Tasks Unique ID Offset. When Microsoft Project provides a combined view of two or more MPP files using Subprojects, one issue is that the Unique ID values in each project will no longer be unique. To get around this problem Microsoft Project adds an offset to the Unique ID values of the tasks it displays from each Subproject to ensure that each one has a distinct value. This offset is the value we're retrieving using the getSubprojectTasksUniqueIDOffset method.

"},{"location":"howto-use-external-projects/#reading-subproject-data","title":"Reading Subproject Data","text":"

If you wish, you can use UniversalProjectReader directly to load the external project, as the example below illustrates:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ReadSubprojectData\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      Task externalProject = file.getTaskByID(Integer.valueOf(1));\n      String filePath = externalProject.getSubprojectFile();\n      ProjectFile externalProjectFile = new UniversalProjectReader().read(filePath);\n   }\n}\n

The code above assumes that the file is located on a readable filesystem at the exact path specified by the Subproject File attribute.

Note that these examples assume that the file is on a filesystem which is directly readable. For MPP files exported from Project Server, it is likely that the path to an external project will be in the form <>\\FileName which represents a project hosted by Project Server. MPXJ cannot open this type of external project.

An alternative to writing your own code to do this would be to use the method provided by MPXJ, as illustrated below:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ReadSubprojectDataMpxj\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      Task externalProjectTask = file.getTaskByID(Integer.valueOf(1));\n      ProjectFile externalProjectFile = externalProjectTask.getSubprojectObject();\n   }\n}\n

The advantage of this approach, apart from using less code, is that MPXJ will attempt to find the file in locations other than the full path provided in Subproject File. By default the other place MPXJ will look is in the working directory of the current process, however this behaviour can be configured as the example below illustrates:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\nimport java.io.File;\n\npublic class ReadSubprojectDataDirectory\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      file.getProjectConfig().setSubprojectWorkingDirectory(new File(\"/path/to/directory\"));\n      Task externalProjectTask = file.getTaskByID(Integer.valueOf(1));\n      ProjectFile externalProjectFile = externalProjectTask.getSubprojectObject();\n   }\n}\n

In the code above we're calling the setSubprojectWorkingDirectory method to give MPXJ details of a directory to look in when attempting to read an external project.

Note that if MPXJ can't load the external project for any reason, the getSubprojectObject method will return null.

"},{"location":"howto-use-external-projects/#expanding-subproject-data","title":"Expanding Subproject Data","text":"

In Microsoft Project, when a Subproject task is expanded it behaves just like any other summary task by revealing the child tasks it contains. We can reproduce this behavior using the code shown in the sample below:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ExpandSubprojects\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      Task externalProjectTask = file.getTaskByID(Integer.valueOf(1));\n      System.out.println(\"Task has child tasks: \" + externalProjectTask.hasChildTasks());\n      externalProjectTask.expandSubproject();\n      System.out.println(\"Task has child tasks: \" + externalProjectTask.hasChildTasks());\n   }\n}\n

The expandSubproject method attempts to open the external project, and if successful attaches the tasks from the external project as children of the external project task. You are then able to access the tasks from the parent project along with the tasks from the external project as part of the same MPXJ ProjectFile instance.

Note that when using the expandSubproject method, the setSubprojectWorkingDirectory method on ProjectConfig can be used to tell MPXJ where to find the external projects in the same way we did when using the getSubprojectObject method.

You can also do this globally and expand all Subproject tasks in a project by using the expandSubprojects method on the project file itself (we'll cover the false argument we're passing into this method in the section below on External Predecessors):

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ExpandSubprojectsGlobally\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      file.expandSubprojects(false);\n   }\n}\n

Remember that all the \"expand subproject\" functionality described in the notes above is doing is attaching the tasks from one ProjectFile instance as child tasks of a task in another ProjectFile instance. This will allow you to recursively descend through the tasks in a project and any subprojects. However, these tasks still belong to separate ProjectFile instances, so calling the getTasks() method on the top level ProjectFile instance will only return the tasks from that project, and will not include tasks from any subprojects.

"},{"location":"howto-use-external-projects/#external-predecessors","title":"External Predecessors","text":"

The second way an external project can be referenced in a Microsoft Project schedule is through the use of an external predecessor task. Project allows you to enter the task ID for a predecessor in the form myproject.mpp\\123 which selects the task with ID 123 in myproject.mpp as the predecessor of the task in the schedule you are working on.

When you use an external predecessor task like this, Project includes a \"placeholder\" task in your current schedule which represents the task in the external project and has a copy of all of the relevant attributes of the task from the external project. In many cases this placeholder task is all you need to work with the schedule.

When you are working with MPXJ, how can you identify that you are looking at a placeholder task representing an external predecessor? The sample code below illustrates this:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.Task;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ExternalPredecessors\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      for (Task task : file.getTasks())\n      {\n         if (task.getExternalTask())\n         {\n            System.out.println(task.getName() + \" is an external predecessor\");\n            System.out.println(\"The path to the file containing this task is: \"\n               + task.getSubprojectFile());\n            System.out.println(\"The ID of the task in this file is: \"\n               + task.getSubprojectTaskID());\n            System.out.println(\"The Unique ID of the task in this file is: \"\n               + task.getSubprojectTaskUniqueID());\n         }\n      }\n   }\n}\n

As the code above illustrates, if the getExternalTask method return true, the task is an external predecessor. As illustrated by the code there are three relevant attributes: Subproject File (the location of the external project this predecessor belongs to), and the Subproject Task ID and Subproject Task Unique ID which are the ID and Unique ID of the task in the schedule it comes from.

As with a task representing an external project, you can retrieve the project for an external predecessor task using the getSubprojectObject method. Note however that the expandSubproject method will have no effect as the external predecessor task does not represent an entire project!

"},{"location":"howto-use-external-projects/#predecessors-and-successors-from-subprojects","title":"Predecessors and Successors from Subprojects","text":"

As we saw in a previous section, when working with Microsoft Project you can configure a project with a number of subprojects. When this is the case you can also create predecessor or successor relationships between tasks in any of these projects. When you open your MPP file in Microsoft Project, and all of the subprojects can also be opened, then Microsoft Project will present you with a unified view of the tasks and their relationships, even though the relationships cross different files. However, if you open your project but do not have the subproject files available, you will see placeholder external tasks representing the predecessor or successor tasks from the missing subproject files.

When reading the file using MPXJ, you will encounter the same situation: opening your MPP file without any of the subprojects being available you will see placeholder external tasks for predecessor and successor tasks from the subproject files. As we have already seen, the expandSubprojects method can be used to expand all subprojects, if the files they represent are available, allowing you to traverse the hierarchy of tasks. The expandSubprojects method also offers some additional functionality: when you pass true to this method, MPXJ will attempt to replace any predecessor or successor relationships which include placeholder external tasks with relationships which refer to the original task from a subproject, and those placeholder external tasks will be removed from the project entirely. This functionality is intended to replicate what you would see if you opened your file in Microsoft Project and all subprojects were successfully loaded.

As noted previously, the expandSubprojects method is only stitching together a set of individual ProjectFile instances so the tasks they contain can be traversed seamlessly, and in this case the predecessor and successor relationships between those tasks no longer use placeholder external tasks. This is still not a single unified ProjectFile instance so care should be taken when working with this data to bear in mind that it comes from a number of separate files.

"},{"location":"howto-use-external-projects/#resource-pools","title":"Resource Pools","text":"

The final way an external project can be used from a Microsoft Project schedule is as a resource pool. A resource pool schedule allows you to capture details of all of your organisation's resources in one place, then refer to them from multiple schedules. Setting up a resource pool like this should ensure that your resource utilisation across different projects is accurately captured as the utilisation detail in the resource pool is updated by the projects using those resources.

The full path for a project's resource pool can be retrieved using the getResourcePoolFile method as illustrated below:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ResourcePool\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      String path = file.getProjectProperties().getResourcePoolFile();\n   }\n}\n

In a similar manner to the other external project examples given in previous sections, MPXJ can also open and read the resource pool file for you:

package org.mpxj.howto.use.externalprojects;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class ResourcePoolObject\n{\n   public void process() throws Exception\n   {\n      ProjectFile file = new UniversalProjectReader().read(\"sample.mpp\");\n      ProjectFile resourcePool = file.getProjectProperties().getResourcePoolObject();\n   }\n}\n
"},{"location":"howto-use-external-projects/#mspdi-files","title":"MSPDI Files","text":"

Much of the detail noted above is also applicable to MSPDI files, but with the following exceptions:

  • Where the MSPDI file contains a Subproject, only the Subproject File attribute will be populated, the Subproject GUID add Subproject Tasks Unique ID Offset will not be available.
  • If an MSPDI file has been saved in Microsoft Project from an MPP file which contains Subprojects, and those Subprojects were expanded at the point the file was exported, the MSPDI file will actually contain the data for the Subproject as well as the main project. MPXJ will automatically read this data, which you can access using the getSubprojectObject method on the task, or you can call the expandSubproject or expandSubprojects methods documented in the previous sections to show the tasks contained in the Subproject as part of the main project.
  • Where the original MPP file contained an external task predecessor, the equivalent MSPDI file will not contain a placeholder task for the predecessor. MPXJ will generate one for you, but this will contain none of the attributes you would find if you read the MPP file using MPXJ.
  • MSPDI files do not contain any references to resource pools.

Note that although Microsoft Project will write external predecessor information to an MSPDI file, it will fail to load these correctly when the MSPDI file is reopened.

"},{"location":"howto-use-fields/","title":"How To: Use Fields","text":"

Once you've read a schedule using MPXJ, and you have a ProjectFile instance with tasks, resources and resource assignments, how do you access the data represented as fields in each of these entities? If you're creating or updating a schedule, how can you assign values to fields? This section explains the different approaches you can take in each of these cases.

"},{"location":"howto-use-fields/#setter-and-getter-methods","title":"Setter and Getter Methods","text":"

Let's start by creating a task we can use to demonstrate some of these approaches:

ProjectFile file = new ProjectFile();\nTask task = file.addTask();\n

When you already know exactly which field you need to access, you can work with the data these fields contain in a type-safe way by using the setter and getter methods provided by each class, for example:

task.setName(\"Task 1\");\n\nString name = task.getName();\nSystem.out.println(\"Task name: \" + name);\n

Here's the output from the sample code:

Task name: Task 1\n

Here we can see that we are able to set the name of the task using a String, and when we call the getter method we'll be returned the name as a String. How about working with a field that has a type other than a String?

LocalDateTime startDate = LocalDateTime.of(2022, 5, 10, 8, 0);\ntask.setStart(startDate);\n\nSystem.out.println(\"Start date: \" + task.getStart());\n

Here's the output from the sample code:

Start date: 2022-05-10T08:00\n

We're setting and retrieving the task's start date using a LocalDateTime instance. For almost all of the fields supported by tasks, resources, and resource assignments you'll find a pair of getter and setter methods allowing you to access and modify the field with a convenient type safe interface.

"},{"location":"howto-use-fields/#field-enumerations","title":"Field Enumerations","text":"

What if we don't know ahead of time which fields we need to access? For example, what if our application allows users to choose which fields to display for each task? In this case we can use a data-driven approach to read and write fields, as shown in the example below.

task = file.addTask();\ntask.set(TaskField.NAME, \"Task 2\");\n\nname = (String)task.get(TaskField.NAME);\nSystem.out.println(\"Task name: \" + name);\n\nstartDate = LocalDateTime.of(2022, 5, 11, 8, 0);\ntask.set(TaskField.START, startDate);\n\nSystem.out.println(\"Start date: \" + task.getStart());\n

Here's the output from this sample code:

Task name: Task 2\nStart date: 2022-05-11T08:00\n

What are the TaskField values in the example above? TaskField is an enumeration representing all of the fields of a Task instance. This type of enumeration is not unique to tasks, there are four main enumerations available:

  • ProjectField: fields available from ProjectProperties
  • ResourceField: fields available from a Resource
  • TaskField: fields available from a Task
  • AssignmentField: fields available from a ResourceAssignment

The ProjectProperties, Resource, Task and ResourceAssignment classes noted above actually all implement the FieldContainer interface. This is the interface that gives us the get and set methods we've seen in the examples above. FieldContainer also provides us with one more interesting method: getCachedValue. What is this, and why is it different to the get method? Let's take a step back and look at calculated values to understand where getCachedValue fits in.

"},{"location":"howto-use-fields/#calculated-fields","title":"Calculated Fields","text":"

Some of the fields available from each of these classes can actually contain a calculated value. For example: the Task field \"Start Variance\" represents the difference between the Baseline Start date and the Start date of a task. Some schedules may provide this value for us when we read the data they contain, others may not. If we don't have this value when we read our schedule data, but we do have a Baseline Start and Start date available to us, then we can perform the calculation ourselves to produce the Start Variance value. The example below illustrates this:

// Set up the sample project\nProjectFile file = new ProjectFile();\n\n// We need at least a default calendar to calculate variance\nfile.setDefaultCalendar(file.addDefaultBaseCalendar());\n\n// Create tasks\nTask task1 = file.addTask();\nTask task2 = file.addTask();\n\n// Set up example dates\nLocalDateTime baselineStart = LocalDateTime.of(2022, 5, 1, 8, 0);\nLocalDateTime startDate = LocalDateTime.of(2022,5, 10, 8, 0);\n\n// Update task1 using methods\ntask1.setStart(startDate);\ntask1.setBaselineStart(baselineStart);\n\n// Update task2 using TaskField enumeration\ntask2.set(TaskField.START, startDate);\ntask2.set(TaskField.BASELINE_START, baselineStart);\n\n// Show the variance being retrieved by method and TaskField enumeration\nSystem.out.println(\"Task 1\");\nSystem.out.println(\"Start Variance from method: \"\n   + task1.getStartVariance());\nSystem.out.println(\"Start Variance from get: \"\n   + task1.get(TaskField.START_VARIANCE));\nSystem.out.println();\n\nSystem.out.println(\"Task 2\");\nSystem.out.println(\"Start Variance from method: \"\n   + task2.getStartVariance());\nSystem.out.println(\"Start Variance from get: \"\n   + task2.get(TaskField.START_VARIANCE));\n

Here's the output from running this code:

Task 1\nStart Variance from method: 6.0d\nStart Variance from get: 6.0d\n\nTask 2\nStart Variance from method: 6.0d\nStart Variance from get: 6.0d\n

Regardless of how we set up the data, both the getStartVariance method and the call to get(TaskField.START_VARIANCE) trigger the calculation and produce the expected Start Variance value.

Rather than immediately discarding the Start Variance value we've just calculated, this value is cached as part of the data held by the task, and will be returned next time we use the getStartVariance method or we call get(TaskField.START_VARIANCE).

"},{"location":"howto-use-fields/#cached-values","title":"Cached Values","text":"

The getCachedValue method allows us to retrieve a field without attempting to calculate a value. It's not a method you'd normally expect to use, but it's worth mentioning for completeness. Let's take a look at this using a new example:

// Set up the sample project with a default calendar\nProjectFile file = new ProjectFile();\nfile.setDefaultCalendar(file.addDefaultBaseCalendar());\n\n// Set up example dates\nLocalDateTime baselineStart = LocalDateTime.of(2022, 5, 1, 8, 0);\nLocalDateTime startDate = LocalDateTime.of(2022,5, 10, 8, 0);\n\n// Create a task\nTask task = file.addTask();\ntask.setStart(startDate);\ntask.setBaselineStart(baselineStart);\n\nSystem.out.println(\"Start Variance using getCachedValue(): \" \n   + task.getCachedValue(TaskField.START_VARIANCE));\nSystem.out.println(\"Start Variance using get(): \" \n   + task.get(TaskField.START_VARIANCE));\nSystem.out.println(\"Start Variance using getCachedValue(): \" \n   + task.getCachedValue(TaskField.START_VARIANCE));\n

The output from this code is:

Start Variance using getCachedValue(): null\nStart Variance using get(): 6.0d\nStart Variance using getCachedValue(): 6.0d\n

What we can see happening here is that using the getCachedValue method initially returns null as the Start Variance is not present, and MPXJ doesn't attempt to calculate it. When we use the get method, MPXJ sees that it doesn't have a value for this field and knows how to calculate it, and returns the expected result. Finally if we use the getCachedValue method again, as we've now calculated this value and cached it, the method returns the Start Variance.

In summary, getCachedValue will never attempt to calculate values for fields which are not already present. This can be useful if you want to read a schedule using MPXJ, but retrieve only the fields which were in the original schedule, not calculated or inferred by MPXJ.

"},{"location":"howto-use-fields/#fieldtype","title":"FieldType","text":"

Earlier in this section we noted that there were four main enumerations representing the fields which particular classes can contain.

  • ProjectField
  • ResourceField
  • TaskField
  • AssignmentField

What I didn't mention then is that each of these enumerations implements the FieldType interface which defines a common set of methods for each of these enumerations. The most interesting of these methods are:

  • name()
  • getName()
  • getFieldTypeClass()
  • getDataType()

The name() method retrieves the name of the enumeration value exactly as it appears in the code. The getName() method returns a localized version of the name, suitable for display to end users (currently English is the default and only supported locale).

The getFieldTypeClass() method returns a value from the FieldTypeClass enumeration which will help you to determine which kind of object this FieldType belongs to (for example task, resource, and so on). Finally the getDataType() method will return a value from the DataType enumeration which indicates the data type you will receive from the get method when accessing this field, and the type to pass to the set method when updating the field.

Here's some example code to make this a little clearer:

FieldType type = TaskField.START_VARIANCE;\n\nSystem.out.println(\"name(): \" + type.name());\nSystem.out.println(\"getName(): \" + type.getName());\nSystem.out.println(\"getFieldTypeClass(): \" + type.getFieldTypeClass());\nSystem.out.println(\"getDataType():\" + type.getDataType());\n

In this case we're using the Task Start Variance field as an example. Here's the output:

name(): START_VARIANCE\ngetName(): Start Variance\ngetFieldTypeClass(): TASK\ngetDataType(): DURATION\n

Returning to our earlier example of how we might allow a user to select fields we will display, we can use the data type of the selected field to determine how we format the value for display.

private String getValueAsText(FieldContainer container, FieldType type)\n{\n    Object value = container.get(type);\n    if (value == null)\n    {\n        return \"\";\n    }\n\n    String result;\n    switch (type.getDataType())\n    {\n        case CURRENCY:\n        {\n            result = new DecimalFormat(\"\u00a30.00\").format(value);\n            break;\n        }\n\n        case DATE:\n        {\n            result = DateTimeFormatter.ofPattern(\"dd/MM/yyyy\").format((LocalDateTime)value);\n            break;\n        }\n\n        case BOOLEAN:\n        {\n            result = ((Boolean)value).booleanValue() ? \"Yes\" : \"No\";\n            break;\n        }\n\n        default:\n        {\n            result = value.toString();\n            break;\n        }\n    }\n\n    return result;\n}\n

The sample code above implements a generic method which can work with any class implementing the FieldContainer interface (for example, Task, Resource and so on). Given the particular field the user has asked us to display (passed in via the type argument), we retrieve the value from the container as an Object, then use the data type to decide how best to format the value for display. (This is obviously a contrived example - I wouldn't recommend creating new instances of DecimalFormat and DateTimeFormatter each time you need to format a value!)

"},{"location":"howto-use-fields/#custom-fields","title":"Custom Fields","text":"

So far we've seen how simple fields like Name and Start can be accessed and modified using both field-specific and generic methods. Name and Start are examples of standard fields which might be provided and managed by schedule applications, and have a well understood meaning. What if we have some additional data we want to capture in our schedule, but that data doesn't fit into any of these standard fields?

Microsoft Project's solution to this problem is Custom Fields. By default Microsoft Project provides a number of general purpose fields with names like \"Text 1\", \"Text 2\", \"Date 1\", \"Date 2\" and so on, which can be used to relevant vales as part of the schedule. If we look for methods like setText1 or setDate1 we won't find them, so how can we work with these fields?

The answer is quite straightforward, for each of these custom fields you'll find getter and setter methods which take an integer value, for example:

task.setText(1, \"This is Text 1\");\nString text1 = task.getText(1);\nSystem.out.println(\"Text 1 is: \" + text1);\n

If you're working with the generic get and set methods, the situation is more straightforward as each individual field has its own enumeration, as shown below:

task.set(TaskField.TEXT1, \"This is also Text 1\");\ntext1 = (String)task.get(TaskField.TEXT1);\nSystem.out.println(\"Text 1 is: \" + text1);\n

For Task, Resource and ResourceAssignment the following custom fields are available for use:

  • Cost 1-10
  • Date 1-10
  • Duration 1-10
  • Flag 1-20
  • Finish 1-10
  • Number 1-20
  • Start 1-10
  • Text 1-30
  • Outline Code 1-10 (Task and Resource only)

Microsoft Project allows users to configure custom fields. This facility can be used to do something as simple as provide an alias for the field, allowing it to be displayed with a meaningful name rather than something like \"Text 1\" or \"Date 1\". Alternatively there are more complex configurations available, for example constraining the values that can be entered for a field by using a lookup table, or providing a mask to enforce a particular format.

Information about custom field configurations can be obtained from the CustomFieldsContainer. The sample code below provides a simple illustration of how we can query this data.

ProjectFile file = new UniversalProjectReader().read(\"example.mpp\");\n\nCustomFieldContainer container = file.getCustomFields();\nfor (CustomField field : container)\n{\n    FieldType type = field.getFieldType();\n    String typeClass = type.getFieldTypeClass().toString();\n    String typeName = type.name();\n    String alias = field.getAlias();\n    System.out.println(typeClass + \".\" + typeName + \"\\t\" + alias);\n}\n

Depending on how the custom fields in your schedule are configured, you'll see output like this:

TASK.TEXT1      Change Request Reason\nTASK.NUMBER1    Number of Widgets Required\nRESOURCE.DATE1  Significant Date\n

In the source above, the first thing we're retrieving from each CustomField instance is the FieldType, which identifies the field we're configuring. The values we retrieve here will be from one of the enumerations we've touched on previously in this section, for example TaskField, ResourceField and so on.

The next thing we're doing in our sample code is to create a representation of the parent type to which this field belongs, followed by the name of the field itself (this is what's providing us with the value TASK.TEXT1 for example). Finally we're displaying the alias which has been set by the user for this field.

It's important to note that for schedules from Microsoft Project, there won't necessarily be a CustomField entry for all of the custom fields in use in a schedule. For example, if a user has added values to the \"Text 1\" field for each of the tasks in their schedule, but have not configured Text 1 in some way (for example by setting an alias or adding a lookup table) there won't be an entry for \"Text 1\" in the CustomFieldContainer.

As well as iterating through the collection of CustomField instances for the current schedule, you can directly request the CustomField instance for a specific field, as shown below:

CustomField fieldConfiguration = container.get(TaskField.TEXT1);\n

One common use-case for the configuration data help in CustomFieldContainer is to locate particular information you are expecting to find in the schedule. For example, let's say that you know that the schedule you're reading should have a field on each task which users have named \"Number of Widgets Required\", and you want to read that data. You can determine which field you need by using a method call similar to the one shown below:

FieldType fieldType = container.getFieldTypeByAlias(\n    FieldTypeClass.TASK,\n   \"Number of Widgets Required\");\n

Note that the first argument we need to pass identifies which parent entity we're expecting to find the field in. The CustomFieldContainer will have entries from all field containers (tasks, resources, resource assignments and so on) so this is used to locate the correct one - particularly useful if, for example, a task and a resource might both have a field with the same alias! Remember: this method will return null if we don't have a field with the alias you've provided.

Once we have the FieldType of the field we're looking for, we can use this to retrieve the value using the get method as we've seen earlier in this section:

Task task = file.getTaskByID(Integer.valueOf(1));\nObject value = task.get(fieldType);\n

Finally, there are a couple of convenience methods to make retrieving a field by its alias easier. The first is that each \"container\" class for the various entities also provides a getFieldTypeByAlias method. If you know ahead of time you're looking for a field in a particular entity, this will simplify your code somewhat. The example below illustrates this: as we're looking for a task field we can go straight to the TaskContainer and ask for the field with the alias we're looking for:

fieldType = file.getTasks().getFieldTypeByAlias(\"Number of Widgets Required\");\n

Lastly, you can actually retrieve the value of a field directly from the parent entity using its alias, as shown below:

value = task.getFieldByAlias(\"Number of Widgets Required\");\n

This is not recommended where you are iterating across multiple tasks to retrieve values: it's more efficient to look up the FieldType once before you start, then use that to retrieve the value you are interested in from each task.

"},{"location":"howto-use-fields/#populated-fields","title":"Populated Fields","text":"

So far we've touched on how to can read and write fields in examples where we are targeting specific fields. If we're reading a schedule whose contents are unknown to us, how can we tell which fields are actually populated? A typical use-case for this might be where we need to read a schedule, then present the user with the ability to select the columns they'd like to see in a tabular display of the schedule contents. If you look at the various enumerations we have mentioned previously in this section (TaskField, ResourceField and so on) you can see that there are a large number of possible fields a user could choose from, so ideally we only want to show a user fields which actually contain non-default values.

To solve this problem we need to use the appropriate getPopulatedFields method for each of the entities we're interested in.

ProjectFile file = new UniversalProjectReader().read(\"example.mpp\");\n\nSet<ProjectField> projectFields = file.getProjectProperties().getPopulatedFields();\nSet<TaskField> taskFields = file.getTasks().getPopulatedFields();\nSet<ResourceField> resourceFields = file.getResources().getPopulatedFields();\nSet<AssignmentField> assignmentFields = file.getResourceAssignments().getPopulatedFields();\n

In the example above we're opening a sample file, then for each of the main classes which implement the FieldContainer interface, we'll query the container which holds those classes and call its getPopulatedFields method. In each case this will return a Set containing the enumeration values representing fields which have non-default values.

If you need to you can retrieve all of this information in one go:

ProjectFile file = new UniversalProjectReader().read(\"example.mpp\");\n\nSet<FieldType> allFields = file.getPopulatedFields();\n

The set returned by the project's getPopulatedFields will contain all the populated fields from all entities which implement the FieldContainer interface. You'll need to remember to look at the FieldTypeClass value of each field in the resulting set to determine which entity the field belongs to. The following section provides more detail on this.

"},{"location":"howto-use-fields/#user-defined-fields","title":"User Defined Fields","text":"

In an earlier section we touched briefly on how Microsoft Project uses a fixed set of \"custom fields\" to allow you to store arbitrary data as part of the schedule. A more common approach in other applications is to allow you to create your own fields to represent the data you need to store - that way you can have exactly the fields you need, without needing to worry if you can fit your data into the fixed set of custom fields. In fact Microsoft Project also supports this concept, in the form of Enterprise Custom Fields, although these are only available if you are working with a schedule hosted in Project Server (Project 365).

As you can imagine MPXJ can't provide dedicated getter and setter methods for these fields as it doesn't know ahead of time what they are - they're user defined! Instead we rely on the get and set methods to work with these fields.

When a schedule is read by MPXJ, each user defined field is represented internally by an instance of the UserDefinedField class. This class implements the FieldType interface, and so can be used with the get and set methods to read and write these values.

You can see which user defined fields exist in a project using code similar to the example below:

for (UserDefinedField field : project.getUserDefinedFields())\n{\n    System.out.println(\"name(): \" + field.name());\n    System.out.println(\"getName(): \" + field.getName());\n    System.out.println(\"getFieldTypeClass(): \" + field.getFieldTypeClass());\n    System.out.println(\"getDataType():\" + field.getDataType());         \n}\n

As well as using the getUserDefinedFields method on the project to see which fields are defined, the getPopulatedFields methods discussed in an earlier section will also return UserDefinedField instances if these fields have values in the schedule. Information about UserDefinedField instances is also available in the CustomFieldContainer. This means that when you read a schedule and you are expecting certain user defined fields to be present, you can use the getFieldTypeByAlias or getFieldByAlias methods to find the fields you are interested in by name, as described in an earlier section.

If you import schedules data from an application which supports user defined fields and export to a Microsoft Project file format (MPX or MSPDI), MPXJ will automatically map any user defined fields to unused custom fields. Note that as there are only a finite number of custom field available, it is possible that not all user defined fields will be available when the resulting file is opened in Microsoft Project.

"},{"location":"howto-use-universal/","title":"How To: Use the Universal Project Reader","text":"

As you may have seen elsewhere in this documentation, the preferred way to read from most sources of schedule data is to use the UniversalProjectReader:

package org.mpxj.howto.use.universal;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.reader.ProjectReader;\nimport net.sf.mpxj.reader.UniversalProjectReader;\n\npublic class SimpleExample\n{\n   public void process() throws Exception\n   {\n      ProjectReader reader = new UniversalProjectReader();\n      ProjectFile project = reader.read(\"example.mpp\");\n   }\n}\n

This is very convenient as you don't need to know ahead of time what type of schedule file you are working with, UniversalProjectReader will figure this out for you. The drawback to this approach is that for a number of schedule types, the reader class for that type may provide additional configuration options to guide the way schedule data is read. In the example above, you can see that there is no opportunity to provide any extra configuration to the reader class selected by UniversalProjectReader.

To get around this issue, UniversalProjectReader provides access to \"project reader proxy\" classes. These proxy classes implement the UniversalProjectReader.ProjectReaderProxy interface and provide access to the reader class which UniversalProjectReader has selected to read the project data at the point just before schedule data has been read.

You can use these proxy classes to, for example, choose whether or not to continue reading the type of schedule contained in the supplied file or stream, or you can change the reader's settings before continuing to read the schedule. The example code below illustrates both these situations.

package org.mpxj.howto.use.universal;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.phoenix.PhoenixReader;\nimport net.sf.mpxj.reader.ProjectReader;\nimport net.sf.mpxj.reader.UniversalProjectReader;\nimport net.sf.mpxj.sdef.SDEFReader;\n\nimport java.io.File;\n\npublic class ProxyExample\n{\n   public void process(File file) throws Exception\n   {\n      UniversalProjectReader upr = new UniversalProjectReader();\n\n      // Retrieve the proxy\n      try (UniversalProjectReader.ProjectReaderProxy proxy\n              = upr.getProjectReaderProxy(file))\n      {\n         // Retrieve the reader class\n         ProjectReader reader = proxy.getProjectReader();\n\n         // Determine if we want to continue processing this file type.\n         // In this example we are ignoring SDEF files.\n         if (reader instanceof SDEFReader)\n         {\n            return;\n         }\n\n         // Provide configuration for specific reader types.\n         // In this example we are changing the behavior of the Phoenix reader.\n         if (reader instanceof PhoenixReader)\n         {\n            ((PhoenixReader)reader).setUseActivityCodesForTaskHierarchy(false);\n         }\n\n         // Finally, we read the schedule\n         ProjectFile project = proxy.read();\n\n         // Now we can work with the schedule data...\n      }\n   }\n}\n

The first thing to notice is that the proxy class is being used within a \"try with resources\" statement. This is important as the UniversalProjectReader may have a number of resources open (streams, temporary files, and so on) which need to be released once you have finished with the proxy class. UniversalProjectReader.ProjectReaderProxy implements the AutoCloseable interface, so you can either arrange to explicitly call the close method yourself at an appropriate point, or you can use try with resources to ensure this happens automatically.

The initial line of the try statement calls getProjectReaderProxy to retrieve the proxy. This method can be called with either a file name, a File instance, or an InputStream. Within the try block, the first thing we do is retrieve the reader class instance which the UniversalProjectReader has selected to read our schedule data.

The next two stanzas of code use instanceof to determine the type of the reader selected: in the first stanza we're choosing not to continue if we've been provided with an SDEF file. In the second stanza, if we are dealing with a Phoenix schedule, we're choosing to change the default behavior of the reader.

Finally at the end of the try block we're calling the read method of the proxy to read the schedule. The proxy also provides a readAll method: if the source data contains multiple schedules you can use this method to read them all.

Note that we're using the read or readAll methods provided by the proxy class, we're not attempting to use the methods provided on the reader class itself. This is important as the UniversalProjectReader may have located the schedule within a larger set of data, for example within a Zip file or sub-directory. The proxy class already has this context, whereas you won't necessarily have this information if you tried to use the reader class methods directly.

"},{"location":"howto-write-mpx/","title":"How To: Write MPX files","text":"

Versions of Microsoft Project up to Project 98 could read and write MPX files as a data interchange format. Versions of Project after Project 98 until Project 2010 can only read MPX files. Versions of Microsoft Project after 2010 cannot read MPX files. Other third party project planning applications continue to use MPX as a data interchange format.

"},{"location":"howto-write-mpx/#writing-mpx-files","title":"Writing MPX files","text":"

The sample code below illustrates how to write data to an MPX file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class MPX\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.MPX).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MPX\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.MPX).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mpx/#using-mpxwriter","title":"Using MPXWriter","text":"

If required, the MPXWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-mpx/#locale","title":"Locale","text":"

The MPX file format is actually locale specific, so in the example code below we can see that the writer is being asked to produce a file suitable for reading with a localized German version of Microsoft Project.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXWriter;\n\nimport java.util.Locale;\n\npublic class MPXLocale\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MPXWriter writer = new MPXWriter();\n        writer.setLocale(Locale.GERMAN);\n        writer.write(project, fileName);\n    }\n}\n
using System.Globalization;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MPXLocale\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MPXWriter();\n        writer.Culture = CultureInfo.GetCultureInfo(\"de\");\n        writer.Write(project, fileName);\n    }\n}\n

The locales supported by the MPX writer class can be retrieved using the following call:

JavaC#
MPXWriter.getSupportedLocales()\n
MPXWriter.SupportedCultures\n
"},{"location":"howto-write-mpx/#locale-defaults","title":"Locale Defaults","text":"

By default the MPX writer ignores the date, time, number and currency formats specified in the project properties and instead uses the defaults from the specified locale. Calling the setUseLocaleDefaults method and passing false ensures that the information present in the project properties is used instead of the locale defaults. This is illustrated in the sample code below:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mpx.MPXWriter;\n\nimport java.util.Locale;\n\npublic class MPXLocaleDefaults\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MPXWriter writer = new MPXWriter();\n        writer.setLocale(Locale.GERMAN);\n        writer.setUseLocaleDefaults(false);\n        writer.write(project, fileName);\n    }\n}\n
using System.Globalization;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MPXLocaleDefaults\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MPXWriter();\n        writer.Culture = CultureInfo.GetCultureInfo(\"de\");\n        writer.UseCultureDefaults = false;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/","title":"How To: Write MSPDI files","text":"

Since Microsoft Project 2002, Microsoft Project has been able to read and write an XML-based data interchange format called MSPDI.

"},{"location":"howto-write-mspdi/#writing-mspdi-files","title":"Writing MSPDI files","text":"

The sample code below illustrates how to write data to an MSPDI file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class MSPDI\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.MSPDI).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDI\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.MSPDI).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/#using-mspdiwriter","title":"Using MSPDIWriter","text":"

If required, the MSPDIWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-mspdi/#microsoft-project-compatible-output","title":"Microsoft Project Compatible Output","text":"

Microsoft Project has a non-standard way of representing negative duration values (it should have a minus sign as a prefix at the start of the XSD duration expression rather than embedded in it).

Originally MPXJ read and wrote correctly formatted XSD duration values, but unfortunately this meant that Project would not read these values correctly, and MPXJ would not be able to consume these values correctly from an MSPDI file written by Project. MPXJ has been updated so that it reads and writes the form of these duration values understood by Project, but this does mean that if you were previously expecting to be able to parse valid XSD duration values from output generated by MPXJ, that will no longer be the case.

To provide backward compatibility the MicrosoftProjectCompatibleOutput flag has been introduced. This defaults to true so MSPDI files containing negative durations written by MPXJ can be read by Project. If you need to produce correctly formatted XSD durations for consumption by applications other than Project you can set this flag to false:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\n\npublic class MSPDICompatibleOutput\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setMicrosoftProjectCompatibleOutput(false);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDICompatibleOutput\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.MicrosoftProjectCompatibleOutput = false;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/#save-version","title":"Save Version","text":"

The MSPDI file contains a SaveVersion attribute which indicates the version of Microsoft Project used to save the file. The value of SaveVersion is defined by the net.sf.mpxj.mspdi.SaveVersion enum, which provides the following values:

Project2002\nProject2003\nProject2007\nProject2010\nProject2013\nProject2016\n

By default MSPDIWriter sets the SaveVersion value to Project2016. The only functional difference this setting makes when writing MSPDI files is that the format of calendar exceptions changed in Project 2003 and onwards. MPXJ will always write calendar exceptions using the original Project 2002 format, and if the SaveVersion is set to Project2003 or later it will also write the new format data as well.

Here's an example of the SaveVersion attribute being set to ensure that only the older style of calendar exceptions is written to the MSPDI file:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\nimport net.sf.mpxj.mspdi.SaveVersion;\n\npublic class MSPDISaveVersion\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setSaveVersion(SaveVersion.Project2002);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDISaveVersion\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.SaveVersion = SaveVersion.Project2002;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-mspdi/#timephased-data","title":"Timephased Data","text":"

By default MSPDIWriter does not write timephased data to an MSPDI file. To enable writing timephased data, you can call the setWriteTimephasedData method.

When this setting is enabled, the default behaviour is for the timephased data is broken down into days when written to the file. If it better suits your use case (or you need a more compact file) you can choose to write an aggregated form of the timephased data by calling the setSplitTimephasedAsDays method and passing false. The difference between the two formats is that if for example you have a 10 day block with 8 hours work per day, this can either be represented as 10 entries in the file each for a single day with a value of 8 hours, or a single entry for a 10 day range with a value of 80 hours. Although the latter case is more compact, if you are consuming the MSPDI timephased data yourself you will need to differentiate between working and non-working days in order to break the single block down into smaller ranges. The default day-by-day format MPXJ writes does this for you automatically.

In the first example below we're enabling timephased data, and using the default day-by-dat breakdown:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\n\npublic class MSPDITimephased\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setWriteTimephasedData(true);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDITimephased\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.WriteTimephasedData = true;\n        writer.Write(project, fileName);\n    }\n}\n

In this second example we're overriding the default behaviour as asking MPXJ to write an aggregated form of the timephased data:

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.mspdi.MSPDIWriter;\n\npublic class MSPDITimephasedAggregate\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        MSPDIWriter writer = new MSPDIWriter();\n        writer.setWriteTimephasedData(true);\n        writer.setSplitTimephasedAsDays(false);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class MSPDITimephasedAggregate\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new MSPDIWriter();\n        writer.WriteTimephasedData = true;\n        writer.SplitTimephasedAsDays = true;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-planner/","title":"How To: Write Planner files","text":"

Gnome Planner is a simple cross platform planning tool. MPXJ can be used to write a schedule as a Planner file, which the Gnome Planner application can open.

"},{"location":"howto-write-planner/#writing-planner-files","title":"Writing Planner files","text":"

The sample code below illustrates how to write data to a Planner file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class Planner\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.PLANNER).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class Planner\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.PLANNER).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-planner/#using-plannerwriter","title":"Using PlannerWriter","text":"

If required, the PlannerWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-planner/#charset","title":"Charset","text":"

The character set used to write a Planner file can be specified using the setCharset method, as illustrated below.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.planner.PlannerWriter;\n\nimport java.nio.charset.Charset;\n\npublic class PlannerCharset\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        PlannerWriter writer = new PlannerWriter();\n        writer.setCharset(Charset.forName(\"GB2312\"));\n        writer.write(project, fileName);\n    }\n}\n
using System.Text;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class PlannerCharset\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new PlannerWriter();\n        writer.Encoding = Encoding.GetEncoding(\"GB2312\");\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-pmxml/","title":"How To: Write PMXML files","text":"

The XML file format supported by Primavera P6 for import and export is known as PMXML.

"},{"location":"howto-write-pmxml/#writing-pmxml-files","title":"Writing PMXML files","text":"

The sample code below illustrates how to write data to a PMXML file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class PMXML\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.PMXML).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class PMXML\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.PMXML).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-pmxml/#using-primaverapmfilewriter","title":"Using PrimaveraPMFileWriter","text":"

If required, the PrimaveraPMFileWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-pmxml/#baselines","title":"Baselines","text":"

By default baselines are not written to PMXML files. If the ProjectFile instance you are writing contains a baseline, this can be included in the PMXML file by calling the setWriteBaselines method as shown below.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraPMFileWriter;\n\npublic class PMXMLBaselines\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        PrimaveraPMFileWriter writer = new PrimaveraPMFileWriter();\n        writer.setWriteBaselines(true);\n        writer.write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class PMXMLBaselines\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new PrimaveraPMFileWriter();\n        writer.WriteBaselines = true;\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-sdef/","title":"How To: Write SDEF files","text":"

SDEF is the Standard Data Exchange Format, as defined by the USACE (United States Army Corps of Engineers). SDEF is a fixed column format text file, used to import a project schedule up into the QCS (Quality Control System) software from USACE. The specification for the file format can be found here.

"},{"location":"howto-write-sdef/#writing-sdef-files","title":"Writing SDEF files","text":"

The sample code below illustrates how to write data to an SDEF file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class SDEF\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.SDEF).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class SDEF\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.SDEF).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-sdef/#using-sdefwriter","title":"Using SDEFWriter","text":"

If required, the SDEFWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-sdef/#charset","title":"Charset","text":"

By default SDEF files are written using the US_ASCII charset. The setCharset method on the SDEFWriter class can be used to change this if required:

package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.sdef.SDEFWriter;\n\nimport java.nio.charset.StandardCharsets;\n\npublic class SDEFCharset\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        SDEFWriter writer = new SDEFWriter();\n        writer.setCharset(StandardCharsets.UTF_8);\n        writer.write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-xer/","title":"How To: Write XER files","text":"

XER files have been imported and exported by Primavera software since the earliest days of P6 and this format is still often the preferred way to move schedule data between instances of P6 even today.

"},{"location":"howto-write-xer/#writing-xer-files","title":"Writing XER files","text":"

The sample code below illustrates how to write data to an XER file.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.writer.FileFormat;\nimport net.sf.mpxj.writer.UniversalProjectWriter;\n\npublic class XER\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        new UniversalProjectWriter(FileFormat.XER).write(project, fileName);\n    }\n}\n
using MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class XER\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        new UniversalProjectWriter(FileFormat.XER).Write(project, fileName);\n    }\n}\n
"},{"location":"howto-write-xer/#using-primaveraxerfilewriter","title":"Using PrimaveraXERFileWriter","text":"

If required, the PrimaveraXERFileWriter class can be used directly, which provides access to additional options, as described below.

"},{"location":"howto-write-xer/#charset","title":"Charset","text":"

By default XER files written by MPXJ are encoded using the Windows-1252 character set. If you need to use a different character set, the setCharset method can be used to achieve this, as illustrated by the code below.

JavaC#
package org.mpxj.howto.write;\n\nimport net.sf.mpxj.ProjectFile;\nimport net.sf.mpxj.primavera.PrimaveraXERFileWriter;\n\nimport java.nio.charset.Charset;\n\npublic class XERCharset\n{\n    public void write(ProjectFile project, String fileName) throws Exception\n    {\n        PrimaveraXERFileWriter writer = new PrimaveraXERFileWriter();\n        writer.setCharset(Charset.forName(\"GB2312\"));\n        writer.write(project, fileName);\n    }\n}\n
using System.Text;\nusing MPXJ.Net;\n\nnamespace MPXJ.Samples.HowToWrite;\n\npublic class XERChatset\n{\n    public void Write(ProjectFile project, string fileName)\n    {\n        var writer = new PrimaveraXERFileWriter();\n        writer.Encoding = Encoding.GetEncoding(\"GB2312\");\n        writer.Write(project, fileName);\n    }\n}\n
"},{"location":"mpp-field-guide/","title":"MPP Field Guide","text":""},{"location":"mpp-field-guide/#mpp-field-guide","title":"MPP Field Guide","text":"

The tables below provide an indication of which fields are populated when different MPP file versions are read using MPXJ The tables are not hand-crafted: they have been generated from test data and are therefore may be missing some details.

"},{"location":"mpp-field-guide/#project","title":"Project","text":""},{"location":"mpp-field-guide/#core-fields","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 AM Text \u2713 \u2713 \u2713 \u2713 Activity ID Increment \u2713 \u2713 \u2713 \u2713 Activity ID Increment Based On Selected Activity \u2713 \u2713 \u2713 \u2713 Activity ID Prefix \u2713 \u2713 \u2713 \u2713 Activity ID Suffix \u2713 \u2713 \u2713 \u2713 Application Version \u2713 \u2713 \u2713 \u2713 Author \u2713 \u2713 \u2713 \u2713 Auto Add New Resources and Tasks \u2713 \u2713 \u2713 \u2713 Auto Filter \u2713 \u2713 Auto Link \u2713 \u2713 \u2713 \u2713 Bar Text Date Format \u2713 \u2713 \u2713 \u2713 Calculate Float on Finish Date of Each Project \u2713 \u2713 \u2713 \u2713 Calculate Multiple Paths Using Total Float \u2713 \u2713 \u2713 \u2713 Category \u2713 \u2713 \u2713 \u2713 Comments \u2713 \u2713 \u2713 \u2713 Company \u2713 \u2713 \u2713 \u2713 Compute Start to Start Lag From Early Start \u2713 \u2713 \u2713 \u2713 Consider Assignments In Other Project With Priority Equal or Higher Than \u2713 \u2713 \u2713 \u2713 Content Status \u2713 \u2713 \u2713 Content Type \u2713 \u2713 \u2713 Creation Date \u2713 \u2713 \u2713 \u2713 Critical Activity Type \u2713 \u2713 \u2713 \u2713 Critical Slack Limit \u2713 \u2713 Currency Code \u2713 \u2713 \u2713 Currency Digits \u2713 \u2713 \u2713 \u2713 Currency Symbol \u2713 \u2713 \u2713 \u2713 Currency Symbol Position \u2713 \u2713 \u2713 \u2713 Current Date \u2713 \u2713 \u2713 \u2713 Custom Properties \u2713 \u2713 \u2713 \u2713 Date Format \u2713 \u2713 \u2713 \u2713 Date Order \u2713 \u2713 \u2713 \u2713 Date Separator \u2713 \u2713 \u2713 \u2713 Days per Month \u2713 \u2713 \u2713 \u2713 Decimal Separator \u2713 \u2713 \u2713 \u2713 Default Calendar Unique ID \u2713 \u2713 \u2713 \u2713 Default End Time \u2713 \u2713 \u2713 \u2713 Default Overtime Rate \u2713 \u2713 \u2713 Default Standard Rate \u2713 \u2713 \u2713 Default Start Time \u2713 \u2713 \u2713 \u2713 Default Work Units \u2713 \u2713 \u2713 \u2713 Document Version \u2713 \u2713 \u2713 Editable Actual Costs \u2713 \u2713 Editing Time \u2713 \u2713 \u2713 \u2713 File Application \u2713 \u2713 \u2713 \u2713 File Type \u2713 \u2713 \u2713 \u2713 Finish Date \u2713 \u2713 \u2713 \u2713 Fiscal Year Start \u2713 \u2713 \u2713 \u2713 Fiscal Year Start Month \u2713 \u2713 \u2713 \u2713 Full Application Name \u2713 \u2713 \u2713 \u2713 GUID \u2713 \u2713 \u2713 \u2713 Honor Constraints \u2713 \u2713 \u2713 \u2713 Hyperlink Base \u2713 \u2713 \u2713 \u2713 Keywords \u2713 \u2713 \u2713 \u2713 Language \u2713 \u2713 \u2713 Last Author \u2713 \u2713 \u2713 \u2713 Last Printed \u2713 \u2713 \u2713 \u2713 Last Saved \u2713 \u2713 \u2713 \u2713 Level All Resources \u2713 \u2713 \u2713 \u2713 Leveling Priorities \u2713 \u2713 \u2713 \u2713 Limit Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 MPP File Type \u2713 \u2713 \u2713 \u2713 MPX Code Page \u2713 \u2713 \u2713 \u2713 MPX Delimiter \u2713 \u2713 \u2713 \u2713 MPX File Version \u2713 \u2713 \u2713 \u2713 MPX Program Name \u2713 \u2713 \u2713 \u2713 Manager \u2713 \u2713 \u2713 \u2713 Maximum Percentage to Overallocate Resources \u2713 \u2713 \u2713 \u2713 Microsoft Project Server URL \u2713 \u2713 \u2713 \u2713 Minutes per Day \u2713 \u2713 \u2713 \u2713 Minutes per Month \u2713 \u2713 \u2713 \u2713 Minutes per Week \u2713 \u2713 \u2713 \u2713 Minutes per Year \u2713 \u2713 \u2713 \u2713 Multiple Critical Paths \u2713 \u2713 \u2713 New Task Start Is Project Start \u2713 \u2713 \u2713 \u2713 New Tasks Are Manual \u2713 \u2713 \u2713 New Tasks Estimated \u2713 \u2713 \u2713 \u2713 Number of Float Paths to Calculate \u2713 \u2713 \u2713 \u2713 PM Text \u2713 \u2713 \u2713 \u2713 Presentation Format \u2713 \u2713 \u2713 Preserve Minimum Float When Leveling \u2713 \u2713 \u2713 \u2713 Preserve Scheduled Early and Late Dates \u2713 \u2713 \u2713 \u2713 Project File Path \u2713 \u2713 \u2713 Project Title \u2713 \u2713 \u2713 \u2713 Relationship Lag Calendar \u2713 \u2713 \u2713 \u2713 Resource Pool File \u2713 \u2713 \u2713 Revision \u2713 \u2713 \u2713 \u2713 Schedule From \u2713 \u2713 \u2713 \u2713 Short Application Name \u2713 \u2713 \u2713 \u2713 Show Project Summary Task \u2713 \u2713 \u2713 \u2713 Split In Progress Tasks \u2713 \u2713 \u2713 \u2713 Start Date \u2713 \u2713 \u2713 \u2713 Status Date \u2713 \u2713 \u2713 Subject \u2713 \u2713 \u2713 \u2713 Template \u2713 \u2713 \u2713 \u2713 Thousands Separator \u2713 \u2713 \u2713 \u2713 Time Format \u2713 \u2713 \u2713 \u2713 Time Separator \u2713 \u2713 \u2713 \u2713 Total Slack Calculation Type \u2713 \u2713 \u2713 \u2713 Updating Task Status Updates Resource Status \u2713 \u2713 \u2713 \u2713 Use Expected Finish Dates \u2713 \u2713 \u2713 \u2713 WBS Code Separator \u2713 \u2713 \u2713 \u2713 Week Start Day \u2713 \u2713 \u2713 \u2713 When Scheduling Progressed Activities Use \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Date \u2713 \u2713 \u2713 Baseline2 Date \u2713 \u2713 Baseline3 Date \u2713 \u2713 Baseline4 Date \u2713 \u2713 Baseline5 Date \u2713 \u2713 Baseline6 Date \u2713 \u2713 Baseline7 Date \u2713 \u2713 Baseline8 Date \u2713 \u2713 Baseline9 Date \u2713 \u2713 Baseline10 Date \u2713 \u2713 Baseline Calendar Name \u2713 \u2713 \u2713 \u2713 Baseline Date \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#task","title":"Task","text":""},{"location":"mpp-field-guide/#core-fields_1","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 % Complete \u2713 \u2713 \u2713 \u2713 % Work Complete \u2713 \u2713 \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 Activity Codes \u2713 \u2713 \u2713 \u2713 Activity Percent Complete \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 \u2713 Actual Duration \u2713 \u2713 \u2713 \u2713 Actual Duration Units \u2713 \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Board Status ID \u2713 Budget Cost \u2713 \u2713 \u2713 Budget Work \u2713 \u2713 \u2713 Calendar Unique ID \u2713 \u2713 \u2713 Complete Through \u2713 \u2713 \u2713 \u2713 Constraint Date \u2713 \u2713 \u2713 \u2713 Constraint Type \u2713 \u2713 \u2713 \u2713 Contact \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 \u2713 Critical \u2713 \u2713 \u2713 \u2713 Deadline \u2713 \u2713 \u2713 Duration \u2713 \u2713 \u2713 \u2713 Duration Units \u2713 \u2713 \u2713 Duration Variance \u2713 \u2713 \u2713 \u2713 Early Finish \u2713 \u2713 \u2713 \u2713 Early Start \u2713 \u2713 \u2713 \u2713 Earned Value Method \u2713 \u2713 Effort Driven \u2713 \u2713 \u2713 \u2713 Estimated \u2713 \u2713 \u2713 Expanded \u2713 \u2713 \u2713 \u2713 Expense Items \u2713 \u2713 \u2713 \u2713 External Project \u2713 \u2713 \u2713 External Task \u2713 \u2713 \u2713 Finish \u2713 \u2713 \u2713 \u2713 Finish Slack \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 \u2713 Fixed Cost \u2713 \u2713 \u2713 \u2713 Fixed Cost Accrual \u2713 \u2713 \u2713 \u2713 Free Slack \u2713 \u2713 \u2713 GUID \u2713 \u2713 Hide Bar \u2713 \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 \u2713 Hyperlink Data \u2713 \u2713 \u2713 Hyperlink Screen Tip \u2713 \u2713 \u2713 Hyperlink SubAddress \u2713 \u2713 \u2713 \u2713 ID \u2713 \u2713 \u2713 \u2713 Ignore Resource Calendar \u2713 \u2713 \u2713 Late Finish \u2713 \u2713 \u2713 \u2713 Late Start \u2713 \u2713 \u2713 \u2713 Level Assignments \u2713 \u2713 \u2713 \u2713 Leveling Can Split \u2713 \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 \u2713 \u2713 Leveling Delay Units \u2713 \u2713 \u2713 Manual Duration \u2713 Manual Duration Units \u2713 Marked \u2713 \u2713 \u2713 Milestone \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 Null \u2713 \u2713 \u2713 Outline Level \u2713 \u2713 \u2713 \u2713 Outline Number \u2713 \u2713 \u2713 \u2713 Overtime Cost \u2713 \u2713 \u2713 \u2713 Parent Task Unique ID \u2713 \u2713 \u2713 Physical % Complete \u2713 \u2713 \u2713 Preleveled Finish \u2713 \u2713 \u2713 \u2713 Preleveled Start \u2713 \u2713 \u2713 \u2713 Priority \u2713 \u2713 \u2713 \u2713 Project \u2713 \u2713 \u2713 Recalc Outline Codes \u2713 \u2713 Recurring \u2713 \u2713 \u2713 \u2713 Recurring Data \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 Remaining Duration \u2713 \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Resume \u2713 \u2713 \u2713 \u2713 Resume No Earlier Than \u2713 \u2713 \u2713 Rollup \u2713 \u2713 \u2713 \u2713 Scheduled Duration \u2713 Scheduled Finish \u2713 Scheduled Start \u2713 Show Duration Text \u2713 Show Finish Text \u2713 Show Start Text \u2713 Splits \u2713 \u2713 \u2713 Sprint ID \u2713 Start \u2713 \u2713 \u2713 \u2713 Start Slack \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 \u2713 Steps \u2713 \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 \u2713 Subproject File \u2713 \u2713 \u2713 Subproject GUID \u2713 \u2713 Subproject Task ID \u2713 \u2713 \u2713 Subproject Task Unique ID \u2713 \u2713 \u2713 Subproject Tasks Unique ID Offset \u2713 \u2713 \u2713 Summary \u2713 \u2713 \u2713 \u2713 Summary Progress \u2713 \u2713 \u2713 Task Calendar GUID \u2713 \u2713 Task Mode \u2713 Task Name \u2713 \u2713 \u2713 \u2713 Total Slack \u2713 \u2713 \u2713 \u2713 Type \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 WBS \u2713 \u2713 \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields_1","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Duration \u2713 \u2713 \u2713 Baseline1 Duration Units \u2713 \u2713 Baseline1 Estimated Duration \u2713 Baseline1 Estimated Finish \u2713 Baseline1 Estimated Start \u2713 Baseline1 Finish \u2713 \u2713 \u2713 Baseline1 Fixed Cost \u2713 \u2713 \u2713 Baseline1 Fixed Cost Accrual \u2713 \u2713 Baseline1 Start \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Duration \u2713 \u2713 \u2713 Baseline2 Duration Units \u2713 \u2713 Baseline2 Estimated Duration \u2713 Baseline2 Estimated Finish \u2713 Baseline2 Estimated Start \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Fixed Cost \u2713 \u2713 \u2713 Baseline2 Fixed Cost Accrual \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Duration \u2713 \u2713 \u2713 Baseline3 Duration Units \u2713 \u2713 Baseline3 Estimated Duration \u2713 Baseline3 Estimated Finish \u2713 Baseline3 Estimated Start \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Fixed Cost \u2713 \u2713 \u2713 Baseline3 Fixed Cost Accrual \u2713 \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Duration \u2713 \u2713 \u2713 Baseline4 Duration Units \u2713 \u2713 Baseline4 Estimated Duration \u2713 Baseline4 Estimated Finish \u2713 Baseline4 Estimated Start \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Fixed Cost \u2713 \u2713 \u2713 Baseline4 Fixed Cost Accrual \u2713 \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Duration \u2713 \u2713 \u2713 Baseline5 Duration Units \u2713 \u2713 Baseline5 Estimated Duration \u2713 Baseline5 Estimated Finish \u2713 Baseline5 Estimated Start \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Fixed Cost \u2713 \u2713 \u2713 Baseline5 Fixed Cost Accrual \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Duration \u2713 \u2713 \u2713 Baseline6 Duration Units \u2713 \u2713 Baseline6 Estimated Duration \u2713 Baseline6 Estimated Finish \u2713 Baseline6 Estimated Start \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Fixed Cost \u2713 \u2713 \u2713 Baseline6 Fixed Cost Accrual \u2713 \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Duration \u2713 \u2713 \u2713 Baseline7 Duration Units \u2713 \u2713 Baseline7 Estimated Duration \u2713 Baseline7 Estimated Finish \u2713 Baseline7 Estimated Start \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Fixed Cost \u2713 \u2713 \u2713 Baseline7 Fixed Cost Accrual \u2713 \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Duration \u2713 \u2713 \u2713 Baseline8 Duration Units \u2713 \u2713 Baseline8 Estimated Duration \u2713 Baseline8 Estimated Finish \u2713 Baseline8 Estimated Start \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Fixed Cost \u2713 \u2713 \u2713 Baseline8 Fixed Cost Accrual \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Duration \u2713 \u2713 \u2713 Baseline9 Duration Units \u2713 \u2713 Baseline9 Estimated Duration \u2713 Baseline9 Estimated Finish \u2713 Baseline9 Estimated Start \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Fixed Cost \u2713 \u2713 \u2713 Baseline9 Fixed Cost Accrual \u2713 \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Deliverable Finish \u2713 Baseline10 Duration \u2713 \u2713 \u2713 Baseline10 Duration Units \u2713 \u2713 Baseline10 Estimated Duration \u2713 Baseline10 Estimated Finish \u2713 Baseline10 Estimated Start \u2713 Baseline10 Finish \u2713 \u2713 \u2713 Baseline10 Fixed Cost \u2713 \u2713 \u2713 Baseline10 Fixed Cost Accrual \u2713 \u2713 Baseline10 Start \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 \u2713 Baseline Deliverable Finish \u2713 Baseline Deliverable Start \u2713 Baseline Duration \u2713 \u2713 \u2713 \u2713 Baseline Duration Units \u2713 \u2713 \u2713 Baseline Estimated Duration \u2713 Baseline Estimated Finish \u2713 Baseline Estimated Start \u2713 Baseline Finish \u2713 \u2713 \u2713 \u2713 Baseline Fixed Cost \u2713 \u2713 \u2713 Baseline Fixed Cost Accrual \u2713 \u2713 Baseline Start \u2713 \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#custom-fields","title":"Custom Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 \u2713 Duration1 Units \u2713 \u2713 \u2713 Duration2 \u2713 \u2713 \u2713 \u2713 Duration2 Units \u2713 \u2713 \u2713 Duration3 \u2713 \u2713 \u2713 \u2713 Duration3 Units \u2713 \u2713 \u2713 Duration4 \u2713 \u2713 \u2713 \u2713 Duration4 Units \u2713 \u2713 \u2713 Duration5 \u2713 \u2713 \u2713 \u2713 Duration5 Units \u2713 \u2713 \u2713 Duration6 \u2713 \u2713 \u2713 \u2713 Duration6 Units \u2713 \u2713 \u2713 Duration7 \u2713 \u2713 \u2713 \u2713 Duration7 Units \u2713 \u2713 \u2713 Duration8 \u2713 \u2713 \u2713 \u2713 Duration8 Units \u2713 \u2713 \u2713 Duration9 \u2713 \u2713 \u2713 \u2713 Duration9 Units \u2713 \u2713 \u2713 Duration10 \u2713 \u2713 \u2713 \u2713 Duration10 Units \u2713 \u2713 \u2713 Finish1 \u2713 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 \u2713 \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 \u2713 \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 \u2713 \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 \u2713 \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 \u2713 \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 \u2713 \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 \u2713 \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 \u2713 \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 \u2713 \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#enterprise-fields","title":"Enterprise Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Enterprise Data \u2713 Enterprise Duration1 Units \u2713 \u2713 Enterprise Duration2 Units \u2713 \u2713 Enterprise Duration3 Units \u2713 \u2713 Enterprise Duration4 Units \u2713 \u2713 Enterprise Duration5 Units \u2713 \u2713 Enterprise Duration6 Units \u2713 \u2713 Enterprise Duration7 Units \u2713 \u2713 Enterprise Duration8 Units \u2713 \u2713 Enterprise Duration9 Units \u2713 \u2713 Enterprise Duration10 Units \u2713 \u2713 Enterprise Project Date1 \u2713 Enterprise Project Date2 \u2713 Enterprise Project Date3 \u2713 Enterprise Project Date4 \u2713 Enterprise Project Number2 \u2713 Enterprise Project Number4 \u2713 Enterprise Project Number5 \u2713 Enterprise Project Number22 \u2713 Enterprise Project Text1 \u2713 \u2713 \u2713 Enterprise Project Text2 \u2713 \u2713 Enterprise Project Text3 \u2713 \u2713 Enterprise Project Text4 \u2713 \u2713 Enterprise Project Text5 \u2713 Enterprise Project Text6 \u2713 \u2713 Enterprise Project Text8 \u2713 Enterprise Project Text9 \u2713 Enterprise Project Text10 \u2713 Enterprise Project Text11 \u2713 Enterprise Project Text12 \u2713 Enterprise Project Text13 \u2713 Enterprise Project Text14 \u2713 Enterprise Project Text15 \u2713 Enterprise Project Text16 \u2713 Enterprise Project Text17 \u2713 Enterprise Project Text18 \u2713 Enterprise Project Text19 \u2713 Enterprise Project Text21 \u2713 Enterprise Project Text40 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#resource","title":"Resource","text":""},{"location":"mpp-field-guide/#core-fields_2","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Accrue At \u2713 \u2713 \u2713 \u2713 Active \u2713 \u2713 \u2713 \u2713 Actual Cost \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Availability Data \u2713 \u2713 \u2713 Available From \u2713 \u2713 \u2713 Available To \u2713 \u2713 \u2713 Booking Type \u2713 \u2713 Budget \u2713 \u2713 Budget Cost \u2713 \u2713 \u2713 Budget Work \u2713 \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 Calendar GUID \u2713 \u2713 Calendar Unique ID \u2713 \u2713 \u2713 \u2713 Code \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Center \u2713 Cost Per Use \u2713 \u2713 \u2713 Cost Rate A \u2713 \u2713 \u2713 Cost Rate B \u2713 \u2713 \u2713 Cost Rate C \u2713 \u2713 \u2713 Cost Rate D \u2713 \u2713 \u2713 Cost Rate E \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 Default Units \u2713 \u2713 \u2713 \u2713 Email Address \u2713 \u2713 \u2713 GUID \u2713 \u2713 Generic \u2713 \u2713 \u2713 Group \u2713 \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 Hyperlink Data \u2713 \u2713 \u2713 Hyperlink Screen Tip \u2713 \u2713 \u2713 Hyperlink SubAddress \u2713 \u2713 \u2713 ID \u2713 \u2713 \u2713 \u2713 Initials \u2713 \u2713 \u2713 \u2713 Material Label \u2713 \u2713 \u2713 Max Units \u2713 \u2713 \u2713 Name \u2713 \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 \u2713 Overallocated \u2713 \u2713 \u2713 \u2713 Overtime Cost \u2713 \u2713 \u2713 Overtime Rate \u2713 \u2713 \u2713 Overtime Rate Units \u2713 \u2713 \u2713 Overtime Work \u2713 \u2713 \u2713 Peak \u2713 \u2713 \u2713 \u2713 Phonetics \u2713 Regular Work \u2713 \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Standard Rate \u2713 \u2713 \u2713 Standard Rate Units \u2713 \u2713 \u2713 Subproject Unique Resource ID \u2713 \u2713 Type \u2713 \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 Unit of Measure Unique ID \u2713 \u2713 \u2713 Windows User Account \u2713 \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713 \u2713 Workgroup \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields_2","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Budget Cost \u2713 Baseline1 Budget Work \u2713 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Budget Cost \u2713 Baseline2 Budget Work \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Budget Cost \u2713 Baseline3 Budget Work \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Budget Cost \u2713 Baseline4 Budget Work \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Budget Cost \u2713 Baseline5 Budget Work \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Budget Cost \u2713 Baseline6 Budget Work \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Budget Cost \u2713 Baseline7 Budget Work \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Budget Cost \u2713 Baseline8 Budget Work \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Budget Cost \u2713 Baseline9 Budget Work \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Budget Cost \u2713 Baseline10 Budget Work \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 Baseline Budget Work \u2713 Baseline Cost \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#custom-fields_1","title":"Custom Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 \u2713 \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 \u2713 \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 \u2713 \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 \u2713 \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 \u2713 \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 \u2713 \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 \u2713 \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 \u2713 \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 \u2713 \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 \u2713 \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Outline Code1 \u2713 \u2713 \u2713 Outline Code1 Index \u2713 \u2713 \u2713 Outline Code2 \u2713 \u2713 \u2713 Outline Code2 Index \u2713 \u2713 \u2713 Outline Code3 \u2713 \u2713 \u2713 Outline Code3 Index \u2713 \u2713 \u2713 Outline Code4 \u2713 \u2713 \u2713 Outline Code4 Index \u2713 \u2713 \u2713 Outline Code5 \u2713 \u2713 \u2713 Outline Code5 Index \u2713 \u2713 \u2713 Outline Code6 \u2713 \u2713 \u2713 Outline Code6 Index \u2713 \u2713 \u2713 Outline Code7 \u2713 \u2713 \u2713 Outline Code7 Index \u2713 \u2713 \u2713 Outline Code8 \u2713 \u2713 \u2713 Outline Code8 Index \u2713 \u2713 \u2713 Outline Code9 \u2713 \u2713 \u2713 Outline Code9 Index \u2713 \u2713 \u2713 Outline Code10 \u2713 \u2713 \u2713 Outline Code10 Index \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#enterprise-fields_1","title":"Enterprise Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Enterprise \u2713 \u2713 Enterprise Data \u2713 Enterprise Duration1 Units \u2713 \u2713 Enterprise Duration2 Units \u2713 \u2713 Enterprise Duration3 Units \u2713 \u2713 Enterprise Duration4 Units \u2713 \u2713 Enterprise Duration5 Units \u2713 \u2713 Enterprise Duration6 Units \u2713 \u2713 Enterprise Duration7 Units \u2713 \u2713 Enterprise Duration8 Units \u2713 \u2713 Enterprise Duration9 Units \u2713 \u2713 Enterprise Duration10 Units \u2713 \u2713 Enterprise Unique ID \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#resource-assignment","title":"Resource Assignment","text":""},{"location":"mpp-field-guide/#core-fields_3","title":"Core Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Actual Cost \u2713 \u2713 \u2713 Actual Finish \u2713 \u2713 \u2713 Actual Overtime Cost \u2713 \u2713 \u2713 Actual Overtime Work \u2713 \u2713 \u2713 Actual Start \u2713 \u2713 \u2713 Actual Work \u2713 \u2713 \u2713 \u2713 Actual Work Protected \u2713 Assignment Delay \u2713 \u2713 \u2713 Assignment GUID \u2713 \u2713 Assignment Resource GUID \u2713 \u2713 Assignment Task GUID \u2713 \u2713 Assignment Units \u2713 \u2713 \u2713 \u2713 Budget Cost \u2713 \u2713 Budget Work \u2713 \u2713 Calculate Costs From Units \u2713 \u2713 \u2713 \u2713 Confirmed \u2713 \u2713 \u2713 Cost \u2713 \u2713 \u2713 \u2713 Cost Rate Table \u2713 \u2713 \u2713 Cost Variance \u2713 \u2713 \u2713 Created \u2713 \u2713 \u2713 Finish \u2713 \u2713 \u2713 \u2713 Finish Variance \u2713 \u2713 \u2713 Hyperlink \u2713 \u2713 \u2713 Hyperlink Address \u2713 \u2713 \u2713 Hyperlink Data \u2713 \u2713 \u2713 Hyperlink Screen Tip \u2713 \u2713 \u2713 Hyperlink Subaddress \u2713 \u2713 \u2713 Leveling Delay \u2713 \u2713 \u2713 Leveling Delay Units \u2713 \u2713 Linked Fields \u2713 \u2713 \u2713 Notes \u2713 \u2713 \u2713 Overtime Work \u2713 \u2713 \u2713 Owner \u2713 \u2713 Percent Work Complete \u2713 \u2713 \u2713 \u2713 Rate Source \u2713 \u2713 \u2713 \u2713 Regular Work \u2713 \u2713 \u2713 Remaining Assignment Units \u2713 \u2713 \u2713 \u2713 Remaining Cost \u2713 \u2713 \u2713 Remaining Overtime Cost \u2713 \u2713 \u2713 Remaining Overtime Work \u2713 \u2713 \u2713 Remaining Work \u2713 \u2713 \u2713 \u2713 Resource Request Type \u2713 \u2713 Resource Unique ID \u2713 \u2713 \u2713 \u2713 Response Pending \u2713 \u2713 \u2713 Resume \u2713 \u2713 \u2713 Start \u2713 \u2713 \u2713 \u2713 Start Variance \u2713 \u2713 \u2713 Stop \u2713 \u2713 \u2713 Task Unique ID \u2713 \u2713 \u2713 \u2713 Team Status Pending \u2713 \u2713 \u2713 Timephased Actual Overtime Work \u2713 \u2713 \u2713 Timephased Actual Work \u2713 \u2713 \u2713 Timephased Work \u2713 \u2713 \u2713 Unique ID \u2713 \u2713 \u2713 \u2713 Variable Rate Units \u2713 \u2713 Work \u2713 \u2713 \u2713 \u2713 Work Contour \u2713 \u2713 \u2713 Work Variance \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#baseline-fields_3","title":"Baseline Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Baseline1 Budget Cost \u2713 \u2713 Baseline1 Budget Work \u2713 \u2713 Baseline1 Cost \u2713 \u2713 \u2713 Baseline1 Finish \u2713 \u2713 \u2713 Baseline1 Start \u2713 \u2713 \u2713 Baseline1 Work \u2713 \u2713 \u2713 Baseline2 Budget Cost \u2713 \u2713 Baseline2 Budget Work \u2713 \u2713 Baseline2 Cost \u2713 \u2713 \u2713 Baseline2 Finish \u2713 \u2713 \u2713 Baseline2 Start \u2713 \u2713 \u2713 Baseline2 Work \u2713 \u2713 \u2713 Baseline3 Budget Cost \u2713 \u2713 Baseline3 Budget Work \u2713 \u2713 Baseline3 Cost \u2713 \u2713 \u2713 Baseline3 Finish \u2713 \u2713 \u2713 Baseline3 Start \u2713 \u2713 \u2713 Baseline3 Work \u2713 \u2713 \u2713 Baseline4 Budget Cost \u2713 \u2713 Baseline4 Budget Work \u2713 \u2713 Baseline4 Cost \u2713 \u2713 \u2713 Baseline4 Finish \u2713 \u2713 \u2713 Baseline4 Start \u2713 \u2713 \u2713 Baseline4 Work \u2713 \u2713 \u2713 Baseline5 Budget Cost \u2713 \u2713 Baseline5 Budget Work \u2713 \u2713 Baseline5 Cost \u2713 \u2713 \u2713 Baseline5 Finish \u2713 \u2713 \u2713 Baseline5 Start \u2713 \u2713 \u2713 Baseline5 Work \u2713 \u2713 \u2713 Baseline6 Budget Cost \u2713 \u2713 Baseline6 Budget Work \u2713 \u2713 Baseline6 Cost \u2713 \u2713 \u2713 Baseline6 Finish \u2713 \u2713 \u2713 Baseline6 Start \u2713 \u2713 \u2713 Baseline6 Work \u2713 \u2713 \u2713 Baseline7 Budget Cost \u2713 \u2713 Baseline7 Budget Work \u2713 \u2713 Baseline7 Cost \u2713 \u2713 \u2713 Baseline7 Finish \u2713 \u2713 \u2713 Baseline7 Start \u2713 \u2713 \u2713 Baseline7 Work \u2713 \u2713 \u2713 Baseline8 Budget Cost \u2713 \u2713 Baseline8 Budget Work \u2713 \u2713 Baseline8 Cost \u2713 \u2713 \u2713 Baseline8 Finish \u2713 \u2713 \u2713 Baseline8 Start \u2713 \u2713 \u2713 Baseline8 Work \u2713 \u2713 \u2713 Baseline9 Budget Cost \u2713 \u2713 Baseline9 Budget Work \u2713 \u2713 Baseline9 Cost \u2713 \u2713 \u2713 Baseline9 Finish \u2713 \u2713 \u2713 Baseline9 Start \u2713 \u2713 \u2713 Baseline9 Work \u2713 \u2713 \u2713 Baseline10 Budget Cost \u2713 \u2713 Baseline10 Budget Work \u2713 \u2713 Baseline10 Cost \u2713 \u2713 \u2713 Baseline10 Finish \u2713 \u2713 \u2713 Baseline10 Start \u2713 \u2713 \u2713 Baseline10 Work \u2713 \u2713 \u2713 Baseline Budget Cost \u2713 \u2713 Baseline Budget Work \u2713 \u2713 Baseline Cost \u2713 \u2713 \u2713 Baseline Finish \u2713 \u2713 \u2713 Baseline Start \u2713 \u2713 \u2713 Baseline Work \u2713 \u2713 \u2713 Timephased Baseline1 Cost \u2713 \u2713 \u2713 Timephased Baseline1 Work \u2713 \u2713 \u2713 Timephased Baseline2 Cost \u2713 \u2713 Timephased Baseline2 Work \u2713 \u2713 Timephased Baseline3 Cost \u2713 \u2713 Timephased Baseline3 Work \u2713 \u2713 Timephased Baseline4 Cost \u2713 \u2713 Timephased Baseline4 Work \u2713 \u2713 Timephased Baseline5 Cost \u2713 \u2713 Timephased Baseline5 Work \u2713 \u2713 Timephased Baseline6 Cost \u2713 \u2713 Timephased Baseline6 Work \u2713 \u2713 Timephased Baseline7 Cost \u2713 \u2713 Timephased Baseline7 Work \u2713 \u2713 Timephased Baseline8 Cost \u2713 \u2713 Timephased Baseline8 Work \u2713 \u2713 Timephased Baseline9 Cost \u2713 \u2713 Timephased Baseline9 Work \u2713 \u2713 Timephased Baseline10 Cost \u2713 \u2713 \u2713 Timephased Baseline10 Work \u2713 \u2713 \u2713 Timephased Baseline Cost \u2713 \u2713 \u2713 Timephased Baseline Work \u2713 \u2713 \u2713"},{"location":"mpp-field-guide/#custom-fields_2","title":"Custom Fields","text":"Field MPP8 MPP9 MPP12 MPP14 Cost1 \u2713 \u2713 \u2713 Cost2 \u2713 \u2713 \u2713 Cost3 \u2713 \u2713 \u2713 Cost4 \u2713 \u2713 \u2713 Cost5 \u2713 \u2713 \u2713 Cost6 \u2713 \u2713 \u2713 Cost7 \u2713 \u2713 \u2713 Cost8 \u2713 \u2713 \u2713 Cost9 \u2713 \u2713 \u2713 Cost10 \u2713 \u2713 \u2713 Date1 \u2713 \u2713 \u2713 Date2 \u2713 \u2713 \u2713 Date3 \u2713 \u2713 \u2713 Date4 \u2713 \u2713 \u2713 Date5 \u2713 \u2713 \u2713 Date6 \u2713 \u2713 \u2713 Date7 \u2713 \u2713 \u2713 Date8 \u2713 \u2713 \u2713 Date9 \u2713 \u2713 \u2713 Date10 \u2713 \u2713 \u2713 Duration1 \u2713 \u2713 \u2713 Duration1 Units \u2713 \u2713 \u2713 Duration2 \u2713 \u2713 \u2713 Duration2 Units \u2713 \u2713 \u2713 Duration3 \u2713 \u2713 \u2713 Duration3 Units \u2713 \u2713 \u2713 Duration4 \u2713 \u2713 \u2713 Duration4 Units \u2713 \u2713 \u2713 Duration5 \u2713 \u2713 \u2713 Duration5 Units \u2713 \u2713 \u2713 Duration6 \u2713 \u2713 \u2713 Duration6 Units \u2713 \u2713 \u2713 Duration7 \u2713 \u2713 \u2713 Duration7 Units \u2713 \u2713 \u2713 Duration8 \u2713 \u2713 \u2713 Duration8 Units \u2713 \u2713 \u2713 Duration9 \u2713 \u2713 \u2713 Duration9 Units \u2713 \u2713 \u2713 Duration10 \u2713 \u2713 \u2713 Duration10 Units \u2713 \u2713 \u2713 Finish1 \u2713 \u2713 \u2713 Finish2 \u2713 \u2713 \u2713 Finish3 \u2713 \u2713 \u2713 Finish4 \u2713 \u2713 \u2713 Finish5 \u2713 \u2713 \u2713 Finish6 \u2713 \u2713 \u2713 Finish7 \u2713 \u2713 \u2713 Finish8 \u2713 \u2713 \u2713 Finish9 \u2713 \u2713 \u2713 Finish10 \u2713 \u2713 \u2713 Flag1 \u2713 \u2713 \u2713 Flag2 \u2713 \u2713 \u2713 Flag3 \u2713 \u2713 \u2713 Flag4 \u2713 \u2713 \u2713 Flag5 \u2713 \u2713 \u2713 Flag6 \u2713 \u2713 \u2713 Flag7 \u2713 \u2713 \u2713 Flag8 \u2713 \u2713 \u2713 Flag9 \u2713 \u2713 \u2713 Flag10 \u2713 \u2713 \u2713 Flag11 \u2713 \u2713 \u2713 Flag12 \u2713 \u2713 \u2713 Flag13 \u2713 \u2713 \u2713 Flag14 \u2713 \u2713 \u2713 Flag15 \u2713 \u2713 \u2713 Flag16 \u2713 \u2713 \u2713 Flag17 \u2713 \u2713 \u2713 Flag18 \u2713 \u2713 \u2713 Flag19 \u2713 \u2713 \u2713 Flag20 \u2713 \u2713 \u2713 Number1 \u2713 \u2713 \u2713 Number2 \u2713 \u2713 \u2713 Number3 \u2713 \u2713 \u2713 Number4 \u2713 \u2713 \u2713 Number5 \u2713 \u2713 \u2713 Number6 \u2713 \u2713 \u2713 Number7 \u2713 \u2713 \u2713 Number8 \u2713 \u2713 \u2713 Number9 \u2713 \u2713 \u2713 Number10 \u2713 \u2713 \u2713 Number11 \u2713 \u2713 \u2713 Number12 \u2713 \u2713 \u2713 Number13 \u2713 \u2713 \u2713 Number14 \u2713 \u2713 \u2713 Number15 \u2713 \u2713 \u2713 Number16 \u2713 \u2713 \u2713 Number17 \u2713 \u2713 \u2713 Number18 \u2713 \u2713 \u2713 Number19 \u2713 \u2713 \u2713 Number20 \u2713 \u2713 \u2713 Start1 \u2713 \u2713 \u2713 Start2 \u2713 \u2713 \u2713 Start3 \u2713 \u2713 \u2713 Start4 \u2713 \u2713 \u2713 Start5 \u2713 \u2713 \u2713 Start6 \u2713 \u2713 \u2713 Start7 \u2713 \u2713 \u2713 Start8 \u2713 \u2713 \u2713 Start9 \u2713 \u2713 \u2713 Start10 \u2713 \u2713 \u2713 Text1 \u2713 \u2713 \u2713 Text2 \u2713 \u2713 \u2713 Text3 \u2713 \u2713 \u2713 Text4 \u2713 \u2713 \u2713 Text5 \u2713 \u2713 \u2713 Text6 \u2713 \u2713 \u2713 Text7 \u2713 \u2713 \u2713 Text8 \u2713 \u2713 \u2713 Text9 \u2713 \u2713 \u2713 Text10 \u2713 \u2713 \u2713 Text11 \u2713 \u2713 \u2713 Text12 \u2713 \u2713 \u2713 Text13 \u2713 \u2713 \u2713 Text14 \u2713 \u2713 \u2713 Text15 \u2713 \u2713 \u2713 Text16 \u2713 \u2713 \u2713 Text17 \u2713 \u2713 \u2713 Text18 \u2713 \u2713 \u2713 Text19 \u2713 \u2713 \u2713 Text20 \u2713 \u2713 \u2713 Text21 \u2713 \u2713 \u2713 Text22 \u2713 \u2713 \u2713 Text23 \u2713 \u2713 \u2713 Text24 \u2713 \u2713 \u2713 Text25 \u2713 \u2713 \u2713 Text26 \u2713 \u2713 \u2713 Text27 \u2713 \u2713 \u2713 Text28 \u2713 \u2713 \u2713 Text29 \u2713 \u2713 \u2713 Text30 \u2713 \u2713 \u2713"},{"location":"support/","title":"Support","text":"

Support and feature requests can be opened on MPXJ's issue tracker. I will respond to these as time permits.

For more pressing issues, commercial support is available via my company Timephased. I can also provide consultancy around the use of MPXJ and implementation services. Please contact me directly for further details.

"},{"location":"supported-formats/","title":"Supported Formats","text":"
  • MPX: The MPX file format can be read by versions of Microsoft Project up to and including Microsoft Project 2010, and written by versions of Microsoft Project up to Microsoft Project 98. Applications other than Microsoft Project also commonly write MPX files as a way of sharing project data. MPXJ can read and write MPX files. See this Microsoft support article for a definition of the file format.

  • MPP: Microsoft Project by default stores projects as MPP files. MPXJ supports read only access to MPP files produced by Microsoft Project from Microsoft Project 98 onwards (Microsoft Project 98, Microsoft Project 2000, Microsoft Project 2002, Microsoft Project 2003, Microsoft Project 2007, Microsoft Project 2010, Microsoft Project 2013, Microsoft Project 2016, and Microsoft Project 2019). MPP template files, with the suffix MPT can also be read by MPXJ.

  • MSPDI: The MSPDI file format is Microsoft's XML file format for sharing project data. Versions of Microsoft Project from 2002 onwards can read and write MSPDI files. Applications other than Microsoft Project also commonly write MSPDI files as a way of sharing project data. MPXJ can read and write MSPDI files. The MSDPI file format has remained broadly unchanged since it was introduced, although several versions of Microsoft Project have tweaked the file format slightly, and have their own updated documentation. Documentation is available online here. Documentation for the Project 2003 MSPDI file format can be downloaded as part of the Office 2003 XML Reference Schemas package. Documentation for the Project 2007 MSPDI file format can be downloaded as part of the Project 2007 SDK. Documentation for the Project 2010 MSPDI file format can be downloaded as part of the Project 2010 Reference: Software Development Kit. Documentation for the Project 2013 MSPDI file format can be downloaded as part of the Project 2013 SDK.

  • MPD: The Microsoft Project MPD file format is a Microsoft Access database used to store one or more projects. Versions of Microsoft Project from Microsoft Project 98 to Microsoft Project 2003 can write MPD files. Later versions of Microsoft Project can read MPD files but can't write them. MPXJ can read MPD files natively, without using a JDBC driver, or via a JDBC connection. MPXJ supports reading MPD files written by versions of Microsoft Project 2000 onwards.

  • PLANNER: Gnome Planner is a cross-platform Open Source project management tool which uses an XML file format to store project data. MPXJ can read and write Planner files.

  • PRIMAVERA P6: Primavera P6 is an industry-leading tool favoured by users with complex planning requirements. It can export project data in the form of XER or PMXML files, both of which MPXJ can read and write. It is also possible for MPXJ to connect directly to a P6 database via JDBC to read project data, or if a standalone SQLite P6 database is being used, MPXJ can read projects from this natively without using JDBC. The PMXML schema forms part of the P6 distribution media, which can be downloaded from the Oracle Software Delivery Cloud.

  • PRIMAVERA P3: Primavera P3 (Primavera Project Planner) is the forerunner of P6. It stores each project as a directory containing Btrieve database files which MPXJ can read from the directory itself or from a zip archive of the directory. MPXJ can also read P3 data from PRX backup files.

  • PRIMAVERA SURETRAK: Primavera SureTrak is an early iteration of the application which eventually became Primavera P6. SureTrak stores each project as a directory containing Btrieve database files which MPXJ can read from the directory itself or from a zip archive of the directory. MPXJ can also read SureTrak data from STX backup files.

  • POWERPROJECT: Asta Powerproject is a planning tool used in a number of industries, particularly construction. Powerproject saves data to PP files. MPXJ can read PP files produced by Powerproject version 8 onwards (although earlier versions may also be supported). Powerproject can also write one or more projects to MDB (Microsoft Access) database files which MPXJ can read natively without a JDBC driver, or via a JDBC connection.

  • PHOENIX: Phoenix Project Manager is an easy-to-use critical path method scheduling tool aimed primarily at the construction industry. Phoenix stores projects as XML files with the file extension PPX. MPXJ can read PPX files written by Phoenix from version 4 onwards.

  • FASTTRACK: Fasttrack Schedule is general purpose planning tool. FastTrack stores projects as FTX files. MPXJ can read FTX files written by Fasttrack version 10 onwards, although FTX files written by earlier versions may be supported.

  • GANTTPROJECT: GanttProject is an open source general purpose planning tool. GanttProject stores projects as GAN files, which can be read by MPXJ.

  • TURBOPROJECT: TurboProject is general purpose planning tool. TurboProject store projects as PEP files, which can be read by MPXJ.

  • CONECPTDRAW PROJECT: ConceptDraw PROJECT is general purpose planning tool. ConceptDraw PROJECT writes CDPX, CDPZ and CDPTZ files which MPXJ can read.

  • SYNCHRO SCHEDULER: Synchro Scheduler is general purpose planning tool from Bentley Systems. Synchro Scheduler stores projects as SP files. MPXJ can read SP files written by Synchro Scheduler version 6 and onwards, although SP files written by earlier versions may be supported.

  • GANTT DESIGNER: Gantt Designer is a simple Gantt chart drawing tool. Gantt Designer stores projects as GNT files, which can be read using MPXJ.

  • SDEF: SDEF is the Standard Data Exchange Format, as defined by the United States Army Corps of Engineers (USACE). SDEF is a fixed column format text file, used to export a project schedule to the QCS (Quality Control System) software from USACE. MPXJ can read and write SDEF files.

  • SCHEDULE_GRID: Sage 100 Contractor is an application for small to medium sized companies in the construction industry, providing accounting, and estimating and project management functionality. Project plans managed in Sage 100 Contractor can be exported as schedule grid files, which can be read by MPXJ.

  • PROJECT COMMANDER: Project Commander is a general purpose project planning application. Project Commander stores projects as PC files. PC files written by Project Commander version 7 and onwards can be read by MPXJ, although PC files written by earlier versions may be supported.

  • DELTEK OPEN PLAN: Deltek Open Plan Deltek Open Plan is an enterprise project management application offering resource management, critical path analysis, and customizable reporting. Projects managed in Open Plan can be exported to BK3 files, which can be read by MPXJ.

"},{"location":"users/","title":"MPXJ Users","text":"

Here is a list of organisations and projects currently using, or believed to be using MPXJ. Feel free to contact me if you would like to be featured in this list.

  • ]project-open[ www.project-open.com
  • a-dato www.a-dato.net
  • Afinion Project Viewer www.afinion.de
  • allProView www.allproview.com
  • Atlas Authority atlasauthority.com
  • Aurea Savvion BPM Studio www.aurea.com
  • Autodesk Build \u2013 Schedule construction.autodesk.com/products/autodesk-build/
  • Bosch RefinemySite www.bosch-refinemysite.com
  • Bryntum bryntum.com
  • Buildots buildots.com
  • Celoxis www.celoxis.com
  • Change Inspector www.changeinspector.com
  • Comindwork www.comindwork.com
  • Complex Data Exchange www.informatica.com
  • ConceptDraw www.conceptdraw.com/
  • Concourse concourse.tools
  • CS Project www.crestsoftware.co.uk/cs-project/planning/
  • CV Projects www.cvprojects.com
  • DHTMLX Gantt dhtmlx.com/docs/products/dhtmlxGantt
  • DTP www.parasoft.com/products/parasoft-dtp
  • eProject www.eprocorp.com
  • Exicom www.exicom.se/en
  • FastTrack Schedule www.aecsoftware.com
  • forProject www.forproject.com
  • Frontline www.frontlinec.com
  • Gantt Designer timios.net/Gantt
  • Gantter gantter.com
  • GanttPro ganttpro.com
  • GanttProject www.ganttproject.biz
  • Ganttzilla www.ganttzilla.com
  • GIS PAM www.gish.de
  • Housatonic Project Viewer Central www.projectviewercentral.com
  • HPE Project and Portfolio Management Center admhelp.microfocus.com/ppm
  • HudsonFog www.hudsonfog.com
  • i-lign www.ilign.com
  • IBM TRIRIGA www.ibm.com/uk-en/marketplace/ibm-tririga
  • Incremental www.incremental.eu.com
  • Ingantt ingantt.com
  • Intellisys www.webintellisys.com
  • Lean Station leanstation.com/
  • LibrePlan www.libreplan.dev
  • Lighthouse www.artifactsoftware.com
  • LiveProject www.kadonk.com
  • Merlin www.projectwizards.net
  • Milestones Professional kidasa.com
  • MOOS Project Viewer www.moosprojectviewer.com
  • mpower www.monitor-mpower.com
  • Mpp Viewer www.sourceforge.net/projects/mppviewer
  • MsProjecttools www.msprojecttools.com
  • OmniPlan www.omnigroup.com
  • OnePager www.onepager.com
  • Onepoint Project www.onepoint-project.com
  • Opdec www.opdec.com
  • OpenProj openproj.org
  • Pavone www.pavone.com
  • Pemari www.pemari.com
  • PIEmatrix piematrix.com
  • PlantSight www.bentley.com/en/products/brands/plantsight
  • Plexus www.plexsusplanning.com
  • Predict! www.riskdecisions.com
  • Primavera Unifier www.oracle.com/industries/construction-engineering/unifier-facilities-asset-management/
  • Procore www.procore.com
  • ProjectForge www.projectforge.org
  • PROJECT in a box projectinabox.org.uk
  • Project Kit www.methodpark.de
  • ProjectLibre www.projectlibre.org
  • Projec.to Online Microsoft Project Viewer www.onlineprojectviewer.com/
  • ProjExec www.triloggroup.com
  • RationalPlan www.rationalplan.com
  • Safran www.safran.com
  • SAP Conversion Agent by Informatica help.sap.com
  • SharedPlan www.sharedplan.com
  • Siemens COMOS www.siemens.com/global/en/products/automation/industry-software/plant-engineering-software-comos.html
  • SmartWorks www.smartworks.us/
  • StaffPM code.google.com/p/mhe3-staffpm
  • Steelray Project Viewer www.steelray.com
  • Tamara www.vosesoftware.com/products/tamara
  • Task Adapter www.taskadapter.com
  • Team Elements sourceforge.net/projects/teamelements
  • Teamwork www.twproject.com
  • ThoughtWeb www.thoughtweb.com
  • Timenow timenow.com.br
  • TrackStudio www.trackstudio.com
  • Turbo Chart - Linear Project Software turbo-chart.com
  • Virtuelle Projektverwaltung www.swissasp.ch
  • VisiLean visilean.com
  • Windchill ProjectLink www.ptc.com/products/windchill-projectlink
  • Workfront www.workfront.com
  • Xena xena.sourceforge.net
  • xPlanner www.xplanner.org
  • xProcess www.openxprocess.com
  • Zilicus www.zilicus.com
  • ZTimeView www.tuwien.ac.at
  • Zurvan Planning zurvan-planning.com
"}]} \ No newline at end of file diff --git a/docs/summary.html b/docs/summary.html index 9378a65a34..0170619916 100644 --- a/docs/summary.html +++ b/docs/summary.html @@ -32,7 +32,7 @@ diff --git a/docs/team.html b/docs/team.html index 88ce5fd331..34d5bdf10f 100644 --- a/docs/team.html +++ b/docs/team.html @@ -32,7 +32,7 @@