Error in update function for CRUD in Windows Form - c#

Am new to programming, so please assist as much as possible!
Recently, im tasked to do a CRUD windows form application using C# & MS access.
In my update function, i face one of the following errors which im not sure why..
My data are not able to be updated either.
Error: ArgumentException was unhandled
Input string was not in a correct format.Couldn't store
in staff_id Column. Expected type is
Int32.
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AcuzioSapp.AcuzioSecureStore_DatabaseDataSetTableAdapters;
namespace AcuzioSapp
{
public partial class Update_Client : Form
{
private DataRow row;
private ClientTableAdapter adapter;
public Update_Client(DataRow row, ClientTableAdapter adapter)
{
InitializeComponent();
this.row = row;
this.adapter = adapter;
textBox_id1.Text = Convert.ToString(row["c_id"]);
textBox_name1.Text = Convert.ToString(row["c_name"]);
textBox_address1.Text = Convert.ToString(row["c_address"]);
textBox_cinfo1.Text = Convert.ToString(row["c_contactinfo"]);
textBox_pinfo1.Text = Convert.ToString(row["profile_info"]);
textBox_refno1.Text = Convert.ToString(row["c_8digitrefno"]);
textBox_staffid1.Text = Convert.ToString(row["staff_id"]);
}
private void button_close_Click(object sender, EventArgs e)
{
Close();
}
private void button_update_Click(object sender, EventArgs e)
{
row["c_name"] = "textBox_name1";
row["c_address"] = "textBox_address1";
row["c_contactinfo"] = "int.Parse(textBox_cinfo1)";
row["c_8digitrefno"] = "(textBox_pinfo1)";
row["profile_info"] = "textBox_refno1";
row["staff_id"] = "int.Parse(textBox_staffid1)";
adapter.Update(row);
}
}
}
Appreciated for help and explanation thankyou.

Thats because of your column is declared integer in your Access database and you try to insert a String value in it. And I also think you will not get proper value in your specified table because you update your columns by constant string (row["profile_info"] = "textBox_refno1";), this will insert textBox_refno1 into profile_info column not TextBox value.
Try this :
row["staff_id"] = Convert.ToInt32(textBox_staffid1.Text);
Update:
Copy and paste following code, and you will never have any issue:
private void button_update_Click(object sender, EventArgs e)
{
row["c_name"] = textBox_name1.Text;
row["c_address"] = textBox_address1.Text;
row["c_contactinfo"] = int.Parse(textBox_cinfo1.Text);
row["c_8digitrefno"] = textBox_pinfo1.Text;
row["profile_info"] = textBox_refno1.Text;
row["staff_id"] = int.Parse(textBox_staffid1.Text);
adapter.Update(row);
MessageBox.Show("Data has been updated");
}
Hope this help.

row["c_name"] = textBox_name1.Text;
row["c_address"] = textBox_address1.Text;
...
int val;
if(int.TryParse(textBox_staffid1.Text, out val))
{
row["staff_id"] = val;
}
I consider, that text in your textbox not in correct format.

Related

max number from array in library

I'm trying to create a library for C#, that would get the maximum number in a listbox.
Currently I am just trying the method in the program before creating the library. The following code is what I have:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace SPE16
{
public partial class FormExamStatistics : Form
{
List<double> ExamScores = new List<double>();
double highScore = 0;
public FormExamStatistics()
{
InitializeComponent();
}
private double HighScore(List<double> anyList) //return the highest score
{
return highScore = ExamScores.Max();
}
private void buttonAddFromFile_Click(object sender, EventArgs e)
{
StreamReader reader;
reader = File.OpenText("ExamScores.txt");
while (!reader.EndOfStream)
{
double Scores;
double.TryParse(reader.ReadLine(), out Scores);
ExamScores.Add(Scores);
listBoxScores.Items.Add(Scores);
labelHighScore.Text = highScore.ToString();
}
reader.Close();
/////////////
HighScore(ExamScores);
/////////////
}
}
}
Now, it is supposed to return the maximum value from the list created on top, which is populated by a text file "ExamScores.txt". This text file contains 60 (double) scores with a maximum number of 120.
The maximum number, should be 120, but it returns "0".
Now I need to make this as a method first, in order to create a (dll) library later.
What am I doing wrong?
you need to check your file because.NET Framework design guidelines recommend using the Try methods. Avoiding exceptions is usually a good ide
if (value == null)
{
return 0.0;
}
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider)
please post a your file content
did you tried,
private void buttonAddFromFile_Click(object sender, EventArgs e){
StreamReader reader;
reader = File.OpenText("ExamScores.txt");
while (!reader.EndOfStream){
double Scores;
double.TryParse(reader.ReadLine(), out Scores);
ExamScores.Add(Scores);
listBoxScores.Items.Add(Scores);
labelHighScore.Text = highScore.ToString();
}
reader.Close();
/////////////
HighScore(ExamScores);
/////////////
}
Proper sample for the question would be:
var highScore = 0;
labelHighScore.Text = highScore.ToString();
highScore = 42;
Written this way it clearly demonstrates that showing value first and only than changing it does not actually display updated value.
Fix: set value before showing it, likely labelHighScore.Text = highScore.ToString(); should be just moved to the end of the function.
Note that there are likely other problems in the code based on strange way HighScore returns result and how code completely ignores result of the function.

Error when converting String to Float/Int. C# Windows Forms

I am new at C#. I hope someone can help me.
I am programing a small Windows Forms Application.
Two textBoxes and one result label.
For hours I am trying to get from the Strings in the textBoxes a Float Value.
Later some one will write for example 1.25 in TextBox1 and divide it with a value in the second TextBox.
I tryed lot of code. If a code is working (not red underlined) than I get this
Error Message: "Error kind of System.Format.Exception in mscorlib.dll".
"The entered String has wrong format".
How can I fix this?! Or what am I m doing wrong?! Please help. I am a Noob.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string a = textBox1.Text;
string b = textBox2.Text;
float num = float.Parse(textBox1.Text);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
`
If you use the Parse function & an invalid number is entered - then you will get an error message (in the form of an unhandled exception) of the type you described.
You can either implement exception handling :
float num;
try
{
num = float.Parse(textBox1.Text);
}
catch (FormatException)
{
// report format error here
}
you can also catch the out of range & null argument exceptions : https://msdn.microsoft.com/en-us/library/2thct5cb(v=vs.110).aspx
Or use the TryParse method :
float num;
bool NumberOK = float.TryParse(textBox1.Text, out num);
if (!NumberOK)
{
// report error here
}
https://msdn.microsoft.com/en-us/library/26sxas5t(v=vs.110).aspx

Calling BackgroundWorker.ReportProgress from an instantiated class? C#

I am writing a program that involves some heavy conversion of an Excel file into a very specifically formatted flat file. There are over 50,000 rows that need converted, so needless to say, it will take a while to process.
With that said, using a BackgroundWorker would make the most sense.
Everything I have executes properly and works fine except for one issue: trying to call the BackgroundWorker.ReportProgress() method from an instantiated class to update a counter on the parent Form.
If I'm not making sense, maybe my code will make more sense:
The Processing GUI Form:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
namespace CityTaxImport
{
public partial class Processing : Form
{
string s_sourceFile;
bool b_fileSaved;
CityConvert convert = new CityConvert();
public Processing(string s_incomingPath)
{
BackgroundWorker bg_Taxes = new BackgroundWorker();
s_sourceFile = s_incomingPath;
//background worker
bg_Taxes.DoWork += new DoWorkEventHandler(bg_Taxes_DoWork);
bg_Taxes.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_Taxes_RunWorkerCompleted);
bg_Taxes.ProgressChanged += new ProgressChangedEventHandler(bg_Taxes_ProgressChanged);
bg_Taxes.WorkerSupportsCancellation = true;
bg_Taxes.WorkerReportsProgress = true;
InitializeComponent();
bg_Taxes.RunWorkerAsync();
}
#region METHODS
#region BACKGROUND WORKER
//do work/runworker Async stuff
private void bg_Taxes_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bg_Taxes = sender as BackgroundWorker;
CityConvert convert = new CityConvert();
convert.ConvertFile(s_sourceFile);
}
//when the worker completes, let user know, end program
private void bg_Taxes_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pb_Progress.MarqueeAnimationSpeed = 0;
//lets the user know the file is done and prompts them on where to save it at
if (MessageBox.Show(this, "The file has been created.\nChoose where you would like to save it.",
"Conversion Finished", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) == DialogResult.OK)
{
while (b_fileSaved != true)
{
SaveFile();
}
}
}
//used to update the progress count
public void bg_Taxes_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//RIGHT HERE IS WHAT SHOULD UPDATE THE COUNTER
lb_recordCount.Text = convert.i_RowCount.ToString();
}
#endregion
And now the class with all of the hard work:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace CityTaxImport
{
class CityConvert
{
#region VARIABLES AND OBJECTS AND ALL THE OTHER VARS AND CHARS
//the Excel squad
Excel._Application xl_app;
Excel._Workbook xl_wrkBk;
Excel._Worksheet xl_wrkSht;
//our friend object Type.Missing
private object o_miss = Type.Missing;
//dataset and table
private DataSet ds_taxes;
private DataTable dt_taxes;
private DataRow dr_taxes;
//strings and counts and stuff
private string s_sourceFile;
private int i_xlRowTotal;
private int i_xlRowCount;
private int i_dtRowCount;
private string s_output;
public int i_RowCount{get; set;}
#endregion
#region METHODS
//the initial convert file method called by the main window
public bool ConvertFile(string s_selectedFile)
{
s_sourceFile = s_selectedFile;
CreateDataSet();
OpenExcel();
PopulateDateSet();
WriteFile();
CloseExcel();
return true;
}
//builds the dataset to use
//creates the column names that will be written into and then written to the flat file
//SOME WILL JUST BE SPACES
private void CreateDataSet()
{
ds_taxes = new DataSet();
ds_taxes.Tables.Add("Taxes");
dt_taxes = new DataTable();
dt_taxes = ds_taxes.Tables["Taxes"];
dt_taxes.Columns.Add("Pr_Ward");
dt_taxes.Columns.Add("Pr_Block");
dt_taxes.Columns.Add("Pr_Map");
dt_taxes.Columns.Add("Pr_Parcel");
dt_taxes.Columns.Add("Pr_LeaseHold");
dt_taxes.Columns.Add("ParFill");
dt_taxes.Columns.Add("Stub");
dt_taxes.Columns.Add("Pa_Amt");
dt_taxes.Columns.Add("TOTFLG");
dt_taxes.Columns.Add("Pr_WardBATCH");
dt_taxes.Columns.Add("BSEQ");
dt_taxes.Columns.Add("TRANSNO");
dt_taxes.Columns.Add("TRANCD");
dt_taxes.Columns.Add("Pa_BatchDate_TD");
dt_taxes.Columns.Add("Pa_BatchDate_ED");
dt_taxes.Columns.Add("BUSDATE");
dt_taxes.Columns.Add("METH");
dt_taxes.Columns.Add("Pa_Amt2");
dt_taxes.Columns.Add("Payment_ID");
dt_taxes.Columns.Add("OWNSEQ");
dt_taxes.Columns.Add("Pr_OwnerInfo1");
}
//time to populate the dataset form the info from the ExcelSheet
private void PopulateDateSet()
{
//
i_xlRowTotal = 2;
while (xl_wrkSht.Cells.Range["A" + i_xlRowTotal].Value2 != null)
{
i_xlRowTotal++;
}
i_xlRowCount = 2;
i_xlRowTotal = i_xlRowTotal - 2;
for (i_dtRowCount = 0; i_dtRowCount < (i_xlRowTotal); ++i_dtRowCount)
{
//this is used to make conversions of the strings to add paddings, length modifiers, what have you...
//all that fun stuff
dr_taxes = dt_taxes.NewRow();
dr_taxes["Pr_Ward"] = Convert.ToString(xl_wrkSht.Cells.Cells.Range["P" + (i_xlRowCount)].Value2);
dr_taxes["Pr_Block"] = Convert.ToString(xl_wrkSht.Cells.Range["Q" + (i_xlRowCount)].Value2);
dr_taxes["Pr_Map"] = Convert.ToString(xl_wrkSht.Cells.Range["R" + (i_xlRowCount)].Value2);
dr_taxes["Pr_Parcel"] = Convert.ToString(xl_wrkSht.Cells.Range["S" + (i_xlRowCount)].Value2);
dr_taxes["Pr_LeaseHold"] = Convert.ToString(xl_wrkSht.Cells.Range["T" + (i_xlRowCount)].Value2);
dr_taxes["ParFill"] = #" ";//12 spaces
dr_taxes["Stub"] = #" ";//10 spaces ALWAYS
dr_taxes["Pa_Amt"] = AppendAmt();
dr_taxes["TOTFLG"] = "N";
dr_taxes["Pr_WardBATCH"] = AppendWard();
dr_taxes["BSEQ"] = AppendBSEQ();
dr_taxes["TRANSNO"] = "000000000";
dr_taxes["TRANCD"] = "P";
dr_taxes["Pa_BatchDate_TD"] = AppendBatchDates();
dr_taxes["Pa_BatchDate_ED"] = AppendBatchDates();
dr_taxes["BUSDATE"] = #" "; //6 spaces
dr_taxes["METH"] = "Check";
dr_taxes["Pa_Amt2"] = AppendAmt();
dr_taxes["Payment_ID"] = AppendID();
dr_taxes["OWNSEQ"] = "000";
dr_taxes["Pr_OwnerInfo1"] = AppendOwner();
dt_taxes.Rows.Add(dr_taxes);
++i_xlRowCount;
i_RowCount = i_xlRowCount;
//RIGHT HERE IS WHERE I WANT TO CALL THE
Processing.bg_Taxes.ReportProgress() //method
}
}
I have tried Processing.bg_Taxes.ReportProgress(); but I get the Object reference is required for the non-static...method error (which I understand what that is.)
I have also looked at a lot of other Q&As on here about the using BackgroundWorkers however none of them seem to quite answer my question or I am just not getting it (which may be the issue as well).
My questions are, then: is there a way to call that method without making my BackgroundWorker static?
And with that: is there any problem with MAKING it static (I have always been told avoid static methods and what have you when writing code).
And finally: am I missing something in my logic here about how exactly I should be going about this? Is there another more "best practice" way?
Any help or advice is appreciated.
Thank you all in advance.
UPDATE
I ended up solving my problem by just some of the essential methods over to the Form class and altering my code from there. Just wanted to throw it out there and thank everyone for pointing in me in the right directions.

Simple yet frustrating Listbox and Texbox search again

I have spent few days searching everywhere for a solution to this.
This is for C# with Visual Studio 2013 (ya, I am a newbie):
two textboxes (Last name and First Name) and a listbox with 5 names (Higgins M, Higgins J, King J, Tran A, Dempsey S). I set listbox property as sorted.
if I select Higgins J in listbox, then the word Higgins should appear in Last Name textbox and J should appear in First Name textbox.
if I type Higgins in Last Name textbox, Higgins J should be the selected item in listbox (Higgins J will be selected before Higgins M). If I type M in the First Name textbox, the selected item should change from Higgins J to Higgins M.
but....here are the problems that made me decide to create an account here:
If I type Hi or Hig instead of Higgins, it has to stay that way, it does not become Higgins in the textbox. Only the index/highlight in listbox is changed, not the entry in textbox (whatever I type in the textbox stays). I suspect the events that I use are the reason I cannot get this done. Textbox_textchanged and listbox_selectedindexchanged. So whatever I do in one event will automatically triggers the other. I have tried changing the events, but so far the result simply worse. Using: if (LastName_textbox.Text = "") did not help either.
How do I combine Last Name and First Name as one index?
I apologise if this question has appeared or sounded ambiguous. I suppose I do not know how to phrase the search to get something similar to my problem and English is not my first language. Any help is very much appreciated .Thanks.
Here is part of the codes:
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project
{
public partial class frmContact : Form
{
//declare file to save all contacts
private string fileName = Directory.GetCurrentDirectory() + "\\Contacts.txt";
//create temporary file for updating and deleting contacts
private string newContacts = Directory.GetCurrentDirectory() + "\\newContacts.txt";
public frmContact()
{
InitializeComponent();
}
private void frmContact_Load(object sender, EventArgs e)
{
//create Contacts.txt if it does not exist
if (!File.Exists(fileName))
{
File.Create(fileName).Close();
MessageBox.Show("New " + fileName +" Has Been Created");
tbLast.Select();
}
//if file already exists
else
{
StreamReader readOb = new StreamReader(fileName);
using (readOb)
{
while (!readOb.EndOfStream)
{
string rdLine = readOb.ReadLine(); //read data in file by line
string[] tmpArr = rdLine.Split(',');
lbContact.Items.Add(tmpArr[0] + "," + tmpArr[1]);
}
tbLast.Select();
}
}
}
private void lbContact_SelectedIndexChanged(object sender, EventArgs e)
{
//show details of contact selected in listbox
string findNames = lbContact.GetItemText(lbContact.SelectedItem);
StreamReader obRead = new StreamReader(fileName);
using (obRead)
{
while (!obRead.EndOfStream)
{
string rdLine = obRead.ReadLine();
if (rdLine.StartsWith(findNames))
{
string[] tmpArr = rdLine.Split(',');
tbLast.Text = tmpArr[0];
tbFirst.Text = tmpArr[1].Trim();
tbAddr.Text = tmpArr[2].Trim();
tbSub.Text = tmpArr[3].Trim();
tbPost.Text = tmpArr[4].Trim();
tbEmail.Text = tmpArr[5].Trim();
tbPhone.Text = tmpArr[6].Trim();
tbMob.Text = tmpArr[7].Trim();
}
}
lbContact.SelectedIndex = lbContact.FindString(findNames);
}
}
private void tbLast_TextChanged(object sender, EventArgs e)
{
lbContact.SelectedItem = lbContact.FindString(tbLast.Text);
}
A simple (but kind of ugly solution) would consist in using a boolean value to inform your lbContact_SelectedIndexChanged method that the index was manually changed thanks to the code. A class member would do the job, something like:
private bool fromCode;
private void lbContact_SelectedIndexChanged(object sender, EventArgs e)
{
if (fromCode)
return;
// Do the job
}
private void tbLast_TextChanged(object sender, EventArgs e)
{
fromCode = true;
lbContact.SetSelected(lbContact.FindString(tbLast.Text), true);
fromCode = false;
}
[Personal remark]
I would also create a Contact struct/class to store your information along with a collection in your form so that you only have to access your file twice:
At loading, so that you can populate your collection
At closing, so that you can save the changes to your file
[Update]
My last remark can be not relevant as I do not have the context in which you are developing your application, that's why I said it was a personal point of view, you don't have to do it.
[Update 2]
What you can do to avoid access your file each time your lbContact_SelectedIndexChanged event is called:
Create a structure or a class to store your contacts information (firstname, lastname, adress, ...)
Create a collection (as a class member of your form) that will contain the contacts (like a List<Contact>)
In your frmContact_Load method, fill this collection with the data contained in the file instead of populating your listbox
So that in your lbContact_SelectedIndexChanged method you will search inside the collection instead of opening your file
Your Add() and Delete() operations must also modify the collection and not the file anymore
Remember to save your collection back to your file at application closing
Hope it helped.
I found the solution (for whoever encounters similar problem), the answer is in the textbox.focused :) and combined with listbox.setselected from Tim.
private void tbLast_TextChanged(object sender, EventArgs e)
{
if (tbLast.Focused && tbLast.Text != "")
{
if (lbContact.FindString(tbLast.Text) > -1)
{
lbContact.SetSelected(lbContact.FindString(tbLast.Text), true);
}
}
}
private void lbContact_SelectedIndexChanged(object sender, EventArgs e)
{
//show details of contact selected in listbox
string findNames = lbContact.GetItemText(lbContact.SelectedItem);
StreamReader obRead = new StreamReader(fileName);
using (obRead)
{
while (!obRead.EndOfStream)
{
string rdLine = obRead.ReadLine();
if (rdLine.StartsWith(findNames))
{
string[] tmpArr = rdLine.Split(',');
if (!tbLast.Focused)
{
tbLast.Text = tmpArr[0];
tbFirst.Text = tmpArr[1].Trim();
tbAddr.Text = tmpArr[2].Trim();
tbSub.Text = tmpArr[3].Trim();
tbPost.Text = tmpArr[4].Trim();
tbEmail.Text = tmpArr[5].Trim();
tbPhone.Text = tmpArr[6].Trim();
tbMob.Text = tmpArr[7].Trim();
}
}
}
lbContact.SelectedIndex = lbContact.FindString(findNames);
}
}

C# How to program find function

I have a C# program that utilizes a find function however it is able to find the word but does not highlights the found word in the richTextBox.
Can someone please advise me on the codes?
Thanks.
Find Function Class Form:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Syscrawl
{
public partial class Find_Form : Form
{
FTK_Menu_Browsing_History fmbh = new FTK_Menu_Browsing_History();
public Find_Form()
{
InitializeComponent();
}
public void searchButton_Click(object sender, EventArgs e)
{
string s1 = fmbh.getSearchBrowsing().ToLower();
string s2 = textBoxSearch.Text.ToLower();
if (s1.Contains(s2))
{
MessageBox.Show("Word found!");
this.fmbh.richTextBoxBrowsing.Find(s2);
this.fmbh.richTextBoxBrowsing.SelectionLength = s2.Length;
this.fmbh.richTextBoxBrowsing.SelectionColor = Color.Red;
this.Close();
}
else
{
MessageBox.Show("Word not found!");
}
}
}
}
You need to select what you are looking for first. This:
int offset = s1.IndexOf(s2);
richTextBox1.Select(offset, s2.Length);
After that you can make the whole highlightining. Another tip, to prevent the flickering in the selection process, use this code in your form:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0) {
if (!_doPaint)
return;
}
base.WndProc(ref m);
}
Before selecting anything set _doPaint to false and after the selection set it to true.
Hope I can help!
You need to call s1.IndexOf(s2, StringComparison.CurrentCultureIgnoreCase) to find the position of the match.
Also, it looks like your Find form creates its own instance of the History form; it doesn't use the existing instance.
You should consider accepting a constructor parameter.

Categories

Resources