SnTT: Date based views that don’t perform like dogs
Views that are based on today's date are the bane of my existence as a Notes Developer. Any application that deals with approvals or workflow or project management inevitably needs a view that calculates information off of @Today or @Now. But, as Andre talked about recently, any use of those 2 functions are a real drag on performance. So what's a Notes developer supposed to do when faced with a doe eyed client who just wants to get her work done? We do what we do best....we write an agent to do work around it.

The great thing about @Today is that it's value only changes once a day. So why worry about calculating it when you can just as easily set it's value on a nightly basis. Instead of setting a variable using @Today (e.g. tdy := @Today;), you set the variable to a date (e.g. tdy := [06/07/2007]) and then change that date on a daily basis. For those readers who are unaware, surrounding a date and/or time in brackets ([ ]) sets the value as a time-date constant.

The next hurdle to pass is how do you know exactly where to look for the constant. The value could be in a selection formula or a column formula. How do you make sure you only change the constant and not something else in the formula? You have to make the variable name unique enough that it won't accidentally be used elsewhere. I use something like ASNDtdy. And while it might not be necessary, I try to make this variable set in the first line of the formula. It makes writing the agent so much easier.

Finally, you need an agent that updates the views while everyone is sleeping. Luckily, LotusScript gives us the NotesView class to get a handle on everything you need to change:
Forall v In db.Views
If Left(v.SelectionFormula,Len(tdystring)) = tdystring Then
v.SelectionFormula = tdystring & todaydate.DateOnly &"]" & Strright(v.SelectionFormula,"]")
End If
Forall c In v.Columns
If Not (c.Formula = "") Then
If Left(c.Formula,Len(tdystring)) = tdystring Then
c.Formula = tdystring & todaydate.DateOnly &"]" & Strright(c.Formula,"]")
End If
End If
End Forall
End Forall
I have scheduled our agents to run at 12:10 AM every night on the server.

By using this methodology, I am able to give our users the date based views they crave without bringing the database performance to a grinding halt. And even better is the fact that the refresh icon doesn't constantly show!
<< Previous Document / Next Document >>
  • 1) Intriguing - Tim Tripcony
    Created 6/8/2007 9:19:08 AM email | website

    I like this approach... but I'm assuming this prevents association of the impacted views with a template?

  • 2) Are the brackets portable? - JP Mens
    Created 6/8/2007 9:29:09 AM email | website

    Interesting. One question arises here: are the bracketed dates "tdy := [06/07/2007]" actually portable across installations? In the US that is June 7th, but (albeit with periods) in Europe it would be July 6th.

  • 3) Re: Questions - Sean Burgess
    Created 6/8/2007 9:39:35 AM email | website

    @Tim I can see where that might be a problem, but if the agent is set to run after the design task, you should be ok.

    @JP Well, the LS will use the system format for date. Of course, if you have to deal with multiple formats, you can use the @Date(year; month; day) instead of putting the value in brackets.

  • 4) Thanks for being the one to finally write it - Kevin Pettitt
    Created 6/8/2007 11:27:18 AM email | website

    Hey Sean, this is great, although it would be necessary to modify it to be date-format-neutral as JP suggests. Given that the agent is governed by the server OS date settings, the view should theoretically calculate the "correct" date as long as the db is on the server. I suspect it would break though if a local replica were pulled down to a PC with a different date format (or for that matter a server with a different format). Then there is the question of "when everyone is sleeping", which gets complicated when your enterprise spans multiple time zones.

    Here's what I came up with by modifying your original agent (yes, I have tested this successfully):

    ********* START CODE *************

    Option Public

    Use "OpenLogFunctions" 'Get OpenLog from OpenNTF for those wondering

    Sub Initialize

    On Error Goto ErrorHandler

    Dim session As New notessession

    Dim db As NotesDatabase

    tdystring = "ASNDtdy := "

    Set db = Session.CurrentDatabase 'change this so it loops through several dbs if you want to run one agent per server

    Forall v In db.Views

    If Left(v.SelectionFormula,Len(tdystring)) = tdystring Then

    'v.SelectionFormula = tdystring & todaydate.DateOnly &"]" & Strright(v.SelectionFormula,"]")

    v.SelectionFormula = tdystring & "@Date(" & Year(Today) & "; " & Month(Today) & "; " & Day(Today) & ")" & Strright(v.SelectionFormula,")")

    End If

    Forall c In v.Columns

    If Not (c.Formula = "") Then

    If Left(c.Formula,Len(tdystring)) = tdystring Then

    'c.Formula = tdystring & todaydate.DateOnly &"]" & Strright(c.Formula,"]")

    c.Formula = tdystring & "@Date(" & Year(Today) & "; " & Month(Today) & "; " & Day(Today) & ")" & Strright(c.Formula,")")

    End If

    End If

    End Forall

    End Forall

    Exit Sub

    ErrorHandler:

    Call LogError

    End Sub

    Using a "Today's Mail" view as a sample (new view, based on Inbox), change the selection formula to:

    ASNDtdy := @Date(2007; 6; 8);

    SELECT DeliveredDate = ASNDtdy

    Should handle any date format, on THIS planet anyway ;-)

  • 5) Complete code posted in OpenNTF Code Bin - Kevin Pettitt
    Created 6/9/2007 8:43:25 AM email | website

    { Link }

  • 6) Just a thought - Nathan T. Freeman
    Created 6/11/2007 7:10:20 AM email | website

    I stopped using date-based views for most applications a while ago. There are some exceptions, but really I find that .AddToFolder accomplishes what I need much more readily.

    Rather than doing some kind of view with a selection formula of...

    Status = "Open" & DueDate < @Today

    ... or something, I'll set up an agent process to gather and place all the new docs into the "Overdue" folder.

    The performance advantage can be enormous, plus it allows for some fairly easy coding to move things OUT of that queue as well.

    Just food for thought. As Notes developers, we're typically over-responsive to the users' request for "a view" when what they really want is "a work queue" which may or may not be best achieved through a view design element.

  • 7) Re: Just a thought - Sean Burgess
    Created 6/11/2007 10:29:04 AM email | website

    While adding documents to a folder does fix the SelectionFormula issue with @Today, it doesn't accomodate the use of @Today in the column formulas. Further more, with the use of folders, you run the risk of your users inadvertently removing or adding documents to the folder.

  • 8) Leverage it. - Nathan T. Freeman
    Created 6/11/2007 11:47:35 AM email | website

    I use that as an advantage, Sean. Removing or adding to the folder becomes part of the overall workflow interface. :-)

  • 9) International - no worries, mon - Andre Guirard
    Created 6/28/2007 12:33:54 PM email | website

    It is not necessary to change this to use an OS-neutral date format. Here's why. When you save a formula, the original text of the formula is not preserved. Date/time constants are converted to an internal binary representation. Since the formula code is immediately compiled by the same system that generated the string, using "[" + x.DateOnly + "]" should work just fine -- and of course it's more efficient than having to evaluate an @Function with multiple args for every document processed.

    Oh, and as for folders, that's another approach that I like. You can set the folder accesses so people can't add and remove documents manually.

  • 10) Thanks Andre - Kevin Pettitt
    Created 6/29/2007 11:19:52 PM email | website

    Andre, nice to have you around to validate these things. So, forget everything I said :-)

Post A Comment
Subject: (required)
Name: (required)
Email: (required)
Web Site:
Comment:(No HTML - Links will be converted if prefixed http://)

Remember Me?