Closed alex-matatov closed 1 month ago
Interesting!
I tried a couple of things to verify what MPXJ is doing. The first was to try a straightforward conversion from XER to MSPDI.
I used this XER file (sorry I had to ad the .txt
extension to get GitHub to accept it as an attachment) test.xer.txt
Which I then ran through the MpxjConvert
sample to produce an MSPDI file: test.xml.txt
I'm seeing these field definitions at the head of the MSPDI file:
<ExtendedAttributes>
<ExtendedAttribute>
<FieldID>188743731</FieldID>
<FieldName>Text1</FieldName>
<Alias>UDF 1</Alias>
</ExtendedAttribute>
<ExtendedAttribute>
<FieldID>188743767</FieldID>
<FieldName>Number1</FieldName>
<Alias>UDF 2</Alias>
</ExtendedAttribute>
</ExtendedAttributes>
Then on each task I'm seeing assignments like this:
<ExtendedAttribute>
<FieldID>188743731</FieldID>
<Value>Text Value 3</Value>
</ExtendedAttribute>
<ExtendedAttribute>
<FieldID>188743767</FieldID>
<Value>3</Value>
</ExtendedAttribute>
Which is what I'd expect.
I then updated the MpxjCreate
sample to try out the code to create and populate a UDF from scratch. I added this block of code just before the file is written:
UserDefinedField udf = new UserDefinedField(
1,
"External Name",
"Internal Name",
FieldTypeClass.TASK,
false,
DataType.STRING);
file.getUserDefinedFields().add(udf);
task6.set(udf, "Task 6");
Here's the definition section at the head of the resulting file:
<ExtendedAttributes>
<ExtendedAttribute>
<FieldID>188743734</FieldID>
<FieldName>Text2</FieldName>
</ExtendedAttribute>
<ExtendedAttribute>
<FieldID>188743731</FieldID>
<FieldName>Text1</FieldName>
<Alias>My Custom Field</Alias>
</ExtendedAttribute>
</ExtendedAttributes>
Then we can see the assignment to the task:
<ExtendedAttribute>
<FieldID>188743734</FieldID>
<Value>Task 6</Value>
</ExtendedAttribute>
So I'm seeing pretty much what I expect - the only caveat is that the MSPDI code could be a bit smarter in that it is expecting a CustomField
instance to supply the alias for the field, whereas we've only set up a UserDefinedField
. The code should be able to fall back on the "external name" attribute of the UserDefinedField
instance for the alias.
It would be interesting to compare this sample code to your own code to see where things diverge. For the moment I've deliberately ignored lookup tables. Typically we'd only want to use a lookup table if we wanted to constrain user input when editing the schedule in MS Project. I would agree with you that the code for handling lookup tables could be made more "developer friendly". I'd be keen to ensure that we can get your code working without lookup tables first.
Hi Jon,
Thank you so much for the code! I found out the reason why UDFs were not written. It was due to "bug" in my code. Everything works as expected. I am sorry that I distracted you.
Have a good day, Alex
No problem - I'm glad you identified the issue.
Hi Jon,
I need your help with exporting
UserDefineFields/CustomFields
inMSPDIWriter
.Our case: we create
UserDefineField
and assign it toTask
. Then we would like to export UDFs to P6[xml | xer] (works) and MSPDI formats (doesn’t work)By looking on the code I see that
MSPDIWriter
maps UDFs to MSP/CustomFields. Excellent!m_userDefinedFieldMap = new UserDefinedFieldMap(projectFile, MAPPING_TARGET_CUSTOM_FIELDS);
Indeed, in the output file I see UDF definitions like that:
If I populate lookup table like below I see
OutlineCodes
By the way, maybe MPXJ could run “add to lookup table” code above when value is assigned to Task ? ->
externalTask.set(udf.getFieldType(), fieldValue);
However, the writer does not add
Task/ExtendedAttribute
(assign custom code) because it expects to seeTaskField
instead ofUserDefinedField
So, my question is - how can I export UDFs as MSP/Custom codes ?