Working with Extended Task Attributes
Extended Task Attributes in Microsoft Project allow you to define custom fields and capture additional information about tasks. Aspose.Tasks for .NET fully supports creating, reading, and managing extended attributes for tasks in both MPP and XML formats across all versions of Microsoft Project (2003–2019).
What Are Extended Task Attributes?
In Microsoft Project, an Extended Attribute is a custom field (such as Text1, Cost2, or Flag5) that you can use to store business-specific information not covered by standard fields. These attributes are extremely useful for:
- Tracking additional metadata about tasks (e.g., task category, risk level, budget code).
- Adding project-specific information required for reporting.
- Enforcing company-wide project management standards.
Aspose.Tasks exposes this functionality via two main classes:
- ExtendedAttributeDefinition – defines the custom field (name, type, calculation rules, lookup values).
- ExtendedAttribute – stores the actual value of that custom field for a specific task.
Adding Extended Attribute Information to a Task
To add an extended attribute to a task programmatically:
- Create an
ExtendedAttributeDefinition
that defines the custom field type. - Create an
ExtendedAttribute
object based on that definition. - Assign the attribute to the desired task.
Example: Adding Extended Attributes
1// Create new project
2Project project = new Project("New Project.mpp");
3
4// Create an Extended Attribute Definition of Text1 type
5var taskExtendedAttributeText1Definition = ExtendedAttributeDefinition.CreateTaskDefinition(CustomFieldType.Text, ExtendedAttributeTask.Text1, "Task City Name");
6
7// Add it to the project's Extended Attributes collection
8project.ExtendedAttributes.Add(taskExtendedAttributeText1Definition);
9
10// Add a task to the project
11Task task = project.RootTask.Children.Add("Task 1");
12
13// Create an Extended Attribute from the Attribute Definition
14var taskExtendedAttributeText1 = taskExtendedAttributeText1Definition.CreateExtendedAttribute();
15
16// Assign a value to the generated Extended Attribute. The type of the attribute is "Text", the "TextValue" property should be used.
17taskExtendedAttributeText1.TextValue = "London";
18
19// Add the Extended Attribute to task
20task.ExtendedAttributes.Add(taskExtendedAttributeText1);
21
22project.Save("PlainTextExtendedAttribute_out.mpp", SaveFileFormat.MPP);
23
24Project project = new Project("New Project.mpp");
25
26// Create an Extended Attribute Definition of Text2 type
27var taskExtendedAttributeText2Definition = ExtendedAttributeDefinition.CreateLookupTaskDefinition(CustomFieldType.Text, ExtendedAttributeTask.Text2, "Task Towns Name");
28
29// Add lookup values for the extended attribute definition
30taskExtendedAttributeText2Definition.AddLookupValue(new Value { Id = 1, StringValue = "Town1", Description = "This is Town1" });
31taskExtendedAttributeText2Definition.AddLookupValue(new Value { Id = 2, StringValue = "Town2", Description = "This is Town2" });
32
33// Add it to the project's Extended Attributes collection
34project.ExtendedAttributes.Add(taskExtendedAttributeText2Definition);
35
36// Add a task to the project
37var task2 = project.RootTask.Children.Add("Task 2");
38
39// Crate an Extended Attribute from the Text2 Lookup Definition for Id 1
40var taskExtendedAttributeText2 = taskExtendedAttributeText2Definition.CreateExtendedAttribute(taskExtendedAttributeText2Definition.ValueList[1]);
41
42// Add the Extended Attribute to task
43task2.ExtendedAttributes.Add(taskExtendedAttributeText2);
44
45project.Save("TextExtendedAttributeWithLookup_out.mpp", SaveFileFormat.MPP);
46
47Project project2 = new Project("New Project.mpp");
48
49// Create an Extended Attribute Definition of Duration2 type
50var taskExtendedAttributeDuration2Definition = ExtendedAttributeDefinition.CreateLookupTaskDefinition(CustomFieldType.Duration, ExtendedAttributeTask.Duration2, "Some duration");
51
52// Add lookup values for extended attribute definition
53taskExtendedAttributeDuration2Definition.AddLookupValue(new Value { Id = 2, Duration = project2.GetDuration(4, TimeUnitType.Hour), Description = "4 hours" });
54taskExtendedAttributeDuration2Definition.AddLookupValue(new Value { Id = 3, Duration = project2.GetDuration(1, TimeUnitType.Day), Description = "1 day" });
55taskExtendedAttributeDuration2Definition.AddLookupValue(new Value { Id = 4, Duration = project2.GetDuration(1, TimeUnitType.Hour), Description = "1 hour" });
56taskExtendedAttributeDuration2Definition.AddLookupValue(new Value { Id = 7, Duration = project2.GetDuration(10, TimeUnitType.Day), Description = "10 days" });
57
58// Add the definition to the project's Extended Attributes collection
59project2.ExtendedAttributes.Add(taskExtendedAttributeDuration2Definition);
60
61// Add a task to the project
62var task3 = project2.RootTask.Children.Add("Task 3");
63
64// Create an Extended Attribute from the Duration2 Lookup Definition for Id 3
65var taskExtendedAttributeDuration2 = taskExtendedAttributeDuration2Definition.CreateExtendedAttribute(taskExtendedAttributeDuration2Definition.ValueList[3]);
66
67// Add the Extended Attribute to task
68task3.ExtendedAttributes.Add(taskExtendedAttributeDuration2);
69
70project2.Save("DurationExtendedAttributeWithLookup_out.mpp", SaveFileFormat.MPP);
71
72Project project3 = new Project("New Project.mpp");
73
74// Create an Extended Attribute Definition of Finish2 Type
75var taskExtendedAttributeFinish2Definition = ExtendedAttributeDefinition.CreateLookupTaskDefinition(CustomFieldType.Finish, ExtendedAttributeTask.Finish2, "Some finish");
76
77// Add lookup values for extended attribute defintion
78taskExtendedAttributeFinish2Definition.AddLookupValue(new Value { Id = 2, DateTimeValue = new DateTime(1984, 01, 01, 00, 00, 01), Description = "This is Value2" });
79taskExtendedAttributeFinish2Definition.AddLookupValue(new Value { Id = 3, DateTimeValue = new DateTime(1994, 01, 01, 00, 01, 01), Description = "This is Value3" });
80taskExtendedAttributeFinish2Definition.AddLookupValue(new Value { Id = 4, DateTimeValue = new DateTime(2009, 12, 31, 00, 00, 00), Description = "This is Value4" });
81taskExtendedAttributeFinish2Definition.AddLookupValue(new Value { Id = 7, DateTimeValue = DateTime.Now, Description = "This is Value6" });
82
83// Add the definition to the project's Extended Attributes collection
84project3.ExtendedAttributes.Add(taskExtendedAttributeFinish2Definition);
85
86// Add a task to the project
87var task4 = project3.RootTask.Children.Add("Task 4");
88
89// Create an Extended Attribute from the Finish2 Lookup Definition for Id 3
90var taskExtendedAttributeFinish2 = taskExtendedAttributeFinish2Definition.CreateExtendedAttribute(taskExtendedAttributeFinish2Definition.ValueList[3]);
91
92// Add the Extended Attribute to task
93task4.ExtendedAttributes.Add(taskExtendedAttributeFinish2);
94
95project3.Save("FinishExtendedAttributeWithLookup_out.mpp", SaveFileFormat.MPP);
Explanation:
- First, we define a Text custom field (e.g., Text1).
- Then we create an instance of
ExtendedAttribute
with a specific value. - Finally, we attach it to the task, enabling storage of custom information.
Reading Extended Task Attributes
Once extended attributes are assigned, you can read them using the ExtendedAttributes collection of the Task
class. This property returns a list of ExtendedAttribute
objects, each containing details about the task’s custom fields.
Example: Reading Extended Attributes
1Project project = new Project("New Project.mpp");
2
3// Read extended attributes for tasks
4foreach (Task task in project.RootTask.Children)
5{
6 foreach (ExtendedAttribute ea in task.ExtendedAttributes)
7 {
8 Console.WriteLine(ea.FieldId);
9 Console.WriteLine(ea.ValueGuid);
10
11 switch (ea.AttributeDefinition.CfType)
12 {
13 case CustomFieldType.Date:
14 case CustomFieldType.Start:
15 case CustomFieldType.Finish:
16 Console.WriteLine(ea.DateValue);
17 break;
18
19 case CustomFieldType.Text:
20 Console.WriteLine(ea.TextValue);
21 break;
22
23 case CustomFieldType.Duration:
24 Console.WriteLine(ea.DurationValue.ToString());
25 break;
26
27 case CustomFieldType.Cost:
28 case CustomFieldType.Number:
29 Console.WriteLine(ea.NumericValue);
30 break;
31
32 case CustomFieldType.Flag:
33 Console.WriteLine(ea.FlagValue);
34 break;
35 }
36 }
37}
Explanation:
- Each task can hold multiple extended attributes.
- You can loop through them to extract custom data (e.g., text labels, numerical values, flags).
- This enables integration with reporting, dashboards, or business logic.
Key Notes
- Extended attributes provide flexibility for customizing project data.
- You can define, assign, and read extended attributes programmatically.
- The
ExtendedAttributeDefinition
class is used to define the schema of a custom field. - The
ExtendedAttribute
class stores actual values per task. - Supported for all major MS Project versions (MPP 2003–2019) and XML format.
FAQ
Q: Can I create a lookup table for an extended attribute?
- Yes. The
ExtendedAttributeDefinition
class supports lookup values, just like in Microsoft Project.
Q: What types of extended attributes are supported?
- Text, Number, Cost, Flag, Date, Duration, and Start/Finish fields.
Q: Can I modify extended attributes after task creation?
- Absolutely. You can update or remove extended attributes at any point.
Q: Do extended attributes get saved back to MPP/XML files?
- Yes. Aspose.Tasks preserves extended attributes when saving modified project files.
Q: Is this feature available in both .NET Framework and .NET Core?
- Yes. Aspose.Tasks for .NET supports both platforms.