Sunday, 9 March 2008

Moving values up and down in multiple multivalue fields

A while ago I received a request to be able to maintain a table of values. In Notes that means creating several multivalue fields that are displayed in a table.
I had done this before using the tablewalker solution by Michael Rohrbach and it still works fine after all these years.
However the current user was not really satisfied with the sorting option in the Tablewalker solution and wanted to be able to visually move rows up and down. This is basically moving values up and down in multivalue fields. So I started thinking about how to do this while the user is viewing the table on the form using @functions.
Based on an application I found on OpenNTF by Tomas Ekström, TEd, Table Editor I build a fairly simple solution for this using @functions.

This is the solution:
To start I created a computed multivalue field in which the fields to sort are stored, I called this field "MoveFields".

On the form there are a couple of (hidden) multivalue fields to hold the user data and computed for display fields to display the values of the hidden fields neatly in the table (cut-off if need be for each seperate value to fit on one line).
To move the values up and down in the array I added an extra field in which the user can enter the row to move "CurrPos".
Finally two arrows (up and down) are added with action hotspots, in which the sorting is done. The code should be self-explanatory.

Screenshot of the (part of) the table and buttons:











Code for the up hotspot:

REM {CODE FOR MOVING UP };
Fields := @GetField("MoveFields");

NoOfFields := @Elements(Fields);
NoOfElements := @Elements(@GetField(Fields[1]));

@If(CurrPos < 1 | CurrPos > NoOfElements;
@Return(@Prompt([Ok];"move up"; "Number must be within range of available rows"));
""
);
@If(CurrPos = 1;
@Return(@Prompt([Ok];"move up"; "Cannot move the first row further up !"));
""
);
REM { ----------------------------------------------------------------------------------------------------------
move the current row one position UP
1st subset gets the elements above the current element and the element to switch (only when current position is below second row)
2nd subset gets the current element
3rd subset gets the element above the current element
4th subset subset gets the elements below the current element (only when current position is above the last position)
-------------------------------------------------------------------------------------------------------------------- };
@For(n:=1; n <= NoOfFields; n:=n+1;
@SetField(Fields[n];
@If(CurrPos <= 2; null; @Subset(@GetField(Fields[n]); CurrPos-2)) :
@Subset(@Subset(@GetField(Fields[n]); CurrPos);-1) :
@Subset(@Subset(@GetField(Fields[n]); CurrPos-1); -1) :
@If(CurrPos = NoOfElements; null; @Subset(@GetField(Fields[n]); CurrPos-NoOfElements))
)
);
REM { set currunt position to new rownumber };
@SetField("CurrPos"; CurrPos -1);
@Command([ViewRefreshFields])


Code for the down hotspot

REM {CODE FOR MOVING DOWN };
Fields := @GetField("MoveFields");

NoOfFields := @Elements(Fields);
NoOfElements := @Elements(@GetField(Fields[1]));

@If(CurrPos < 1 | CurrPos > NoOfElements;
@Return(@Prompt([Ok];"move down"; "Row number must be within range of available rows"));
""
);
@If(CurrPos = NoOfElements;
@Return(@Prompt([Ok];"move down"; "Cannot move the last row further down !"));
""
);
REM { ------------------------------------------------------------------------------------------
move the current row one position DOWN
1st subset gets the elements above the current element and the element to switch (only when current position is below first row)
2nd subset gets the element below the current element
3rd subset gets the current element
4th subset subset gets the elements below the elements to switch (current element +1) (only when current position is at least 2 rows the last row)
----------------------------------------------------------------------------------------------------- };
@For(n:=1; n <= NoOfFields; n:=n+1;
@SetField(Fields[n];
@If(CurrPos = 1; null; @Subset(@GetField(Fields[n]); CurrPos-1)) :
@Subset(@Subset(@GetField(Fields[n]); CurrPos+1);-1) :
@Subset(@Subset(@GetField(Fields[n]); CurrPos); -1) :
@If(CurrPos = NoOfElements-1; null; @Subset(@GetField(Fields[n]); CurrPos+1-NoOfElements))
)
);
REM { set the current position to the new row };
@SetField("CurrPos"; CurrPos +1);
@Command([ViewRefreshFields])

No comments: