Skip to content

Instantly share code, notes, and snippets.

@trgraglia
Last active December 11, 2015 22:49
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trgraglia/4672176 to your computer and use it in GitHub Desktop.
Save trgraglia/4672176 to your computer and use it in GitHub Desktop.
SPQueryHandler for easily creating SharePoint SPQuery queries.
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint;
namespace slnNamespace
{
/// <summary>
/// An enumeration of the different operators.
/// </summary>
/// <remarks>
/// This is to make the calls easier and remove more chances for error.
/// </remarks>
public enum SPQueryOperator
{
/// <summary>
/// Value type "Eq".
/// </summary>
Equal,
/// <summary>
/// Value type "Neq".
/// </summary>
NotEqual,
/// <summary>
/// Value type "BeginsWith".
/// </summary>
BeginsWith,
/// <summary>
/// Value type "Contains".
/// </summary>
Contains,
/// <summary>
/// Value type "Lt".
/// </summary>
LessThan,
/// <summary>
/// Value type "Leq".
/// </summary>
LessThanEqual,
/// <summary>
/// Value type "Gt".
/// </summary>
GreaterThan,
/// <summary>
/// Value type "Geq".
/// </summary>
GreaterThanEqual,
/// <summary>
/// Value type "IsNull".
/// </summary>
IsNull,
/// <summary>
/// Value type "IsNotNull".
/// </summary>
IsNotNull
}
/// <summary>
/// An enumeration of the different field value types.
/// </summary>
/// <remarks>
/// This is to make the calls easier and remove more chances for error.
/// </remarks>
public enum SPQueryValueType
{
/// <summary>
/// Value type "Text".
/// </summary>
Text,
/// <summary>
/// Value type "Boolean".
/// </summary>
Boolean,
/// <summary>
/// Value type "DateTime".
/// </summary>
DateTime,
/// <summary>
/// Value type "URL".
/// </summary>
Url,
/// <summary>
/// Value type "Guid".
/// </summary>
Guid,
/// <summary>
/// Value type "Number".
/// </summary>
Number,
/// <summary>
/// Value type "UserMulti".
/// </summary>
UserMulti,
/// <summary>
/// Value type "User".
/// </summary>
User
}
/// <summary>
/// An enumeration of the different logic operators.
/// </summary>
public enum SPQueryLogicOperator
{
/// <summary>
/// Value type "And".
/// </summary>
And,
/// <summary>
/// Value type "Or".
/// </summary>
Or
}
/// <summary>
/// A handler to create SPQuery objects easier and faster.
/// </summary>
/// <remarks>
/// Author: Anthony Graglia - https://github.com/trgraglia
/// </remarks>
/// <example>
/// // Get all list items which are currently checked out to include subfolders.
/// QueryHandler query = new QueryHandler()
/// .AddQuery(SPQueryOperator.IsNotNull, "CheckoutUser", SPQueryLogicOperator.And)
/// .AddViewAttributes("Scope='Recursive'");
/// SPListItemCollection items = list.GetItems(query.Query);
///
/// // Get all list items which have the following URL in a hyperlink field.
/// // NOTE: We need '/sites/site-collection' in the query and not the full URL.
/// // http://malcan.com/EN/Lists/Tips%20and%20tricks/DispForm.aspx?ID=23
/// QueryHandler query = new QueryHandler()
/// .AddQuery(SPQueryOperator.BeginsWith, "URLField", SPQueryValueType.Url, "/sites/testing, SPQueryLogicOperator.And);
/// </example>
public class QueryHandler
{
private List<string> _lstViewFields;
private List<string> _lstSubQueries;
private List<string> _lstSubQueriesAndOr;
private static readonly string[] SPQueryOperators = { "Eq", "Neq", "BeginsWith", "Contains", "Lt", "Leq", "Gt", "Geq", "IsNull", "IsNotNull" };
private static readonly string[] SPQueryValueTypes = { "Text", "Boolean", "DateTime", "URL", "Guid", "Number", "UserMulti", "User" };
private static readonly string[] SPQueryLogicOperators = { "And", "Or" };
private const string StrViewFieldFormat = "<FieldRef Name='{0}' />";
private const string StrWhereFormat = "<Where>{0}</Where>";
private const string StrGroupByFormat = "{1}<GroupBy><FieldRef Name='{0}' /></GroupBy>";
private const string StrOrderByFormat = "{1}<OrderBy><FieldRef Name='{0}' /></OrderBy> ";
private const string StrQueryFormatLong = "<{0}><FieldRef Name='{1}' /><Value {4} Type='{2}'>{3}</Value></{0}>";
private const string StrQueryFormatShort = "<{0}><FieldRef Name='{1}' /></{0}>";
/// <summary>
/// The current <see cref="SPQuery"/> object.
/// It is updated after every added view field, sub query, grouping, ordering or row limit change.
/// </summary>
public SPQuery Query { get; private set; }
/// <summary>
/// The row limit of the query.
/// Use <see cref="SetRowLimit"/> to set and <see cref="ClearRowLimit"/> to remove it.
/// </summary>
public int IntRowLimit { get; private set; }
/// <summary>
/// The order by field name for the query.
/// Use <see cref="SetOrderBy"/> to set and <see cref="ClearOrderBy"/> to remove it.
/// </summary>
public string StrOrderBy { get; private set; }
/// <summary>
/// The grouping field name for the query.
/// Use <see cref="SetGroupBy"/> to set and <see cref="ClearGroupBy"/> to remove it.
/// </summary>
public string StrGroupBy { get; private set; }
/// <summary>
/// The View Attributes of the query.
/// </summary>
public string StrViewAttributes { get; private set; }
/// <summary>
/// The string to represent the current user in a query. ("<UserID />")
/// </summary>
public const string CurrentUser = "<UserID />";
/// <summary>
/// The string to represent the current user in a query. ("<Today />")
/// </summary>
public const string Today = "<Today />";
/// <summary>
/// The string to represent a true boolean. ("1")
/// </summary>
public const string TrueValue = "1";
/// <summary>
/// The string to represent a false boolean. ("0")
/// </summary>
public const string FalseValue = "0";
/// <summary>
/// Constructor - A new handler with an empty query.
/// </summary>
public QueryHandler()
{
Query = new SPQuery();
_lstViewFields = new List<string>();
_lstSubQueries = new List<string>();
_lstSubQueriesAndOr = new List<string>();
IntRowLimit = 0;
}
/// <summary>
/// Sets the <see cref="IntRowLimit"/> int value. (Chainable)
/// </summary>
/// <param name="intRowLimit">The row limit value.</param>
public QueryHandler SetRowLimit(int intRowLimit)
{
IntRowLimit = intRowLimit;
BuildSpQuery();
return this;
}
/// <summary>
/// Removes the <see cref="IntRowLimit"/> int value. (Chainable)
/// </summary>
public QueryHandler ClearRowLimit()
{
IntRowLimit = 0;
BuildSpQuery();
return this;
}
/// <summary>
/// Adds a subquery to the query. (Chainable)
/// </summary>
/// <param name="queryOperator">The operator. Use <see cref="SPQueryOperator"/></param>
/// <param name="strFieldName">The field name.</param>
/// <param name="valueType">The type of the value. Use <see cref="SPQueryValueType"/></param>
/// <param name="strValue">The value of the subquery.</param>
/// <param name="strAdditionalProperties">Additional properties as a string for the 'Value' tag. (e.g. "property='value'" )</param>
/// <param name="andOr">The logical operator. Use <see cref="SPQueryLogicOperator"/></param>
public QueryHandler AddQuery(SPQueryOperator queryOperator, string strFieldName, SPQueryValueType valueType, string strValue, string strAdditionalProperties, SPQueryLogicOperator andOr)
{
// This depends on if the URLs are stored in the field with https or not.
if (valueType == SPQueryValueType.Url)
strValue = strValue.Replace("https://", "http://");
_lstSubQueries.Add(string.Format(StrQueryFormatLong, SPQueryOperators[(int)queryOperator], strFieldName, SPQueryValueTypes[(int)valueType], strValue, strAdditionalProperties));
_lstSubQueriesAndOr.Add(SPQueryLogicOperators[(int)andOr]);
BuildSpQuery();
return this;
}
/// <summary>
/// Adds a subquery to the query. (Chainable)
/// </summary>
/// <param name="queryOperator">The operator. Use <see cref="SPQueryOperator"/></param>
/// <param name="strFieldName">The field name.</param>
/// <param name="valueType">The type of the value. Use <see cref="SPQueryValueType"/></param>
/// <param name="strValue">The value of the subquery.</param>
/// <param name="andOr">The logical operator. Use <see cref="SPQueryLogicOperator"/></param>
public QueryHandler AddQuery(SPQueryOperator queryOperator, string strFieldName, SPQueryValueType valueType, string strValue, SPQueryLogicOperator andOr)
{
// This depends on if the URLs are stored in the field with https or not.
if (valueType == SPQueryValueType.Url)
strValue = strValue.Replace("https://", "http://");
_lstSubQueries.Add(string.Format(StrQueryFormatLong, SPQueryOperators[(int)queryOperator], strFieldName, SPQueryValueTypes[(int)valueType], strValue, string.Empty));
_lstSubQueriesAndOr.Add(SPQueryLogicOperators[(int)andOr]);
BuildSpQuery();
return this;
}
/// <summary>
/// Adds a subquery to the query. (Chainable)
/// </summary>
/// <param name="queryOperator">The operator. Use <see cref="SPQueryOperator"/></param>
/// <param name="strFieldName">The field name.</param>
/// <param name="andOr">The logical operator. Use <see cref="SPQueryLogicOperator"/></param>
public QueryHandler AddQuery(SPQueryOperator queryOperator, string strFieldName, SPQueryLogicOperator andOr)
{
_lstSubQueries.Add(string.Format(StrQueryFormatShort, SPQueryOperators[(int)queryOperator], strFieldName));
_lstSubQueriesAndOr.Add(SPQueryLogicOperators[(int)andOr]);
BuildSpQuery();
return this;
}
/// <Summary>
/// Clear all of the subqueries from the query. (Chainable)
/// </summary>
public QueryHandler ClearQueries()
{
_lstSubQueries.Clear();
_lstSubQueriesAndOr.Clear();
BuildSpQuery();
return this;
}
/// <summary>
/// Add the given 'ViewField' field to the query. (Chainable)
/// </summary>
/// <param name="strFieldName">The 'ViewField' field name of the field to add to the query.</param>
public QueryHandler AddViewField(string strFieldName)
{
_lstViewFields.Add(strFieldName);
BuildSpQuery();
return this;
}
/// <summary>
/// Add the array of given 'ViewField' fields to the query. (Chainable)
/// </summary>
/// <param name="strFieldNames">The array of 'ViewField' field names of the fields to add to the query.</param>
public QueryHandler AddViewField(string[] strFieldNames)
{
foreach (string strFieldName in strFieldNames)
_lstViewFields.Add(strFieldName);
BuildSpQuery();
return this;
}
/// <summary>
/// Remove the given 'ViewField' from the query. (Chainable)
/// </summary>
/// <param name="strFieldName">The 'ViewField' to remove from the query.</param>
public QueryHandler RemoveViewField(string strFieldName)
{
_lstViewFields.Remove(strFieldName);
BuildSpQuery();
return this;
}
/// <summary>
/// Add the string of given 'ViewAttributes' field to the query. (Chainable)
/// </summary>
/// <param name="strViewAttributes">The string of 'ViewAttributes' to add to the query.</param>
public QueryHandler AddViewAttributes(string strViewAttributes)
{
StrViewAttributes = strViewAttributes;
BuildSpQuery();
return this;
}
/// <summary>
/// Remove the 'ViewAttributes' from the query. (Chainable)
/// </summary>
public QueryHandler RemoveViewAttributes()
{
StrViewAttributes = string.Empty;
BuildSpQuery();
return this;
}
/// <summary>
/// Clear all the 'ViewFields' from the query. (Chainable)
/// </summary>
public QueryHandler ClearViewField()
{
_lstViewFields.Clear();
BuildSpQuery();
return this;
}
/// <summary>
/// Set the field name for order by in the query. (Chainable)
/// </summary>
/// <param name="fieldName">The field name to order the query by.</param>
public QueryHandler SetOrderBy(string fieldName)
{
StrOrderBy = fieldName;
BuildSpQuery();
return this;
}
/// <summary>
/// Clears the order by field name if a order by field name was previously set. (Chainable)
/// </summary>
public QueryHandler ClearOrderBy()
{
StrOrderBy = string.Empty;
BuildSpQuery();
return this;
}
/// <summary>
/// Set the field name for group by in the query. (Chainable)
/// </summary>
/// <param name="fieldName">The field name to group the query by.</param>
public QueryHandler SetGroupBy(string fieldName)
{
StrGroupBy = fieldName;
BuildSpQuery();
return this;
}
/// <summary>
/// Clears the grouping field name if a group by field name was previously set. (Chainable)
/// </summary>
public QueryHandler ClearGroupBy()
{
StrGroupBy = string.Empty;
BuildSpQuery();
return this;
}
private void BuildSpQuery()
{
// Build the new SPQuery object.
Query = new SPQuery();
// Add the row limit.
if (IntRowLimit > 0)
Query.RowLimit = (uint)IntRowLimit;
// Add the view fields to the query object.
string strViewFields = _lstViewFields.Aggregate(string.Empty, (current, strViewField) => current + (string.Format(StrViewFieldFormat, strViewField)));
if (!string.IsNullOrEmpty(strViewFields))
Query.ViewFields = strViewFields;
// Add the query to the query object.
int intSubQueriesCount = _lstSubQueries.Count;
string strSubQueries = string.Empty;
if (intSubQueriesCount == 1)
strSubQueries = _lstSubQueries[0];
else if (intSubQueriesCount >= 2)
strSubQueries = string.Format("<{0}>{1}{2}</{3}>", _lstSubQueriesAndOr[1], _lstSubQueries[0], _lstSubQueries[1], _lstSubQueriesAndOr[1]);
if (intSubQueriesCount > 2)
{
for (int i = 2; i < intSubQueriesCount; i++)
strSubQueries = string.Format("<{0}>{1}{2}</{3}>", _lstSubQueriesAndOr[i], strSubQueries, _lstSubQueries[i], _lstSubQueriesAndOr[i]);
}
if (!string.IsNullOrEmpty(strSubQueries))
Query.Query = string.Format(StrWhereFormat, strSubQueries);
if (!string.IsNullOrEmpty(StrGroupBy))
Query.Query = string.Format(StrGroupByFormat, StrGroupBy, Query.Query);
if (!string.IsNullOrEmpty(StrOrderBy))
Query.Query = string.Format(StrOrderByFormat, StrOrderBy, Query.Query);
if (!string.IsNullOrEmpty(StrViewAttributes))
Query.ViewAttributes = StrViewAttributes;
}
}
}
@trgraglia
Copy link
Author

Updated with revision 7:
Added SPQueryValueType enumeration and created overrides.
Added SPQueryOperator enumeration and created overrides.

@trgraglia
Copy link
Author

Added OrderBy and moved a lot of filter strings to const variables. Updated methods to use consistent naming.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment