RecRef and Form.runmodal(ID,record)

garakgarak Member Posts: 3,263
edited 2013-05-20 in NAV Tips & Tricks
If you select, modify or insert many Record in different tables per RecRef and you will see the result in the "original" form (like 21 for Customer), you can use this codeexample to run the original Form without creating a Record variable (like 18 for customer). But you must know the formid that you will run.
.
.
.
RecRef.OPEN(18); //this you know
.
.
.

//Here we will open the base form to an Record

HYPERLINK(CreateHyperlink(RecRef,21);
RecRef.CLOSE();


CreateHyperlink(VAR RecRef : RecordRef;FormID : Integer) : Text[1024]

PreFix := '0'; //Form, Report ist 1

KeyString := FORMAT(RecRef.KEYINDEX(1));  //PK

FieldNoTxt := DELCHR(KeyString,'=','Field');

REPEAT
  IF (STRPOS(FieldNoTxt,',') > 1) THEN BEGIN
    SingleNoTxt := COPYSTR(FieldNoTxt,1,STRPOS(FieldNoTxt,',') - 1);
    EVALUATE(FieldNo,SingleNoTxt);
    FieldValue := FORMAT(RecRef.FIELD(FieldNo).VALUE);
    FieldNoTxt := COPYSTR(FieldNoTxt,STRPOS(FieldNoTxt,',') + 1,100);
    PosStr := PosStr + 'Field' + SingleNoTxt + '=' +
                      PreFix + '(%22' + FieldValue + '%22),';
  END;
UNTIL (STRPOS(FieldNoTxt,',') = 0);

EVALUATE(FieldNo,FieldNoTxt);
FieldValue := FORMAT(RecRef.FIELD(FieldNo).VALUE);
PosStr := PosStr + 'Field' + FORMAT(FieldNo) + 
                  '=' + PreFix + '(%22' + FieldValue + '%22)';

TxtStr := CONTEXTURL + '%26target=Form' + '%20' +
              FORMAT(FormID) + '%26view=SORTING(' + FORMAT(KeyString) + ')' +
              '%26position=' + PosStr;

EXIT(TxtStr);

Regards Garak

PS: Can the admin delete the second post. Thanks
Do you make it right, it works too!

Comments

  • jjanauskasjjanauskas Member Posts: 49
    There is another solution for that problem. The general idea is based that you create your own codeunit with function "Lookup", which runs a specified record form. For ex.:
    Lookup(p_txtFieldName : Text[250];VAR p_txtResult : Text[1024]) booResult : Boolean
    ...
    rrfMain: RecordRef;
    recTmp: Record 15;
    frfMain: FieldRef;
    ...
    
    booResult := FALSE;
    p_txtResult := '';
    IF FORM.RUNMODAL(0, recTmp) = ACTION::LookupOK THEN
    BEGIN
      rrfMain.GETTABLE(recTmp);
      .. assign frfMain by p_txtFieldName ..
      p_txtResult := FORMAT(frfMain.VALUE);
      booResult := TRUE;
    END;
    

    and then, whenever you want to lookup another table, you have to export the blob of codeunit above to file/stream (it is stored in table Object), change the binary code of exported file/stream so that new ID of recTmp would be assigned and import the blob back to table Object.

    You can find the places where navision stores the record No by exporting blob of codeunit with several variations of record No of recTmp in codeunit above. In my situation it changes in two places: from bytes 536 and 1088.

    The code would look like smth like that:
    ...
    recObject: Record 'Object';
    fleMain: File;
    i: Integer;
    ...
    recObject.GET(recObject.Type::Codeunit, '', 50010);
    recObject.CALCFIELDS("BLOB Reference");
    recObject."BLOB Reference".EXPORT(<tmp file>);
    i := <table id you want to lookup>;
    
    fleMain.WRITEMODE:= TRUE;
    fleMain.TEXTMODE := FALSE;
    fleMain.OPEN(<tmp file>);
    fleMain.SEEK(536); // 536 must be changes in your situation
    fleMain.WRITE(i);
    
    fleMain.SEEK(1088); // 1088 must be changed in your situation
    fleMain.WRITE(i);
    fleMain.CLOSE;
    
    recObject."BLOB Reference".IMPORT(<tmp file>);
    recObject.MODIFY(TRUE);
    COMMIT;
    booResult := <your codeunit>.Lookup(<field name>, p_txtResult);
    

    This smells of 'breaking navision', but it works great! Even with several concurent users. But just be carefull with user permissions for table 'Object'.

    Have fun!
  • ajhvdbajhvdb Member Posts: 672
    @jjanauskas
    Thx, it does work in 4.0 and later on in 5.0. even with the same fob.
  • Matjaz_SegaMatjaz_Sega Member Posts: 3
    Not sure about the older versions, but in NAV 2009 R2 this can be done with the use of Variant datatype:
    rRef: RecordRef;
    var: Variant;
    
    rRef.OPEN(18); //Customer
    var := rRef;
    FORM.RUNMODAL(0,var);
    


    The only problem is that you can not apply filters to the record, because they get lost when you assign RecRef to the Variant variable. First record in the filter DOES get selected though. Example below:

    rRef.OPEN(18); //Customer
    rRef.FILTERGROUP(5);
    fRef := rRef.FIELD(2); //Customer.Name
    fRef.SETFILTER('T*');
    rRef.FILTERGROUP(0);
    rRef.FINDSET;
    var := rRef;
    FORM.RUNMODAL(0,var); //Form shows all records but is focused on the first that fits in the filter 'T*'.
    


    I hope that helps someone else too.
  • itinkiamitinkiam Member Posts: 37
    This is great. But I have (perhaps) a stupid question. When you use the Variant for the lookup, how do you retrieve the recordref of the field?

    I tried if form.runmodal(var,0) = action::lookupOK....but this didn't go anywhere. Version 2009R2.

    Help?
Sign In or Register to comment.