0

I want to write an windows form application who can do auto data filling in an textbox on the web page and get the corresponding data show on the page one by one. I met a problem that my loop goes too fast and I cannot see the result showing on the page. How can I let the page fully loaded and then go the next loop?

My designer has a textbox which is used to input url, webBrowser to browse the web page, the button is used to lunch the page.

My code are as below. I use "http://finance.yahoo.com/" as testing page. Testing data is in excel format. the data is a row, like " msft, bac, f, aapl".

using System;
   using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
 using System.Drawing;
 using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;

 using System.Data.OleDb;

 using System.Net;
 using System.IO;

    namespace WindowsFormsApplication2
    {
    public partial class Form1 : Form
    {

    public Form1()
    {
        InitializeComponent();

    }

    private void button1_Click(object sender, EventArgs e)
    {

        string url = textBox1.Text;
        var request = (HttpWebRequest)WebRequest.Create(url);  
        var response = (HttpWebResponse)request.GetResponse();  
        Stream stream = response.GetResponseStream();    
        StreamReader sr = new StreamReader(stream);     
        string content = sr.ReadToEnd();
        webBrowser1.DocumentText = content;


    }


    public void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {

        HtmlElement tbUserid = webBrowser1.Document.GetElementById("mnp-search_box");
        //HtmlElement tbPasswd = webBrowser1.Document.GetElementById("pwdInput");
        HtmlElement btnSubmit = webBrowser1.Document.GetElementById("yucs-sprop_button");
        webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
        if (tbUserid == null || btnSubmit == null)
        {
            return;
        }

        OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source='d:\\testing file\\list.xls';Extended Properties= \"Excel 8.0;HDR=Yes;IMEX=1\";");
        OleDbDataAdapter da = new OleDbDataAdapter("select * from [List$]", con);
        DataTable dt = new DataTable();
        da.Fill(dt);


       /* int i = 0;
        do
        {
            string str = dt.Rows[i][0].ToString();
            tbUserid.SetAttribute("value", str);
            //System.Threading.Thread.Sleep(10000);
            btnSubmit.InvokeMember("click");
            evt.WaitOne();
            i++;
        }
        while (i < dt.Rows.Count);
        */
        for (int i = 0; i < dt.Rows.Count; i++)
         {

            string str = dt.Rows[i][0].ToString();
             tbUserid.SetAttribute("value", str);
            btnSubmit.InvokeMember("click");
            Application.DoEvents();

            //System.Threading.Thread.Sleep(100);
         }
       // ((WebBrowser)sender).Dispose();


    }



}

}

Rita
  • 1
  • 1
  • This may not be the best code practice, but you can call `Application.DoEvents()` which will update your winform in the background. – Elias Jun 10 '14 at 15:39
  • You are submitting each time you fill data from a row, so I suppose that's wrong, what you want is -to fill the row, do the submit, wait for the new DocumentCompleted, navigate again to the correct page and redo until end- or -fill all the rows and then submit all-, what is your concrete case? – Gusman Jun 10 '14 at 15:43
  • @Gusman Thank you for your comment. I have an web page based Information System. I do not have the access to the database either the source code of the web site. I have thousands of account numbers. I want to get the transaction records for each account. So I came out an idea to use webBrowser to do auto filling and auto search. – Rita Jun 10 '14 at 16:08
  • Ok, but you must submit on each row filled or you must fill all the rows and then submit? – Gusman Jun 10 '14 at 16:10
  • @Gusman Thank you for your quick reply! The information system only allow me to input one account number at one time so which means I have to submit on each row after I filled the textbox. – Rita Jun 10 '14 at 16:13
  • FYI: http://stackoverflow.com/a/22262976/1768303 – noseratio Jun 11 '14 at 06:26

1 Answers1

0

Ok, so, let's suppose your target page is http://thisis.my/addres.html and when the page has been used to insert a row it redirects to http://thisis.my/secondaddres.html.

First, let's create a List to hold all the data from the table and two strings to hold the concrete addresses:

List<string> rows = new List<string>();
static string fillAddress = "http://thisis.my/addres.html";
static string sentAddress = "http://thisis.my/secondaddres.html";

Second, when the button is pressed load the data in the list and do your first navigation:

private void button1_Click(object sender, EventArgs e)
{
    OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source='d:\\testing file\\list.xls';Extended Properties= \"Excel 8.0;HDR=Yes;IMEX=1\";");
    OleDbDataAdapter da = new OleDbDataAdapter("select * from [List$]", con);
    DataTable dt = new DataTable();
    da.Fill(dt);

    for (int i = 0; i < dt.Rows.Count; i++)
    {

        string str = dt.Rows[i][0].ToString();
        rows.Add(str);
    }

    webBrowser1.NavigateTo(fillAddress);

}

Ensure that your DocumentCompleted event is hooked thorugh designer or code.

And finally when a document has been fully loaded the do this sequence:

If page == fillAddress
    If rows is not empty
        Extract row
        Fill row
        Submit
    else
        We have finished
else
    Navigate to fillAddress

-

public async void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{

    if(e.Url.ToString() == fillAddress)
    {
        if(rows.Count > 0)
        {

            HtmlElement tbUserid = webBrowser1.Document.GetElementById("mnp-search_box");
            HtmlElement btnSubmit = webBrowser1.Document.GetElementById("yucs-sprop_button");

            if (tbUserid == null || btnSubmit == null)
                return;

            string str = rows[0];
            rows.RemoveAt(0);
            tbUserid.SetAttribute("value", str);
            btnSubmit.InvokeMember("click");

        }
        else
            return;

    }
    else if(e.Url.ToString() == sentAddress)
        webBrowser1.NavigateTo(fillAddress);
}

I have done tons of assumptions but you will get the general idea: get a list of data, navigate, when the page to fill is loaded fill the row and send the data, when the confirmation is done navigate again to the fill form and repeat until no data is left.

Gusman
  • 14,905
  • 2
  • 34
  • 50
  • Hi, Gusman! Thank you for your generous help! I so sorry that I didn't make my question clear. I edit my question. – Rita Jun 10 '14 at 17:17
  • I do not have to navigate to a concrete address. And I try your code, It doesn't loop all my account numbers in the row. – Rita Jun 10 '14 at 17:18
  • So, to navigate to the next page which criteria has to be met? user presses another button? X time passes after loading? – Gusman Jun 10 '14 at 17:20
  • it's a framed web page. When I enter a number and click search, the data will show in the bottom part of the page. So when I click the search button on the web page, it will still be the same page. – Rita Jun 10 '14 at 17:24