SharePoint Content Types and Templates

One of the most powerful features of SharePoint 2007 (MOSS), in my opinion, seems to be one that doesn’t get a lot of attention in the blogosphere: Content Types.  From a Knowledge Management or Content Management perspective, Content Types are a huge benefit.

Not only do Content Types allow you to define metadata (columns) that uniquely make up the Content Type, but you can also attach a template to each Content Type.  This allows you to provide the user the appropriate skeletal form or document whenever they click on New/[Content Type Name] in a library.  (If they already have the template instantiated, then they would use the Upload button instead.)

This means that you will want folks to change their work behavior slightly.  Whenever they create a new document, you will want them to go to the library and start with the blank template, because it may have changed since the last time they used it.  (I think that most people dig around on their hard drive and find the last one that they created and start there, which is a sloppy habit and leads to divergence from any standards that you are trying to put in place.)

The other thing that you will want to do for this approach to be successful is to make sure that you have Best Practice examples that have been instantiated from the templates easily available for the user.  These examples can (and should) change over time, as new instances are seen as improvements on the old Best Practices.  For something like a Network Access Request Form, the Best Practice isn’t going to change often, but for richer Content Types like Proposals they will.

A big part of the power behind Content Types is the capability for them in have parents from which they inherit metadata.  For instance, for an Intranet build out, you might create a base document Content Type called Intranet Base Document, and have all of the other document-based Content Types inherit from it.  That way you can manage columns that apply to all document Content Types in the parent.  Careful design and architecture of your Content Types up front will ensure that the foundation you lay will be of the greatest use going forward.  (You can’t change Content Type parentage after you’ve built them.)

If you haven’t looked at what Content Types in MOSS can do for you, it’s time to do so!

Faceted Search for SharePoint 2007 (MOSS)

I had seen the post on the Microsoft SharePoint Products and Technologies Team Blog the other day about faceted search, but for some reason, it didn’t make an impression.  Today, Scott Jamison posted about it, so I took another look.  (I’ve worked with Scott, and I pay attention when he touts something.)

This is really a cool option to enhance what SharePoint Search can do for you.  The most immediate use I thought of was for a company directory or facebook that is much more interactive than basic Search.  (I’ve posted a few other times about ways to build up this capability, but none of my ideas worked this well.)  Check out the WSS Demo site for an interactive demo.

A few other ideas from the Microsoft SharePoint Products and Technologies Team Blog post:

  • Music catalog: songs have attributes such as artist, title, length, genre, date.
  • Company white pages: directory of people with names, department, role, region.
  • Recipes: cuisine, main ingredients, cooking style, holiday.
  • Travel site: articles have authors, dates, places, prices.
  • Regulatory documents: product and part codes, machine types, expiration dates.
  • Image collection: artist, date, style, type of image, major colors, theme.

A new release is planned in a week or so, with these new features:

  • Multi-thread processing. 1st thread runs for up to 500 facets synchronously, while the 2nd thread is running asynchronously against up to ~30,000 facets.
  • Client side refresh (not AJAX) that updates only facets web part without page refresh.
  • Web part connections to pass Facet settings to the bread crumbs.

Extended facet schema now supports:

  • Facet icons — default icon per facet name complimented by an icon per facet value .
  • Friendly names for facet values.
  • Exclusions — allow exclude facet when values match pattern.
  • Built-in wildcard match, especially useful for exclusions.
  • Improved search syntax, added supports for sentences and quoted phrases.

Pre-Populating SharePoint List Item Values Using Query String Variables

A client of ours was having trouble getting this idea to work based on a post he found on the Microsoft SharePoint Designer Team Blog.  I took a look and got it to work nicely in a test situation.  This is a nice trick, as it can help to pre-populate metadata that your users might otherwise need to provide.

Here’s how I got it to work:

  • I created a Custom List on a MOSS site with no customizations
  • I added the script below into the page, just below the line:       <asp:Content ContentPlaceHolderId=”PlaceHolderMain” runat=”server”>
  • Now, when I hit the New button on the list, I get alerts that the JavaScript is parsing out the Query String variables, as expected
  • I altered the default URL to look something like: http://<<servername>>/Lists/<<List Name>>/NewForm.aspx?Title=XXX
  • The Title is pre-populated with the Query String value that I provide, like ‘XXX’ above

The original post above shows how to make this work for a lookup column, and the code can be extended to work with any column type.  (It would be a nice exercise to make the code work regardless of the column type, but I’ll leave that as an exercise for the reader.)

I’ve left in the alerts that I used to test things so that you can see how it flows.

<script type="text/javascript">

_spBodyOnLoadFunctionNames.push("fillDefaultValues");

function fillDefaultValues() {
  var qs = location.search.substring(1, location.search.length);
  var args = qs.split("&");
  var vals = new Object();

  for (var i=0; i < args.length; i++) {
    var nameVal = args[i].split("=");
    var temp = unescape(nameVal[1]).split('+');

    nameVal[1] = temp.join(' ');
    vals[nameVal[0]] = nameVal[1];
    alert('fillDefaultValues: vals[nameVal[0]]=' + vals[nameVal[0]] + ' nameVal[0]=' + nameVal[0] );
  } 
  setValueFromQueryString(nameVal[0], vals[nameVal[0]]);
}

function setValueFromQueryString(fieldName, value) {
  alert('setValueFromQueryString: fieldName=' + fieldName + ' value=' + value);
  if (value == undefined) return;
  var theField = getTagFromIdentifierAndTitle("input","TextField",fieldName);
  if (theField != null) theField.value = value;
}

function getTagFromIdentifierAndTitle(tagName, identifier, title) {
  alert('getTagFromIdentifierAndTitle: tagName=' + tagName + ' identifier=' + identifier + ' title=' + title);
  var len = identifier.length;
  var tags = document.getElementsByTagName(tagName);

  for (var i=0; i < tags.length; i++) {
    var tempString = tags[i].id;
    if (tags[i].title == title && (identifier == "" || tempString.indexOf(identifier) == tempString.length - len)) {
                alert('getTagFromIdentifierAndTitle: tags[i].id=' + tags[i].id + ' tags[i].title=' + tags[i].title + ' tags[i]=' + tags[i]);
      return tags[i];
    }
  }
  return null;
}
</script>

NOTE: This approach will NOT work in SharePoint 2003 because the column input fields on the page are generated differently.  Rather than just using the basic <INPUT> tag to construct the input fields (as MOSS does), each column is displayed by using JavaScript, like the example below (do a View Source on your page to see this in your environment):

<TR>
  <TH nowrap valign=top class="ms-formlabel"><nobr>Year</nobr></TH>
  <TD class="ms-formbody" style="padding-left:5px">
    <SCRIPT>
      fld = new TextField(frm,"Year","Year","2008");
      fld.cchMaxLength = "255";
      fld.cchDisplaySize = "";
      fld.IMEMode="";
      fld.BuildUI();
    </SCRIPT>
    &nbsp;
<SPAN class="ms-formdescription"></SPAN>
  </TD>
</TR>

This is done internally in the ListFormWebPart, so short of writing a custom Web Part with a new BuildUI function, I just don’t see a way to make this approach work.  Too bad, as, while it isn’t very elegant, it works well!

Yet another good argument to move to MOSS.

Showing This Month’s Documents in a SharePoint List

I’ve frequently been asked if it is possible to display only the current month’s documents in a SharePoint list.  There is no obvious way to do this, as the filtering mechanism in a view will not allow you to specify a formula as its criteria.

The trick is to create a calculated column on the list.  I like to create a Site Column for this so that it is available to me anywhere in the Site Collection that it might turn out to be useful.

So, create a column (either on the list or as a Site Column), choose “Calculated (calculation based on other columns)” as the type of column, and make the data type “Yes/No”. (This is simply a Boolean column, but Yes and No are the values displayed rather than TRUE or FALSE.)  Now all you need is a formula that evaluates to TRUE if your conditions are met, and you’re off and running.

Here’s an example.  I created a column called ThisFiscalPeriod, with the formula:

=AND(TEXT(YEAR(Today),”####”)=[Fiscal Year],(TEXT(29*MONTH(Today),”mmmm”)=[Fiscal Month]))

I had already created columns called Fiscal Year and Fiscal Month that were part of the Content Type that I was using in the list.  Whenever the current year and month matched the Fiscal Year and Fiscal Month, the formula evaluates to TRUE, and the column will display or can be tested to see if it is “Yes”.  (See my earlier post on how to use the Today value in a formula.)

If you wanted to show all of the items that had been modified in the current month, then the formula would look like this:

=AND(TEXT(YEAR(Today),”####”)=TEXT(YEAR([Modified]),”####”),(TEXT(29*MONTH(Today),”mmmm”)=TEXT(29*MONTH([Modified]),”mmmm”)))

Note the neat trick in this part of the formula: TEXT(29*MONTH(Today),”mmmm”).  MONTH(Today) returns a number from 1 to 12 which indicates the current month (1=January, 2=February, etc.).  Multiplying that number by 29 gives a serial day number that *has* to be in the right month.  The following table shows how it works:

  

Date Month Serial Day Text Month
1-Jan      1 29 January
1-Feb      2 58 February
1-Mar      3 87 March
1-Apr      4 116 April
1-May      5 145 May
1-Jun      6 174 June
1-Jul      7 203 July
1-Aug      8 232 August
1-Sep      9 261 September
1-Oct    10 290 October
1-Nov    11 319 November
1-Dec    12 348 December

How To Extend Wildcard People Search on MOSS 2007

I just ran across a pair of postings on this from Ramon Scott and Kanwal Khipple (on the SharePointBuzz blog).  Almost every client that I’ve worked with on their Intranet has wanted some sort of variation on this, calling it the Company Directory, the Facebook, or something similar.  The way I’ve always done it was to use a focused search (usually just embedding a link that passes the appropriate keyword into the People Search page), but the scripts that Ramon and Kanwal provide allow the user to take control of their searches on the People Search page themselves.  Nice!

Technorati tags: , ,