February 21, 2009
@ 05:36 PM

I just posted a new release of my calendar controls that includes a bunch of new functionality, some more documentation (courtesy of HTML Help Builder from West Wind), along with a few more samples of how this is all supposed to work.

A Bit of History

This all initially started with a small calendar. I initially planned on using Microsoft's ActiveX calendar but realized I needed to be able to select multiple days. Their control really didn't quite work the way I needed it to, so I created my own. I created three different sizes (normal, smaller, and smallest) just because it was easy to do (they're all the same control) and I thought I might need it. Like any project the "hey, wouldn't it be cool if..." features started to grow. In some cases, I needed this functionality for an application anyway, so I went ahead and improved them.

Calendar

The first thing I ended up needing was a drop-down calendar. I already had the calendar portion, so all I needed to do was show and hide it when you clicked on a button next to a text box. So that's basically what I did. It worked well enough, but if the control happened to be at the bottom of a form it was clipped - the initial control was based on a container. I moved this into a form and adjusted the code a bit so it would be able to bleed off the form.

I needed to be able to bind to a date/time field but only display the date portion for data coming from SQL Server, so I named it "rcsDatetimePicker". In hindsight, not a great name. It gives you the impression it lets you view/edit both the date and time portion when in fact it doesn't. At this point I've got a bunch of code which depends on it so it's not being renamed (sorry).

DatePicker

A common use-case for dropdown calendars is to pick a date range. I took an idea from a previous job where you could link two date controls to keep the start date and the end dates from overlapping (ex. the start date can be after the end date). So this was added.

I worked on another project which needed a time control (hours/minutes) so I created one. It seemed like a natural fit to this calendar library so it's been added in. The next logical idea is, "hey, I need a date/time dropdown calendar". The better name for this was already taken, so this was was named rcsCtrDateTimePicker. Yeah, not great, but I didn't have any other ideas.

DateTimePicker

Finally, I just worked on an application which needed an Outlook-style calendar (month view). It seemed like I already had most of the work done from my other calendar, so (I optimistically though) it wouldn't be a big deal to re-purpose it. It actually required a number of changes so it could be nicely resized, display events, etc.

That's basically where the library is today: 3 different sized "static" calendars, a drop-down date w/calendar, a drop-down date/time w/calendar, a time control, plus a large resizable calendar that can have events displayed on it.

LargeCalendar

LargeCalendarMoreEvents

I've tried to provide a few more examples of how these controls can be used along with a help file. It's not as comprehensive as I'd like, but it's a decent start.

Misc. Notes

One thing that's not really covered in the help yet is related to performance of the large calendar when you have a lot of events on it. I ran into this during testing - as you add more events, the calendar navigation became slower and slower. I attempted to optimize this a bit but ultimately ended up modifying my application code to only populate events for the current month plus one month prior and one month following. The calendar shows days from the previous and following months, so if I didn't populate them they'd be missing from the calendar.

You can hook in populating events via the RefreshEvents() event. It fires anytime the calendar needs to be refreshed. I'd suggest just using BINDEVENT to call a form-level method for this event:

BINDEVENT(This.ctrCalendar, "RefreshEvents", This, "RefreshEvents") 

You can determine the current month by looking at the iCurrentYear/iCurrentMonth properties.

Getting Started

I'd suggest playing around with the samples and digging through the help file to get started. The examples cover most of the basic functionality (try clicking on everything and hovering over things, resizing, etc.) and the help file explains some of the class structure.

Let me know what you think.

Links

http://www.west-wind.com/wwHelp/
http://www.rcs-solutions.com/downloads.aspx


 
Categories: VFP

February 14, 2009
@ 12:39 PM

I just uploaded an update for the collapsing comments plug-in for CodeRush/Refactor! I noticed after updating to the latest version (3.2.3) that it suddenly stopped working. After a bunch of digging, and going back and forth with Rory Becker on twitter. He suggested I take a look at manually loading the plug-in via the new Plug-in Manager (DevExpress > Options > Core > Plug-in Manager). I noticed that my plug-in (which is written as a refactoring) had it's Load Type set as "Demand", but most of the other ones were set as "Idle". After a bit of digging I figured out how to change this in my code - it's an attribute in AssemblyInfo. Making this change and recompiling seemed to fix the issue.

 

Links:

http://www.rcs-solutions.com/downloads.aspx
http://twitter.com/rorybecker


 
Categories: CodeRush

February 7, 2009
@ 03:22 PM

I just finished up a report which generates a list of customers whose birthdays fall within a specified date range. I wrote a simple query which did essentially:


DECLARE @startDate datetime
DECLARE @endDate datetime
SET @startDate = '2009-2-15'
SET @endDate = '2009-3-14'

SELECT c.iid,
        c.FirstName,
        c.LastName,
        c.BirthDate,
        c.Address1,
        c.Address2,
        c.City,
        c.State,
        c.ZipCode
   FROM Customers c
  WHERE c.BirthDate BETWEEN @startDate AND @endDate


Of course, that didn't work. That is, unless our customers happened to actually just been born (as of when I wrote this they wouldn't have been even born yet). Hmm....My first thought was maybe joining this to a date table to get the month and day split apart but that idea falls apart pretty quickly so I dismissed it. I'll come back to this idea in a second.

The other simple way to do this is to convert the date to a day of the year, so January 1st is 1, Jan. 2nd is 2, December 31st is 365. SQL Server includes a nice DATEPART() function to make this easy - you can specify that you want the day of the year with it.

So my query was rewritten as:

SELECT c.iid,
        c.FirstName,
        c.LastName,
        c.BirthDate,
        c.Address1,
        c.Address2,
        c.City,
        c.State,
        c.ZipCode
   FROM Customers c
  WHERE DATEPART(dayofyear, c.BirthDate)
BETWEEN DATEPART(dayofyear, @startDate) AND DATEPART(dayofyear, @endDate)


While this one works it's a bit slow. That's not so surprising since it has to use DATEPART on the rows to generate the day of the year in the WHERE clause. My actual code filters the customers a bit more but it was still a fair number of records. Ultimately, since this a summary/reporting table that gets populated and updated nightly I just added another (integer) column to store the precalculated day of the year number.

Surprisingly, this version isn't that much faster - maybe 15% or so. Apparently DATEPART is pretty quick.

It wasn't until after making these changes that I realized I could have added a day of the year column to my date table, done a join then used this column in my WHERE clause. That actually would have been easier if it had occurred to me sooner. I'm guessing performance is probably equivalent, especially since adding the column directly in the table didn't have a huge impact on the speed of the query.


 
Categories: SQL