[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 552
  • Last Modified:

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"]);
            }
0
rwheeler23
Asked:
rwheeler23
  • 9
  • 8
  • 3
2 Solutions
 
rwheeler23Author Commented:
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.
0
 
MajorBigDealCommented:
Try putting Application.DoEvents() under the if statement and see if that helps.
0
 
MajorBigDealCommented:
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.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
AndyAinscowCommented:
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();
}
0
 
rwheeler23Author Commented:
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();
       
            }
0
 
AndyAinscowCommented:
//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.
0
 
AndyAinscowCommented:
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
0
 
rwheeler23Author Commented:
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.
0
 
AndyAinscowCommented:
>>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 ?
0
 
rwheeler23Author Commented:
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?
0
 
AndyAinscowCommented:
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) ?
0
 
rwheeler23Author Commented:
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.
0
 
AndyAinscowCommented:
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.
0
 
rwheeler23Author Commented:
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?
0
 
AndyAinscowCommented:
>>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
0
 
rwheeler23Author Commented:
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();
                 
        }
0
 
MajorBigDealCommented:
rwheeler, as a debugging technique, I'd like to suggest that you try to create a simplified version of your form and keep simplifying until the problem goes away.  At that point you should be able to cause and fix the problem in your simplified application at will. If you do that, you will then have a very good idea (or at least a good clue) as to what is causing the problem.
0
 
rwheeler23Author Commented:
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.
0
 
AndyAinscowCommented:
public frmIntegratePayables()
        {
            InitializeComponent();

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

        }

Open in new window


You seem to call the IntegrateTransactions functions BEFORE the form is actually even loaded/shown.


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

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

IntegratePayables.IntegrateTransactions();

        }

Instead, remove from the constructor, have as a public function then call AFTER the form is visible.
0
 
rwheeler23Author Commented:
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.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 9
  • 8
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now