SyntaxHighlighter

Saturday, 22 March 2014

C# & VB.NET Trim String To a Specific Length

I needed to trim some strings that if over a certain length would trim nicely and add "..." to the end. I particularly like to use extension methods in .NET where possible so I created this little TrimTo extension. There are some optionals that can be sent through including the characters whack on the end and whether to swap out the HTML br tag (I needed this - you may not ;) )

C#
public static class Extensions
{
 /// <summary>
 /// <summary>
 /// Trim a string to a specific length
 /// </summary>
 /// <param name="size">The finishing size of the string</param>
 public static string TrimTo(this string s, int size)
 {
  return TrimTo(s, size, "...");
 }

 /// <summary>
 /// Trim a string to a specific length
 /// </summary>
 /// <param name="size">The finishing size of the string</param>
 /// <param name="chars">The characters to put at the end of the string. Defaults to "..."</param>
 public static string TrimTo(this string s, int size, string chars)
 {
  return TrimTo(s, size, chars, false);
 }

 /// <summary>
 /// Trim a string to a specific length
 /// </summary>
 /// <param name="size">The finishing size of the string</param>
 /// <param name="chars">The characters to put at the end of the string. Defaults to "..."</param>
 /// <param name="doBRs">Where to replace new lines with &lt;br /&gt;. Defaults to false</param>
 public static string TrimTo(this string s, int size, string chars, bool doBRs)
 {
  if (s.Length > size)
   s = String.Format("{0}{1}", s.Substring(0, size), chars);
  if (doBRs)
   s = s.Replace("\n", "<br />");
  return s;
 }
}

VB.NET
Public Shared Class Extensions
 ''' <summary>
 ''' <summary>
 ''' Trim a string to a specific length
 ''' </summary>
 ''' <param name="size">The finishing size of the string</param>
 Public Shared Function TrimTo(this string s, int size) As String
  Return TrimTo(s, size, "...")
 End Function

 ''' <summary>
 ''' Trim a string to a specific length
 ''' </summary>
 ''' <param name="size">The finishing size of the string</param>
 ''' <param name="chars">The characters to put at the end of the string. Defaults to "..."</param>
 Public Shared Function TrimTo(this string s, int size, string chars) As String
  Return TrimTo(s, size, chars, false)
 End Function

 ''' <summary>
 ''' Trim a string to a specific length
 ''' </summary>
 ''' <param name="size">The finishing size of the string</param>
 ''' <param name="chars">The characters to put at the end of the string. Defaults to "..."</param>
 ''' <param name="doBRs">Where to replace new lines with &lt;br /&gt;. Defaults to false</param>
 Public Shared Function TrimTo(this string s, int size, string chars, bool doBRs) As String
  If s.Length > size Then s = String.Format("{0}{1}", s.Substring(0, size), chars)
  If doBRs Then s = s.Replace("\n", "<br />")
  Return s
 End Function
End Class

C# Hex Colour to RGB

I have to do a lot of interop work with Word & Excel and generally struggle matching up colour pallets across the two applications and the only way I've found to consistently do this is by using RGB colours and the RGB function provided in VB(A).

Having recently started a new C# project that I am using hex colour codes with (e.g. #000000), I thought I would write a simple RGB colour handling class that converts the hex colour code into RGB codes for me. And here it is...

/// A helper class used to hold the RGB values of a hex colour e.g. #000000
/// </summary>
public class RGBColour
{
 private string _HexRef = String.Empty;
 public string HexRef
 {
  get { return this._HexRef; }
  set
  {
   if (!value.StartsWith("#"))
    throw new Exception("The hex colour reference must start with a #. e.g. #000000");
   if (value.Length < 7)
    throw new Exception("The hex colour reference must be 7 characters. e.g. #000000");
   this._HexRef = value;
   Color c = ColorTranslator.FromHtml(value);
   this._R = Convert.ToInt32(c.R);
   this._G = Convert.ToInt32(c.G);
   this._B = Convert.ToInt32(c.B);
  }
 }

 private int _R = 0;
 public int R { get { return this._R; } }

 private int _G = 0;
 public int G { get { return this._G; } }

 private int _B = 0;
 public int B { get { return this._B; } }

 public RGBColour()
 {
 }
 public RGBColour(string hexRef)
 {
  this.HexRef = hexRef;
 }
} 

It quite simply uses the System.Drawing.ColorTranslator.FromHtml method to convert the hex value into a System.Drawing.Color object. The Color RGB properties are then converted to an int32.

This can then be used like this...

RGBColour rgb = new RGBColour("#000000");
xl.ActiveCell.Interior.Color = xl.RGB(rgb.R, rgb.G, rgb.B);

Return Dynamic Generic IList in C#

I had a situation where I had a SQL statement stored against a row in a database. Depending on the row would depend on what data was output. For example, row 1 would return all the industries and row 2 would  return all the age groups and so on. Each of my tables has it's own C# class/object associated to it. So I have an Industry class and an AgeGroup class and so on.

The data that has the SQL logged against it was a table and object called PersonalDetail and the SQL was stored in a column/property called LookUpStatement. I wanted to get an Ilist<> of the data results that LookUpStatement returns when executed. The key thing I wanted to achieve was that the new method would return the IList<> strongly typed. So in the case of the industry data I would have IList<Industry> returned by it or for AgeGroup an IList<AgeGroup>.

The whole passing and returning of dynamic types has been something I have wanted to master for some time. After some extensive searching and no single article telling me exactly what I needed I managed to pile it all together and ended with this...

Calling and using it:

//Get the personal detail row that is required
// The Load method loads a specifc row from the database
// In this instance, row 1 LookUpStatement will select all industires (e.g. SELECT * FROM [Industry]) 
PersonalDetail personalDetail = PersonalDetail.Load(1);

//Get the industries as an IList from the personal detail object
IList<Industry> industries = personalDetail.LookUpData<List<Indstry>>();

Note that the LookUpData call is made using a List<> and not an IList<>.The code itself:

public class PersonalDetail
{

 public LookUpStatement
 {
  get; set;
 }
 
 //Other properties, constructor, etc...
 
 public T LookUpData<T>()
 {
  if (!typeof(T).Name.StartsWith("List"))
   throw new ArgumentException("The generic pass type must be a List<>"); 
  
  //Create a typed instance of the required List
  T os = (T)Activator.CreateInstance(typeof(T));
  
  //Get the base object propertype. e.g. Industry
        Type propType = typeof(T).GetProperty("Item").PropertyType;
  
  //Get the data as a DataSet
  DataSet ds = _DB.GetDataSet(this.LookUpStatement);
  
  //Iterate the data
  for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
  {
   //Get the data row
   DataRow dr = ds.Tables[0].Rows[i];

   //Use relfection to execute the Add method of the dynmaic List
   //Then use relfection to execute the LogItem method of the base object
   // Logitem converts the data row into the base object. e.g. Industry
   os.GetType().GetMethod("Add").Invoke(
    os,
    new object[] {
     propType.GetMethod("LogItem").Invoke(null, new object[] { dr })
    }
   );
  }
 }

}

The comments in the code should hopefully give an indication of how it works. Working out the T os = (T)Activator.CreateInstance(typeof(T)); took a while as defining the os object as IList<object> just wasn't working. Got there in the end though :)