Welcome to SharePoint User Group UK Sign in | Join | Help

First of all, thanks to Andy Kinnear for writing this piece of code! What this control does is to allow you to add a list view to any layout or master page :)

Notes:

  • You only need to specify the name of the list (no GUID)
  • You are able to type in the name of the view you would like displayed; if you dont specify a view name it will display the default view of this list. 
  • The custom control will only look for the frist list name as specified it can find in the current site, or any sites above the current site if the list name is not in the current site.
  • You can only specify the list name and view name in master / layout page where you add the control.

INSTRUCTIONS:

  • Build the class:

    using System;
    using System.ComponentModel;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;

    using Microsoft.SharePoint.Publishing.Navigation;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.SharePoint;
    using PortalCustomNav.ComponentModel;

    namespace PortalCustomNav.WebControls
    {
    [ToolboxData("<{0}:ListViewControl runat=\"server\" />")]
    public class ListViewControl : SPControl
    {

    [Browsable(true)]
    [SPCategory("SPCategory_Configuration")]
    [DefaultValue("")]
    [SPDescription("ListControlDescription_ListName")]

    private string _listName = "";

    public string ListName
    {
    get
    {
    return _listName;
    }
    set
    {
    _listName = value;
    }
    }

    [Browsable(true)]
    [SPCategory("SPCategory_Configuration")]
    [DefaultValue("")]
    [SPDescription("ListControlDescription_ListName")]

    private string _listViewName = "";

    public string ListViewName
    {
    get
    {
    return _listViewName;
    }
    set
    {
    _listViewName = value;
    }
    }

    protected SPList GetCurrentList(SPWeb site)
    {

    SPListCollection view = site.GetListsOfType(SPBaseType.GenericList);

    foreach (SPList list in view)
    {
    if (list.Title == this._listName)
    {
    return list;
    }
    }

    if (site.ParentWeb != null)
    {
    return GetCurrentList(site.ParentWeb);
    }
    return null;
    }

    protected SPList GetCurrentList()
    {
    SPWeb site = Microsoft.SharePoint.SPContext.Current.Web;
    SPList list = GetCurrentList(site);
    return list;
    }

    //Render the list view
    protected override void Render(HtmlTextWriter writer)
    {

    SPList lst = GetCurrentList();

    if (lst != null)
    {

    foreach (SPView view in lst.Views)
    {
    if (view.Title == this._listViewName)
    {
    SPQuery query = new SPQuery(view);
    writer.Write(lst.RenderAsHtml(query));
    return;
    }
    }

    writer.Write("View " + this._listViewName + " not found in list");

    }
    else
    {
    writer.Write ("List "+this._listName+" not found in site or parent site");
    }
    }

    }
    }
  • Register the class in the GAC and add a "Safe Control" entry in the web.conf file.
  • Register the control in the master page:

    <%@ Register Tagprefix="PortalCustomNav" Namespace="PortalCustomNav.WebControls" Assembly="PortalCustomNav, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0c07a529847e943d" %>

  • Add the control to the master page:

    <PortalCustomNav:ListViewControl runat="server" ListName="Comments" ListViewName=""></PortalCustomNav:ListViewControl>


In "Part 1" is showed a sql query example of how you could get a rolling total of all content added to a content database on a monthly basis. Here I will show how to further filter this query to exclude records of items that may exist within the recycle bin, items which are only document related, etc.

You may need to do this when you want to report on only documents and their versions that exist within lists and libraries, but not in Recycle Bins. Remember that once the default storage period of a recycle bin is reached, the record of the item is removed from all related tables, this could be problematic when you include the items in the recycle bin in your total item count (it will differ from a previous version of the report).

So...on with the examples:

Returning the amount of documents excluding those in recyclebin

In this example I need to join two tables: Alldocs and AllUserData; the reason for this is that I need to query the tp_deletetransactionid which is stored as a var Binary value in the AllUserData table.

USE {add your selected content database here}

SELECT DATENAME([month], x1.monthdate) + ' ' + DATENAME([year], x1.monthdate) AS [Month and Year], MAX(x1.added) AS [Added in Month], SUM(x2.added) AS [Rolling Total]

FROM

(SELECT MONTH(TimeCreated) AS monthno, DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0) AS monthdate, COUNT(*) AS added FROM alldocs WHERE id IN  (SELECT id FROM alldocstreams) GROUP BY DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0), MONTH(TimeCreated)) AS x1

INNER JOIN

(SELECT MONTH(TimeCreated) AS monthno, DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0) AS monthdate, COUNT(*) AS added FROM alldocs WHERE id IN  (SELECT id FROM alldocstreams) GROUP BY DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0), MONTH(TimeCreated)) AS x2

ON x1.monthdate >= x2.monthdate

GROUP BY x1.monthdate ORDER BY x1.monthdate

Returning all content excluding that which is created from Site Templates and Features

Whenever we use the default site templates and features avaiable to us in MOSS 2007 (and custom ones) a bunch of records are created  in the AllDocs table for the files that are created from these templates and features. When it comes to reporting on actual content usage, it is important to keep these numbers out as they bump up the numbers when they should not (creating a site / activating a feature is not actual content usage). Obviously the clients definition of content usage may differ :)

USE {add your select content database here}

SELECT DATENAME([year], x1.monthdate) + '-' + RIGHT('00' + CONVERT(varchar, DATEPART(m, x1.monthdate)), 2) AS [Month and Year], MAX(x1.added)  AS [Added in Month], SUM(x2.added) AS [Rolling Total]

FROM

(SELECT MONTH(AllUserData.tp_Created) AS monthno, DATEADD([month], DATEDIFF([month], 0, AllUserData.tp_Created), 0) AS monthdate, COUNT(*)  AS added
FROM
AllDocs INNER JOIN 
AllUserData ON AllDocs.LeafName = AllUserData.tp_LeafName AND
AllDocs.DirName = AllUserData.tp_DirName AND
AllDocs.ListId = AllUserData.tp_ListId
WHERE (AllDocs.SetupPath IS NULL) AND alldocs.id IN (SELECT id FROM alldocstreams)
GROUP BY DATEADD([month], DATEDIFF([month], 0, AllUserData.tp_Created), 0), MONTH(AllUserData.tp_Created)) x1

INNER JOIN

 SELECT MONTH(AllUserData.tp_Created) AS monthno, DATEADD([month], DATEDIFF([month], 0, AllUserData.tp_Created), 0) AS monthdate, COUNT(*)  AS added
FROM
AllDocs INNER JOIN 
AllUserData ON AllDocs.LeafName = AllUserData.tp_LeafName AND
AllDocs.DirName = AllUserData.tp_DirName AND
AllDocs.ListId = AllUserData.tp_ListId
WHERE (AllDocs.SetupPath IS NULL) AND alldocs.id IN (SELECT id FROM alldocstreams)
GROUP BY DATEADD([month], DATEDIFF([month], 0, AllUserData.tp_Created), 0), MONTH(AllUserData.tp_Created))
) x2

ON x1.monthdate >= x2.monthdate

GROUP BY x1.monthdate

Part 3 comming soon....

As this is going to be an ongoing exercise I am splitting this into parts.

At the moment I am busy finding ways to create different types of usage reports for MOSS deployments. There are some good tools out there that help with this (Reporting Framework from Codeplex) and of course the default MOSS usage reports. None of these however quite fit my or most of my clients requirements, some examples of which are:

  • We want to see how many documents were added in each month with a rolling total.
    • This must EXCLUDE folders, lists and list items (they only want to see what has been uploaded to the system).
  • Show total content on the system excluding content in the recycle bin
    • Eventually items are removed from the recycle bin and from all MOSS tables, when showing rolling totals items in the recycle bin will modify previous known figures.
  • Show percentage values of content type usage. (10% Agenda, 12% Minutes etc.)
  • Show percentage values of file type usage (10% Word Documents, 20% PDF Documents, etc.)
  • And more....

I have managed to achieve all the above and more and will be addind to this post as I have time.

First things first, what tables should be used for these reporting requirements? I am using the following:

  • Alldocs
    This contains records of everything that has been added to MOSS excluding the following:
    • Lists and Libraries
    • Sites
  • AllDocStreams
    This contains records of everything that has been added to MOSS excluding the following:
    • Lists and Libraries
    • List Items
    • Folders
    • Sites
  • AllUserData
    I am using this table as it contains extra information like "Content Type" and other data for items in the Alldocs and AlldocStreams tables that I need to use.
  • RecycleBin
    Self explanatory.
  • Alllists
    I need this to get list names for some of my other reports.
  • Webs
    I need this to get a breakdown of content usage per site.

Example: Show how many items have been added per month with a rolling total

NOTE: as always it is never recommended by MS that you run queries / stored procedures directly on a production DB, rather make copies of the required tables. (if you are like many of my clients who cannot afford the extra data storage, run these reports at midnight :) )

My SQL is rough - you have been warned :)

The following SQL query will get all items that have been added to the system, show how many were added per month and what each months rolling total was (usefull for a growth line):

USE {add your selected content database here}

SELECT DATENAME([month], x1.monthdate) + ' ' + DATENAME([year], x1.monthdate) AS [Month and Year], MAX(x1.added) AS [Added in Month], SUM(x2.added) AS [Rolling Total]

FROM

(SELECT MONTH(TimeCreated) AS monthno, DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0) AS monthdate, COUNT(*) AS added FROM alldocs WHERE id IN  (SELECT id FROM alldocstreams) GROUP BY DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0), MONTH(TimeCreated)) AS x1

INNER JOIN

(SELECT MONTH(TimeCreated) AS monthno, DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0) AS monthdate, COUNT(*) AS added FROM alldocs WHERE id IN  (SELECT id FROM alldocstreams) GROUP BY DATEADD([month], DATEDIFF([month], 0, TimeCreated), 0), MONTH(TimeCreated)) AS x2

ON x1.monthdate >= x2.monthdate

GROUP BY x1.monthdate ORDER BY x1.monthdate

NOTE: The above query returns only items that have been uploaded into the environment, to show all content remove the following WHERE queries:
WHERE id IN (SELECT id from alldocstreams)

The above is just a sample of the query I used which is combined in my stored procs which read off of a custom reporting database. My queries go further as they automatically find all relevant content databases and run this query....this I will not show as we all need to learn :)

If I had place to put screenshots I would show how the pivot tables pulled into Excel Services work.

Part 2 here.

We all know the pitfalls of messing around with default MOSS files and that the basic rules are always to create and modify your own rather than the defaults. One of the main reasons for this is ongoing support for the product from MS (they wont support cusomised changes to defaukt files) as well as the impact of service packs and hotfixes (they generally overwrite default files and hence any changes you made to them).

Now in most cases we dont always know about changes we need to make, and when we do it is sometimes neccessary to change the default files as previous sites are now linked to those files; take the CORE.js and Viewpage.aspx files as examples:

  • CORE.js controls things like context menus and other nice things.
  • Viewpage.aspx is the default page used to create list pages like "Allitems.aspx"

Example:

Recently I needed to modify the CORE.js file to fix a problem with emailed links (some people could not open the link as it was an encoded URL), now rather than modifying the default CORE.js I made a copy and renamed it ClientCore.js, made the changes and replace the reference to the CORE.js in all my custom pages.

Problem: Most list pages are created from the "Viewpage.aspx" page, this page has the default.master as it's master page and I do not want to mess with a MOSS default file.

Solution: Make a copy of the "Viewpage.aspx", change the default.master to my custom master (that references my ClientCore.js instead), change the references in my custom Document Library SCHEMA.xml to create views from the new page. There we go.

Problem: All previous document libraries have been created from the original file with the reference to the original Core.js.

Solution: None really, unless I change the default Core.js / add a the code manually to all preivous libraries. As soon as I apply a hotfix / sp the changes are going to be overwritten.

The real solution?

Planing, planning and paranoia: Now days I automatically ensure I make copies of the files I know / suspect will need to change and ensure that I make references to them; specifically:

  • Core.js
  • Viewpage.aspx
  • default.master
  • (and some others)

What about updates?

This is another problem with no quick-win situation: when a SP or Hotfix does come along and makes changes to the Core.js for instance that are neccessary I simply copy those changes accross into my customized file (look at the documentation, all changes are recorded).

Conclusion:

I know most will disagree with my methods, but when you are facing large, multi farm environments where changes / fixes need to be made after deployment this really works out easier for me. Schlep in the begining to make my life easier in the end :)

Your feedback and ideas would be appreciated on this!

 

I thought I would start a page on some interseting side effects I come accross when playing with the content types in a document library feature:

Try this:

  • Create a document library feature and remove the content types from the schema.xml file.
  • Now activate the feature on a site and browse to the new document library.
    • Click the "New" dropdown and you will see that a content type with the same name as your document library is available :)
  • If you create a instance of this document library that has content type bindings, then you will not have this problem.

This question has been asked many times: "Each folder in my document library must have a different content type, is this possible?"

The only reason for me posting this is that MANY people think that you are unable to associate a content type to a specific folder, when in fact you can and is very easy to do:

  • Add all the content types that you are going to use for each of your folders to the document library (dont panic, the users will not see all of them!).
  • Create a new folder.
  • Open the drop-down context menu for the folder and select the "change new button order" link. (yes, it is actually this simple)
  • Select the content types that should be displayed when the user is in this folder.

NOTE: This will not affect the content type selection on the Upload page though, users will still be able to select from all content types when uploading a document.

Most of you probably already know this, but I thought I would post about it for those who dont.

I have had a couple of questions from people on how to add a content editor web part to a site template (site definition) that contains custom html / javascript code as its content. They have no problem with inserting normal text into the web part that they include in the site template, only when they add some html code.

  • Lets say we want to add the following table code:
    <Table><td>My table in the Web Part</td></table>

The problem lies with the duplicate <![CDATA[ tags in the web part itself; the second one prematurely ends the first ones tag:

  • The first <![CDATA[ tag is just after the "<AllUsersWebPart WebPartZoneID="Left" WebPartOrder="1"> tag.
  • The second <![CDATA[ tag is just after the "<Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor">" tag.

Replace the second instance of the "<![CDATA[" and "]]" tag with <Value> and </Value>:

  • From this:
    <Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><![CDATA[<Table><td>My table in the Web Part</td></table>]]</Content>
  • To this:
    <Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><Value><Table><td>My table in the Web Part</td></table></Value></Content>his:

The other problem lies within the format of the html / javascript tags within the <Content...></Content> tags:

  • The "<" and ">" opening and closing brackets need to be replaced with "&lt;" and "&gt;" respectively.

So, replace the opening and closing tags:

  • From this:
    <Table><td>My table in the Web Part</td></table>
  • To this:
    &lt;Table&gt;&lt;td&gt;My table in the Web Part&lt;/td&gt;&lt;/table&gt;

Now your content editor webpart will work in your site template, below is the whole piece of code:

<AllUsersWebPart WebPartZoneID="Left" WebPartOrder="1"><![CDATA[<WebPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/WebPart/v2">
  <Title>My Table Web Part</Title>
  <FrameType>None</FrameType>
  <Description>Use for formatted text, tables, and images.</Description>
  <IsIncluded>true</IsIncluded>
  <ZoneID>Left</ZoneID>
  <PartOrder>0</PartOrder>
  <FrameState>Normal</FrameState>
  <Height />
  <Width />
  <AllowRemove>true</AllowRemove>
  <AllowZoneChange>true</AllowZoneChange>
  <AllowMinimize>true</AllowMinimize>
  <AllowConnect>true</AllowConnect>
  <AllowEdit>true</AllowEdit>
  <AllowHide>true</AllowHide>
  <IsVisible>true</IsVisible>
  <DetailLink />
  <HelpLink />
  <HelpMode>Modeless</HelpMode>
  <Dir>Default</Dir>
  <PartImageSmall />
  <MissingAssembly>Cannot import this Web Part.</MissingAssembly>
  <PartImageLarge>/_layouts/images/mscontl.gif</PartImageLarge>
  <IsIncludedFilter />
  <Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
  <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>
  <ContentLink xmlns="" />
  <Content xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor"><Value>&lt;Table&gt;&lt;td&gt;My table in the Web Part&lt;/td&gt;&lt;/table&gt;</Value>
</Content>
  <PartStorage xmlns="http://schemas.microsoft.com/WebPart/v2/ContentEditor" />
</WebPart>]]></AllUsersWebPart>

The other day I needed to make a change to one of my features (added a new site template to my custom sites feature, and changed an existing one) which I had already deployed through a solution file. Now the farm environment was quite large and I did not really want to retract the solution, remove it, add it and then redeploy it again as this was very time consuming.

So this is what I did and it works like a charm (completely tested on my DEV environment before going to production):

  • Made the change to the site template.
  • Added the new site template to the solution file.
  • Rebuilt the solution file (keeping the same solution ID)
  • Ran the following stsadm command on the server to remove but not retract the solution from existing sites: stsadm -o deletesolution -name "CustomSiteTemplates.wsp" -override
    • The -override command forces the removal of the solution from the solution store without retracting it.
  • Ran the stsadm command to add the modified solution to the solution store.
  • Redeployed the solution to the Farm.

 

There have been some issues with users that when they select a document link in SharePoint 2007 they do not get prompted to edit the document; instead the document opens directly in "Read Only" mode.

This is a known issue with Office 2003 and MOSS 2007, the easiest way to fix this is to install any Office 2007 component / to modify the registry keys as outlined in this MS KB article:

http://support.microsoft.com/kb/870853

There are a few posts out there that tell you how you can show / hide the QuickLaunch / Treeview menus, but most of them did not really work out so well for me.

So here is how I did it through cusomized master pages:

  • Open your / a default master page (obviously better to have your own) i nyour favorite editor.
  • Look for the </HEAD> tag and paste the following Java Script before the closing tag:

    <script language="javascript">
    <!--
    function showhide(layer_ref) {
    var state = 'block';
    eval( "state=document.all." + layer_ref + ".style.display");
    if (state == 'block') {
    state = 'none';
    eval( "document.all[\"img" + layer_ref + "\"].src = \"_layouts/images/BLK_RGT.GIF\";");
    }
    else {
    state = 'block';
    eval( "document.all[\"img" + layer_ref + "\"].src = \"_layouts/images/BLK_LEFT.GIF\";");
    }
    if (document.all) { //IS IE 4 or 5 (or 6 beta)
    eval( "document.all." + layer_ref + ".style.display = state");
    }
    if (document.getElementById &&!document.all) {
    hza = document.getElementById(layer_ref);
    hza.style.display = state;
    }
    }
    //-->
    </script>


    Basically, this script allows us to show and hide the contents of any <div> tags contained within the .master page. If you look at the script you will see that I have used default MOSS images for my "show" and "hide" functions.
  • Next: locate the TreeView / QuickLaunch tags you wish to hide, for the purposes of this blog I am going to modify the TreeView, find the following tag:

    <div class="ms-treeviewouter">
  • Add the followinf attributes: <div class="ms-treeviewouter" id="regionalNav" style="display:block">

    What we are doing here is giving the TreeView an ID so we know what our action link is going to hide, and we are also specifying that we would like it to be displayed by default (change to display:none) if you wish to hide it by default.
  • Next: locate the following code just above your treeview:

    <SharePoint:SPLinkButton runat="server" NavigateUrl="~site/_layouts/viewlsts.aspx" id="idNavLinkSiteHierarchy" Text="<%$Resources:wss,treeview_header%>" AccessKey="<%$Resources:wss,quiklnch_allcontent_AK%>"/></td>

    This is the title bar of the TreeView (the one that says "Site Hierarchy").
  • Next: add the following code:

    <td style="margin-right:0pt" width="10%"><a id="lnkregionalNav" style="cursor:hand" onclick="showhide('regionalNav');"><img src="_layouts/images/BLK_LEFT.GIF" name="imgregionalNav"/></a></td>

    Here we are adding a new column for the "Show" and "Hide" images and actions. Note that I have stated that I want to show / hide the TreeView with the ID of "regionalNav". I have also specified what image should be displayed on initial page load (if you change the display state of the treeview; be sure to change the image to the correct one!)
  • Save and apply your master pages :)
  • You can do the same to any control with a div tag in your .master.

P.S I would dump screenshots if I were able to :)

Often companies have certain standards around version which they would like maintained when users work with documents, this post explains how to specify the document library versioning options in a document library feature.

Lets take the following scenario: A client wants all document libraries that are created to have the following settings in place:

  • Document library must allow multiple content types.
  • Document library must force users to check the document out before changes are made.
  • Document library must maintain 5 Major versions of each document.
  • Document library must maintain 5 Minor versions of each major version.

This is actually very easy and only requires a minor code addition :)

Lets go:

  • Go to your custom document library feature and open the SCHEMA.xml file (features\customFeature\doclib\schema.xml).

    Look for the following code:

    <?xml version="1.0" encoding="utf-8"?>
    <List xmlns:ows="Microsoft SharePoint" Title="$Resources:shareddocuments_Title;" Direction="$Resources:Direction;" Url="Shared Documents" BaseType="1">
    <Metadata>

    Note: The above code is taken from the default document library so yours may differ - the area where we are going to add our code is within the <List> tag.
  • You want to add the following bits of code in the <List> tag:

    <?xml version="1.0" encoding="utf-8"?>
    <List xmlns:ows="Microsoft SharePoint" Title="$Resources:shareddocuments_Title;" Direction="$Resources:Direction;" Url="Shared Documents" BaseType="1"
    EnableContentTypes="TRUE" ForceCheckout="TRUE" EnableMinorVersions="TRUE" VersioningEnabled="TRUE" MajorVersionLimit="5" MajorWithMinorVersionsLimit="5" >

    Note: The code additions are pretty self explanetory!

  • Save, IISRESET (or enable your feature), create the document library.

    IMPORTANT: when creating the document library ensure to select "Create a version each time you edit a document" - otherwise your versioning settings will be overwritten!
    When created automatically via template though, the activation the settings will be in place.

  • View the versioning settings. Happy days :)

UPDATE:

Here are some more settings you can include:

  • If you want to ensure that only users who have "edit" rights on documents can view draft versions of documents:
    DraftVersionVisibility="1" ("0" for read access)

 

Regards,

Doug "bobthebuilder" McCusker


 

 

When creating custom Site Templates (features, definitions - whichever you prefer), one of the things most clients want is a document library included in the Site Template with a pre-defined folder structure. So I thought I would share my solution for creating a document library with a pre-populated folder structure as it is becoming more popular as of late.

Now there are actually 3 different methods of doing this:

  • Through the ONET.XML file in your custom Site Template 
  • Through the manifest.xml file of your custom document library feature. 
  • Through the manifest.xml file of a custom document library instance feature.

In this post I am going to explain how to add it via option 3 (the instance feature) as this requires the least amount of code :) I am NOT going to explain how to create an list template instance feature (plenty of other posts out there).

Lets go:

  • Open your features manifest file (features/feature/listTemplates/featureName.xml)

    You should see something along the lines of:

    <?xml version="1.0" encoding="utf-8" ?>

<!-- _lcid="1033" _version="12.0.3820" _dal="1" -->

<!-- _LocalBinding -->

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

<ListInstance
    FeatureId="00BFEA71-E717-4E80-AA17-D0C71B360101"
    TemplateType="101"
    Title="Documents"
    Url="Docs"               
    Description=""
    QuickLaunchUrl="Docs/Forms/AllItems.aspx"
    />

</Elements>


  • Add the following code just before the </Elements> tag:

    <Module Path="Folder01" Url="Docs\Folder" />

    Note: The Url in the above tag begins with the url of the list instance
  • Now, lets add a subfolder to the above folder:

    <Module Path="Folder01" Url="Docs\Folder\Sub-Folder" />

You can carry on like this for as long as you like. Once you are finished, install your feature. When you activate the feature your document library will be created with your pre-loaded folder structure in place.

Below is an example of one of mine:

<?xml version="1.0" encoding="utf-8" ?>

<!-- _lcid="1033" _version="12.0.3820" _dal="1" -->

<!-- _LocalBinding -->

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

<ListInstance
    FeatureId="00BFEA71-E717-4E80-AA17-D0C71B360101"
    TemplateType="101"
    Title="Documents"
    Url="Docs"               
    Description=""
    QuickLaunchUrl="Docs/Forms/AllItems.aspx"
    />

<!-- required custom content type for this document library instance -->
<ContentTypeBinding ListUrl="Docs" ContentTypeId="0x010110" />

<!-- Single folder no sub-folders -->
<Module Path="Administration" Url="Docs/Administration" />

<!-- A Folder and associated sub-folders -->
<Module Path="Audits" Url="Docs/Audits" />
<Module Path="Audits" Url="Docs/Audits/Assurance" />
<Module Path="Audits" Url="Docs/Audits/Corporate" />
<Module Path="Audits" Url="Docs/Audits/Risk"/>
<Module Path="Audits" Url="Docs/Audits/Committee"/>
<Module Path="Audits" Url="Docs/Audits/Fraud"/>
<Module Path="Audits" Url="Docs/Audits/Information"/>
<Module Path="Audits" Url="Docs/Audits/External"/>
<Module Path="Audits" Url="Docs/Audits/Internal"/>
<Module Path="Audits" Url="Docs/Audits/Other"/>

</Elements>

Regards,

Doug "bobthebuilder" McCusker


Have you ever tried add a list web part (like "Shared Documents") to the default landing page of your site, but seem unable to to change the title of the webpart, frame type etc. as the code differs from that of a standard web part?

Recently I had a requirement for a site template that should by default create a document library with 2 new views ("My Items" and "My Edited Items"), the landing page of the site should also display two web parts of the document library: one displaying the "My Items" view and the other the "My Edited Items" view.

When you add a standard web part to a site template you generally have something like the following code:

<AllUsersWebPart WebPartZoneID="Right" WebPartOrder="1">
<![CDATA[<WebPart ... >
<Assembly>...</Assembly>
<TypeName>...</TypeName>

<Title>...</Title>
<FrameType>...</FrameType>
   etc, etc, etc
</WebPart>]]>
</AllUsersWebPart>

Now when you want to add a web part for a document library or list, you have to put in the following type of code:

<View List="MyCustomDocumentLibrary" BaseViewID="13" WebPartZoneID="MiddleRight" />

Simply add the following code to the list view web part:

<View List="MyCustomDocumentLibrary" BaseViewID="13" WebPartZoneID="MiddleLeft" >
<![CDATA[
<WebPart xmlns="
http://schemas.microsoft.com/WebPart/v2">
<Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
<TypeName>Microsoft.SharePoint.WebPartPages.ListViewWebPart</TypeName>
<FrameType>TitleBarOnly</FrameType>
<Title>My Edited Documents</Title>
<Toolbar>None</Toolbar>
<!-- Add your other tag changes here -->
</WebPart>]]>
</View>

Note: I added the <![CDATA[ attributes of a standard web part into my document library list view and ensured that the <TypeName> attribute was that of a ListViewWebPart.

You may want to change the type of toolbar that is displayed for a document library web part (eg: summary), unfortunately I have not worked this one out yet.

Regards,

Doug "bobthebuilder" McCusker

Long time no post, and I have plenty to post about! So lets get started with a simple one:

Problem:

You enable the tree view to be displayed on the page and the client loves it! Problem is though that the client does not like the vertical and horizontal scrollbars that are displayed as the width and height of the TreeView changes.

Solution:

  • Choose your master page where you would like to make the change and open it in your favorite editor (mine is notepad ++).
  • Look for the following tag: SharePoint:SPRememberScroll runat="server" id="TreeViewRememberScroll" onscroll="BLOCKED SCRIPT_spRecordScrollPositions(this);" Style="overflow: auto;height: 400;width: 150;  and change it to: SharePoint:SPRememberScroll runat="server" id="TreeViewRememberScroll" onscroll="BLOCKED SCRIPT_spRecordScrollPositions(this);" Style="overflow: auto;height: auto;width: auto;
  • Done!

Like I said, nice and simple and you have probably figured this out already :)

Web based InfoPath 2007 forms do not support the Role Based Access that is available as an InfoPath 2007 client form; so we need a work-a-round:

Scenario:

You create an application form that needs to be filled out and completed by various types of users:

  • User A needs to fill out and submit the form by selecting a "Submit for Approval" button.
  • User B needs to approve the form by selecting and "Approve" button.
    • User A must not see "Approve" button.

Solution:

  • Create your form.
  • Add an "Approve" and "Submit" button.
  • Add the following fields (do not include them in the form):
    • "CurrentlyLoggedInUser" (text field) and "Profile" (text field)
      • Set the default value of this field to be the fuction "CurrentUser()"
      • Add a rule to the "CurrentlyLoggedInUser" field to update the value of the "Profile" field to "1" is the user contains the username of the person who is an approver. Else set the value to "0".
  • Add conditional formatting to the "Approve" button to only display the button if the "Profile" field is equal to "1"
    • Note: The conditional formating will not work based on the value of "CurrentlyLoggedInUser"
  • Add conditional formatting to the "Submit" button to only display the button if the "Profile" field is equal to "0"
  • Done.