Thursday, April 23, 2015

Preserve properties after overriding document

The value from SharePoint columns for Office documents is actually stored in the document. When user updates the column values in the SharePoint document library(Edit Form), the values are updated in document itself. Columns included in the content type are represented as properties in the content type schema stored in the document. They are identified in the document Management node of the properties element in the schema. These document properties map to document library columns, represented by Field elements in the content type definition stored in the document library.

When user overrides document with different properties in SharePoint document library then it overwrites the current values.  Following are the ways to preserve the old column values:


  • Checkout and update document content
    Checkout the document and open it from SharePoint. Update the document content with new data and check in.
  • Edit document and update the properties
    You can open the document in Client(Word, Excel etc) and update the the properties. After that upload the document to SharePoint.


SharePoint does not provide any event to check if document is overrode. One of my client wanted to preserve the old values after override the document. I came up with following code to preserve the values. Its not full proof. It only works with new document for which properties are not set or the document is not uploaded to SharePoint previously. Same time Title field should be mandatory field. This code fires on ItemUpdated list item event. Following is the code:

/// <summary>
/// An item is being updated.
/// </summary>
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
// Get Current ListItem
SPListItem item = properties.ListItem;
// Check if Title is Null Or Empty.
// Title will be empty in case user is uploading the new document without any property. Same time Title field should be mandatory field.
if (string.IsNullOrEmpty(item.Title))
{
// Get Before Properties
var beforeProperties = properties.BeforeProperties;
// Loop and update all the properties
foreach (System.Collections.DictionaryEntry prop in beforeProperties)
{
try
{
if (prop.Key.ToString().Equals("vti_title"))
{
item["Title"] = beforeProperties[prop.Key.ToString()];
}
if (item.Fields.ContainsField(prop.Key.ToString()))
{
var field = item.Fields.GetField(prop.Key.ToString());
// Check if it is valid property
if (item.Fields.ContainsField(prop.Key.ToString()) && !field.ReadOnlyField && !field.Sealed)
{
item[prop.Key.ToString()] = beforeProperties[prop.Key.ToString()];
}
}
}
catch
{ }
}
// Update the ListItem
EventFiringEnabled = false;
item.SystemUpdate();
EventFiringEnabled = true;
}
}

Above code helped me to preserve the properties in case user is uploading new document without setting properties. I hope this will help someone. Add comment if anyone knows other workaround.

Some useful JavaScript methods and objects in Sharepoint

SharePoint provides some useful methods and objects in JavaScript. Followings are some methods and objects which I use frequently in my client side code:

SP.ScriptUtility

SP.ScriptUtility provides methods and an emptyString field. It contains following methods:


  • isNullOrEmptyString - Checks if the specified text is null, an empty string or undefined
  • isNullOrUndefined - Checks if the specified object is null or undefined.
  • isUndefined - Checks if the specified object is undefined.
  • truncateToInt - Returns largest integer value that is less than or equal to the specified number if the number is greater than 0 else returns the smallest integer value that is greater than or equal to the number.

SP.Guid

SP.Guid.newGuid().toString() return new guid.

_spPageContextInfo

_spPageContextInfo provides following properties:
  • pageListId - Get Current List Guid
  • pageItemId - Get id for current item. 
  • serverRequestPath - Get current server requested relative path. 
  • siteAbsoluteUrl - Get current site absolute URL
  • siteServerRelativeUrl - Get current site relative url
  • userId - Get current user ID
  • webTitle - Get current web Title
  • webAbsoluteUrl - Get current web absolute Url
  • webServerRelativeUrl - Get web server relative url. For exmaple "/teams/SITE_NAME"

escapeProperly(str)

escapeProperly function returns the encoded value for provided string.

var encodedString = escapeProperly("SharePoint 2013 & JavaScript"); // Returns "SharePoint%202013%20%26%20JavaScript"

unescapeProperly(str)

unescapeProperly function returns decoded string for provided encoded string.

var decodedString = unescapeProperly("SharePoint%202013%20%26%20JavaScript"); // Returns "SharePoint 2013 & JavaScript"

Cookies

GetCookie(str)

GetCookie function returns the value for the cookie. It returns null in case cookie is not available.

DeleteCookie(str)

DeleteCookie function remove the cookie by setting expiry to minimum DateTime. 

SetCookie(str, str)

SetCookie function adds session cookie. But this is not very useful function as it adds value as true or false.  Its only useful if you want to set a flag. Second parameter is optional. If you pass second parameter then value of cookie will be "true" else its "false".

JSRequest

You can use JSRequest object to get the FileName, PathName and QueryString. To use the JSRequest object, you must initialize it using EnsureSetup method.

// Initialize JSRequest
JSRequest.EnsureSetup();
var fileName = JSRequest.FileName; // Returns the webpage file name. For example "default.aspx"
var pagePath = JSRequest.PathName; // Returns the relative path. For example "/Sites/SITE_NAME/default.aspx"
var querystringValue = JSRequest.QueryString["QUERYSTRING_NAME"]; // Returns the querystring value if exists else returns undefined
view raw JSRequest.js hosted with ❤ by GitHub

String.format(str, arguments)

You can apply formatting to string using format method.

var stringValue = String.format("{0} and {1} is fun", "SharePoint", "JavaScript"); // Returns "SharePoint and JavaScript is fun"
view raw format.js hosted with ❤ by GitHub

GetUrlKeyValue

GetUrlKeyValue is very useful function when you want to get the querystring values. It can return the querystring value from current url or provided url. Followings are the ways you can use GetURLKeyValue method:

GetUrlKeyValue(str)

It will return the querystring value for provided parameter name from current url. 

GetUrlKeyValue(str, bool)

It will return the encoded or decoded querystring value for provided parameter name from current url on the basis of second parameter. 

GetUrlKeyValue(str, bool, str)

It will return the encoded or decoded querystring value for provided parameter name from given url.

// For example current Url = http://MYWEBAPPLICATION/sites/MYSITE/default.aspx?Param1=SharePoint%20%26%20JavaScript&Param2=100
var qs1 = GetUrlKeyValue("Param2"); // Returns "100"
var qs2 = GetUrlKeyValue("Param1"); // Returns "SharePoint & JavaScript"
var qs3 = GetUrlKeyValue("Param1", true); // Returns "SharePoint%20%26%20JavaScript"
var qs3 = GetUrlKeyValue("Param1", false); // Returns "SharePoint & JavaScript"
var qs4 = GetUrlKeyValue("q", true, "http://www.google.com?q=SharePoint%20%26%20JavaScript"); // Returns "SharePoint%20%26%20JavaScript"
var qs4 = GetUrlKeyValue("q", false, "http://www.google.com?q=SharePoint%20%26%20JavaScript"); // Returns "SharePoint & JavaScript"

STSHtmlEncode(str)

STSHtmlEncode function ecodes the provided HTML string.

var encodedHtml = STSHtmlEncode("<div>This is HTML</div>"); // Returns "&lt;div&gt;This is HTML&lt;/div&gt;"

STSHtmlDecode(str)

STSHtmlDecode function decodes the provided string into HTML.

val decodedHtml = STSHtmlDecode("&lt;div&gt;This is HTML&lt;/div&gt;"); // Returns "<div>This is HTML</div>"

Wednesday, April 15, 2015

Creating SharePoint Columns Programatically Using C#

As a SharePoint developer you can use SharePoint API to create columns programmatically in Lists or Document Libraries. You can set the different properties for the column. Followings are few snippets to create SharePoint column programmatically using C#.

Single line of text

Represents a column that contains a single line of text.

private void AddTextField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.Text, false);
// Get Field
SPFieldText textField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldText;
// Set other properties
textField.Description = "Text Field Description";
// Update field
textField.Update();
}
view raw TextField.cs hosted with ❤ by GitHub

Multiple lines of text

Represents a column that contains a multiple line of text.

private void AddMultiLineTextField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.Note, false);
// Get Field
SPFieldMultiLineText multiLinetextField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldMultiLineText;
// Set other properties
multiLinetextField.Description = "Multiline Text Field Description";
multiLinetextField.NumberOfLines = 10;
// Update field
multiLinetextField.Update();
}

Choice (menu to choose from)

Represents a column that contains choices. It can be single select or multiple select. For single select Choice field renders Dropdown list or Radio button list and for multiple select it renders Checkbox list.

private void AddChoiceField(SPList list)
{
string fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.Choice, false);
// Get field
SPFieldChoice choiceField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldChoice;
// Add options
string[] options = { "Enter Choice #1", "Enter Choice #2", "Enter Choice #3" };
choiceField.Choices.AddRange(options);
// By Default it will be dropdown list
// If multi choice Checkbox list.
choiceField.Type = SPFieldType.MultiChoice;
// Set other properties
choiceField.Description = "Choice Field Description";
choiceField.DefaultValue = "Enter Choice #1";
// Update field
choiceField.Update();
}
view raw ChoiceField.cs hosted with ❤ by GitHub

Number (1, 1.0, 100)

Represents a column that contains numbers. You can use DisplayFormat property to set the allowed number of decimal.

private void AddNumberField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.Number, false);
// Get field
SPFieldNumber numberField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldNumber;
// Set other properties
numberField.Description = "Number Field Description";
numberField.DisplayFormat = SPNumberFormatTypes.NoDecimal;
// Update field
numberField.Update();
}
view raw NumberField.cs hosted with ❤ by GitHub

Currency ($, ¥, €)

Represents a column that contains currency. You can use DisplayFormat property to set the allowed number of decimal. You can use CurrencyLocaleId property to set the currency symbol. You can find full list of Locale Ids here

private void AddCurrencyField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.Currency, false);
// Get field
SPFieldCurrency currencyField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldCurrency;
// Set other properties
currencyField.Description = "Currency Field Description";
currencyField.DisplayFormat = SPNumberFormatTypes.TwoDecimals;
currencyField.CurrencyLocaleId = 1033; // United States
// Update field
currencyField.Update();
}

Date and Time

Represents a column that contains a DateTime value. You can use DisplayFormat property to set the date format.

private void AddDateTimeField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.DateTime, false);
// Get field
SPFieldDateTime dateTimeField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldDateTime;
// Set other properties
dateTimeField.Description = "DateTime Field Description";
dateTimeField.DisplayFormat = SPDateTimeFieldFormatType.DateOnly;
dateTimeField.DefaultValue = "[Today]";
// Update field
dateTimeField.Update();
}

Lookup (information already on this site)

Represents a column that contains a information from other List/Document Library from current site.

private void AddLookupField(SPList lookupList, SPList list)
{
var lookupFieldName = "LookupFieldName";
var fieldName = "FieldName";
// Create field
var fieldInternalName = list.Fields.AddLookup(fieldName, lookupList.ID, true);
// Get field
SPFieldLookup lookupField = list.Fields[fieldInternalName] as SPFieldLookup;
// Set properties
lookupField.Description = "Lookup Field Description";
lookupField.LookupField = lookupList.Fields[lookupFieldName].InternalName;
// Update field
lookupField.Update();
}
view raw LookupField.cs hosted with ❤ by GitHub

Yes/No (check box)

Represents a column that contains Boolean value.

private void AddBooleanField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.Boolean, false);
// Get field
SPFieldBoolean booleanField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldBoolean;
// Set other properties
booleanField.Description = "Boolean Field Description";
// Update field
booleanField.Update();
}
view raw BooleanField.cs hosted with ❤ by GitHub

Person or Group

Represents a column that contains a user or group information.

private void AddUserField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.User, false);
// Get field
SPFieldUser userField = new SPFieldUser(list.Fields, fieldInternalName);
// Set other properties
userField.Description = "User Field Description";
userField.AllowMultipleValues = false;
userField.SelectionMode = SPFieldUserSelectionMode.PeopleAndGroups;
userField.LookupField = "Title";
userField.Update();
// Update field
userField.Update();
}
view raw UserField.cs hosted with ❤ by GitHub

Hyperlink or Picture

Represents a column that contains a Url information. It can be Hyperlink or Picture Url.

private void AddUrlField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.URL, false);
// Get field
SPFieldUrl urlField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldUrl;
// Set other properties
urlField.Description = "Url Field Description";
// SPUrlFieldFormatType.Hyperlink or SPUrlFieldFormatType.Image
urlField.DisplayFormat = SPUrlFieldFormatType.Hyperlink;
// Update field
urlField.Update();
}
view raw UrlField.cs hosted with ❤ by GitHub

Calculated (calculation based on other columns)

Represents a column that contains a calculated value based on other columns.

private void AddCalculatedField(SPList list)
{
var fieldName = "FieldName";
// Create field
string fieldInternalName = list.Fields.Add(fieldName, SPFieldType.Calculated, false);
// Get field
SPFieldCalculated calculatedField = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldCalculated;
// Set other properties
calculatedField.Description = "Calculated Field Description";
calculatedField.Formula = "=[Title]";
calculatedField.OutputType = SPFieldType.Text;
// Update field
calculatedField.Update();
}

Managed Metadata

Represents a column that contains information from Term Store.

private void AddTaxonomyField(SPSite site, SPList list)
{
var fieldName = "FieldName";
// Get TermSet
TaxonomySession taxonomySession = new TaxonomySession(site);
TermStore termStore = taxonomySession.TermStores["MANAGED_METADATA_SERVICE_NAME"];
Group group = termStore.Groups["GROUP_NAME"];
TermSet termset = group.TermSets["TERMSET_NAME"];
// Create field
TaxonomyField taxonomyField = list.Fields.CreateNewField("TaxonomyFieldType", "DISPLAY_NAME") as TaxonomyField;
taxonomyField.Description = "Managed Metadata Field Description";
taxonomyField.SspId = termStore.Id;
taxonomyField.TermSetId = termset.Id;
taxonomyField.AllowMultipleValues = false;
taxonomyField.Group = "GROUP_NAME";
list.Fields.Add(taxonomyField);
}