Searching for categories and storing them This checks each row for a category. It stores ONE version of the category, ignore duplications. It then counts how many times a category appears.

There are a lot of for loops and a lot of table-checking. This takes time as the table is quite large. If it's possible, I would like to incorporate some of the loops to reduce time spent.

public partial class Stats : Form
{
    public Stats(ref TabControl languageTabs)
    {
        InitializeComponent();

        for (int i = 0; i &lt; languageTabs.TabCount; i++)
        {
            Control[] ctrls = languageTabs.TabPages[i].Controls.Find(languageTabs.TabPages[i].Name + "Grid", true);
            DataGridView dgv = ctrls[0] as DataGridView;

            int charCount = 0;
            for (int j = 0; j &lt; dgv.RowCount; j++)
            {
                charCount += (int)dgv.Rows[j].Cells[4].Value;
            }

            treeView1.Nodes.Add(languageTabs.TabPages[i].Text.ToUpper() + " Statistics");
            treeView1.Nodes[i].Nodes.Add("Total Number Of Strings: " + dgv.RowCount); // might need to remove '--' from count
            treeView1.Nodes[i].Nodes.Add("Total Number Of Chars: " + charCount);
            treeView1.Nodes[i].Nodes.Add("Total Number Of Strings and Chars per Category: ");

            //check for all different categories
            List&lt;string&gt; categories = new List&lt;string&gt;();

            int count = 0;
            for (int j = 0; j &lt; dgv.RowCount; j++)
            {
                // look at every category in the dgv and see if we have a unique value in a container
                List&lt;string&gt; result = categories.FindAll(
                    delegate(string b)
                    {
                        return b == dgv.Rows[j].Cells[1].Value.ToString();
                    }
                );

                // if we don't have a unique ID then add it
                if (result.Count == 0)
                {
                    categories.Add(dgv.Rows[j].Cells[1].Value.ToString());
                }  
            }

            int[] categoryCount = new int[categories.Count];

            foreach (string cat in categories)
            {
                for (int j = 0; j &lt; dgv.RowCount; j++)
                {
                    if (dgv.Rows[j].Cells[1].Value.ToString() == cat)
                    {
                        categoryCount[count]++;
                    }
                }
                count++;
            }

            int countTwo = 0;
            foreach (string cat in categories)
            {
                treeView1.Nodes[i].Nodes[2].Nodes.Add(cat + ":   " + categoryCount[countTwo].ToString());
                countTwo++;
            }

        }
    }
There are two pairs of loops that are the same and can be combined like this:

int charCount = 0;
List&lt;string&gt; categories = new List&lt;string&gt;();
for (int j = 0; j &lt; dgv.RowCount; j++)
{
    charCount += (int)dgv.Rows[j].Cells[4].Value;

    // look at every category in the dgv and see if we have a unique value in a container
    List&lt;string&gt; result = categories.FindAll(
        delegate(string b)
        {
            return b == dgv.Rows[j].Cells[1].Value.ToString();
        }
    );
    // if we don't have a unique ID then add it
    if (result.Count == 0)
    {
        categories.Add(dgv.Rows[j].Cells[1].Value.ToString());
    }
}

treeView1.Nodes.Add(languageTabs.TabPages[i].Text.ToUpper() + " Statistics");
treeView1.Nodes[i].Nodes.Add("Total Number Of Strings: " + dgv.RowCount); // might need to remove '--' from count
treeView1.Nodes[i].Nodes.Add("Total Number Of Chars: " + charCount);
treeView1.Nodes[i].Nodes.Add("Total Number Of Strings and Chars per Category: ");

int[] categoryCount = new int[categories.Count];
int count = 0;
foreach (string cat in categories)
{
    for (int j = 0; j &lt; dgv.RowCount; j++)
    {
        if (dgv.Rows[j].Cells[1].Value.ToString() == cat)
        {
            categoryCount[count]++;
        }
    }

    treeView1.Nodes[i].Nodes[2].Nodes.Add(cat + ":   " + categoryCount[count].ToString());
    count++;
}


Note that the categoryCount array is no longer ncessary, and add Saeed's answer and you get:

int charCount = 0;
List&lt;string&gt; categories = new List&lt;string&gt;();
for (int j = 0; j &lt; dgv.RowCount; j++)
{
    charCount += (int)dgv.Rows[j].Cells[4].Value;

    if (!categories.Any(x=&gt;x == dgv.Rows[j].Cells[1].Value.ToString()))
        categories.Add(dgv.Rows[j].Cells[1].Value.ToString()); 
}

treeView1.Nodes.Add(languageTabs.TabPages[i].Text.ToUpper() + " Statistics");
treeView1.Nodes[i].Nodes.Add("Total Number Of Strings: " + dgv.RowCount); // might need to remove '--' from count
treeView1.Nodes[i].Nodes.Add("Total Number Of Chars: " + charCount);
treeView1.Nodes[i].Nodes.Add("Total Number Of Strings and Chars per Category: ");

foreach (string cat in categories)
{
    int count = 0;
    for (int j = 0; j &lt; dgv.RowCount; j++)
    {
        if (dgv.Rows[j].Cells[1].Value.ToString() == cat)
        {
            count++;
        }
    }

    treeView1.Nodes[i].Nodes[2].Nodes.Add(cat + ":   " + count.ToString());
}


Then, assuming that dgv.Rows implements IEnumerable you can do this to the second loop:

foreach (string cat in categories)
{
    int count = dgv.Rows.Where(r =&gt; r.Cells[1].Value.ToString() == cat).Count();
    treeView1.Nodes[i].Nodes[2].Nodes.Add(cat + ":   " + count.ToString());
}