Link to home
Start Free TrialLog in
Avatar of rwheeler23
rwheeler23Flag for United States of America

asked on

VS C# Record Counter

In this little snippet of code I am trying to display a record counter as records are read. I am trying to use    lblCounter.Text = rc.ToString();

However, all this does is give me a blank screen and the only record counter that appears is the final record counter after all records have been read.

How do I update this code to show a record count as each record is read?

foreach (DataRow dr_cmploop in DataDataTable.Rows)
            {                            
                if ( rc % 50 == 0) /* Allow no more than 50 transactions per batch. For each 50 transactions create a new batch */
                {
                    bcounter++; /* Increment the batch counter for each 50 transactions */
                 
                    /* Create the batch name */
                    BACHNUMB = bprefix + string.Format("{0:d4}", DateTime.Today.Year) + "-" + string.Format("{0:d2}", DateTime.Today.Month) + "-" + string.Format("{0:d3}",bcounter);
                                       
                    /* Create the batch header */
                    CreateBatchHeader();
                }
               
                rc++; /* Increment the record counter for each transaction to be imported */

                lblCounter.Text = rc.ToString();
               
                dr = dr_cmploop;
                //tw.WriteLine("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", dr["YYYY"], dr["MM"], dr["Company_Code"], dr["Inter_Company_Code"], dr["Master_Account"], dr["Account"], dr["Sign"], dr["Balance"], dr["Master_Account_Description"], dr["Account_Description"]);
            }
Avatar of rwheeler23
rwheeler23
Flag of United States of America image

ASKER

P.S. I would like to do this without a progress bar or using backgroundworker. Just simple record count as the records are read will suffice.
Try putting Application.DoEvents() under the if statement and see if that helps.
That would update after every 50 records.  Put directly under the for loop if you want every record.  Of course that will slow things down.
Avatar of AndyAinscow
This is a copy from a previous question by you about this:

you mean something like the following where lbl is a label on your form.
int i = 1;
foreach(record in rs)
{
i++;
lbl.Text = i.ToString();
DoEvents();  //allow message loop to run, else lbl never appears to update
DoSomething();
}
I added the Application.DoEvents() command right after the if statement. I only see the record count once all records have been processed.

foreach (DataRow dr_cmploop in DataDataTable.Rows)
            {                            
                if ( rc % 50 == 0) /* Allow no more than 50 transactions per batch. For each 50 transactions create a new batch */
                {
                    bcounter++; /* Increment the batch counter for each 50 transactions */
                 
                    /* Create the batch name */
                    BACHNUMB = bprefix + string.Format("{0:d4}", DateTime.Today.Year) + "-" + string.Format("{0:d2}", DateTime.Today.Month) + "-" + string.Format("{0:d3}",bcounter);
                                       
                    /* Create the batch header */
                    CreateBatchHeader();
                }
                Application.DoEvents();
                rc++; /* Increment the record counter for each transaction to be imported */

                lblCounter.Text = rc.ToString();
               
                dr = dr_cmploop;

                /* Get the next AP voucher number */
                SqlCommand cmd = new SqlCommand();
                Object returnValue;

                cmd.CommandText = "SELECT NTVCHNUM FROM PM40100";
                cmd.CommandType = CommandType.Text;
                cmd.Connection = DataConnection;

                returnValue = cmd.ExecuteScalar();
                NTVCHNUM = returnValue.ToString();

                /* Increment the next AP voucher number */
                IncrementNextAPVoucher();
       
            }
//Application.DoEvents();
                rc++; /* Increment the record counter for each transaction to be imported */

                lblCounter.Text = rc.ToString();
               Application.DoEvents();


But I don't see why your code didn't update as processing happened.
I've made a new project, one form with a button and a label.

        private void button1_Click(object sender, EventArgs e)
        {
            for(int i = 0; i < 100; i++)
            {
                foo();
                label1.Text = i.ToString();
                Application.DoEvents();
            }
        }

        private void foo()
        {
            for(int i = 0; i < 100; i++)
            {
                for (int j = 0; j < 100; j++)
                {
                    for (int k = 0; k < 100; k++)
                    {
                        int m = i * 100 * 100 + j * 100 + k;
                    }
                }
            }
        }

Open in new window


Try it both with and without the line Application.DoEvents() - with the line you should see the label change (rapidly), without it is unchanging until it shows 99
OK, i need to find the difference in the code. I just placed a test button and pasted your code in there. I click the Test button and there is the counter. One difference I see is that using your example the button click directly  has the loop. In my code, the button click opens a window and then there is a call to a function that has the loop in it. So the iteration happens another level deep. Let me play with this and see if I can arrange things differently.
>>In my code, the button click opens a window...

thinks....   Modal window ?  With the label on the parent (disabled) form because it has opened a modal child window ?
Please excuse my ignorance but this is a concept I have been fighting with ever since I started coding in VS C#. So I have a parent window that has a button that opens a child window. From my understanding the modal child form now has control until the user exits it. So is there some way I reference the label in the child form? The child window is opened and displayed on the screen. Or is there some way to get the Application.DoEvent() to reference the child window?
Before we get all confused where is the label, on which form ?
Also is the 'new' form a modal form or modeless (.Show or .ShowDialog) ?
Here is how the form is called.

private void btnIntegrate_Click(object sender, EventArgs e)
        {
            if (IntegratePayables == null || IntegratePayables.Created == false)
            {
                IntegratePayables = new frmIntegratePayables();
            }

            IntegratePayables.Show();
            IntegratePayables.Activate();
            IntegratePayables.Focus();
        }

On this form(child form) there is a label called label1. It is this label I am trying to get to display the record count. Right now it only shows the record count when the loop is completed not while it is running.
That is modeless - so both forms should be enabled.
As the label is also on the form running the code (and active) then that should be processing messages without problems.
Is there some property of the form that may be controlling this? I noticed that when I click the integrate button, a blank form appears and it is only when the loop is done that I see the record count. Should I move the loop into the main body of the code as opposed to putting it down in a function?
>>I noticed that when I click the integrate button, a blank form appears

Are you putting the record processing code inside the FormLoad event?  If yes then that might be the problem
Here is the code in the form. There is nothing in the form load event.
public frmIntegratePayables()
        {
            InitializeComponent();

            /* Open the connection */
            DataConnection = GetConnection();
           
            /* Parse the import records and insert the payables transactions into batches */
            IntegrateTransactions();

        }

===================================================================

Here is the IntegrateTransaction code
private void IntegrateTransactions()
        {
            /* Set the batch and record counters to 1 */
            bcounter = 0;
            rc = 0;
           
            /* Define dataset for Transaction Types */
            DataDataSet = new System.Data.DataSet();
            DataDataSet.CaseSensitive = false;

            DataDataCommand = new System.Data.SqlClient.SqlCommand();
            DataDataCommand.Connection = DataConnection;

            DataDataCommand.CommandText = "select distinct Number,case when DocumentType = 'Invoice' then 1 else 4 end as DocType," +
            "coalesce(Reference,'') as Reference,PurchaseDate,PostDate,coalesce(CRI,'') as PONUMBER,VENDORID, Purchases " +
            "from PEF_VendorBatchLoadTransaction where wasimported = 0 and VendorFound = 1 and GLAccountMatched=1";

            DataDataAdapter = new System.Data.SqlClient.SqlDataAdapter();
            DataDataAdapter.SelectCommand = DataDataCommand;

            DataDataAdapter.Fill(DataDataSet);
            DataDataTable = DataDataSet.Tables[0];

            foreach (DataRow dr_cmploop in DataDataTable.Rows)
            {                            
                if ( rc % 50 == 0) /* Allow no more than 50 transactions per batch. For each 50 transactions create a new batch */
                {
                    bcounter++; /* Increment the batch counter for each 50 transactions */
                 
                    /* Create the batch name */
                    BACHNUMB = bprefix + string.Format("{0:d4}", DateTime.Today.Year) + "-" + string.Format("{0:d2}", DateTime.Today.Month) + "-" + string.Format("{0:d3}",bcounter);
                                       
                    /* Create the batch header */
                    CreateBatchHeader();
                }

                label2.Text = rc.ToString(); /* Here is the label getting the record count
               
                Application.DoEvents();
                rc++; /* Increment the record counter for each transaction to be imported */
                               
                dr = dr_cmploop;

                /* Get the next AP voucher number */
                SqlCommand cmd = new SqlCommand();
                Object returnValue;

                cmd.CommandText = "SELECT NTVCHNUM FROM PM40100";
                cmd.CommandType = CommandType.Text;
                cmd.Connection = DataConnection;

                returnValue = cmd.ExecuteScalar();
                NTVCHNUM = returnValue.ToString();

                /* Increment the next AP voucher number */
                IncrementNextAPVoucher();

                /* Insert the PM Key Master record for each transaction */
                CreatePMKeyMaster();
            }

            DataDataSet.Dispose();
                 
        }
SOLUTION
Avatar of MajorBigDeal
MajorBigDeal
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Not a bad idea. First I need to get the program finished so users can do what they have to do. Then I will create fresh code and restructure it. Code is always easier the second time around.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is where I have much to learn. I would have preferred to just have functions in a code file and not even have this function assiocated with a form. I need to learn more about how to share code between applications.