This is just a first pass, but I can see that this could be very handy. Basically all that is happening is that we are checking which star (column) is being clicked in the InViewEdit event. Then, we're equating this column to a value, which we add on to the total votes count to date divided by the number of votes. Then, in the final step of the InViewEdit code, we write the new rating value back to the document. I even added a simple check to make sure the user doesn't vote more than once.
Let's break it down step by step:
Step 1: Add columns to your view. I created a separate column for each star, since I want to know explicitly which one was clicked. Set the column to be editable and set it to "Display values as icons".
Step 2: The column value checks the current rating and based on the position of the column determines if it should show the filled or unfilled star.
@If(num_Rating >= 1; "star_red"; "star_open")
Step 3: Add the code to the InViewEdit event. I've included a bunch of comments so you can see what I was going for
Sub Inviewedit(Source As Notesuiview, Requesttype As Integer, Colprogname As Variant, Columnvalue As Variant, Continue As Variant)
Dim session As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim caret As String
'Get the CaretNoteID - exit if it does not point at a document
caret = Source.CaretNoteID
If caret = "0" Then Exit Sub
'Get the current database and document
Set db = Source.View.Parent
Set doc = db.GetDocumentByID(caret)
'Check if user already voted by looking if the user's name is in the nam_UsersRated field
'This is just one possible approach. Not sure how this will scale...might want to create a
'new doc in the backend that just records the user's vote for this doc. Have to explore...
Dim alreadyRated As NotesItem
Dim check As Variant
Dim currentUser As String
currentUser = session.UserName
check = Evaluate ( |@IsMember("| & currentUser & |" ; nam_UsersRated)| , doc )
If check(0) = 1 Then
Messagebox "Sorry...you've already voted for this document"
'If we got this far, the user hasn't voted yet, so we'll take their entry
Dim numRatings As Double '# of users who have rated doc
Dim voteTotal As Double 'numeric total of votes
Dim newRating As Integer 'the new rating for the doc (1 to 5)
numRatings = doc.num_NumberOfRatings(0) + 1
voteTotal = doc.num_VoteTotal(0)
Select Case Colprogname(0)
voteTotal = voteTotal + 1
voteTotal = voteTotal + 2
voteTotal = voteTotal + 3
voteTotal = voteTotal + 4
voteTotal = voteTotal + 5
newRating = Round((voteTotal / numRatings), 1)
doc.num_Rating = newRating
doc.num_VoteTotal = voteTotal
doc.num_NumberOfRatings = numRatings
'Add the user's name to the list of people that voted
Set item = doc.GetFirstItem( "nam_UsersRated" )
Call item.AppendToTextList( session.UserName )
Call doc.Save(True, False, True)
provided by Julian Robichaux at nsftools.com.
Of course, before you implement something like this, you need to think through the implications of it in a production database. Do all users have the ability to edit documents? If not, perhaps you could use stub documents instead. Also, do you want to give the users the ability to see their vote vs. the actual vote? All of these things can be done...this is just the tip of the iceberg.
While this is really rough and I can think of several enhancements to be made, please feel free to download the sample database if you want to play around with it. If you actually use this technique or enhance it, please let me know...I'd be interested to see it.
Have a great holiday everyone!