Query in Web browser control - c#

I'm trying to automate a web application. What i'm trying to do is login to a website, select a dropdown and insert some Id into textbox and then click on a button and finally reading some text.
All is well when this is done for a single Id. Now I have a datatable containing say 100 rows. I want to loop and change the texbox value, click on the button and read new text.
Can this be achieved with web browser control? I shall post my test code tomorrow...
Any approach in right direction is highly appreciated. Thank a ton in advance.
if (this.wbProject1.ReadyState == WebBrowserReadyState.Complete)
{
mFrameCount += 1;
wbProject1.Document.Window.Frames[1].Document.GetElementsByTagName("select")[0].SetAttribute("Value", "1");
HtmlWindow win = wbProject1.Document.Window;
if (win.Frames.Count > mFrameCount && win.Frames.Count > 0) done = false;
for (int rowCount = dtCertificateNo.Rows.Count - 1; rowCount >= 0; rowCount--)
{
int loopCount = 0;
DataRow drow = dtCertificateNo.Rows[rowCount];
wbProject1.Document.Window.Frames[1].Document.GetElementsByTagName("input")[1].SetAttribute("value", drow["CertificateNo"].ToString().Trim());
wbProject1.Document.Window.Frames[1].Document.GetElementsByTagName("a")[4].InvokeMember("click");
System.Threading.Thread.Sleep(2000);
if (done)
{
string[] str2 = wbProject1.Document.Window.Frames[1].Document.Body.InnerText.Replace("\r\n", "").Split(' ');
string[] str3 = wbProject1.Document.Window.Frames[1].Document.Body.InnerText.Replace("\r\n", "|").Split('|');
for (int i = 0; i < str2.Length - 1; i++)
{
if (str2[i] == "Status:")
{
if (str2[i + 1] == "Unperfected")
{
for (int j = 0; j < str3.Length - 1; j++)
{
if (str3[j].Contains("Reason:"))
{
DataRow drowFirst = dtReasons.NewRow();
drowFirst["CertificateNo"] = drow["ID"].ToString();
drowFirst["Reason"] = str3[j];
drowFirst["Comment"] = str3[j + 1];
dtReasons.Rows.Add(drowFirst);
// Here document inner text does not refreshes and remains the same for all the id's (holds the last one).
}
}
}
}
}
drow.Delete();
dtCertificateNo.AcceptChanges();
}
}
if (done)
{
ExcelExport(dtReasons, "D:\\Test");
this.Close();
}
}
else
{
Application.DoEvents();
}

Related

Getting DataGridView rows shifting code working?

Can someone help me fix this piece of code I found?
It's suppose to shift a whole row up on a winform datagridview.
It works like it's supposed to except for the fact that the old row position stays selected when there is only 1 selected item shifted.
DataGridViewSelectedRowCollection selectedRows = dataGridView.SelectedRows;
dataGridView.ClearSelection(); //this does not work.
for (int i = 0; i <= selectedRows.Count - 1; i++)
{
int selRowIndex = selectedRows[i].Index;
if (selRowIndex > 0)
{
dataGridView.Rows.Remove(selectedRows[i]);
dataGridView.Rows.Insert(selRowIndex - 1, selectedRows[i]);
dataGridView.Rows[selRowIndex - 1].Selected = true;
}
}
Not a fan of what that code you found was trying to do. Try moving selected rows up this way:
for (int i = 1; i < dataGridView.Rows.Count; ++i) {
if(dataGridView.Rows[i].Selected) {
var prevRow = dataGridView.Rows[i - 1];
dataGridView.Rows.RemoveAt(i - 1);
dataGridView.Rows.Insert(i, prevRow);
}
}
Do not call ClearSelection().
To move the selected rows down, try it this way:
for (int i = dataGridView.Rows.Count - 2; i >= 0; --i) {
if (dataGridView.Rows[i].Selected) {
var prevRow = dataGridView.Rows[i + 1];
if (!prevRow.IsNewRow) {
dataGridView.Rows.RemoveAt(i + 1);
dataGridView.Rows.Insert(i, prevRow);
}
}
}

Automatic serialwise string generator followed by integer

Hello every one I am working on my college project I am trying to make an windows application using sql server 2008 and visual c#. I am using grid view for input. Problem is when a new row is added the string does not increment. I mean my empid is at row[i] and cell[0] when i go on to next row the empid is same as in previous row according to my code it should increase by 1 from initial value The result which i want is
row[0]cell[0] = emp6;
row[1]cell[0] = emp7;
row[2]cell[0] = emp8;
row[3]cell[0] = emp9;
and yes i don't want to use row count (digit) as a Id integer because of duplicacy of employeeID in database so to avoid this i am using SQL COUNT to get initial value for ID.
here is my code please help me soon
void emp_id_generator(DataGridView dataGridView1)
{
if (dataGridView1 != null)
{
for (int count = 0; (count <= (dataGridView1.Rows.Count - 2)); count++)
{
int j = 6; //this is what i want to increment
Label l = new Label();
l.Text = "EmpID" + (j);
dataGridView1.Rows[count].Cells[0].Value = l.Text;
j=j+1;
}
}
}
Try this way.
J must be initialized outside the loop.
Have a nice day.
void emp_id_generator(DataGridView dataGridView1)
{
if (dataGridView1 != null)
{
int j = 6; //this is what i want to increment
for (int count = 0; (count <= (dataGridView1.Rows.Count - 2)); count++)
{
Label l = new Label();
l.Text = "EmpID" + (j);
dataGridView1.Rows[count].Cells[0].Value = l.Text;
j=j+1;
}
}
}

Show the beginning of scrollable panel, when starting program

I have program that is some kind of testing. I keep questions in panel, but when I run my program, it show the middle of panel. How to make it show the beginning of the panel?
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
Dictionary<string, bool> answers = new Dictionary<string,bool>();
for (int j = 0; j < 4; j++)
{
string ans = "Відповідь " + (j+1);
bool flag = false;
if( i > 5)
{
if( j == 0 || j == 2)
{
flag = true;
}
}else
if (j == 0)
{
flag = true;
}
answers.Add(ans, flag);
}
string q_text = "Питання № " + (i+1);
this.AddQuestion(q_text, answers);
}
panel1.ScrollControlIntoView(panel1.Controls[0]);
}
Try to set focus on the first control in the panel on Form_Load event:
panel1.Controls[0].Select();
You could use:
The ScrollControlIntoView method:
panel.ScrollControlIntoView(panel.Controls[0]);
Panel's VerticalScroll property:
panel.VerticalScroll.Value = 0;

Writing to text file doesn't match

i have a 10x10 text box ( 100 of them )
I write this code to write into text file :
foreach (Control control in Panel1.Controls)
{
var textBox = control as TextBox;
if (textBox != null)
{
if (string.IsNullOrEmpty(textBox.Text)) // ignore this
{
textBox.Style["visibility"] = "hidden";
}
textBox.Enabled = false;
if (numberofCommas > 8)
{
stringWriter.Write(textBox.Text);
numberofCommas = 0;
}
else
{
stringWriter.Write("," + textBox.Text );
numberofCommas++;
recordsWritten++;
}
if (recordsWritten == 10)
{
stringWriter.WriteLine();
recordsWritten = 0;
}
else
{
}
From the above i want to have 10 rows of 9 commas in the text file but instead i have 9 rows of 10 commas in the text file , is my code logic wrong? because i have been looking it for hours , i still couldn't solve it . sorry if my logic is bad , i am new to programming.
I think that you should increment recordsWritten in the last step:
if (numberofCommas > 8)
{
stringWriter.Write(textBox.Text);
numberofCommas = 0;
recordsWritten++;
}
Here is a better way to do it using Linq:
var textBoxes = Panel1.Controls.OfType<TextBox>().Select((t, i) => new { TextBox = t, Index = i }).ToList();
foreach (var tb in textBoxes)
{
if (string.IsNullOrEmpty(tb.TextBox.Text))
tb.TextBox.Style["visibility"] = "hidden";
tb.TextBox.Enabled = false;
}
foreach (var line in textBoxes.GroupBy(e => e.Index / 10)
.Select(e =>
string.Join(", ",
e.Select(a => a.TextBox.Text).ToArray())))
stringWriter.WriteLine(line);
I wouldn't recommend you to use 100 TextBox objects, you can use a DataGridView binded to a DataTable with 10 rows and 10 columns. You can still edit your data and save it to a file.
Try the below code
StringWriter stringWriter1 = new StringWriter();
DataTable dataTable1 = new DataTable();
private void Form1_Shown(object sender, EventArgs e)
{
dataGridView1.AllowUserToAddRows = false;
int i;
for (i = 0; i < 10; i++)
{
dataTable1.Columns.Add("Column" + (i + 1), typeof(string));
}
for (i = 0; i < 10; i++)
{
DataRow dataRow1 = dataTable1.NewRow();
dataTable1.Rows.Add(dataRow1);
}
dataGridView1.DataSource = dataTable1;
}
private void button1_Click(object sender, EventArgs e)
{
string rowString = "";
int i,j;
for (i = 0; i < 10; i++)
{
rowString = "";
for (j = 0; j < 10; j++)
{
if (dataTable1.Rows[i][j].ToString().Contains(",") == true)
{
//Enclosing the field data inside quotes so that it can
//be identified as a single entity.
rowString += "\"" + dataTable1.Rows[i][j] + "\"" + ",";
}
else
{
rowString += dataTable1.Rows[i][j] + ",";
}
}
rowString = rowString.Substring(0, rowString.Length - 1);
stringWriter1.WriteLine(rowString);
}
}
you just need to add a DataGridView onto your Form.

DataGridView: Copy complete to clipboard

I have a DataGridView in a .Net application (V4 C# VS2010) & want to copy all the data to the clipboard on the click of a button. No problem -
private void copyToClipboard()
{
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
Problem is that the user might already have some cells, rows etc selected on the DataGrid & I don't really want to change that selection. The above obviously selects everything. I could dataGridView1.ClearSelection(); at the end which is marginally better but still doesn't achieve what's required.
I can save the selected cells:
var mySelectedCells = dataGridView1.SelectedCells;
but how do I get those selected cells reselected on the DataGrid after the copy? Is there an easy way to get the selected cells collection back into the DataGrid? Perhaps there is a better way to get the whole grid copied to the clipboard in the first place without affecting presently selected cells?
I suppose if you just wanted to represent the contents of the cells as text and copy them to the clipboard, tab-delimited, you could do something like:
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = "";
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i=0; i < row.Cells.Count; i++)
{
if(i == (row.Cells.Count - 1))
clipboard_string += row.Cells[i].Value + newline;
else
clipboard_string += row.Cells[i].Value + tab;
}
}
Clipboard.SetText(clipboard_string);
The output seems pretty similar to that of the GetClipboardContent(), but be careful for any DataGridViewImageColumns or any type that isn't implicitly a string.
Edit: Anthony is correct, use StringBuilder to avoid allocating a new string for every concatenation. The new code:
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = new StringBuilder();
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i = 0; i < row.Cells.Count; i++)
{
if (i == (row.Cells.Count - 1))
clipboard_string.Append(row.Cells[i].Value + newline);
else
clipboard_string.Append(row.Cells[i].Value + tab);
}
}
Clipboard.SetText(clipboard_string.ToString());
Here is a version of the VB code in C# with options to copy headers and to only copy selected rows.
private void CopyDataGridViewToClipboard(DataGridView dgv, bool includeHeaders = true, bool allRows = false)
{
// copies the contents of selected/all rows in a data grid view control to clipboard with optional headers
try
{
string s = "";
DataGridViewColumn oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
if (includeHeaders)
{
do
{
s = s + oCurrentCol.HeaderText + "\t";
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
}
while (oCurrentCol != null);
s = s.Substring(0, s.Length - 1);
s = s + Environment.NewLine; //Get rows
}
foreach (DataGridViewRow row in dgv.Rows)
{
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
if (row.Selected || allRows)
{
do
{
if (row.Cells[oCurrentCol.Index].Value != null) s = s + row.Cells[oCurrentCol.Index].Value.ToString();
s = s + "\t";
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
}
while (oCurrentCol != null);
s = s.Substring(0, s.Length - 1);
s = s + Environment.NewLine;
}
}
Clipboard.SetText(s);
}
catch (Exception ex)
{
toolStripStatusLabel2.Text = #"Error: " + ex.Message;
}
}
You might want to include the column headers:
private void copyAllToClipboard()
{
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = new StringBuilder();
int i;
for (i = 0; i < this.Columns.Count - 1; i++)
{
clipboard_string.Append(this.Columns[i].Name);
clipboard_string.Append(tab);
}
clipboard_string.Append(this.Columns[i].Name);
clipboard_string.Append(newline);
foreach (DataGridViewRow row in this.Rows)
{
for ( i = 0; i < row.Cells.Count - 1; i++)
{
clipboard_string.Append(row.Cells[i].Value);
clipboard_string.Append(tab);
}
clipboard_string.Append(row.Cells[i].Value);
clipboard_string.Append(newline);
}
Clipboard.SetText(clipboard_string.ToString());
}
I think below method will exactly do what you want. Just call this method with the DataGridView name at the button click event.
Private Sub CopyDataGridViewToClipboard(ByRef dgv As DataGridView)
Try
Dim s As String = ""
Dim oCurrentCol As DataGridViewColumn 'Get header
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
Do
s &= oCurrentCol.HeaderText & Chr(Keys.Tab)
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
Loop Until oCurrentCol Is Nothing
s = s.Substring(0, s.Length - 1)
s &= Environment.NewLine 'Get rows
For Each row As DataGridViewRow In dgv.Rows
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
Do
If row.Cells(oCurrentCol.Index).Value IsNot Nothing Then
s &= row.Cells(oCurrentCol.Index).Value.ToString
End If
s &= Chr(Keys.Tab)
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
Loop Until oCurrentCol Is Nothing
s = s.Substring(0, s.Length - 1)
s &= Environment.NewLine
Next 'Put to clipboard
Dim o As New DataObject
o.SetText(s)
Clipboard.SetDataObject(o, True)
Catch ex As Exception
ShowError(ex, Me)
End Try
End Sub
DataGridView columns can be visible/invisible and also can be displayed in different order then the order they were created. This code takes care of both:
public static void CopyGridViewToClipboard(DataGridView gvCopy)
{
if (gvCopy == null) return;
StringBuilder s = new StringBuilder();
int offset = gvCopy.ColumnHeadersVisible ? 1 : 0;
int visibleColumnsCount = 0;
//count visible columns and build mapping between each column and it's display position
Dictionary<int, int> indexMapping = new Dictionary<int, int>();
int currIndex = 0;
int lastFoundMinDisplayIndex = -1;
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
//find min DisplayIndex >= currIndex where column is visible
int minDisplayIndex = 100000;
int minDisplayIndexColumn = 100000;
for (int k = 0; k < gvCopy.ColumnCount; k++)
{
if ((gvCopy.Columns[k].Visible) && (gvCopy.Columns[k].DisplayIndex >= currIndex) && (gvCopy.Columns[k].DisplayIndex > lastFoundMinDisplayIndex))
{
if (gvCopy.Columns[k].DisplayIndex < minDisplayIndex)
{
minDisplayIndex = gvCopy.Columns[k].DisplayIndex;
minDisplayIndexColumn = k;
}
}
}
if (minDisplayIndex == 100000) break;
indexMapping.Add(minDisplayIndexColumn, currIndex);
lastFoundMinDisplayIndex = minDisplayIndex;
currIndex++;
}
visibleColumnsCount = currIndex;
//put data in temp array -- required to position columns in display order
string[,] data = new string[gvCopy.RowCount + offset, visibleColumnsCount];
if (gvCopy.ColumnHeadersVisible)
{
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
if (gvCopy.Columns[j].Visible)
{
data[0, indexMapping[j]] = gvCopy.Columns[j].HeaderText;
}
}
}
for (int i = 0; i < gvCopy.RowCount; i++)
{
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
if (gvCopy.Columns[j].Visible)
{
data[i + offset, indexMapping[j]] = gvCopy[j, i].FormattedValue.ToString();
}
}
}
//copy data
for (int i = 0; i < gvCopy.RowCount + offset; i++)
{
for (int j = 0; j < visibleColumnsCount; j++)
{
s.Append(data[i, j]);
s.Append("\t");
}
s.Append("\r\n");
}
Clipboard.SetDataObject(s.ToString());
}
You should change multiselect property of DataGridView. Here is the code:
private void copyToClipboard()
{
dataGridView1.MultiSelect = True;
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}

Categories

Resources