(Mimicry/Extension of Excel's VLookup/HLookup in C#)

Here I will give you my VLookup and HLookup methods; they have been overloaded to allow flexibility. In Excel the first row or column of values is referred to/searched through. In the HLookup/VLookup functions I wrote, row/column name/index can be specified.

Sometimes a developer may need to dynamically locate a specific text value in order to get an associated data point for that text value (in the same data row or data column). Put another way: these lookup functions allow a developer to determine the contents of one cell by locating an associated cell (at runtime).

I am attaching a demo application that contains examples of HLookup and VLookup and all dependent code. You may download it here: Download Demo App


Data Finder Demo Form


The Lookup Methods:

   61         /// <summary>

   62         /// Similar to Excel's hlookup. Searches for value (column by column)

   63         /// beginning in the first row of the passed in table and returns

   64         /// corresponding value from the same (found) column as specified by the

   65         /// matchRow value.

   66         /// </summary>

   67         /// <remarks>

   68         /// If user looks for the 'color' field and the 5th row,

   69         /// the function will grab data from the color column, 5th row

   70         /// </remarks>

   71         /// <param name="tbl">table to look in</param>

   72         /// <param name="val">value to locate (will pinpoint a row)</param>

   73         /// <param name="lookInRow">

   74         /// row index to look in for specified value, excel uses first row,

   75         /// let us allow a bit more flexibility. (set to 0 for 1st row)

   76         /// </param>

   77         /// <param name="matchRowIdx">index of row to get return data from</param>

   78         /// <param name="partialMatch">whether to stop at a partial match</param>

   79         /// <returns>

   80         /// null if value not found, or data from matching row in same column as found value

   81         /// </returns>

   82         /// <writer>aendenne</writer>

   83         /// <created>5/28/09</created>

   84         /// <edited>5/28/09</edited>

   85         public static string HLookup(DataTable tbl, string val, int lookInRow,

   86             int matchRowIdx, bool partialMatch)

   87         {

   88             if (tbl == null || tbl.Rows.Count <= 0) return null;

   89             if (string.IsNullOrEmpty(val)) return null;

   90             if (tbl.Rows.Count <= lookInRow || tbl.Rows.Count <= matchRowIdx) return null;

   91 

   92             //still here--try to locate value in specified row:

   93             val = val.Trim().ToUpper();

   94 

   95             DataRow rw = tbl.Rows[lookInRow];

   96             for (int i = 0; i < tbl.Columns.Count; i++)

   97             {

   98                 string fldData = rwIdea.ToString().Trim().ToUpper();

   99                 if (partialMatch && fldData.Contains(val))

  100                     return tbl.Rows[matchRowIdx]Idea.ToString();

  101                 if (fldData == val.Trim().ToUpper())

  102                     return tbl.Rows[matchRowIdx]Idea.ToString();

  103             }

  104             return null;

  105         }

  106 

  107         /// <summary>

  108         /// Similar to Excel's vlookup. Searches for value (row by row)

  109         /// in one column and returns ENTIRE row where that value was found (first instance)

  110         /// </summary>

  111         /// <param name="tbl">table to look in</param>

  112         /// <param name="val">value to locate (will pinpoint a row)</param>

  113         /// <param name="valColName">name of column to find value in</param>

  114         /// <returns>

  115         /// null if value not found, or data from matching column in same row as found value

  116         /// </returns>

  117         /// <writer>aendenne</writer>

  118         /// <created>5/28/09</created>

  119         /// <edited>5/28/09</edited>

  120         public static DataRow VLookup(DataTable tbl, string val, string valColName)

  121         {

  122             if (tbl == null || tbl.Rows.Count <= 0) return null;

  123 

  124             if (string.IsNullOrEmpty(val) || string.IsNullOrEmpty(valColName))

  125                 return null;

  126 

  127             int valCol = tbl.Columns.IndexOf(valColName);

  128 

  129             //chk that col names do exist in this tbl:

  130             if (valCol < 0) return null;

  131 

  132             foreach (DataRow rw in tbl.Rows)

  133                 if (rw[valCol].ToString().Trim().ToUpper() == val.Trim().ToUpper())

  134                     return rw;

  135 

  136             return null;

  137         }

  138 

  139         /// <summary>

  140         /// Similar to Excel's vlookup. Searches for value (row by row)

  141         /// in one column and returns value from matching column in same row.

  142         /// </summary>

  143         /// <param name="tbl">table to look in</param>

  144         /// <param name="val">value to locate (will pinpoint a row)</param>

  145         /// <param name="valColName">name of column to find value in</param>

  146         /// <param name="matchColName">name of column to get return data from</param>

  147         /// <returns>

  148         /// null if value not found, or data from matching column in same row as found value

  149         /// </returns>

  150         /// <writer>aendenne</writer>

  151         /// <created>5/28/09</created>

  152         /// <edited>5/28/09</edited>

  153         public static string VLookup(DataTable tbl, string val,

  154             string valColName, string matchColName)

  155         {

  156             if (tbl == null || tbl.Rows.Count <= 0) return null;

  157 

  158             if (string.IsNullOrEmpty(val) || string.IsNullOrEmpty(valColName)

  159                 || string.IsNullOrEmpty(matchColName))

  160                 return null;

  161 

  162             int valCol = tbl.Columns.IndexOf(valColName);

  163             int matchCol = tbl.Columns.IndexOf(matchColName);

  164 

  165             //chk that col names do exist in this tbl:

  166             if (valCol < 0 || matchCol < 0) return null;

  167 

  168             foreach (DataRow rw in tbl.Rows)

  169                 if (rw[valCol].ToString().Trim().ToUpper() == val.Trim().ToUpper())

  170                     return rw[matchCol].ToString();

  171 

  172             return null;

  173         }

  174 

  175         /// <summary>

  176         /// Similar to Excel's vlookup. Searches for value (row by row)

  177         /// in one column and returns value from matching column in same row.

  178         /// </summary>

  179         /// <param name="tbl">table to look in</param>

  180         /// <param name="val">value to locate (will pinpoint a row)</param>

  181         /// <param name="valColIdx">index of column to find value in</param>

  182         /// <param name="matchColIdx">index of column to get return data from</param>

  183         /// <param name="partialMatch">whether to stop at a partial match</param>

  184         /// <returns>

  185         /// null if value not found, or data from matching column in same row as found value

  186         /// </returns>

  187         /// <writer>aendenne</writer>

  188         /// <created>5/28/09</created>

  189         /// <edited>5/28/09</edited>

  190         public static string VLookup(DataTable tbl, string val, int valColIdx,

  191             int matchColIdx, bool partialMatch)

  192         {

  193             if (tbl == null || tbl.Rows.Count <= 0) return null;

  194 

  195             if (string.IsNullOrEmpty(val) || tbl.Columns.Count <= valColIdx ||

  196                 tbl.Columns.Count <= matchColIdx)

  197                 return null;

  198 

  199             val = val.Trim().ToUpper();

  200             foreach (DataRow rw in tbl.Rows)

  201             {

  202                 string fldData = rw[valColIdx].ToString().Trim().ToUpper();

  203                 if (partialMatch && fldData.Contains(val))

  204                     return rw[matchColIdx].ToString();

  205                 if (fldData == val.Trim().ToUpper())

  206                     return rw[matchColIdx].ToString();

  207             }

  208             return null;

  209         }


Posted by aendenne | with no comments

In using the predicate find and replace methods, I wondered whether they were faster or slower than the less elegant for...loop approach.

The code herein demonstrates find, findall and replace predicate usage.

My initial findings are that for...loops searching through an array or list are quicker than using predicates. UNLESS the collection to be sifted through is HUGE.

The form's code-behind file is printed below, but you may download the entire 2008 solution:

http://footheory.com/blogs/aendenne/PredicatesVsForLoops.zip

[Note, yes I am aware that 3.5 language features could be used in this solution. I don't want to get used to them right now, because I have a habit of writing them into my projects at work, where our TFS is not compatible with that framework.]

Predicates vs. For...Loops Test App 


    1 using System;

    2 using System.Collections.Generic;

    3 using System.Drawing;

    4 using System.Windows.Forms;

    5 

    6 namespace PredicatesVsForLoops

    7 {

    8     public partial class frmListMethodUsage : Form

    9     {

   10         #region Constructors

   11         /// <summary>

   12         /// Constructor: starts up the form object

   13         /// </summary>

   14         public frmListMethodUsage()

   15         {

   16             InitializeComponent();

   17             _formatTxtBox();

   18         }

   19         #endregion

   20 

   21         #region InternalMembers

   22         private double _findTimeForSingleElement;

   23         private double _findTimeForMultiElements;

   24         private double _findTimeForSingleElementWithForLoop;

   25         private double _findTimeForMultiElementsWithForLoop;

   26         private double _removeTime;

   27         private double _removeTimeWithForLoop;

   28 

   29         private int _arrayMemberIdx;

   30         #endregion

   31 

   32         #region StringConstants

   33         private const string _valueProperty = "Value";

   34         //private const string _nameProperty = "Name";

   35         private const string _commonValue = "Same";

   36         //private const string _nonExistentValue = "NonExistentValue";

   37         private const string _setIntro = " Set # ";

   38         private const string _fooObjectName = "foo";

   39         private const string _msgNoResults = "no results found";

   40         //private const string _msgResultsFoundIntro = "The items found";

   41         private const string _msgTimeElapsed = "Time elapsed for";

   42         private const string _findFooMethod = "_findFoo() method";

   43         private const string _findFooInForLoopMethod = "_findFooInForLoop() method";

   44         private const string _findFoosMethod = "_findFoos() method";

   45         private const string _findFoosInForLoopMethod = "_findFoosInForLoop() method";

   46         private const string _removeFooMethod = "_removeFoo() method";

   47         private const string _removeFooWithForLoopMethod = "_removeFooWithLoop() method";

   48         private const string _seconds = "seconds";

   49         private const string _nameFound = "Name of item found";

   50         private const string _valueFound = "Value of item found";

   51         private const string _qtyFound = "Number of items found";

   52         private const string _qtyRemoved = "Number of items removed";

   53         private const string _firstFound = "First Item Found";

   54         private const string _lastFound = "Last Item Found";

   55         private const string _spacerLine =

   56             "--------------------------------------------------------";

   57         private const string _no = "There was no";

   58         private const string _winningMethod = "Winning Method";

   59         private const string _timeDiff = "Time Difference";

   60         private const string _arrayCreation = "Array creation";

   61         private const string _listCreation = "List creation";

   62         private const string _durationWas = "Duration was";

   63         private const string _for = "for";

   64         private const string _items = "items";

   65         private const string _listAddFailedAt = "List.Add method failed at item #";

   66         private const string _arrayAddFailedAt = "Array member access failed at item #";

   67         private const string _success = "SUCCESS";

   68         private const string _failure = "FAILURE";

   69         private const string _outOfMemoryCustomErr =

   70             "Out of memory error: view details in text box";

   71         private const string _otherCustomErr =

   72             "Other error: view details in text box";

   73         #endregion

   74 

   75         #region Events

   76         private void btnRunAll_Click(object sender, EventArgs e)

   77         {

   78             Cursor curr = Cursor;

   79             Cursor = Cursors.WaitCursor;

   80 

   81             btnClear_Click(null, null);

   82             btnDemoFind_Click(null, null);

   83             _addToTxtBox(Environment.NewLine + _spacerLine, Color.Black, true,

   84                 false, false, 14);

   85             btnDemoForLoopFind_Click(null, null);

   86             _showWinner(_findFooMethod, _findTimeForSingleElement,

   87                 _findFooInForLoopMethod, _findTimeForSingleElementWithForLoop);

   88 

   89             btnDemoFindAll_Click(null, null);

   90             _addToTxtBox(Environment.NewLine + _spacerLine, Color.Black, true,

   91                 false, false, 14);

   92             btnDemoForLoopFindAll_Click(null, null);

   93             _showWinner(_findFoosMethod, _findTimeForMultiElements,

   94                 _findFoosInForLoopMethod, _findTimeForMultiElementsWithForLoop);

   95 

   96             btnDemoRemove_Click(null, null);

   97             _addToTxtBox(Environment.NewLine + _spacerLine, Color.Black, true,

   98                 false, false, 14);

   99             btnDemoForLoopRemove_Click(null, null);

  100             _showWinner(_removeFooMethod, _removeTime,

  101                 _removeFooWithForLoopMethod, _removeTimeWithForLoop);

  102 

  103             Cursor = curr;

  104         }

  105 

  106         /// <summary>

  107         /// Button click event that shows implementation

  108         /// of the Find method for a List of objects

  109         /// </summary>

  110         /// <param name="sender">Object that requested the event</param>

  111         /// <param name="e">Event arguments</param>

  112         private void btnDemoFind_Click(object sender, EventArgs e)

  113         {

  114             Cursor curr = Cursor;

  115             Cursor = Cursors.WaitCursor;

  116 

  117             long start = DateTime.Now.Ticks;

  118             int qty = _getQty(txtItemQty);

  119 

  120             List<Foo> findList = _getFooListWithDistinctValues(qty);

  121             Foo f = _findFoo(findList, _valueProperty + (qty - 2));

  122 

  123             //if we run this line INSTEAD of prior, we will receive NO results-here for testing/demo

  124             //Foo m = _findFoo(findList, _valueProperty + 1000000); 

  125 

  126             double ms = _getDuration(start);

  127             _findTimeForSingleElement = ms;

  128             _showResultsOfFindMethod(f, ms, _findFooMethod);

  129 

  130             Cursor = curr;

  131         }

  132 

  133         /// <summary>

  134         /// Button click event that shows implementation

  135         /// of the FindAll method for a List of objects

  136         /// </summary>

  137         /// <param name="sender">Object that requested the event</param>

  138         /// <param name="e">Event arguments</param>

  139         private void btnDemoFindAll_Click(object sender, EventArgs e)

  140         {

  141             Cursor curr = Cursor;

  142             Cursor = Cursors.WaitCursor;

  143 

  144             long start = DateTime.Now.Ticks;

  145             int qty = _getQty(txtItemQty);

  146 

  147             List<Foo> findList = _getFooListWithMatchingValues(qty);

  148             List<Foo> foundList = _findFoos(findList, _commonValue + _valueProperty);

  149 

  150             //if we run this line INSTEAD of prior, we will receive NO results-here for testing/demo

  151             //List<Foo> list = _findFoos(findList, _nonExistentValue);   

  152 

  153             double ms = _getDuration(start);

  154             _findTimeForMultiElements = ms;

  155             _showResultsOfFindAllMethod(foundList, ms, _findFoosMethod);

  156 

  157             Cursor = curr;

  158         }

  159 

  160         private void btnDemoRemove_Click(object sender, EventArgs e)

  161         {

  162             Cursor curr = Cursor;

  163             Cursor = Cursors.WaitCursor;

  164 

  165             long start = DateTime.Now.Ticks;

  166             int qty = _getQty(txtItemQty);

  167 

  168             List<Foo> fullList = _getFooListWithSomeSharedValues(qty);

  169             List<Foo> filteredList = _removeFoo(fullList, _valueProperty + _setIntro + 8);

  170 

  171             //if we run this line INSTEAD of prior, we will receive same results as fullList-here for testing/demo

  172             //List<Foo> filteredList = _removeFoo(findList, _nonExistentValue);   

  173 

  174             double ms = _getDuration(start);

  175             _removeTime = ms;

  176 

  177             _showResultsOfRemoveMethod(fullList, filteredList, ms, _removeFooMethod);

  178 

  179             Cursor = curr;

  180         }

  181 

  182         private void btnDemoForLoopRemove_Click(object sender, EventArgs e)

  183         {

  184             Cursor curr = Cursor;

  185             Cursor = Cursors.WaitCursor;

  186 

  187             long start = DateTime.Now.Ticks;

  188             int qty = _getQty(txtItemQty);

  189 

  190             Foo[] fullArray = _getFooArrayWithSomeSharedValues(qty);

  191             Foo[] filteredArray = _removeFooWithLoop(fullArray, _valueProperty + _setIntro + 8);

  192 

  193             //if we run this line INSTEAD of prior, we will receive same results as fullList-here for testing/demo

  194             //List<Foo> filteredList = _removeFoo(findList, _nonExistentValue);   

  195 

  196             double ms = _getDuration(start);

  197             _removeTimeWithForLoop = ms;

  198 

  199             _showResultsOfRemoveMethod(fullArray, filteredArray, ms, _removeFooWithForLoopMethod);

  200 

  201             Cursor = curr;

  202         }

  203 

  204         /// <summary>

  205         /// Button click event that shows implementation

  206         /// of the old standard for...loop to find an item in a List of objects

  207         /// </summary>

  208         /// <param name="sender">Object that requested the event</param>

  209         /// <param name="e">Event arguments</param>

  210         private void btnDemoForLoopFind_Click(object sender, EventArgs e)

  211         {

  212             Cursor curr = Cursor;

  213             Cursor = Cursors.WaitCursor;

  214 

  215             long start = DateTime.Now.Ticks;

  216             int qty = _getQty(txtItemQty);

  217 

  218             List<Foo> findList = _getFooListWithDistinctValues(qty);

  219             Foo f = _findFooInForLoop(findList, _valueProperty + (qty - 2));

  220 

  221             //if we run this line INSTEAD of prior, we will receive NO results-here for testing/demo

  222             //Foo m = _findFoo(findList, _valueProperty + 1000000); 

  223 

  224             double ms = _getDuration(start);

  225             _findTimeForSingleElementWithForLoop = ms;

  226             _showResultsOfFindMethod(f, ms, _findFooInForLoopMethod);

  227 

  228             Cursor = curr;

  229         }

  230 

  231         /// <summary>

  232         /// Button click event that shows implementation

  233         /// of the old standard for...loop to find all items in a List of objects

  234         /// matching specified value

  235         /// </summary>

  236         /// <param name="sender">Object that requested the event</param>

  237         /// <param name="e">Event arguments</param>

  238         private void btnDemoForLoopFindAll_Click(object sender, EventArgs e)

  239         {

  240             Cursor curr = Cursor;

  241             Cursor = Cursors.WaitCursor;

  242 

  243             long start = DateTime.Now.Ticks;

  244             int qty = _getQty(txtItemQty);

  245 

  246             List<Foo> findList = _getFooListWithMatchingValues(qty);

  247             List<Foo> foundList = _findFoosInForLoop(findList, _commonValue + _valueProperty);

  248 

  249             //if we run this line INSTEAD of prior, we will receive NO results-here for testing/demo

  250             //List<Foo> list = _findFoos(findList, _nonExistentValue);   

  251 

  252             double ms = _getDuration(start);

  253             _findTimeForMultiElementsWithForLoop = ms;

  254             _showResultsOfFindAllMethod(foundList, ms, _findFoosInForLoopMethod);

  255 

  256             Cursor = curr;

  257         }

  258 

  259         /// <summary>

  260         /// Resets the text box contents and formats

  261         /// </summary>

  262         /// <param name="sender">object that called this method</param>

  263         /// <param name="e">Event arguments</param>

  264         private void btnClear_Click(object sender, EventArgs e)

  265         {

  266             txtRpt.ResetBackColor();

  267             txtRpt.ResetFont();

  268             txtRpt.ResetText();

  269         }

  270 

  271         /// <summary>

  272         /// Grabs quantity from text box and adds integers to a List object

  273         /// </summary>

  274         /// <param name="sender">calling object</param>

  275         /// <param name="e">Event arguments</param>

  276         private void btnTestListAddLimits_Click(object sender, EventArgs e)

  277         {

  278             Cursor curr = Cursor;

  279             Cursor = Cursors.WaitCursor;

  280 

  281             long start = DateTime.Now.Ticks;

  282             int qty = _getQty(txtQtyXtra);

  283 

  284             List<int> fooList = new List<int>();

  285             int i = 0;

  286             string msg = string.Empty;

  287             try

  288             {

  289                 for (i = 0; i < qty; i++)

  290                     fooList.Add(i);

  291             }

  292             catch (OutOfMemoryException oe)

  293             {

  294                 msg = oe.Message + " - " + _listAddFailedAt + " " + i;

  295                 MessageBox.Show(_outOfMemoryCustomErr);

  296             }

  297             catch (Exception ex)

  298             {

  299                 msg = ex.Message + " - " + _listAddFailedAt + " " + i;

  300                 MessageBox.Show(_otherCustomErr);

  301             }

  302             finally

  303             {

  304                 double ms = _getDuration(start);

  305                 msg += Environment.NewLine + _durationWas + ": " + ms / 1000 +

  306                     " " + _seconds + " " + _for + " " + i + " " + _items;

  307                 _addToTxtBox(msg, Color.Black, false, false, false, 13);

  308             }

  309             Cursor = curr;

  310         }

  311 

  312         /// <summary>

  313         /// Grabs quantity from text box, builds a List and an Array of Foo

  314         /// for specified quantity, and reports upon success/failure, and exec time

  315         /// </summary>

  316         /// <param name="sender">calling object</param>

  317         /// <param name="e">Event arguments</param>

  318         private void btnCompareListAndArrayCreation_Click(object sender, EventArgs e)

  319         {

  320             Cursor curr = Cursor;

  321             Cursor = Cursors.WaitCursor;

  322 

  323             long start = DateTime.Now.Ticks;

  324             int qty = _getQty(txtQtyXtra);

  325 

  326             Foo[] fooArray = _getFooArrayWithDistinctValues(qty);

  327             double ms = _getDuration(start);

  328 

  329             if (fooArray == null)

  330                 _showResultsOfCreate(_arrayCreation, qty, 0, ms);

  331             else

  332                 _showResultsOfCreate(_arrayCreation, qty, _arrayMemberIdx, ms);

  333 

  334             start = DateTime.Now.Ticks;

  335             List<Foo> fooList = _getFooListWithDistinctValues(qty);

  336             ms = _getDuration(start);

  337 

  338             if (fooList == null)

  339                 _showResultsOfCreate(_listCreation, qty, 0, ms);

  340             else

  341                 _showResultsOfCreate(_listCreation, qty, fooList.Count, ms);

  342 

  343             Cursor = curr;

  344         }

  345         #endregion

  346 

  347         #region RichTextBoxMethods

  348         /// <summary>

  349         /// To be called after object initialization---sets some style props

  350         /// </summary>

  351         private void _formatTxtBox()

  352         {

  353             txtRpt.Font = new Font("Courier New", 11);

  354             txtRpt.WordWrap = true;

  355             txtRpt.ScrollBars = RichTextBoxScrollBars.Vertical;

  356         }

  357 

  358         /// <summary>

  359         /// Appends any existing text in the text box, can be formatted

  360         /// </summary>

  361         /// <param name="txtToAdd">text to add to box</param>

  362         /// /// <param name="color">Color to set font to</param>

  363         /// <param name="bold">whether to bold this text</param>

  364         /// <param name="italic">whether to italicize this text</param>

  365         /// <param name="bullet">whether to bullet this text</param>

  366         /// <param name="size">font size for this text</param>

  367         private void _addToTxtBox(string txtToAdd, Color color, bool bold,

  368             bool italic, bool bullet, int size)

  369         {

  370             if (string.IsNullOrEmpty(txtToAdd))

  371                 return;

  372 

  373             int beg = txtRpt.TextLength;

  374             txtRpt.AppendText(txtToAdd);

  375             if (beg == 0)

  376                 _formatTxt(beg, txtToAdd.Length - 1, color, bold, italic, bullet, size);

  377             else

  378                 _formatTxt(beg, txtToAdd.Length, color, bold, italic, bullet, size);

  379         }

  380 

  381         /// <summary>

  382         /// Formats text in the text box, from start position to end position

  383         /// as specified by arguments

  384         /// </summary>

  385         /// <param name="startPos">character number to begin formatting from</param>

  386         /// <param name="endPos">character number to end formatting at</param>

  387         /// <param name="color">Color to set font to</param>

  388         /// <param name="bold">whether to bold this text</param>

  389         /// <param name="italic">whether to italicize this text</param>

  390         /// <param name="bullet">whether to bullet this text</param>

  391         /// <param name="size">font size for this text</param>

  392         private void _formatTxt(int startPos, int endPos, Color color, bool bold,

  393             bool italic, bool bullet, int size)

  394         {

  395             if (txtRpt.TextLength < startPos + (endPos - startPos))

  396                 return;

  397 

  398             txtRpt.Select(startPos, endPos);

  399             txtRpt.SelectionColor = color;

  400             FontStyle style = _getFontStyle(bold, italic);

  401             txtRpt.SelectionFont = new Font(txtRpt.Font.FontFamily, size, style);

  402             txtRpt.SelectionBullet = bullet;

  403         }

  404 

  405         /// <summary>

  406         /// Evaluates bold & italic choices to get style enum

  407         /// </summary>

  408         /// <param name="bold">whether to bold the font</param>

  409         /// <param name="italic">whether to italicize the font</param>

  410         /// <returns>FontStyle object</returns>

  411         private static FontStyle _getFontStyle(bool bold, bool italic)

  412         {

  413             if (bold && italic)

  414                 return FontStyle.Bold | FontStyle.Italic;

  415             if (bold)

  416                 return FontStyle.Bold;

  417             if (italic)

  418                 return FontStyle.Italic;

  419             return FontStyle.Regular;

  420         }

  421         #endregion

  422 

  423         #region ReportResultsMethods

  424         /// <summary>

  425         /// Show msg box if no results, otherwise, summarize duration + item found in text box

  426         /// </summary>

  427         /// <param name="f">Foo object</param>

  428         /// <param name="milliseconds">double: number of milliseconds</param>

  429         /// <param name="method">name of method being tested</param>

  430         private void _showResultsOfFindMethod(Foo f, double milliseconds, string method)

  431         {

  432             if (f == null)

  433             {

  434                 txtRpt.Text = _msgNoResults;

  435                 MessageBox.Show(_msgNoResults);

  436                 return;

  437             }

  438 

  439             Color nameColor = Color.DeepSkyBlue;

  440             Color valueColor = Color.DarkCyan;

  441             string data = Environment.NewLine + _msgTimeElapsed + " " +

  442                 method + ":  ";

  443             _addToTxtBox(data, nameColor, true, false, false, 13);

  444 

  445             string ms = (milliseconds / 1000).ToString();

  446             data = ms + " " + _seconds;

  447             _addToTxtBox(data, valueColor, false, true, false, 12);

  448 

  449             data = Environment.NewLine + _nameFound + ":  ";

  450             _addToTxtBox(data, nameColor, true, false, false, 13);

  451 

  452             data = f.Name;

  453             _addToTxtBox(data, valueColor, false, true, false, 12);

  454 

  455             data = Environment.NewLine + _valueFound + ":  ";

  456             _addToTxtBox(data, nameColor, true, false, false, 13);

  457 

  458             data = f.Value;

  459             _addToTxtBox(data, valueColor, false, true, false, 12);

  460         }

  461 

  462         /// <summary>

  463         /// Show msg box if no results, otherwise, summarize duration + 1st &

  464         /// last item found in text box

  465         /// </summary>

  466         /// <param name="list">List of Foo objects</param>

  467         /// <param name="milliseconds">double: number of milliseconds</param>

  468         private void _showResultsOfFindAllMethod(IList<Foo> list, double milliseconds,

  469             string method)

  470         {

  471             if (list == null || list.Count < 1)

  472             {

  473                 txtRpt.Text = _msgNoResults;

  474                 MessageBox.Show(_msgNoResults);

  475                 return;

  476             }

  477 

  478             Color nameColor = Color.DarkGreen;

  479             Color valColor = Color.ForestGreen;

  480             string data = Environment.NewLine + _msgTimeElapsed + " " +

  481                 method + ":  ";

  482             _addToTxtBox(data, nameColor, true, false, false, 13);

  483 

  484             string ms = (milliseconds / 1000).ToString();

  485             data = ms + " " + _seconds;

  486             _addToTxtBox(data, valColor, false, true, false, 12);

  487 

  488             data = Environment.NewLine + _qtyFound + ":  ";

  489             _addToTxtBox(data, nameColor, true, false, false, 13);

  490 

  491             data = list.Count.ToString();

  492             _addToTxtBox(data, valColor, false, true, false, 12);

  493 

  494             data = Environment.NewLine + _firstFound + ": ";

  495             _addToTxtBox(data, nameColor, true, false, false, 13);

  496 

  497             data = list[0].Name + " - " + list[0].Value;

  498             _addToTxtBox(data, valColor, false, true, false, 12);

  499 

  500             data = Environment.NewLine + _lastFound + ": ";

  501             _addToTxtBox(data, nameColor, true, false, false, 13);

  502 

  503             data = list[list.Count - 1].Name + " - " +

  504                 list[list.Count - 1].Value;

  505             _addToTxtBox(data, valColor, false, true, false, 12);

  506 

  507             //foreach (Foo item in list)

  508             //...

  509         }

  510 

  511         /// <summary>

  512         /// Show msg box if no results, otherwise, summarize duration + 1st &

  513         /// last item found in text box

  514         /// </summary>

  515         /// <param name="origList">full list of foo objects/param>

  516         /// <param name="newList">filtered list of foo objects/param>

  517         /// <param name="milliseconds">double: number of milliseconds</param>

  518         /// <param name="method">string name of method to report on</param>

  519         private void _showResultsOfRemoveMethod(ICollection<Foo> origList,

  520             ICollection<Foo> newList, double milliseconds, string method)

  521         {

  522             if (origList == null || origList.Count < 1)

  523             {

  524                 txtRpt.Text = _msgNoResults;

  525                 MessageBox.Show(_msgNoResults);

  526                 return;

  527             }

  528 

  529             Color nameColor = Color.DarkGreen;

  530             Color valColor = Color.ForestGreen;

  531             string data = Environment.NewLine + _msgTimeElapsed + " " +

  532                 method + ":  ";

  533             _addToTxtBox(data, nameColor, true, false, false, 13);

  534 

  535             string ms = (milliseconds / 1000).ToString();

  536             data = ms + " " + _seconds;

  537             _addToTxtBox(data, valColor, false, true, false, 12);

  538 

  539             data = Environment.NewLine + _qtyRemoved + ":  ";

  540             _addToTxtBox(data, nameColor, true, false, false, 13);

  541 

  542             int diff = origList.Count > newList.Count

  543                 ? origList.Count - newList.Count : 0;

  544 

  545             data = diff.ToString();

  546             _addToTxtBox(data, valColor, false, true, false, 12);

  547         }

  548 

  549         /// <summary>

  550         /// Build text to report upon/display collection creation in txt ctrl

  551         /// </summary>

  552         /// <param name="_collectionIntro">

  553         /// string to intro the collection TYPE (array/list..)

  554         /// </param>

  555         /// <param name="qty">collection qty requested</param>

  556         /// <param name="count">actual collection count</param>

  557         /// <param name="duration">milliseconds (time elapsed to make collection)</param>

  558         private void _showResultsOfCreate(string _collectionIntro, int qty, int count,

  559             double duration)

  560         {

  561             string txt;

  562             if (count == 0 || count < qty)

  563                 txt = Environment.NewLine + _failure + ":  ";

  564             else

  565                 txt = Environment.NewLine + _success + ":  ";

  566 

  567             txt += _collectionIntro + " " + _durationWas + ": " +

  568                 duration / 1000 + " " + _seconds + " " + _for + " " +

  569                 count + " " + _items;

  570 

  571             _addToTxtBox(txt, Color.Black, false, false, false, 12);

  572         }

  573         #endregion

  574 

  575         #region MathMethods

  576         /// <summary>

  577         /// Takes start time, uses NOW time to compute time difference

  578         /// and return double (difference in milliseconds) value

  579         /// </summary>

  580         /// <param name="start">

  581         /// use DateTime.Now.Ticks to correspond with end comparison

  582         /// </param>

  583         /// <returns>Difference in milliseconds from start to now (end)</returns>

  584         private static double _getDuration(long start)

  585         {

  586             long end = DateTime.Now.Ticks;

  587             long elapsed = end - start;

  588             return new TimeSpan(elapsed).TotalMilliseconds;

  589         }

  590 

  591         /// <summary>

  592         /// Evaluates whether control text can be used for quantity

  593         /// returns default quantity value, if not

  594         /// </summary>

  595         /// <param name="ctrl">Control that contains the text property</param>

  596         /// <returns>int to use as quantity</returns>

  597         private static int _getQty(Control ctrl)

  598         {

  599             long l;

  600 

  601             return long.TryParse(ctrl.Text, out l)

  602                 ? Convert.ToInt32(ctrl.Text)

  603                 : 1000000;

  604         }

  605 

  606         /// <summary>

  607         /// Computes difference between method times, and displays

  608         /// winning method (if exists) and a dashed line in the text box

  609         /// </summary>

  610         /// <param name="method1Name">name of 1st method</param>

  611         /// <param name="method1Time">duration of 1st method</param>

  612         /// <param name="method2Name">name of 2nd method</param>

  613         /// <param name="method2Time">duration of 2nd method</param>

  614         private void _showWinner(string method1Name, double method1Time,

  615             string method2Name, double method2Time)

  616         {

  617             string txt;

  618             if (method1Time < method2Time)

  619                 txt = _winningMethod + ": " + method1Name + " - " + _timeDiff +

  620                     ": " + ((method2Time - method1Time) / 1000);

  621             else if (method2Time < method1Time)

  622                 txt = _winningMethod + ": " + method2Name + " - " + _timeDiff +

  623                     ": " + ((method1Time - method2Time) / 1000);

  624             else

  625                 txt = _no + " " + _winningMethod;

  626 

  627             _addToTxtBox(Environment.NewLine + txt, Color.Purple, false, true, true, 12);

  628             _addToTxtBox(Environment.NewLine + _spacerLine, Color.Black, true, false, false, 14);

  629         }

  630         #endregion

  631 

  632         #region PredicateMethods

  633         /// <summary>

  634         /// Uses predicate delegate to search Foo list and return

  635         /// the first foo whose value matches the specified fooValue

  636         /// </summary>

  637         /// <param name="findList">List of foo to search thru</param>

  638         /// <param name="fooValue">Foo value property value to retrieve Foo object by</param>

  639         /// <returns>Foo object</returns>

  640         private static Foo _findFoo(List<Foo> findList, string fooValue)

  641         {

  642             Foo foo = findList.Find(delegate(Foo f)

  643             { return f.Value.Equals(fooValue); });

  644             return foo;

  645         }

  646 

  647         /// <summary>

  648         /// Uses predicate delegate to search Foo list and return

  649         /// all elements whose value match the specified fooValue

  650         /// </summary>

  651         /// <param name="findList">List of foo to search thru</param>

  652         /// <param name="fooValue">Foo value property value to retrieve Foo objects by</param>

  653         /// <returns>Foo object list</returns>

  654         private static List<Foo> _findFoos(List<Foo> findList, string fooValue)

  655         {

  656             List<Foo> returnList = findList.FindAll(delegate(Foo f)

  657             { return f.Value.Equals(fooValue); });

  658             return returnList;

  659         }

  660 

  661         /// <summary>

  662         /// Uses predicate delegate to search Foo list and remove

  663         /// all elements whose value match the specified fooValue

  664         /// </summary>

  665         /// <param name="fullList">List of foo to search/filter</param>

  666         /// <param name="fooValue">Foo value to remove Foo objects for</param>

  667         /// <returns>Foo object list</returns>

  668         private static List<Foo> _removeFoo(IEnumerable<Foo> fullList, string fooValue)

  669         {

  670             List<Foo> filteredList = new List<Foo>(fullList);

  671             filteredList.RemoveAll(delegate(Foo f)

  672             { return f.Value.Equals(fooValue); });

  673             return filteredList;

  674         }

  675         #endregion

  676 

  677         #region ForLoopMethods

  678         /// <summary>

  679         /// Uses for loop to iterate Foo list and return

  680         /// the first foo whose value matches the specified fooValue

  681         /// </summary>

  682         /// <param name="findList">List of foo to loop thru</param>

  683         /// <param name="fooValue">Foo value property value to retrieve Foo object by</param>

  684         /// <returns>Foo object</returns>

  685         private static Foo _findFooInForLoop(IEnumerable<Foo> findList, string fooValue)

  686         {

  687             foreach (Foo f in findList)

  688                 if (f.Value == fooValue)

  689                     return f;

  690             return null;

  691         }

  692 

  693         /// <summary>

  694         /// Uses for loop to iterate Foo list and return all

  695         /// items whose value matches the specified fooValue

  696         /// </summary>

  697         /// <param name="findList">List of foo to loop thru</param>

  698         /// <param name="fooValue">Foo value to retrieve Foo object by</param>

  699         /// <returns>List of Foo objects</returns>

  700         private static List<Foo> _findFoosInForLoop(IEnumerable<Foo> findList, string fooValue)

  701         {

  702             List<Foo> returnList = new List<Foo>();

  703             foreach (Foo f in findList)

  704                 if (f.Value == fooValue)

  705                     returnList.Add(f);

  706             return returnList;

  707         }

  708 

  709         /// <summary>

  710         /// Uses for loop to iterate Foo array and remove all

  711         /// items whose value matches the specified fooValue

  712         /// </summary>

  713         /// <param name="fullArray">Array of foo to loop thru</param>

  714         /// <param name="fooValue">Foo value to remove Foo object by</param>

  715         /// <returns>Filtered Array of Foo objects</returns>

  716         private static Foo[] _removeFooWithLoop(ICollection<Foo> fullArray, string fooValue)

  717         {

  718             Foo[] filteredArray = new Foo[fullArray.Count];

  719             int i = 0;

  720             int subtract = 0;

  721             foreach (Foo origFoo in fullArray)

  722             {

  723                 if (origFoo.Value != fooValue)

  724                     filteredArrayIdea = origFoo;

  725                 else

  726                     subtract += 1;

  727                 i++;

  728             }

  729             Foo[] finalArray = new Foo[i - subtract];

  730 

  731             i = 0;

  732             foreach (Foo newFoo in finalArray)

  733             {

  734                 finalArrayIdea = filteredArrayIdea;

  735                 i++;

  736             }

  737             return finalArray;

  738         }

  739         #endregion

  740 

  741         #region BuildListMethods

  742         private static Foo[] _getFooArrayWithSomeSharedValues(int qty)

  743         {

  744             //force it:

  745             if (qty < 10)

  746                 qty = 10;

  747 

  748             Foo[] fooArray = new Foo[qty];

  749             int i = 0;

  750 

  751             try

  752             {

  753                 for (int j = 0; j < 10; j++)

  754                     for (i = i; i < ((qty / 10) * (j + 1)); i++)

  755                         fooArrayIdea = new Foo(_fooObjectName + i, _valueProperty +

  756                             _setIntro + (j + 1));

  757             }

  758             catch (OutOfMemoryException oe)

  759             {

  760                 MessageBox.Show(oe.Message + " - " + _listAddFailedAt + " " + i);

  761                 return fooArray;

  762             }

  763             catch (Exception ex)

  764             {

  765                 MessageBox.Show(ex.Message + " - " + _listAddFailedAt + " " + i);

  766                 return fooArray;

  767             }

  768             return fooArray;

  769         }

  770         /// <summary>

  771         /// Creates and fills a foo list with some shared/some distinct values for each foo

  772         /// </summary>

  773         /// <param name="qty">number of foo to add to list</param>

  774         /// <returns>foo list of qty specified w/various values</returns>

  775         private static List<Foo> _getFooListWithSomeSharedValues(int qty)

  776         {

  777             //force it:

  778             if (qty < 10)

  779                 qty = 10;

  780 

  781             List<Foo> fooList = new List<Foo>();

  782             int i = 0;

  783 

  784             try

  785             {

  786                 for (int j = 0; j < 10; j++)

  787                     for (i = i; i < ((qty / 10) * (j + 1)); i++)

  788                         fooList.Add(new Foo(_fooObjectName + i, _valueProperty +

  789                             _setIntro + (j + 1)));

  790             }

  791             catch (OutOfMemoryException oe)

  792             {

  793                 MessageBox.Show(oe.Message + " - " + _listAddFailedAt + " " + i);

  794                 return fooList;

  795             }

  796             catch (Exception ex)

  797             {

  798                 MessageBox.Show(ex.Message + " - " + _listAddFailedAt + " " + i);

  799                 return fooList;

  800             }

  801             return fooList;

  802         }

  803 

  804         /// <summary>

  805         /// Creates and fills a foo list with distinct values for each foo

  806         /// </summary>

  807         /// <param name="qty">number of foo to add to list</param>

  808         /// <returns>foo list of qty specified w/various values</returns>

  809         private static List<Foo> _getFooListWithDistinctValues(int qty)

  810         {

  811             List<Foo> fooList = new List<Foo>();

  812             int i = 0;

  813             try

  814             {

  815                 for (i = 0; i < qty; i++)

  816                     fooList.Add(new Foo(_fooObjectName + i, _valueProperty + i));

  817             }

  818             catch (OutOfMemoryException oe)

  819             {

  820                 MessageBox.Show(oe.Message + " - " + _listAddFailedAt + " " + i);

  821                 return fooList;

  822             }

  823             catch (Exception ex)

  824             {

  825                 MessageBox.Show(ex.Message + " - " + _listAddFailedAt + " " + i);

  826                 return fooList;

  827             }

  828             return fooList;

  829         }

  830 

  831         /// <summary>

  832         /// Creates and fills a foo list with the SAME value for each foo

  833         /// </summary>

  834         /// <param name="qty">number of foo to add to list</param>

  835         /// <returns>foo list of qty specified w/the same values</returns>

  836         private static List<Foo> _getFooListWithMatchingValues(int qty)

  837         {

  838             List<Foo> fooList = new List<Foo>();

  839             int i = 0;

  840             try

  841             {

  842                 for (i = 0; i < qty; i++)

  843                     fooList.Add(new Foo(_fooObjectName + i, _commonValue +

  844                         _valueProperty));

  845             }

  846             catch (OutOfMemoryException oe)

  847             {

  848                 MessageBox.Show(oe.Message + " - " + _listAddFailedAt + " " + i);

  849                 return fooList;

  850             }

  851             catch (Exception ex)

  852             {

  853                 MessageBox.Show(ex.Message + " - " + _listAddFailedAt + " " + i);

  854                 return fooList;

  855             }

  856             return fooList;

  857         }

  858 

  859         /// <summary>

  860         /// Creates and fills a foo Array with distinct values for each foo

  861         /// </summary>

  862         /// <param name="qty">number of foo to add to array</param>

  863         /// <returns>foo list of qty specified w/various values</returns>

  864         private Foo[] _getFooArrayWithDistinctValues(int qty)

  865         {

  866             _arrayMemberIdx = 0;

  867             Foo[] fooArray = new Foo[qty];

  868             int i = 0;

  869             try

  870             {

  871                 for (i = 0; i < qty; i++)

  872                     fooArrayIdea = new Foo(_fooObjectName + i, _valueProperty + i);

  873             }

  874             catch (OutOfMemoryException oe)

  875             {

  876                 MessageBox.Show(oe.Message + " - " + _arrayAddFailedAt + " " + i);

  877                 return fooArray;

  878             }

  879             catch (Exception ex)

  880             {

  881                 MessageBox.Show(ex.Message + " - " + _arrayAddFailedAt + " " + i);

  882                 return fooArray;

  883             }

  884             return fooArray;

  885         }

  886 

  887         /// <summary>

  888         /// Creates and fills a foo Array with the SAME value for each foo

  889         /// </summary>

  890         /// <param name="qty">number of foo to add to array</param>

  891         /// <returns>foo list of qty specified w/the same values</returns>

  892         private Foo[] _getFooArrayWithMatchingValues(int qty)

  893         {

  894             _arrayMemberIdx = 0;

  895             Foo[] fooArray = new Foo[qty];

  896             int i = 0;

  897             try

  898             {

  899                 for (i = 0; i < qty; i++)

  900                     fooArrayIdea = new Foo(_fooObjectName + i, _commonValue +

  901                         _valueProperty);

  902             }

  903             catch (OutOfMemoryException oe)

  904             {

  905                 MessageBox.Show(oe.Message + " - " + _arrayAddFailedAt + " " + i);

  906                 _arrayMemberIdx = i;

  907                 return fooArray;

  908             }

  909             catch (Exception ex)

  910             {

  911                 MessageBox.Show(ex.Message + " - " + _arrayAddFailedAt + " " + i);

  912                 return fooArray;

  913             }

  914             return fooArray;

  915         }

  916         #endregion

  917 

  918         #region InternalFooObject

  919         /// <summary>

  920         /// Demo/dummy object with two simple properties: Name and Value

  921         /// </summary>

  922         internal class Foo

  923         {

  924             #region Constructors

  925             /// <summary>

  926             /// Default constructor, sets properties to default values

  927             /// </summary>

  928             public Foo()

  929             {

  930                 _init();

  931             }

  932 

  933             /// <summary>

  934             /// Data constructor for, sets properties to passed-in values

  935             /// </summary>

  936             /// <param name="name">string name</param>

  937             /// <param name="value">string value</param>

  938             public Foo(string name, string value)

  939             {

  940                 _name = name;

  941                 _value = value;

  942             }

  943 

  944             /// <summary>

  945             /// Set default values for the employee object

  946             /// </summary>

  947             private void _init()

  948             {

  949                 _name = string.Empty;

  950                 _value = string.Empty;

  951             }

  952             #endregion

  953 

  954             #region PrivateProps

  955             /// <summary>

  956             /// local member to store method name

  957             /// </summary>

  958             private string _name;

  959 

  960             /// <summary>

  961             /// local member to store method value

  962             /// </summary>

  963             private string _value;

  964             #endregion

  965 

  966             #region PublicProps

  967             /// <summary>

  968             /// Read-write property: method value

  969             /// </summary>

  970             public string Value

  971             {

  972                 get { return _value; }

  973                 set { _value = value; }

  974             }

  975             /// <summary>

  976             /// Read-write property: method name

  977             /// </summary>

  978             public string Name

  979             {

  980                 get { return _name; }

  981                 set { _name = value; }

  982             }

  983             #endregion

  984         }

  985         #endregion

  986     }

  987 }

A couple of the methods I have used most in the following code segment return a List object, or an ArrayList of text found inside a file to inspect.

Other methods that I've used a lot edit an existing file from a specific line number, or retrieve the full text from a specific file.

I've overloaded the AddToFile() method to allow varying ways to edit a file. Let me know if you extend this tool; I like collaboration.

 -aendenne
 

/*
 * Author: aendenne
 * Email: AutomateAnything@yahoo.com
 * Create Date: April 21, 2007
 * Last Modified Date: September 25, 2007
 * Version: 1.1
 */ 


using
System;
using System.Collections;
using System.Collections.Generic;
using System.IO; 

namespace
YourNamespace.Tools
{
    /// <summary>
    /// Class that stores static methods to create, access,
    /// (especially read from) and manipulate files
    /// </summary>
    /// <remarks>
    /// does NOT include good error-handling. this is not a 
    /// recommended practice, please extend the try/catch statements...
    /// i will post a simple error tool soon.
    /// </remarks>
    public class FileTool
    {
        /// <summary>
        /// string constant to store message to return
        /// if file exists, and user does NOT wish to override
        /// </summary>
        private const string m_FileExistsMessage =
            "The file already exists: "; 

       
/// <summary>
        /// Gets string indicating the current directory
        /// </summary>
        /// <returns>string value of the current directory</returns>
        public static string GetCurrentDirectory()
        {
            try
            {
                return Directory.GetCurrentDirectory().ToString();
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return null;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Creates a file in path suggested, and writes the
        /// contents to that file
        /// </summary>
        /// <param name="path">
        /// string value indicating path (include file name)
        /// to store new file in
        /// </param>
        /// <param name="contents">
        /// string value storing the contents to write
        /// to the new file
        /// </param>
        /// <param name="overwrite">
        /// bool value indicating whether to replace file in path
        /// if one already exists at that location
        /// </param>
        public static void WriteNewFile(string path,
            string contents, bool overwrite)
        {
            try
            {
                CreateNewFile(path, overwrite);
                AddToFile(path, contents, true);
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Creates a file at the indicated path
        /// </summary>
        /// <param name="path">
        /// string value indicating where to store
        /// the new file (include file name)
        /// </param>
        /// <param name="overwrite">
        /// bool value indicating whether to replace file in path
        /// if one already exists at that location
        /// </param>
       
/// <returns>
        /// bool value indicating whether file was created
        /// </returns>

        public static bool CreateNewFile(string path, bool overwrite)
        {
            try
            {
                if (File.Exists(path) && !overwrite)
                {
                    //Exception ex = new Exception(m_FileExistsMessage);
                    //ErrorTool.ProcessError(ex);
                   
                    return false;
                }
                FileStream file = new FileStream(
                    path, FileMode.Create);
                file.Close();

                return true;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return false;
                throw(ex);
            }
        } 

       
/// <summary>
        /// Deletes the file indicated from the system
        /// </summary>
        /// <param name="path">
        /// string value indicating full file path to delete
        /// </param>
        private static void m_DeleteFile(string path)
        {
            try
            {
                if (!File.Exists(path))
                    return;
                File.Delete(path);
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Checks path to be sure it's a file, and if so,
        /// makes that file writeable (may have been read-only...)
        /// </summary>
        /// <param name="path">
        /// string path/filename to set as editable
        /// </param>
        private static void m_MakeEditable(string path)
        {
            try
            {
                if (!File.Exists(path))
                {
                    return; //filepath doesn't exist
                } 
                FileAttributes attributes = File.GetAttributes(path); 
                if ((attributes & FileAttributes.Directory) != 0)
                {
                    return; //it's a directory/folder
                }
                attributes = FileAttributes.Normal;
                File.SetAttributes(path, attributes);
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        }
             
        /// <summary>
        /// Opens and existing file, and adds to its contents
        /// </summary>
        /// <param name="path">
        /// string value: full path/filename to add to
        /// </param>
        /// <param name="appendage">
        /// string value: stream of characters/words to add
        /// </param>
        /// <param name="newLine">
        /// bool value indicating whether to start at a new line
        /// </param>
        public static void AddToFile(string path,
            string appendage, bool newLine)
        {
            try
            {
                StreamWriter writer = File.AppendText(path);
                if (newLine)
                {
                    writer.WriteLine();
                }
                writer.Write(appendage);
                writer.Close();
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Opens a file and adds the supplied text
        /// to that file at the specified line number
        /// </summary>
        /// <param name="path">
        /// String indicating the file path, including
        /// the name of the file
        /// </param>
        /// <param name="textToInsert">
        /// String to insert/add to the file
        /// </param>
        /// <param name="lineNumber">
        /// Zero-based line number----if the text should
        /// be added at line 10, then pass 9
        /// </param>
        public static void AddToFile(string path,
            string textToInsert, int lineNumber)
        {
            try
            {
                ArrayList lines = GetLinesFromFile(path); 
                if (lines.Count > lineNumber)
                {
                    lines.Insert(lineNumber, textToInsert);
                }
                else
                {
                    lines.Add(textToInsert);
                } 
                StreamWriter writer = new StreamWriter(path); 
                foreach (string lineToWrite in lines)
                {
                    writer.WriteLine(lineToWrite);
                }
                writer.Close();
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Opens a file and adds the supplied text
        /// to that file after the first line found,
        /// that contains the textToInsertAfter string.
        /// Will add at 0 (first line), if not found at all.
        /// </summary>
        /// <param name="path">
        /// String indicating the file path, including
        /// the name of the file
        /// </param>
        /// <param name="textToInsert">
        /// String to insert/add to the file
        /// </param>
        /// <param name="textToInsertAfter">
        /// Text to place the new string after, will be
        /// inserted on the next line
        /// </param>
        public static void AddToFile(string path,
            string textToInsert, string textToInsertAfter)
        {
            try
            {
                ArrayList lines = GetLinesFromFile(path);
                int location = 0;
                int currentLine = 0;
                foreach (string lineToRead in lines)
                {
                    if (lineToRead.Contains(textToInsertAfter))
                    {
                        location = currentLine + 1;
                    }
                    currentLine += 1;
                }
                lines.Insert(location, textToInsert); 
                StreamWriter writer = new StreamWriter(path); 
                foreach (string lineToWrite in lines)
                {
                    writer.WriteLine(lineToWrite);
                }
                writer.Close();
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Opens and existing file, and adds to its contents
        /// (adds at the end of prior contents)
        /// </summary>
        /// <param name="path">
        /// string value: full path/filename to add to
        /// </param>
        /// <param name="appendage">
        /// string value: stream of characters/words to add
        /// </param>
        public static void AddToFile(string path, string appendage)
        {
            try
            {
                if (!File.Exists(path))
                {
                    CreateNewFile(path, true);
                }
                AddToFile(path, appendage, true);
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Closes an open FileStream object
        /// </summary>
        /// <param name="fileToClose">FileStream to close</param>
        public static void CloseFile(FileStream fileToClose)
        {
            try
            {
                fileToClose.Close();
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        }

                /// <remarks>
        /// USES A METHOD FROM StringTool.cs!
        /// Will not compile/execute without that file,
        /// so remove/comment this method if you don't have it
                /// </remarks>
        /// <summary>
        /// Checks for existence of a path

        /// </summary>
        /// <param name="directoryPath">
        /// string value of path to check for
        /// </param>
        /// <returns>
        /// bool value indicating whether the requested path exists
        /// </returns>
        public static bool CheckForDirectory(string directoryPath)
        {
            try
            {
                string path = StringTool.GetFolderPath(directoryPath);
                if (!Directory.Exists(path))
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        }

                /// <remarks>
        /// USES A METHOD FROM StringTool.cs!
        /// Will not compile/execute without that file,
        /// so remove/comment this method if you don't have it
                /// </remarks>
        /// <summary>
        /// Creates a directory (folder)
        /// </summary>
        /// <param name="directoryPath">
        /// string value of path to create
        /// </param>
        public static void CreateDirectory(string directoryPath)
        {
            try
            {
                string path = StringTool.GetFolderPath(directoryPath); 
                if (Directory.Exists(directoryPath))
                {
                    return;
                }
                Directory.CreateDirectory(path);
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        }

                /// <remarks>
        /// USES A METHOD FROM StringTool.cs!
        /// Will not compile/execute without that file,
        /// so remove/comment this method if you don't have it
                /// </remarks>
        /// <summary>
        /// Creates a directory (folder) inside the path indicated
        /// </summary>
        /// <param name="directoryPath">
        /// string value of path to create
        /// </param>
        /// <param name="folderName">
        /// string name of the folder to create
        /// </param>
        public static void CreateDirectory(string directoryPath,
            string folderName)
        {
            try
            {
                string path = StringTool.GetFolderPath(directoryPath);
                path = path + folderName; 
                if (Directory.Exists(directoryPath))
                {
                    return;
                }
                Directory.CreateDirectory(path);
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Grabs an ArrayList of lines from filepath indicated
        /// </summary>
        /// <param name="path">
        /// string value of filepath to get lines from
        /// </param>
        /// <returns>
        /// ArrayList object containing each string line in the file
        /// </returns>
        public static ArrayList GetLinesFromFile(string path)
        {
            try
            {
                ArrayList lines = new ArrayList();
                StreamReader reader = new StreamReader(path); 
                string currentLine = string.Empty; 
                while ((currentLine = reader.ReadLine()) != null)
                {
                    lines.Add(currentLine);
                }
                reader.Close();
                return lines;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Grabs a List of string lines from filepath indicated
        /// </summary>
        /// <param name="path">
        /// string value of filepath to get lines from
        /// </param>
        /// <returns>
        /// List object containing each string line in the file
        /// </returns>
        public static List<string> GetListOfLinesFromFile(string path)
        {
            try
            {
                List<string> lines = new List<string>();
                StreamReader reader = new StreamReader(path); 
                string currentLine = string.Empty; 
                while ((currentLine = reader.ReadLine()) != null)
                {
                    lines.Add(currentLine);
                }
                reader.Close();
                return lines;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        } 

       
/// <summary>
        /// Grabs all text from filepath indicated
        /// </summary>
        /// <param name="path">
        /// string value of filepath to get text from
        /// </param>
        /// <returns>
        /// string (just one) of all text in file
        /// </returns>
        public static string GetFullFileText(string path)
        {
            try
            { 
                StreamReader reader = new StreamReader(path);
                string text = reader.ReadToEnd(); 
                reader.Close();
                return text;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                //return;
                throw (ex);
            }
        }
    }
}

Not much verbiage necessary to introduce a code file I'll paste below. It's all about string manipulation. There are useful string functions in VB, and I have mimicked/extended some of these.

The file includes string conversion functions, some data type identification functions, some string edit functions, and some string locater functions. All methods in the class are static (one can call them without object instantiation).

My favorites:

GetEachFieldValue:        
Easily grabs a list by parsing with any characters the developer chooses

GetExactPartOfString: 
Extricates a portion of a full stream of characters, based on a left and right bound character of the developer's choice

GetFileNameFromPath:  
Returns just the filename, from inside a full path. Developer can choose whether to include the extension, or not.

Clean:                
Purges a string of any characters the developer wishes to remove. There is an exceptions argument that allows fine-tuning.

 

/*
 * Author: aendenne
 * Email: AutomateAnything@yahoo.com
 * Create Date: April 21, 2007
 * Last Modified Date: August 14, 2007
 * Version: 2.1
 */ 


using
System;
using System.Collections.Generic; 

namespace
YourNamespace.Tools
{
    /// <summary>
    /// Static class that exposes many string methods,
   
/// useful for string evaluation and edits
    /// </summary>
    public static class StringTool
    {

        #region StringConstantsToHelpWithComparisons
        private const string m_Letters = "abcdefghijklmnopqrstuvwxyz";
        private const string m_Digits = "0123456789";
        private const string m_ForwardSlash = "/";
        private const string m_BackSlash = "\\";
        private const string m_Period = ".";
        private const string m_DollarSign = "$";
        private const string m_PercentSign = "%";
        private const string m_Comma = ",";
        private const string m_Yes = "yes";
        private const string m_No = "no";
        private const string m_True = "true";
        private const string m_False = "false";
        private const string m_1 = "1";
        private const string m_0 = "0";
        private const string m_y = "y";
        private const string m_n = "n";

        #endregion 

        #region DataTypeStringConstants
        public const string m_GUID = "guid";
        public const string m_Boolean1 = "boolean";
        public const string m_Boolean2 = "bool";
        public const string m_Byte = "byte";
        public const string m_Char = "char";
        public const string m_DateTime = "datetime";
        public const string m_DBNull = "dbnull";
        public const string m_Decimal = "decimal";
        public const string m_Double = "double";
        public const string m_Empty = "empty";
        public const string m_Int16_1 = "int16";
        public const string m_Int16_2 = "short";
        public const string m_Int32_1 = "int32";
        public const string m_Int32_2 = "int";
        public const string m_Int32_3 = "integer";
        public const string m_Int64_1 = "int64";
        public const string m_Int64_2 = "long";
        public const string m_Object = "object";
        public const string m_SByte = "sbyte";
        public const string m_Single = "single";
        public const string m_String = "string";
        public const string m_UInt16 = "uint16";
        public const string m_UInt32 = "uint32";
        public const string m_UInt64 = "uint64";

        #endregion 

        #region MethodsThatCheckDataType
        /// <summary>
        /// Evaluates whether passed-in string can be converted to a bool
        /// </summary>
        /// <param name="stream">string to check</param>
        /// <returns>
        /// bool indicating whether stream is a bool (0, 1, true/True,
        /// false/False)
        /// </returns>
        public static bool IsStandardBool(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false; 
                stream = stream.Trim().ToLower();
                switch (stream)
                {
                    case m_0:
                        return true;
                    case m_1:
                        return true;
                    case m_True:
                        return true;
                    case m_False:
                        return true;
                    default:
                        return false;
                }
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return false;
            }
        } 

        /// <summary>
        /// Evaluates whether string can can be COERCED to a bool
        /// </summary>
        /// <param name="stream">string to check</param>
        /// <returns>
        /// bool indicating whether argument is a standard or custom bool
        /// (0, 1, true/True, false/False) OR (y/Y, yes/Yes, n/N, no/NO)
        /// </returns>
        public static bool IsFriendlyBool(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false; 
                stream = stream.Trim().ToLower();
                switch (stream)
                {
                    case m_0:
                        return true;
                    case m_1:
                        return true;
                    case m_True:
                        return true;
                    case m_False:
                        return true;
                    case m_n:
                        return true;
                    case m_y:
                        return true;
                    case m_No:
                        return true;
                    case m_Yes:
                        return true;
                    default:
                        return false;
                }
            }
            catch (Exception ex)
            {
               
//ErrorTool.ProcessError(ex);
                return false;
            }
        }

        /// <summary>
        /// Returns a bool conversion of the passed in string
        /// </summary>
        /// <param name="stream">string to convert/coerce</param>
        /// <returns>
        /// bool representation of passed-in string
        /// </returns>
        public static bool CoerceToBool(string stream)
        {
            try
            {
                stream = stream.Trim().ToLower();
                switch (stream)
                {
                    case m_0:
                        return true;
                    case m_1:
                        return true;
                    case m_True:
                        return true;
                    case m_False:
                        return false;
                    case m_n:
                        return false;
                    case m_y:
                        return true;
                    case m_No:
                        return false;
                    case m_Yes:
                        return true;
                    default:
                        return false;
                }
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return false;
            }
        } 

        /// <summary>
        /// Evaluates whether passed-in string contains any characters/
       
/// digits/symbols. Trims spaces before checking.
        /// </summary>
        /// <param name="stream">string to check</param>
        /// <returns>
        /// bool indicating whether argument is void of characters/
        ///
digits/symbols
        ///</returns>
        public static bool IsEmpty(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty
                    || stream.Trim() == string.Empty)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
               
//ErrorTool.ProcessError(ex);
                return false;
            }
        } 

        /// <summary>
        /// Checks each character of the string for any character other
        ///
than a digit, or a dollar sign or a percentage sign. If any
        ///
are found, returns false indicating that the stream is NOT
        ///
a number
        /// </summary>
        /// <param name="stream">
        /// The stream of characters (string) to check
        /// </param>
        /// <returns>
        /// True/False value indicating whether the string can be
       
/// coerced to a number
        /// </returns>
        public static bool IsNumber(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false; 
      
                string character = string.Empty;
                //set a string up of all characters that may indicate
                //that the stream is a number, or a formatted number:
                string validCharacters = m_Digits + m_Period +
                    m_DollarSign + m_Comma; 
                for (int i = 0; i < stream.Length; i++)
                {
                    character = stream.Substring(i, 1);
                    if (!validCharacters.Contains(character))
                        return false;
                }
                return true;
            }
            catch (Exception ex)
            {
               
//ErrorTool.ProcessError(ex);
                return false;
            }
        } 

        /// <summary>
        /// Checks the string to see whether it is a number & if it is,
        /// then it checks whether there is formatting applied to that #
        /// </summary>
        /// <param name="stream">
        /// The stream of characters (string) to check
        /// </param>
        /// <returns>
        /// True/False value indicating whether the string is a number
        /// that is formatted (contains digits and number formatting)
        /// </returns>
        public static bool IsFormattedNumber(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false;

                string character = string.Empty;
                //set a string up of all characters that may indicate that
                //the stream is a number, or a formatted number:
                string validCharacters = m_Digits + m_Period +
                    m_DollarSign + m_PercentSign + m_Comma; 

                for (int i = 0; i < stream.Length; i++)
                {
                    character = stream.Substring(i, 1);
                    if (!validCharacters.Contains(character))
                        //the stream contains non-numeric characters:
                        return false;
                }
                //at this point, each single character is a number OR an
                //
allowable symbol, but we must see whether those
                //
characters contain a formatting character:
                string formattingCharacters = m_DollarSign +
                    m_PercentSign + m_Comma;
                for (int i = 0; i < stream.Length; i++)
                {
                    if (formattingCharacters.Contains(character))
                        return true;
                }
                //still here? then the stream is a number, but NOT a
                //formatted number

                return false;
            }
            catch (Exception ex)
            {
               
//ErrorTool.ProcessError(ex);
                return false;
            }
        } 

        /// <summary>
        /// Checks whether string can be coerced into a DateTime value
        /// </summary>
        /// <param name="stream">The string to check/// </param>
        /// <returns>
        /// bool indicating whether stream can be converted to a date
        /// </returns>
        public static bool IsDate(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false; 
                DateTime checkDate = new DateTime();
                bool dateType = true;
                try
                {
                    checkDate = DateTime.Parse(stream);
                }
                catch
                {
                    dateType = false;
                }
                return dateType;
            }
            catch (Exception ex)
            {
               
//ErrorTool.ProcessError(ex);
                return false;
            }
        }  

        /// <summary>
        /// Checks the string to see whether it is a number and if it is,
        /// then it checks whether there is a decimal in that number.
        /// </summary>
        /// <param name="stream">
        /// The stream of characters (string) to check
        /// </param>
        /// <returns>
        /// True/False value indicating whether the string is a
        /// double---must be a number, and include a decimal
        /// in order to pass the test
        /// </returns>
        public static bool IsDouble(string stream)
        {
            try
            {
                if (stream == null || stream == string.Empty)
                    return false; 

                if (!IsNumber(stream))
                    return false; 

                //at this point each character is a number OR an allowable
                //symbol; we must see whether the string holds the decimal:
                if (stream.Contains(m_Period))
                    return true; 

                //still here? the stream is a #, but does NOT have a decimal
                return false;
            }
            catch (Exception ex)
            {
              
//ErrorTool.ProcessError(ex);
                return false;
            }
        } 

        /// <summary>
        /// Checks string to see if it matches a TypeCode string and returns
        /// that TypeCode, or returns TypeCode.Empty if there is no match
        /// </summary>
        /// <param name="dataTypeString">
        /// String representation of a TypeCode (string, int, bool...)
        /// </param>
        /// <returns>TypeCode that maps to the dataTypeString</returns>
        public static TypeCode GetDataType(string dataTypeString)
        {
            try
            {
                switch (dataTypeString.ToLower())
                {
                    // todo: isn't there a better way for guid?
                    case m_GUID:
                        return TypeCode.Object;
                    case m_Boolean1:
                        return TypeCode.Boolean;
                    case m_Boolean2:
                        return TypeCode.Boolean;
                    case m_Byte:
                        return TypeCode.Byte;
                    case m_Char:
                        return TypeCode.Char;
                    case m_DateTime:
                        return TypeCode.DateTime;
                    case m_DBNull:
                        return TypeCode.DBNull;
                    case m_Decimal:
                        return TypeCode.Decimal;
                    case m_Double:
                        return TypeCode.Double;
                    case m_Empty:
                        return TypeCode.Empty;
                    case m_Int16_1:
                        return TypeCode.Int16;
                    case m_Int16_2:
                        return TypeCode.Int16;
                    case m_Int32_1:
                        return TypeCode.Int32;
                    case m_Int32_2:
                        return TypeCode.Int32;
                    case m_Int32_3:
                        return TypeCode.Int32;
                    case m_Int64_1:
                        return TypeCode.Int64;
                    case m_Int64_2:
                        return TypeCode.Int64;
                    case m_Object:
                        return TypeCode.Object;
                    case m_SByte:
                        return TypeCode.SByte;
                    case m_Single:
                        return TypeCode.Single;
                    case m_String:
                        return TypeCode.String;
                    case m_UInt16:
                        return TypeCode.UInt16;
                    case m_UInt32:
                        return TypeCode.UInt32;
                    case m_UInt64:
                        return TypeCode.UInt64;
                    default:
                        return TypeCode.Empty;
                }
            }
            catch (Exception ex)
            {
              
//ErrorTool.ProcessError(ex);
                return TypeCode.Empty;
            }
        }

        #endregion

        #region StringConversions
        /// <summary>
        /// Returns a date, as coerced from the string argument. Will raise
        /// an error, if the string cannot be coerced
        /// ----so, use IsDate in this same class FIRST
        /// </summary>
        /// <param name="stream">string to get date value from</param>
        /// <returns>a DateTime object</returns>
        public static DateTime GetDate(string stream)
        {
            DateTime dateValue = new DateTime(); 
            try
            {
                dateValue = DateTime.Parse(stream);
                return dateValue;
            }
            catch (Exception ex)
            {
              
//ErrorTool.ProcessError(ex);
                return dateValue;
            }
        } 

        /// <summary>
        /// Returns an int, as coerced from the string argument.
        /// Will raise an error, if the string cannot be coerced
        /// ----so, use IsNumber in this same class FIRST
        /// </summary>
        /// <param name="stream">string to get int value from</param>
        /// <returns>an int object</returns>
        public static int GetInteger(string stream)
        {
            try
            {
                int number = 0; 
                if (!IsNumber(stream))
                    return number; 
                //still here? check to see if it is formatted:
                if (IsFormattedNumber(stream))
                {
                    //it's formatted; replace the format characters
                    //with nothing (retain the decimal so as not to change
                    //the intended value
                    stream = stream.Replace(m_Comma, string.Empty);
                    stream = stream.Replace(m_DollarSign, string.Empty);
                    stream = stream.Replace(m_PercentSign, string.Empty);
                }
                //we've removed superfluous formatting characters, if they
                //
did exist, now let's round it/convert it, and return it:
                number = Convert.ToInt32(stream);
                return number;
            }
            catch (Exception ex)
            {
              
//ErrorTool.ProcessError(ex);
                return 0;
            }
        } 

        /// <summary>
        /// Returns a double, as coerced from the string argument.
        /// Will raise an error, if the string cannot be coerced
        /// ----so, use IsNumber in this same class FIRST
        /// </summary>
        /// <param name="stream">string to get double value from</param>
        /// <returns>a double object</returns>
        public static double GetDouble(string stream)
        {
            try
            {
                double number = 0; 
                if (!IsNumber(stream))
                    return number; 
                //still here? check to see if it is formatted:
                if (IsFormattedNumber(stream))
                {
                    //it's formatted; replace the format characters
                    //with nothing (retain the decimal so as not to change
                    //the intended value)
                    stream = stream.Replace(m_Comma, string.Empty);
                    stream = stream.Replace(m_DollarSign, string.Empty);
                    stream = stream.Replace(m_PercentSign, string.Empty);
                }

                //we've removed superfluous formatting characters, if they
                //
did exist, now let's round it/convert it, and return it:
                number = Convert.ToDouble(stream);
                return number;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return 0;
            }
        }

        #endregion 

        #region StringEdits
        /// <summary>
        /// Iterates thru an entire string, and sets the first letter of
        /// each word to uppercase, and all ensuing letters to lowercase
        /// </summary>
        /// <param name="stream">The string to alter the case of</param>
        /// <returns>
        /// Same string w/uppercase initial letters & others as lowercase
        /// </returns>
        public static string MixCase(string stream)
        {
            try
            {
                string newString = string.Empty;
                string character = string.Empty;
                string preceder = string.Empty;
                for (int i = 0; i < stream.Length; i++)
                {
                    character = stream.Substring(i, 1);
                    if (i > 0)
                    {
                        //look at the character immediately before current
                        preceder = stream.Substring(i - 1, 1);
                        //remove white space character from predecessor
                        if (preceder.Trim() == string.Empty)
                            //the preceding character WAS white space, so
                            //we'll change the current character to UPPER
                            character = character.ToUpper();
                        else
                            //the preceding character was NOT white space,
                            //we'll force the current character to LOWER
                            character = character.ToLower();
                    }
                    else
                        //index is 0, thus we are at the first character
                        character = character.ToUpper(); 
                    //add the altered character to the new string:
                    newString += character;
                }
                return newString;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        } 

        /// <summary>
        /// Iterates thru a string, and removes anything set to clean.
        /// Except---Does NOT remove anything in exceptionsToAllow
        /// </summary>
        /// <param name="stream">
        /// The string to clean</param>
        /// <returns>
        /// The same string, missing all elements that were set to clean
        /// (except when a character was listed in exceptionsToAllow)
        /// </returns>
        public static string Clean(string stream, bool cleanWhiteSpace,
            bool cleanDigits, bool cleanLetters, string exceptionsToAllow)
        {
            try
            {
                string newString = string.Empty;
                string character = string.Empty;
                string blessed = string.Empty; 
                if (!cleanDigits)
                    blessed += m_Digits; 
                if (!cleanLetters)
                    blessed += m_Letters; 
                blessed += exceptionsToAllow;
                //we set the comparison string to lower
                //and will compare each character's lower case version
                //against the comparison string, without
                //altering the original case of the character
                blessed = blessed.ToLower(); 
                for (int i = 0; i < stream.Length; i++)
                {
                    character = stream.Substring(i, 1); 
                    if (blessed.Contains(character.ToLower()))
                        //add the altered character to the new string:
                        newString += character;
                    else if (character.Trim() == string.Empty &&
                        !cleanWhiteSpace)
                        newString += character;
                }
                return newString;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        }

        #endregion 

        #region StringLocators 
        /// <summary>
        /// Parses a file system or url path, and locates the file name
        /// </summary>
        /// <param name="fullPath">
        /// String indicating a file system or url path to a file
        /// </param>
        /// <param name="includeFileExtension">
        /// Whether to return file extension in addition to file name
        /// </param>
        /// <returns>
        /// File name, if found, and extension if requested, and located
        /// </returns>
        public static string GetFileNameFromPath(string fullPath,
            bool includeFileExtension)
        {
            try
            {
                bool url = fullPath.Contains(m_ForwardSlash); 
                string search = string.Empty; 
                if (url)
                    search = m_ForwardSlash;
                else
                    search = m_BackSlash; 
                string portion = string.Empty;
              
                int decimals = GetKeyCharCount(fullPath, m_Period);
                if (decimals >= 1)
                    //get all text to the RIGHT of the LAST slash:
                    portion = GetExactPartOfString(fullPath, search, false,
                        false, false);
                else
                    return string.Empty;
              
                if (includeFileExtension)
                    return portion; 
                search = m_Period;
                portion = GetExactPartOfString(portion, search, false,
                    true, false);
                return portion;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        } 

        /// <summary>
        /// Parses a url or file stream string, to get and return the
        /// path portion (sans the file name and extension)
        /// </summary>
        /// <param name="fullPath">
        /// A string indicating a file system path or a url. Can
        /// contain a file name/extension.
        /// </param>
        /// <returns>
        /// The original path minus the file name and extension,
        /// if it had existed, with no extension will return
        /// the original string, plus an optional slash
        /// </returns>
        public static string GetFolderPath(string fullPath)
        {
            try
            {
                bool url = fullPath.Contains(m_ForwardSlash); 
                string slash = string.Empty; 
                if (url)
                    slash = m_ForwardSlash;
                else
                    slash = m_BackSlash;

                string fileName = GetFileNameFromPath(fullPath, true); 
                //use tool to return all text to the LEFT of the file name
                string portion = GetStringBetween(fullPath, string.Empty,
                    fileName);

                //add the pertinent slash to the end of the string;
                if (portion.Length > 0 && portion.Substring(
                    portion.Length - 1, 1) != slash)
                    portion += slash; 
                return portion;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        } 

        /// <summary>
        /// Useful to pinpoint exact string between whatever
        /// characters/string you wish to grab text from
        /// </summary>
        /// <param name="stream">
        /// string from which to cull subtext from
        /// </param>
        /// <param name="from">
        /// string that precedes the text you are looking for
        /// </param>
        /// <param name="to">
        /// string that follows the text you are looking for
        /// </param>
        /// <returns>
        /// The string between point x and point y
        /// </returns>
        public static string GetStringBetween(string stream, string from,
            string to)
        {
            try
            {
                string subField = string.Empty;
                subField = RightOf(stream, from);
                subField = LeftOf(subField, to);
                return subField;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        }

        /// <summary>
        /// Will return the text to the LEFT of indicated substring
        /// </summary>
        /// <param name="stream">
        /// string from which to cull a portion of text
        /// </param>
        /// <param name="stringToStopAt">
        /// string that indicates what char or string to stop at
        /// </param>
        /// <returns>
        /// The string to the left of point x (stringToStopAt)
        /// </returns>
        public static string LeftOf(string stream, string stringToStopAt)
        {
            try
            {
                if (stringToStopAt == null || stringToStopAt == string.Empty)
                    return stream; 

                int stringLength = stream.Length;
                int findLength = stringToStopAt.Length; 

                stringToStopAt = stringToStopAt.ToLower();
                string temp = stream.ToLower();
                int i = temp.IndexOf(stringToStopAt); 

                if ((i <= -1) && (stringToStopAt != temp.Substring(0, findLength))
                    || (i == -1))
                    return stream; 

                string result = stream.Substring(0, i);
                return result;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        } 

        /// <summary>
        /// Will return the text to the RIGHT of whatever substring you indicate
        /// </summary>
        /// <param name="stream">
        /// string from which to cull a portion of text
        /// </param>
        /// <param name="stringToStartAfter">
        /// string that indicates what char or string to start after
        /// </param>
        /// <returns>
        /// The string to the right of point x (stringToStartAfter)
        /// </returns>
        public static string RightOf(string stream, string stringToStartAfter)
        {
            try
            {
                if (stringToStartAfter == null || stringToStartAfter == string.Empty)
                    return stream; 
                stringToStartAfter = stringToStartAfter.ToLower(); 
                string temp = stream.ToLower(); 
                int findLength = stringToStartAfter.Length;
                int i = temp.IndexOf(stringToStartAfter); 
                if ((i <= -1) && (stringToStartAfter != temp.Substring(0, findLength))
                    || (i == -1))
                    return stream;

                string result =
                    stream.Substring(i + findLength, stream.Length - (i + findLength)); 
                return result;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        } 

        /// <summary>
        /// Searches a string for every single instance of the passed-in
        /// field delimiters, and returns all the values between those
        /// delimiters, as a List object
        /// </summary>
        /// <param name="streamToSearch">string to search</param>
        /// <param name="leftFieldDelimiter">string to start at</param>
        /// <param name="rightFieldDelimiter">string to stop at</param>
        /// <returns>A List object of strings</returns>
        public static List<string> GetEachFieldValue(string streamToSearch,
            string leftFieldDelimiter, string rightFieldDelimiter)
        {
            string search = streamToSearch;
            string field = string.Empty;
            List<string> fields = new List<string>();
            while (!string.IsNullOrEmpty(search)
                && search.Contains(leftFieldDelimiter)
                && search.Contains(rightFieldDelimiter))
            {
                //get the val and add to list
                field = GetStringBetween(search, leftFieldDelimiter,
                    rightFieldDelimiter);
                if (!string.IsNullOrEmpty(field))
                    fields.Add(field); 
                //shorten the search string and continue
                search = RightOf(search, field + rightFieldDelimiter);
            }
            return fields;
        } 

        /// <summary>
        /// Instructions on using arguments:
        /// Set firstInstance = true, to stop at first instance of locateChar
        /// If firstInstance = false, then the LAST instance of locateChar will be used
        /// Set fromLeft = true, to return string from the left of locateChar
        /// If fromLeft = false, then the string from the right of locateChar
        /// will be returned.
        /// Set caseSensitive to true/false for case-sensitivity
        /// EXAMPLES:
        /// GetPartOfString('aunt jemima', 'm', 'true', 'true')
        /// will return 'aunt je'
        /// GetPartOfString('aunt jemima', 'm', 'true', 'false')
        /// </summary>
        /// <param name="stream">
        /// The string from which to cull a portion of text
        /// </param>
        /// <param name="locateChar">
        /// The character or string that is the marker
        /// for which to grab text (from left or right depending
        /// on other argument)
        /// </param>
        /// <param name="firstInstance">
        /// Whether or not to get the substring from the first
        /// encountered instance of the locateChar argument
        /// </param>
        /// <param name="fromLeft">
        /// Whether to search from the left. If set to false,
        /// then the string will be searched from the right.
        /// </param>
        /// <param name="caseSensitive">
        /// Whether to consider case (upper/lower)
        /// </param>
        /// <returns>
        /// A portion of the input string, based on ensuing arguments
        /// </returns>
        public static string GetExactPartOfString(string stream, string locateChar,
                  bool firstInstance, bool fromLeft, bool caseSensitive)
        {
            try
            {
                stream = stream.ToString();
                string tempStream = string.Empty;
                string tempLocateChar = string.Empty; 
                if (!caseSensitive)
                { //case doesn't matter, convert to lower:
                    tempStream = stream.ToLower();
                    tempLocateChar = locateChar.ToLower();
                } 
                //default charCnt to 1; for first inst of locateChar:
                int charCount = 1;
                if (firstInstance == false)
                    //get number of times char exists in string:
                    if (caseSensitive)
                        charCount = GetKeyCharCount(stream, locateChar);
                    else
                        charCount = GetKeyCharCount(tempStream, tempLocateChar); 
                //get position of first/last inst of char in str:
                int position = 0;
                if (caseSensitive)
                    position = GetCharPosition(stream, locateChar, charCount);
                else
                    position = GetCharPosition(tempStream, tempLocateChar, charCount); 
                string result = string.Empty; 
                //chk that character exists in str:
                if (position == -1)
                    result = string.Empty;
                else
                {
                    //char exists, proceed:
                    int streamLength = stream.Length;
                    if (fromLeft == true)
                        //return string from left:
                        result = stream.Substring(0, position);
                    else
                    {
                        //return string from right:
                        position += 1;
                        result = stream.Substring(position, streamLength - position);
                    }
                }
                return result;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return null;
            }
        } 

        /// <summary>
        /// Returns the number of times, that the key character is found
        /// in the stream string
        /// </summary>
        /// <param name="stream">
        /// string in which to locate key character
        /// </param>
        /// <param name="keyChar">
        /// key character: the string or char to count inside the stream
        /// </param>
        /// <returns>
        /// The number of times the string or char was located
        /// </returns>
        public static int GetKeyCharCount(string stream, string keyChar)
        {
            try
            {
                string current;
                int keyCount = 0;
                for (int i = 0; i < stream.Length; i++)
                {
                    current = stream.Substring(i, 1); 
                    if (current == keyChar)
                        keyCount += 1;
                }
                if (keyCount <= 0)
                    return -1;
                else
                    return keyCount;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return -1;
            }
        } 

        /// <summary>
        /// Is CASE-SENSITIVE
        /// Returns x position of sChar in sstream, where x = iCharInst.
        /// If: getCharPos('pineapple', 'p', 3) Then: 6 is returned
        /// </summary>
        /// <param name="stream">
        /// string in which to pinpoint the character (or string) position
        /// </param>
        /// <param name="charToPinpoint">character or string to locate</param>
        /// <param name="whichCharInstance">
        /// Number indicating WHICH instance of the character/string to locate
        /// </param>
        /// <returns>
        /// The index of the character or string found inside the input string.
        /// Will return -1 if the string/character is not found, or if the
        /// instance number is not found
        /// </returns>
        public static int GetCharPosition(string stream, string charToPinpoint, int whichCharInstance)
        {
            try
            {
                string current;
                int keyCharCount = 0;
                for (int i = 0; i < stream.Length; i++)
                {
                    current = stream.Substring(i, 1);
                    //was BLOCKED SCRIPT sCurr = sstream.charAt(i);
                    if (current == charToPinpoint)
                    {
                        keyCharCount += 1;
                        if (keyCharCount == whichCharInstance)
                            return i;
                    }
                }
                return -1;
            }
            catch (Exception ex)
            {
                //ErrorTool.ProcessError(ex);
                return -1;
            }
        }

        #endregion
    }
}

Until next time..................