Tuesday, June 22, 2010

Filter linked data source based on the current date

If you use a linked data source for your fancy page, but need to only show "current items", you need to manually edit the SelectCommand CAML attribute of the SharePoint:SPDataSource node for the relevant list:

<View>
  <Query>
    <Where>
      <Gt>
        <FieldRef Name="EventDate" Type="DateTime"/>
        <Value Type="DateTime">
          <Today OffsetDays="-7"/>
        </Value>
      </Gt>
    </Where>
  </Query>
</View>


OffsetDays allows you to specify an offset from Today. In this case it is one week in the past (to show recently "expired" items). Don't forget to htmlencode it!

Wednesday, June 16, 2010

Get Workflow TemplateID

On my custom display form for a list I want to create a link to the Start Workflow page of a specified workflow. Getting the URL is simple, open an item and select to start the desired workflow. Copy the resultant URL and use it on the custom page (after sanitising the Source parameter to make it generic or to add an XSL parameter).

However, one of the required URL parameters is the TemplateID of the workflow, which changes every time it is edited. This is an annoyance if you are in active development and the workflow is being updated regularly.

So what we ideally want is the ability to get the workflow TemplateID from code. Luckily for us, MOSS provides the GetTemplatesForItem method of the Workflow web service. I use Darren Johnstone's JavaScript API for SharePoint services. Darren didn't implement the Workflow web service so I had to create it myself (only implemented the GetTemplatesForItem method so far).

The GetTemplatesForItem method only takes one parameter, the full URL of an item, e.g. 'http://moss2007/sites/WorkflowTestSite/Shared Documents/doc1.docx'. If the item is in a list (and not a library), the ows_FileRef attribute of the item is required, e.g. 'http://moss2007/sites/WorkflowTestSite/Custom List/23_.000'.

The returned XML includes information about the workflows attached to the item. To get the templateID, we use a simple jQuery selector with the name of the workflow:
workflows = new SPAPI_Workflows(GetRootUrl());
wfitems = workflows.getTemplatesForItem("http://moss2007/sites/WorkflowTestSite/Custom List/23_.000");
$(wfitems.responseXML).find("WorkflowTemplate[Name=Name of Workflow] [nodeName=WorkflowTemplateIdSet]").attr("TemplateId")
Of course if all we are really wanting is the URL to get to the start workflow page, we could simply use:
$(wfitems.responseXML).find("WorkflowTemplate[Name=Name of Workflow]").attr("InstantiationUrl")

Tuesday, June 15, 2010

Create list columns via Web Services

I have just spent a day up to my armpits in JavaScript, specifically JavaScript for creating columns on custom lists for a site configuration utility (where the team I was working in doesn't have developer level access to the farm).

The bulk of the work for creating lists and libraries was done by my predecessor but the scope for adding columns to a list was restricted to adding existing site columns. I need to be able to automatically create new list columns.

Using the UpdateList method of the Lists web service makes this quite simple. The tricky part is working out what parameters you use to create the fields (also applies to updating).

The CAML query for creating a field is of the format:

<Fields><Method ID="1"><Field [attributes]/><Field [attributes]/></Method></Fields>

There are lots of attributes to use for the node, but these are the common ones:
  • Type: Corresponds to the column type in the Create Column screen (more details below)
  • Name: Internal name of the field (replaced with the internalised version of the Display Name, see this post).
  • Display Name: The visible name of the column
  • Required: "TRUE" or "FALSE", whether or not this column must contain information (not applicable to Yes/No or Calculated columns)
  • Description: The column description
Other attributes are used depending on the column type (with typical examples):
  • Single line of text

    • Type="Text"
  • Multiple lines of text

    • Type="Note"
    • AppendOnly="TRUE" (append changes to the field, but only if versioning on the list is enabled)
    • RestrictedMode="TRUE" (defines whether users can use normal rich text, or enhanced rich text)
    • RichText="TRUE" (rich or plain text)
    • NumLines="6" (number of lines to display to the user while editing)
  • Choice

    • Type="Choice"
    • Format="Dropdown"
    • FillInChoice="FALSE"
    • Mult="FALSE" (sets multiple selection)
    • <CHOICES><CHOICE>Choice 1</CHOICE><CHOICE>Choice 2</CHOICE></CHOICES>
    • <Default>Choice 2</Default>
  • Currency

    • Type="Currency"
    • Max="321" (maximum value)
    • Min="123" (minimum value)
    • Decimals="0" (number of decimal places)
    • LCID="1033/5129" (currency format, 1033 is USA, 5129 is NZ)
  • Date and Time

    • Type="DateTime"
    • Format="DateOnly"
    • <Default>[today]</Default>
  • Lookup

    • Type="Lookup"
    • List="Lists/[List Name]"
    • ShowField="Title"
    • Mult="FALSE"
  • Yes/No

    • Type="Boolean"
    • <Default>Yes</Default>
  • Person or Group

    • Type="User"
    • UserSelectionMode="0" (all people)
    • ShowField="ImnName" (Name with presence)
  • Calculated

    • Type="Calculated"
    • ResultType="Text"
    • ReadOnly="TRUE"
    • <Formula>=If([ECM Status]="Draft","Work in progress","Submitted")</Formula>
    • <FieldRefs><FieldRef Name="ECM_x0020_Status"/></FieldRefs>

Thursday, June 10, 2010

Use friendly 'developer' column names

When you create new columns in your SharePoint site, an internal name is created from the entered display name. SharePoint uses this internally for what it does and if you use SharePoint Designer to create custom pages for your lists, document libraries, etc. then this internal name is what you interact with.

The internal name (FieldName) is generated by replacing any spaces with _x0020_, so for example, if you create a column called Registration of Interest, the generated FieldName will be Registration_x0020_of_x0020_Interest. You can see this by looking at the field parameter in the URL when editing the column:


In this case, SharePoint encodes the '_' as %5F, which makes it even more messy.

Now if you only work with out of the box configuration through the browser then that's fine, you don't need to worry about the FieldName. But if you work with SharePoint Designer then it becomes horrible to look at, less than to use.

What can you do? If you rename a site column, all you are doing is changing the display name, the FieldName remains the same. So when you create a new column, give it the name you want to use internally, then change it afterwards to what you want it to display. In our above example, we would create the column by calling it RegistrationOfInterest (alternatively RegOfInterest or even RoI). Once the column is created we can then rename it to Registration of Interest but the FieldName will still be RegistrationOfInterest. A lot easier to use.


You can also use this trick when creating lists and libraries to create friendlier URLs. A list called Training Providers will display /Training%20Providers/ in the URL, but if you name the list TrainingProviders on creation, then rename it, the URL portion will remain /TrainingProviders/.