Dailycode.info

Short solution for short problems

Get email from SPUser field in SharePoint

Whe you are working with WSS workflows or webparts, you will come to the point you have to send emails to users.

If you are using a single user field (not allowed to enter multiple users) the value is returned as a string. So if you choose to show the users name and you want to email this users, you cannot get his email out of this field. So how can we get the users email? Here's some functions that might help:

First I get the authors name out of a field in a list:

searchPerson = _doc["Author"].ToString().Substring(_doc["Author"].ToString().IndexOf("#") + 1);
to =  GetEmail(searchPerson);

Sometimes Sharepoint stores #? characters after the names, so multiple values are allowed. The substring will get them out and return the users name correct. E.g. The value could be Mark, Deraeve#2 and after the substring it will be: Mark, Deraeve 

The GetEmail fuction will look for the user in the rootweb, if a user is present in the current web, he will be on the rootweb. Here the code that returns the users email:

        private string GetEmail(string username)
        {
            foreach (SPUser user in SPContext.Current.Site.RootWeb.AllUsers)
            {
                if (user.Name == username)
                {
                    return user.Email;
                }
            }
            return String.Empty;
        } 

So now you get the users email. You could prevent from looping through all users if you have the users login name, but in my case it the users full name, so I cannot use ...AllUsers[loginname] and I have to loop through the entire users collection.

If the user field allows multiple values, you can retrieve the email with the SPFieldUserValueCollection. Because it allows multiple users, it will not return a string, but a SPFieldUserValueCollection. We can use this to build up a list of email addresses:

SPFieldUserValueCollection col = (SPFieldUserValueCollection)_doc["Users"];
StringBuilder sb = new StringBuilder();
foreach (SPFieldUserValue user in col)
{
if (!IsGroup(user,ref sb))
      {
            sb.Append(user.User.Email + ";");
}
}

I will add some extra code that gets the emails of the users who are in a group:

private string GetEmails(string groupName)
        {
            foreach (SPGroup group in SPContext.Current.Site.RootWeb.Groups)
            {
                if (group.Name == groupName)
                {
                    StringBuilder ret = new StringBuilder();
                    foreach (SPUser user in SPContext.Current.Site.RootWeb.Groups[groupName].Users)
                    {
                        ret.Append(user.Email + ";");
                    }
                    return ret.ToString();
                }
            }
            return String.Empty;
        }

I used a function IsGroup, this function simply checks if it is a user or a group and adds all the users in the group to the email addresses (ref sb):

private bool IsGroup(SPFieldUserValue userOrGroup, ref StringBuilder sb)
        {
            SPGroup qsgroup = null;
            try
            {
                qsgroup = SPContext.Current.Site.AllWebs[_sopSiteName].Groups[userOrGroup.ToString()
	.Substring(userOrGroup.ToString().IndexOf("#") + 1)];
                //Page.Response.Write("group");
                foreach (SPUser user in qsgroup.Users)
                {
                    sb.Append(user.Email + ";");
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

Just for fun another function I used to check if a user is a member of a particular group:

        private bool UserInGroup(string group)
        {
            SPGroupCollection grps = CurrentUser().Groups;
            foreach (SPGroup grp in grps)
            {
                if (grp.Name.ToLower().TrimEnd() == group.ToLower().TrimEnd())
                { return true; }
            }
            return false;
        }

 


MOSS 2007 list performance drop

Observation : MOSS 2007 list performance drop

Recently, we discovered that the performance of the MOSS 2007 implemenation of our client dropped significantly for a specific list. The list contains some 1200 records. Most of them contain attachments. The loadtime for the default view would extend to over 20 seconds. Switching views made things even worse!

Analysis

First, the server performance was consulted while loading the list. No special or irregular behaviour of the processor or memory. Services were checked to find out if a service like for example the search was performing a heavy index. No special observations. Then we placed indexes on the key columns. This made no visible difference in performance.

How is it possible that only that list is slow in loading, while other list and doclibs in that same site have a normal loadtime? It had to be something list-specific. And what is specific to a list?  It's views...

Interpretation : Optimizing the GROUP BY

After scrutinizing the views of that list, we discovered that the there were massive groups in certain views. The "group by" statement resulted in records being categorized in over 100 groups. Setting a limit to the number of groups improved performance drastically!
When showing 100 groups on a page, the loadtime took 15-20 or even more seconds. When tuning down the number of groups to 50, the page loaded under 10 seconds.

We tested further and discovered that the number of items under a group hardly alter the page loading time when the groups are collapsed on start. A page with 1 group and 500 items under it will load many times faster than a page with 500 groups and just 1 item under each of those groups.
The key is be wise with GROUP BY statements.

Conclusion : Relation between GROUP BY statement and load time

  1. Group your items in less then 50 categories for optimal performance
  2. Show as few groups as possible on a page (max 50 groups/page)
  3. Place column indexes on the columns you group by 

Applying these principles solved our issue on the spot...

We hope this information will help you further optimizing your WSS/MOSS 2007 environment.


MOSS: Group list by month using calculated fields

How to group a list or library by month if you have a field containing Dates?

 

Simple, create a calculated field in your list or library that returns a string.

Use this code: =TEXT(Date,"yyyy - ")&TEXT(Date,"mm")&TEXT(Date," (mmmm")&TEXT(Date," yyyy)")

Now group by this field and that's it!

You can find everything on functions that you can use in calculated fields on: http://office.microsoft.com/en-us/sharepointtechnology/HA011609471033.aspx