Although the RIM tool was originally designed to assist in the setup of Master data; i.e. Customers, Vendors, Items, etc., the reality is that many are using the Data Migration tool to bring in journal lines to set up beginning balances and to bring over historical data from legacy applications.
With the release of 5.0 SP1, a new data type conversion routine was introduced with codeunit 5302 - Outlook Synch. Type Conversion. There are several known issues with data conversion due to these changes.
All of these issue have been reported to development and are being considered for a fix in a future release of the NAV product.
This post offers some code suggestions and workarounds for the more common and/or critical issues. Many of the suggested workarounds involve one particular codeunit in the Data Migration tool, 8611 – Migration Management, so the following combined change log should be helpful.
This change log applies to 5.0 SP1 application objects ONLY.
Issues addressed by the change log:
1) Overflow on type conversion from Text to Text in Form 8626 when a text field larger than 100 chars is imported.2) Error on import of fields beginning with a number (i.e. 1099 Code) - The call to member selectSingleNode failed. msxml6.dll returned the following message: Expression must evaluate to a node-set.3) Imported dates are blank after migration data is applied.4) Decimal values are converted incorrectly. Ex. - 7,500 becomes 7.5 after the migration data is applied.5) Negative decimal values are converted incorrectly, resulting in changed values.6) Error - Expected token 'EOF' found '$'. Error on fields with $ symbol7) Error - The expression Text cannot be type-converted to a Boolean value (or Date value). This may occur on Setup Questionnaire, Data Migration or Data Template.
Changes are labeled with the associated number above.
*****Start Code fix*****
Form 8626 Migration Records---------------------------Before:CODE { VAR MatrixColumnCaptions@1000 : ARRAY [100] OF Text[100]; MigrationData@1001 : Record 8615; MatrixCellData@1002 : ARRAY [100] OF Text[100]; MigrationColumnField@1004 : ARRAY [100] OF Integer; MatrixColumnOrdinal@1003 : Integer; FormCaption@1005 : Text[1024]; TableNo@1006 : Integer; Text001@1007 : TextConst 'ENU=%1 value ''%2'' does not exist.';
After:CODE { VAR MatrixColumnCaptions@1000 : ARRAY [100] OF Text[100]; MigrationData@1001 : Record 8615; MatrixCellData@1002 : ARRAY [100] OF Text[250]; // #1 Change Text[100] to Text[250] MigrationColumnField@1004 : ARRAY [100] OF Integer; MatrixColumnOrdinal@1003 : Integer; FormCaption@1005 : Text[1024]; TableNo@1006 : Integer; Text001@1007 : TextConst 'ENU=%1 value ''%2'' does not exist.';
* XMLport 8610 - Setup DataSchema ---------------------------------...NameIn := DELCHR(NameIn,'=','Ù''`');NameIn := DELCHR(CONVERTSTR(NameIn,'<>,./\+-&()%',' '),'=',' ');NameIn := DELCHR(NameIn,'=',' ');
EXIT(NameIn);...
After:...NameIn := DELCHR(NameIn,'=','Ù''`');NameIn := DELCHR(CONVERTSTR(NameIn,'<>,./\+-&()%$',' '),'=',' '); // #6 Change line- add $ symbol NameIn := DELCHR(NameIn,'=',' ');
IF (NameIn[1] >= '0') AND (NameIn[1] <= '9') THEN // #2 Add line NameIn := '_' + NameIn; // #2 Add line
EXIT(NameIn);
* Codeunit 8611\Function FieldNodeExists ...--------------------------------------------Before:
FieldNode := RecordNode.selectSingleNode(FieldNodeName);
IF NOT ISCLEAR(FieldNode) THEN EXIT(TRUE);
After:
IF (FieldNodeName[1] >= '0') AND (FieldNodeName[1] <= '9') THEN // #2 Add line FieldNodeName := '_' + FieldNodeName; // #2 Add lineFieldNode := RecordNode.selectSingleNode(FieldNodeName);
* Codeunit 8611, Function GetElementName----------------------------------------Before:
...NameIn := DELCHR(NameIn,'=','Ù''`');NameIn := DELCHR(CONVERTSTR(NameIn,'<>,./\+-&()%',' '),'=',' ');NameIn := DELCHR(NameIn,'=',' ');
After:...NameIn := DELCHR(NameIn,'=','Ù''`');NameIn := DELCHR(CONVERTSTR(NameIn,'<>,./\+-&()%$',' '),'=',' '); // #6 Change line - add $ symbolNameIn := DELCHR(NameIn,'=',' ');
IF (NameIn[1] >= '0') AND (NameIn[1] <= '9') THEN // #2 Add line
NameIn := '_' + NameIn; // #2 Add line
* Codeunit 8611, Function ValidateFieldValue--------------------------------------------Before:
Field.GET(RecRef.NUMBER,FieldRef.NUMBER);
IF Field.Type <> Field.Type::Option THEN BEGIN IF Value <> '' THEN //IF CompanySetupRun THEN // #7 Delete EVALUATE(FieldRef,Value) //ELSE // #7 Delete // FieldRef.VALIDATE(Value); // #7 DeleteEND ELSE IF GetOption(Value,FieldRef.OPTIONCAPTION,OptionAsInteger) THEN IF CompanySetupRun THEN FieldRef.VALUE := OptionAsInteger ELSE FieldRef.VALIDATE(OptionAsInteger);
IF NOT CompanySetupRun THEN IF NOT TestRelation(FieldRef) THEN FieldRef.VALIDATE;
IF Field.Type <> Field.Type::Option THEN BEGIN IF Value <> '' THEN EVALUATE(FieldRef,Value)END ELSE IF GetOption(Value,FieldRef.OPTIONCAPTION,OptionAsInteger) THEN IF CompanySetupRun THEN FieldRef.VALUE := OptionAsInteger ELSE FieldRef.VALIDATE(OptionAsInteger);
* Codeunit 8611, Function ModifyRecordWithOtherFields-----------------------------------------------------Before:
VAR MatrixData@1002 : Record 8615; MigrationTableField@1000 : Record 8616; Question@1003 : Record 8612; Field@1007 : Record 2000000041; MigrationTable@1009 : Record 8613; DataTemplateHeader@1011 : Record 8618; QuestionnaireMgt@1006 : Codeunit 8610; TemplateMgt@1012 : Codeunit 8612; OSynchTypeConversion@1014 : Codeunit 5302; FieldRef@1001 : FieldRef; OptionInt@1008 : Integer; DateFormula@1010 : DateFormula; ToValidate@1013 : Boolean;
VAR MatrixData@1002 : Record 8615; MigrationTableField@1000 : Record 8616; Question@1003 : Record 8612; Field@1007 : Record 2000000041; MigrationTable@1009 : Record 8613; DataTemplateHeader@1011 : Record 8618; QuestionnaireMgt@1006 : Codeunit 8610; TemplateMgt@1012 : Codeunit 8612; OSynchTypeConversion@1014 : Codeunit 5302; FieldRef@1001 : FieldRef; OptionInt@1008 : Integer; DateFormula@1010 : DateFormula; ToValidate@1013 : Boolean; DateValue@1500000 : Date; // #3 Add
Before:
IF MigrationTableField.FIND('-') THEN IF NOT IsKeyField(MigrationTableField.TableID,MigrationTableField.FieldID) THEN BEGIN FieldRef := RecRef.FIELD(MatrixData.FieldID); IF CompanySetupRun THEN ToValidate:= FALSE ELSE ToValidate := MigrationTableField.Validate AND NOT TestRelation(FieldRef); OSynchTypeConversion.EvaluateTextToFieldRef(MatrixData.Value,FieldRef,ToValidate) END; IF DataTemplateHeader.GET(MigrationTable."Data Template") THEN TemplateMgt.UpdateRecord(DataTemplateHeader,RecRef);
IF MigrationTableField.FIND('-') THEN IF NOT IsKeyField(MigrationTableField.TableID,MigrationTableField.FieldID) THEN BEGIN FieldRef := RecRef.FIELD(MatrixData.FieldID); IF CompanySetupRun THEN ToValidate:= FALSE ELSE ToValidate := MigrationTableField.Validate AND NOT TestRelation(FieldRef);
//OSynchTypeConversion.EvaluateTextToFieldRef(MatrixData.Value,FieldRef,ToValidate) // #3 Delete
Field.GET(RecRef.NUMBER, FieldRef.NUMBER); // #3 Add line IF Field.Type <> Field.Type::Date THEN // #3 Add line OSynchTypeConversion.EvaluateTextToFieldRef(MatrixData.Value,FieldRef,ToValidate) // #3 Add line
ELSE BEGIN // #3 Add line EVALUATE(DateValue, MatrixData.Value); // #3 Add line
FieldRef.VALUE := DateValue; // #3 Add line END; // #3 Add line
END; IF DataTemplateHeader.GET(MigrationTable."Data Template") THEN TemplateMgt.UpdateRecord(DataTemplateHeader,RecRef); * Codeunit 8611, Function ImportSetupDataXML--------------------------------------------Before:
IF MigrationData.Value <> '' THEN BEGIN ConvertXMLDates(FieldRef,MigrationData.Value); FieldError(MigrationData,EvaluateValue(FieldRef,MigrationData.Value)); IF FORMAT(FieldRef.VALUE) <> '' THEN IF FORMAT(FieldRef.TYPE) <> 'Option' THEN MigrationData.Value := FORMAT(FieldRef.VALUE) ELSE MigrationData.Value := GetOptionString(FieldRef,FORMAT(FieldRef.VALUE));
IF MigrationData.Value <> '' THEN BEGIN ConvertXMLDates(FieldRef,MigrationData.Value); FieldError(MigrationData,EvaluateValue(FieldRef,MigrationData.Value)); IF FORMAT(FieldRef.VALUE) <> '' THEN IF FORMAT(FieldRef.TYPE) <> 'Option' THEN BEGIN // #4 Add BEGIN IF FORMAT(FieldRef.TYPE) <> 'Decimal' THEN // #4 Add line MigrationData.Value := FORMAT(FieldRef.VALUE); END ELSE // #4 Add END MigrationData.Value := GetOptionString(FieldRef,FORMAT(FieldRef.VALUE));
* Codeunit 8611, Function ConvertXMLDates-----------------------------------------Before:
CASE Field.Type OF Field.Type::Date: BEGIN IF EVALUATE(Date, Value,XMLFormat) THEN BEGIN Value := FORMAT(Date); FldRef.VALUE := Date; END; END;
CASE Field.Type OF
Field.Type::Decimal: // # 4 Add line BEGIN // # 4 Add line IF EVALUATE(Decimal,Value) THEN BEGIN // # 4 Add line Value := FORMAT(Decimal,0,XMLFormat); // # 4 Add line FldRef.VALUE := Decimal; // # 4 Add line END; // # 4 Add line END; // # 4 Add line
Field.Type::Date: BEGIN IF EVALUATE(Date, Value,XMLFormat) THEN BEGIN Value := FORMAT(Date); FldRef.VALUE := Date; END; END;
* Codeunit 5302, Function TextToDecimal----------------------------------------Before:
InputText := CONVERTSTR(InputText,'.',',');IF STRPOS(InputText,',') = 0 THEN EXIT;
PartArray[1] := GetSubStrByNo(1,InputText);
InputText := CONVERTSTR(InputText,'.',',');IF STRPOS(InputText,',') = 0 THEN BEGIN // # 4 Add BEGIN
IsConverted := TextToInteger(InputText,IntegeralPart); // # 4 Add line IF IsConverted THEN // # 4 Add line DecVar := IntegeralPart; // # 4 Add line EXIT;END; // # Add END
DecVar := IntegeralPart + (FractionalPart / POWER(10,STRLEN(PartArray[2])));
IF STRPOS(InputText,'-') = 0 THEN // # 5 Add line Sign := 1 // # 5 Add lineELSE // # 5 Add line Sign := -1; // # 5 Add lineDecVar := (Sign * (ABS(IntegeralPart) + (FractionalPart / POWER(10,STRLEN(PartArray[2]))))); // #5 Change line
*****End Code fix*****
Laura K. Lake
Microsoft Dynamics NA
Microsoft Customer Service and Support (CSS) North America
These postings are provided "AS IS" with no warranties and confer no rights. You assume all risk for your use.