by Jack Wheeler (jwl1@jps.net)
| Jack's application has a "Main Menu" form which shows each user the actions appropriate for that user's security level. In the past, Jack had to recode the application if a user's security privileges changed. In this article Jack discovers a way to allow the client to change user-specific menus without Jack's intervention! |
Do you think it is possible to design a procedure that will allow different users to see only their permitted actions within an application? Can you then allow the system administrator at the client site to easily change user privileges and thereby modify the menu choices each user can see?
I did not think this was possible. I could not even imagine such an alternative. One of the beauties of Dr Wayne's web site is the feedback I get when I submit a tip or article. This is the case with my article on Customizing Your Application for Each User. Robert emailed me and gave me a BRAINSTORM of a tip. He uses a Menu table to base all his menus on. This idea so simplifies application development that I am still thankful someone has shared it with me! I now use it for all my menus that may be different depending on department, user or family member. Here is my new design, which can now be downloaded and implemented 100% (just change the text and values as they pertain to you).
In my previous method of controlling access within my application, it became very clear that when my client decided to add another user or change the restrictions of a current user, it would have to be Jack that did the changes. Everything was coded in the forms design. I estimated that I would take about an hour to update a menu. Not too efficient! I was lead to a different way of looking at my original problem and solution. Once I understood this I quickly redesigned my security issures this way I created a MenuItem table.

You will see that the table has two main fields:
Wow, this seems so simple, I wonder why I had not figured this out on my own! I proceeded in designing the Menu Audit form. All that was needed two sections, one for each menu I was using. I then included a description line and the field that will allow the user to use it or not. Since I was going to apply my codes to a button I decided to include a sample button for each menu choice. Once the form was done and functioning I would have all the codes I could need.

Robert advised me to place my code in a global script and not on the form. At first I was not sure why, but then I remembered an article by Steve Workings where he said the same thing: his point was that if you did this you could edit all and any scripts without needing access to any tables or forms.
The code seemed so easy at first: simply get the name of the field in the table and add the choice to the multistate button. But how do we populate the multistate button with the proper values?
Now we will discover the POWER of Alphas eval() function. (You should check out Peter Wayne's article explaining the eval() function, very powerful!) Here is the script for the Menu Audit forms button:
dim nbr as n
dim f as p
dim i as n
dim number as n
dim text1 as c
dim text2 as c
dim text3 as c
dim text4 as c
dim text5 as c
dim text6 as c
dim text7 as c
dim text8 as c
dim text9 as c
dim text10 as c
dim text11 as c
dim text12 as c
dim filename as c
dim fieldobj as p
f=parentform.this
'debug(1)
nbr = 0
if f:Accounts_Receivables.value="Y" then
nbr1= nbr+1
nbr=nbr1
filename="text"+alltrim(str(nbr))
eval(filename)="Account Receivables"
end if
if f:Accounts_Payables.value="Y" then
nbr2= nbr+1
nbr=nbr2
filename="text"+alltrim(str(nbr))
eval(filename)="Account Payables"
end if
if f:Data_entry.value="Y" then
nbr3= nbr+1
nbr=nbr3
filename="text"+alltrim(str(nbr))
eval(filename)="Data Entry"
end if
if f:Past_due.value="Y" then
nbr4= nbr+1
nbr=nbr4
filename="text"+alltrim(str(nbr))
eval(filename)="Past Due"
end if
if f:Invoice_prep.value="Y" then
nbr5= nbr+1
nbr=nbr5
filename="text"+alltrim(str(nbr))
eval(filename)="Invoice Preparation"
end if
if f:Observation.value="Y" then
nbr6= nbr+1
nbr=nbr6
filename="text"+alltrim(str(nbr))
eval(filename)="Client Observation"
end if
if f:Contact_manager.value="Y" then
nbr7= nbr+1
nbr=nbr7
filename="text"+alltrim(str(nbr))
eval(filename)="Contact Manager"
end if
if f:Calendar.value="Y" then
nbr8= nbr+1
nbr=nbr8
filename="text"+alltrim(str(nbr))
eval(filename)="Appointments Calendar"
end if
if f:Peach_tree.value="Y" then
nbr9= nbr+1
nbr=nbr9
filename="text"+alltrim(str(nbr))
eval(filename)="Peach Tree"
end if
if f:Excel.value="Y" then
nbr10= nbr+1
nbr=nbr10
filename="text"+alltrim(str(nbr))
eval(filename)="Excel"
end if
if f:word.value="Y" then
nbr11= nbr+1
nbr=nbr11
filename="text"+alltrim(str(nbr))
eval(filename)="Word"
end if
if f:Good_bye.value="Y" then
nbr12= nbr+1
nbr=nbr12
filename="text"+alltrim(str(nbr))
eval(filename)="Good Bye"
end if
IF NBR=0 THEN
f:twostbtn1.choice.list.redim(1)
f:twostbtn1.choice.list[1].text=""
END
END IF
f:twostbtn1.choice.list.redim(nbr)
for i = 1 to nbr
f:twostbtn1.choice.list[i].text=eval("text"+str(i))
next
if nbr>7 then
f:Twostbtn1.font.size=12
end if
This is what the final menu will look like:

Here are the problems I ran into while designing these forms and techniques:
We are using this form now and it really is a nice tool. You can see how effective it would be to create many of your user forms like this. Think of your Print option forms, or running saved operations... the list gets bigger and bigger. I have found that most users love the forms that have buttons as objects. This is why this form has become so popular with my users.
I hope this little demo will give you a cleaner and clearer approach to customizing your application menus! You can download sample files to see how it's done!
3/25/00
Don't forget, we need your feedback to make this site better!