0

Find Top 3 Button – which processes the data to find the 3 highest sales amounts and displays these sales persons names along with their place (1st, 2nd, 3rd), and sales amount.

I have two list boxes I just want to find the top 3 highest sales persons with their sales amount and show them as message box to the user in 3 separate lines

Picture of the application: http://s17.postimg.org/6dvo3a4qn/Untitled.jpg

Listboxes names: lstNames, lstTotalSales

My find top 3 button code is:

private void btnFindTop3_Click(object sender, EventArgs e)
{
    decimal dec1HighestAmount = 0;
    decimal dec2HighestAmount = 0;
    decimal dec3HighestAmount = 0;
    for (int Index = 0; Index < lstTotalSales.Items.Count; Index++)
    {
        if (Convert.ToDecimal(lstTotalSales.Items[Index]) > dec1HighestAmount)
        {
            dec1HighestAmount = Convert.ToDecimal(lstTotalSales.Items[Index]);
        }
        if (Convert.ToDecimal(lstTotalSales.Items[Index]) < dec1HighestAmount)
        {
            dec2HighestAmount = Convert.ToDecimal(lstTotalSales.Items[Index]);
        }
        if (Convert.ToDecimal(lstTotalSales.Items[Index]) < dec2HighestAmount)
        {
            dec2HighestAmount = Convert.ToDecimal(lstTotalSales.Items[Index]);
        }
    }
    MessageBox.Show("Highest Amount is " + dec1HighestAmount + " and " + dec2HighestAmount + " and " + dec3HighestAmount);
}

This is the code that I used to fill the listboxes:

public partial class Form1 : Form
{
    List<decimal> lstTotal = new List<decimal>();
    public Form1()
    {
        InitializeComponent();
    }

    private void btnReadInSalesData_Click(object sender, EventArgs e)
    {
        openFileDialog1.FileName = "SalesNumbers.txt";
        if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) //If and Open Dialog OK
        {
            StreamReader srFile = File.OpenText(openFileDialog1.FileName);

            decimal decTotal = 0;

            while (!srFile.EndOfStream)
            {
                string strline = srFile.ReadLine();
                string[] strSplit = strline.Split('$');

                foreach (string strSplittedOutput in strSplit)
                {

                    if (decimal.TryParse(strSplittedOutput, out decTotal))
                    {
                        lstTotal.Add(decTotal);
                        lstTotalSales.Items.Add(strSplittedOutput);
                    }
                    else //else than decimals add strings
                    {
                        lstNames.Items.Add(strSplittedOutput); //add the Sales men names to lstNames listbox
                    }
                }
            } //End of while

            srFile.Close(); //Close StreamReader
        }
        else
            MessageBox.Show("User Cancel Read File Operation."); // if the user cancel the read file operation show this messagebox

        // ... ??
    }

    // ...
}

Thank you

Noctis
  • 11,507
  • 3
  • 43
  • 82
Med1a
  • 92
  • 1
  • 10
  • 2
    And the problem is..? – Jeroen Vannevel Nov 14 '13 at 02:39
  • instead of finding top 3, why not sort the list? Just in case the user of this program wants to find top 5, top 10, etc. – Yang You Nov 14 '13 at 03:03
  • This is the output of the messagebox: http://s22.postimg.org/tb90fml0x/Untitled2.jpg , I'm just trying to get the index number of the person name in lstNames that equals the top 3 to show in the messagebox. Thank you – Med1a Nov 14 '13 at 06:45

1 Answers1

1

something like

var top_three = (from sales in lstTotalSales.Items
                 orderby sales descending
                 select sales).Take(3);

will hold your top 3 using linq...


Argh ... ok ... the bad news ... you have lots of work ahead of you ... the good news, this will set you on the right way:

public partial class Form1 : Form
{
    List<decimal> lstTotal = new List<decimal>();
    List<SalesPerson> lstSalesPerson = new List<SalesPerson>;

    public Form1()
    {
        InitializeComponent();
    }

    private void btnReadInSalesData_Click(object sender, EventArgs e)
    {
        openFileDialog1.FileName = "SalesNumbers.txt";
        if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) //If and Open Dialog OK
        {
            StreamReader srFile = File.OpenText(openFileDialog1.FileName);

            decimal decTotal = 0;
            decimal tempSales =0;
            string tempName = "";

            while (!srFile.EndOfStream)
            {
                string strline = srFile.ReadLine();
                string[] strSplit = strline.Split('$');

                // I'll seriously assume this happens only twice ...
                foreach (string strSplittedOutput in strSplit)
                {

                    if (decimal.TryParse(strSplittedOutput, out decTotal))
                    {
                        lstTotal.Add(decTotal);
                        lstTotalSales.Items.Add(strSplittedOutput);
                        tempSales = strSplittedOutput;
                    }
                    else //else than decimals add strings
                    {
                        lstNames.Items.Add(strSplittedOutput); //add the Sales men names to lstNames listbox
                        tempName = strSplittedOutput;
                    }
                }

                    // Adding this to our people list ...
                    lstSalesPerson.Add(new SalesPerson {Name=tempName,TotalSales=tempSales});

            } //End of while

            srFile.Close(); //Close StreamReader
        }
        else
            MessageBox.Show("User Cancel Read File Operation."); // if the user cancel the read file operation show this messagebox

        // ... ??
    }

    // ...
}


public class SalesPerson {
    public string Name {get; set;}
    public decimal TotalSales {get; set;}
}

I've added a class called SalesPerson ... this objects has a Name and a TotalSales ... doooohhh ... In your loop, I'm assuming you a have a text file with lines and in each one name and sales value ... I've added at the end the creation of a SalesPerson that goes into your lstSalesPerson (added at the top).

Now we're almost there ... Please go read and understand this article: http://www.codeproject.com/Articles/671544/Understanding-SelectedValue-SelectedValuePath-Sele .

Once you do, you'll realize you don't need to have the lstTotalSales and the lstNames, because you can just link those listboxes to the DisplayMemberPath of your lstSalesPerson.

Now, when you select your top 3 using the linq above, you have 3 objects. For each object you can use the values Name and TotalSales since they are just properties on that object.

var top_three = (from person in lstSalesPerson
             orderby person.TotalSales descending
             select person).Take(3);

foreach (var person in top_three) {
     // do something with person.Name
     // do something with person.TotalSales
}
Noctis
  • 11,507
  • 3
  • 43
  • 82
  • Thank u, I'm trying to get their names and sales amount as well! – Med1a Nov 14 '13 at 03:16
  • so ? If you have a collections of people, and each object holds names, and sales and the color of their puppy, you can have each list show only one property using the display value, but running that linq on the main list, will get the objects. then just reference the properties you need, like name and sales ... – Noctis Nov 14 '13 at 03:19
  • It seems u didn't get what i mean or i couldn't understand ur meaning, i have two different list boxes and the linkq will get the total sales without knowing the person name. Please explain more. Thank you for your time :) – Med1a Nov 14 '13 at 04:49
  • Listboxes names: lstNames, lstTotalSales I don't know how to make the c# loop to get the same index number of the person name in the list box that equals the sales amount index number. I hope it is clear enough for you. Thank you :) – Med1a Nov 14 '13 at 06:38
  • how do you fill these lists ? you must have a collections of persons that have names and sales properties in them, right? – Noctis Nov 14 '13 at 07:05