Training Site Template - Part 2: Workflows

Training Site Template - Part 2: Workflows

Rate This

Sean Hey there,

 It's Sean again with another installment of the template development walkthrough. Last time we covered the list schema for the Employee Training Scheduling and Materials template, one of the new Application Templates for Windows SharePoint Services 3.0. In this series I'm showing you how we built one of these templates from the ground up, and today we're going to author all of the training site's workflows using SharePoint Designer. With that done, you'll have built the whole back-end of the template, so in a future installment we'll get our hands dirty with SharePoint's views and forms.

Folder List (Training Site)Open up a fresh installation of the training site in SPD and you'll see the folder list pictured on the right - with the three workflows you'll be creating today in the Workflow Designer. They'll provide some of the rich behavior that you wouldn't see in a static web app, and you won't need to write any code to get it done. Let's get started!

Automatic Reminders

People are forgetful. Computers aren't. So when an instructor comes to your training site to create a course, why should they have to remember when it is? That's where you can come in with this workflow, which we'll set on the Courses list:

  1. In SPD, go to File > New > Workflow...
  2. Name it "Instructor reminder" and attach it to the SharePoint list "Courses"
  3. Check the box to Automatically start this workflow when a new item is created
  4. Click Next > to continue

From here you'll want to create 3 steps which will logically separate our workflow into sets of related actions. Click Add workflow step to move on to the next step, and in each case if you don't see the specific action listed, click the Actions button > More Actions... to see the full list. Additionally I'm using [brackets] to refer to what you need to do in each placeholder.

Also, fx just means the data binding button. You get the same dialog whenever you push Add Lookup to Body in the e-mail builder.

So before you start, first create two variables (click Variables... > Add... to make them), one called "Reminder Time" (Date/Time) and one called "Subject" (String). You'll need them once you get to the individual steps:

  1. First step: name it "Set reminder time"
    1. No conditions
    2. Actions > Add Time to Date - Add -24 hours to [fx :: Current Item, Start Time] (Output to Variable: Reminder Time)
    3. Actions > Build Dynamic String - Store "RE: [fx :: Current Item, Course Title]" in Variable: Subject
  2. Second step: name it "Send confirmation"
    1. No conditions
    2. Actions > Send an Email - Email [...]
      1. To: Workflow Lookup... :: Current Item, Instructor
      2. Subject: fx :: Current Item, Course Title
      3. Body: This is a confirmation that you are scheduled to teach [Add Lookup to Body :: Current Item, Course Title] on [Add Lookup to Body :: Current Item, Start Time] at [Add Lookup to Body :: Current Item, Location]. For more information, please visit the training site.
  3. Third step: name it "Send reminder about course"
    1. Conditions > Compare Courses field - If Created is less than [fx :: Workflow Data, Variable: Reminder Time]
    2. Actions > Pause Until Date - Pause until [fx :: Workflow Data, Variable: Reminder Time]
    3. Actions > Send an Email - Email [...]
      1. To: same as above
      2. Subject: fx :: Workflow Data, Variable: Subject
      3. Body: This is a reminder that you are scheduled to teach [Add Lookup to Body :: Current Item, Course Title] on [Add Lookup to Body :: Current Item, Start Time] at [Add Lookup to Body :: Current Item, Location] in 24 hours. For more information, please visit the training site.
  4. Click Finish

Make sense? We're sending two reminders to anyone who adds a new item to the Courses list (i.e. an instructor creating a course) - one right when they make it as a confirmation, and another 24 hours before the course is scheduled. And the first step was just to keep the variable assignment separate, there's nothing wrong with doing it in the other steps right before they are used.

We'll want to do a similar reminder for students, but we can do it at the same time that we enforce seating policy (each item in Courses has an Available Seats and Total Seats) since it only really makes sense to send reminders if you actually make it into a course.

Processing Student Registrations

If you try to add a new course by browsing to Courses > New..., you'll see this line in the new form:

And you'll also notice that there's no line for Available Seats or Filled Seats, even though we added those fields to the Courses schema in part one. I'll teach you the trick to hide form items next time, what's important here now is that 0 will be our sentinel value in the workflow to come.

Let's go through this one a bit faster by using some shorthand.

  • ... means I'm referring to a string (probably for those long auto-generated e-mails) that you can find the full text for by opening Attendee registration.xoml in SPD.
  • Courses* means you need to perform a lookup back into the Courses list. To do this, start by pushing fx and pick Source: Courses, at which point you'll see the "Find the List Item" section appear. In that section, match Field: Courses:ID to Value: Registrations:Course ID (use the nearby fx :: Current Item, Course ID).
  • Variable: = anything with a leading Variable: in front of it is a workflow variable that can be found in fx :: Workflow Data.

Start with a new workflow called "Attendee registration," attached to Registrations and triggered when an item is created. Create 7 variables before you begin, 4 of type String (Subject, Confirmation Body, Reminder Body, Reminder Body 2), 2 Date/Time (Reminder Time, Reminder Time 2), and 1 Number (New Filled Seats). From there build out the steps:

  1. "Cache all variables"
    1. No conditions
    2. Actions > Build Dynamic String (x4)
      1. Store ... in Variable: Confirmation Body
      2. Store ... in Variable: Reminder Body
      3. Store ... in Variable: Reminder Body 2
      4. Store ... in Variable: Subject
  2. "Enforce seating policy"
    1. Conditions > Compare any data source (x2)
      1. If [fx :: Courses*, Total Seats] equals 0
      2. or [fx :: Courses*, Filled Seats] is less than [fx :: Courses*, Total Seats]
    2. Actions > Set Workflow Variable (x2)
      1. Set Variable: Reminder Time to [fx :: Courses*, Start Time]
      2. Set Variable: Reminder Time 2 to [fx :: Courses*, End Time]
    3. Actions > Do Calculation - Calculate [fx :: Courses*, Filled Seats] plus 1 (Output to Variable: New Filled Seats)
    4. Actions > Update List Item
      1. List: Courses*
      2. Add... :: Set Filled Seats to Variable: New Filled Seats
    5. Click Add 'Else If' Conditional Branch
    6. No conditions
    7. Actions > Delete Item - Delete item in Registrations (Current Item)
    8. Actions > Stop Workflow - Stop the workflow and log "Course is already full."
  3. "Set reminder time"
    1. No conditions
    2. Actions > Add Time to Date - Add -24 hours to Variable: Reminder Time (Output to Variable: Reminder Time)
  4. "Send confirmation"
    1. No conditions
    2. Actions > Send an Email - Email ...
  5. "Send reminder about course"
    1. Conditions > Compare Registrations field - If Created is less than Variable: Reminder Time
    2. Actions > Pause Until Date - Pause until Variable: Reminder Time
    3. Actions > Send an Email - Email ...
  6. "Send reminder for feedback"
    1. Conditions > Compare Registrations field - If Created is less than Variable: Reminder Time 2
    2. Actions > Pause Until Date - Pause until Variable: Reminder Time 2
    3. Actions > Send an Email - Email ...
  7. "Move to Past Registrations"
    1. No conditions
    2. Actions > Copy List Item - Copy item in Registrations (Current Item) to Past Registrations
    3. Actions > Delete Item - Delete item in Registrations (Current Item)

Yikes, I know. But thankfully that's about as bad as it gets. Here's a brief explanation - a student will register for a course, but they won't get in right away (technically, they get in but they may be kicked out immediately if the seating logic fails). After setting all the variables we check if Total Seats is 0 (unlimited) or greater than Filled Seats (i.e. is there room in the course?). If not, we abort prematurely (delete/stop step two), otherwise we do the math and add 1 to the Filled Seats, send reminders, etc. The last step is the archival in the mirror list Past Registrations, something that will become more evident in part three when we build up the front end.

A Dirty Workflow Secret

That's all well and good, but what happens when someone wants to unregister from the course? We need to subtract 1 from the number of Filled Seats, then delete their registration from Registrations, but here's a problem - workflow cannot be triggered to run before an item is deleted. So here's how we'll fake it - since workflow can run when an item is changed, we'll set up another sentinel value for our workflow to be interested in. DELETE seems pretty self explanatory, right?

(Note that this workaround has some serious implications - we'll need to hide item deletion in Registrations and block all edits to our field so the user never trips the sentinel. Don't worry, I'll explain in due time...)

Our last workflow, "Attendee unregistration" (for lack of a better word), attached to Registrations, triggered when an item is changed. One variable before you start: a String called Log Message. Not even really necessary, just for posterity:

  1. "Unregister from course"
    1. Conditions > Compare Registrations field - If Title equals "DELETE"
    2. Actions > Delete Item - Delete item in Registrations (Current Item)
    3. Actions > Build Dynamic String - Store ... in Variable: Log Message
    4. Actions > Stop Workflow - Stop the workflow and log Variable: Log Message

And there you have it, dynamic behavior that takes a long time to spell out in a blog post, but goes a long way towards the richness and robustness of your SharePoint app. It's taken us a few key design decisions to get here, and so in part three we'll learn what consequences that holds for the front end system, which is driven by SharePoint views and forms. I'll see you then!


  • I have some users that can't unregister from any of the courses they registered too during testing when, as it turns out, I had restricted perms too much causing the workflows to fail.  That's corrected now, and they can register/unregister new courses as desired, but how can I delete all the old registrations and failed workflows in the registration list?



  • Regarding security on the Courses list, an alternative that will help is to remove the standard control bar from the list form in courses/dispform.aspx.  Oddly though, I tried this and it has no affect.  I'm guessing the properties are being assigned somewhere else, particularly since the list form web part appears greyed out in dispform.aspx.

    Any thoughts on how to disable that control bar?  The admins could create a copy of the page with control bar enabled for their use, but this keeps the users from getting click-happy.


  • Great !


    But a question: My workflow remains in "Pausing" state !!


  • Thanks!! This works perfectly.

    Had the same issue as Yannis opn the remove button on the MY Registrations.  Your fix did the trick.

    Nice job on the details!

  • How to set Workflow variable  (or field value) to some calculated value?

    I want:

    NewBudget (int) = NewBudget + 1

    So i need to do some math, not just reference to other Fields


    Field3 = Field1 + Field2

    Thank you.

  • I realize it's been a year since this post, but are there any plans for Part 3?  I'm currently working with this template and need to slightly modify the dispform.aspx page for the Courses list.  Unfortunately, SharePoint Designer cannot render the XSLT in the Data View that is being used to display the course information, and I don't have XSLT experience, so I'm somewhat stuck.  It looks like what I need to know would have been included in Part 3 so I'm hoping that someone can help me there.  Thanks!

  • There is a major problem with the Employee Training Scheduling and Materials template.  The template is designed to use several workflows, all very needed and impressive.  The biggest problem I see with it that has not been answered by anyone, including Microsoft is the fact that user need Edit permissions on the “Courses” in order to successfully run the workflow for incremental Seating Policy adjustments.  This is a great feature that automatically adjusts available seating when a user registers or un-registers for a course.  Without this feature, I think the template is nowhere near as useful as it should be.  The problems come in to play with the fact that once you give the users the “Edit” permission, they can also go in and edit every single course scheduled, including those very same Available Seats, along with Course Title, Comments, Location, etc.  Hopefully most users are adult enough not to make these changes but some are invariably not that mature and / or some will mistakenly edit a course, believing they are registering or simply editing their own version of it.  This is a huge bug in my opinion, particularly when Microsoft preaches so much about security and the importance of it.  There should be a way to either run a workflow as another user and / or simply hide the Edit button on the form for users that should not have this permission.  I have literally seen hundreds and hundreds of posts on this and nobody has the answer, including Microsoft posts, which is surprising to me.  Any help would be extremely important and could allow most companies to us this potentially valuable tool fully.

  • The post here has been very helpful.

    In the Emploeye Training  Scheduling templates installed from Microsoft, I see this message: "In progress" for all registrations, what could be responsible. Can anyone help.

  • hi everyone,

    I would also Like to Know the Logic behind the MyRegistration button in CourseList.It passess the URL with parameters to the registrration page but i am not able to do so.Can any body give me steps to rectify this problem..or make me walkthrough the courseregistration part.this would be very helpful in creating other similiar applications as well.

    Thanks in Advance

  • Chandan -

    This is exactly why we need part 3!!! I could use this type of functionality all over SharePoint at my company and I am sure that many others could as well. It's great that I have the template to download, but it doesn't really help me because I do not understand the setup.

  • This tutorial was really great, it helped a lot with getting my mind around workflows. But sadly it doesn't look like the third installment is going to come. Does anyone know of an equivalent tutorial that deals with forms and views.

    Specifically, I'm looking to automatically hide certain fields based on prior answers. I'd also like to change the default based on what was previously answered. In essence i need to dynamically add and remove content based on conditions in the other fields.

  • Can anyone tell me which sets of permission work well on The Training template?

  • Hi,

    I realized that the calendar displayed in course list is displaying the previous day! Today is 9/06/2008 and the day in "Today is..." displays Sunday, June 8, 2008.

    Others calendars in the site are working well. Has anyone any idea what is wrong?

    I have to add the functionality to get the manager's approval for a course registration. How can I add it?

    Thanks in advance.

  • Hi,

    I want to develop a leave sanction loop in Shrepoint. Could you please anybody help me?

    Ours is a software company, here in our staff if anybody wants to apply a Leave, they should upload it to sharepoint and then first it should approve by the PM and then HR head and last CEO (If necessary). After all this he should receive mail that "your leave has been granted" like this. Also there should be comments from all the 3 (?) peoples.



  • when i clicked on share point  templates (file->new->wesite->sharepoint templates) in share point designer 2007 the following message get displayed " microsoft windows share point services required at the website location" i installed wss 3 with sp1. please help me.

Page 5 of 7 (100 items) «34567
Leave a Comment
  • Please add 6 and 3 and type the answer here:
  • Post