C# - Arrays - Enter Names and display them - c#

here is my code that works.
1. Except after hitting Show Names button (after entering names) that stored in Array, display textbox scroll bar jump down and have to pull it up to see entered names.
2. Also, after I continue entering names(after entering few), I get line breaks (in show Names textbox) and entered names are shown repeated. It should display the names after the last entered one without repeating the previously entered names and line breaks.
Any ideas what is causing it?
my code:
namespace Arrays
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
//initialize the Array
string[] names = new string[100];
int index = 0;
//Enter Names up to 100 and store them in array
private void btnEnterName_Click(object sender, EventArgs e)
{
if (index < names.Length)
{
names[index++] += txtName.Text;
txtName.Clear();
}
else
{
// array 'full'
}
}
//Display stored Names in Array using foreach loop in multiline textbox
private void btnShowNames_Click(object sender, EventArgs e)
{
txtName.Clear();
foreach (string item in names)
{
txtNames.AppendText(item + Environment.NewLine);
}
}
}
}

For the scrollbar problem, setting the Text instead of using AppendText will resolve the issue:
//Display stored Names in Array using foreach loop in multiline textbox
private void btnShowNames_Click(object sender, EventArgs e)
{
string allNames = "";
foreach (string item in names)
{
allNames += item + Environment.NewLine;
}
txtNames.Text = allNames;
// or more advanced
//txtNames.Text = string.Join(names, Environment.NewLine);
}
Line breaks should happens if you hit the button without entering a name in it. Test the presence of the Text before adding it:
//Enter Names up to 100 and store them in array
private void btnEnterName_Click(object sender, EventArgs e)
{
// remove spaces at start and end
string trimedName = txtName.Trim();
bool nameExist = !string.IsNullOrEmpty(trimedName);
bool notHittingMaxName = index < names.Length;
if (nameExist && notHittingMaxName)
{
names[index++] += trimedName;
txtName.Clear();
}
else
{
// array 'full' or empty name
}
}

Related

How to check if ListBox contains same text as another ListBox

I have 2 Listbox and I want to check the first Listbox text so that I can add them to the second Listbox. Like, let's say that I have a car registration plate on the first Listbox ( 02-TH-93 ) and now I want to add on my second Listbox that same plate ( 02-TH-93 ) BUT if that plate doesn't exist on the first ListBox then it should just show a message error.
For example:
ListBox1:
02-TH-93
|
06-JK-58
|
07-HJ-95
|
02-FG-56
ListBox2:
02-TH-93
|
06-JK-58
|
07-HJ-95
|
45-ER-01 (Show message error now because there's no match of this registration plate on listbox1)
I tried this but it doesn't really make a lot of sense I guess:
parking.Entrance = textBoxEntrance.Text;
parking.Exit = textBoxExit.Text;
if(parking.Entrance == parking.Exit)
{
listBoxExit.Items.Add("Plate: " + parking.Exit + " Exited ");
}
Thanks
So if I have now understood correctly, this should work after your wishes. If you do not understand something, just ask again!
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace plateManager
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button_LB1_Click(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(txtbox1.Text))
lb1.Items.Add(txtbox1.Text);
else
MessageBox.Show("Please enter something!");
txtbox1.Text = "";
}
private void button_LB2_Click(object sender, EventArgs e)
{
//Asks if the textbox is empty or has space
if (!string.IsNullOrWhiteSpace(txtbox2.Text))
{
List<string> allPlates = new List<string>();
/*The list box will be read from top to bottom
and will add each entry in this list box to the list called "allPlates".*/
for (int i = 0; i < lb1.Items.Count; i++)
allPlates.Add(lb1.Items[i].ToString());
if (ExistsCheck(txtbox2.Text, allPlates))
lb2.Items.Add(txtbox2.Text);
else
MessageBox.Show("This license plate was not found!");
}
else
MessageBox.Show("Please enter something!");
//Reset the textbox
txtbox2.Text = "";
}
private bool ExistsCheck(string newPlate, List<string> allPlates)
{
//Each entry will be checked if it matches, if it does, the boolean is set to true and will be returned afterwards.
bool result = false;
foreach (var plate in allPlates)
if (plate.Equals(newPlate))
result = true;
return result;
}
}
}
I assume that your Listbox.ItemsSource is a list of strings so you could just loop through one of those lists and look for a match like this:
private bool IsInFirst(string plateToAdd, List<string> plates)
{
foreach(string plate in plates)
{
if (plate.Equals(plateToAdd))
{
return true;
}
}
return false;
}
If it returns true the list contains the plate to add and if it returns false it doesn't. This tutorial helped me.
I have created a variate as I understand it, so it asks if the "plate" is present in lb1. If yes then add it if not ignore it and make a message box
private bool ExistsCheck(string newPlate, List<string> allPlates)
{
bool result = false;
foreach (var plate in allPlates)
if (plate.Equals(newPlate))
result = true;
return result;
}
private void AddAndCheck_Click(object sender, EventArgs e)
{
List<string> allPlates = new List<string>();
for (int i = 0; i < lb1.Items.Count; i++)
allPlates.Add(lb1.Items[i].ToString());
if (ExistsCheck(tb_plate.Text, allPlates))
{
// If its return False
lb2.Items.Add(tb_plate.Text);
}
else
{
// If its return True
MessageBox.Show("It is not present in listbox 1");
}
}

How depending the selected value of a combobox, i can allow in a numericupdown the value to be >= 0?

Example
I have a combobox with a list of 3: entry, exit and transfer and a numericupdown called: txtTotal that starts in 0
when i select entry or exit should show error missing total but if a select transfer should allow you to continue even if its 0 or another number
If you want to show error missing total when you select entry or exit and allow you to continue even if txttotal shows 0 or another number when you select transfer, you could refer to the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.Items.Add("Entry");
comboBox1.Items.Add("Exit");
comboBox1.Items.Add("Transfer");
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.Text == "Entry" || comboBox1.Text == "Exit")
{
MessageBox.Show("Error missing total is " + txtTotal.Text);
}
if (comboBox1.Text == "Transfer")
{
// You should replace this code with what you want to do
string FileToRead = "the path of txt file";
string[] lines = File.ReadAllLines(FileToRead);
foreach (string str in lines)
{
if (str == "2")
{
txtTotal.UpButton();
}
}
}
}
}

ListView.FindItemWithText inside WHILE loop fails after first ListView line

I want change the content of 2nd column of each line of ListView with diferents data according with is found via FindItemWith.
My trouble is that from of 2nd line is be overriding the previous columns, for example when i want change the content searching a text that stays on first line works fine, see:
Already when i want change the content searching a text that stays on second line this happens:
This is the code:
public void fillData(string search, string data, ListView haystack)
{
if (haystack.Items.Count > 0)
{
int idx = 0;
ListViewItem found;
while (idx < haystack.Items.Count)
{
found = haystack.FindItemWithText(search, true, idx);
if (found != null)
{
haystack.Items[idx].SubItems[1].Text = data.ToString();
}
idx++;
}
}
}
private void button3_Click(object sender, EventArgs e)
{
int i = 0;
while (i < 3)
{
ListViewItem item = new ListViewItem();
item.Text = i.ToString();
item.SubItems.Add("192.168.0." + i.ToString());
listView1.Items.Add(item);
i++;
}
}
private void button1_Click(object sender, EventArgs e)
{
fillData("192.168.0.0", "AAA", listView1);
}
private void button2_Click(object sender, EventArgs e)
{
fillData("192.168.0.1", "BBB", listView1);
}
This is because the overload function you used for FindItemWithText, keeps searching all the items from the index you passed in.
When the loop has idx = 0 then FindItemWithText will try to search all three items 0,1,2.
When the loop has idx = 1 then FindItemWithText will try to search two items 1,2.
When the loop has idx = 2 then FindItemWithText will try to search only one item 2.
So now in the first case, As you are searching for first item, your loop found it only once. But where as in second case you are searching for second item, it was found twice both (idx = 0 ---- 0,1,2) and (idx = 1 ---- 1,2) iterations. So you are updating two values both for idx=0 and idx = 1.
Here is the documentation link
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.listview.finditemwithtext?view=netframework-4.7.2#System_Windows_Forms_ListView_FindItemWithText_System_String_System_Boolean_System_Int32_
Any how FindItemWithText returns the System.Windows.Forms.ListViewItem. Just search once from zero. Use that item to update.

How to make winforms textbox autocomplete correct capitalisation?

Using a winforms textbox with autocomplete set to SuggestAppend I can type out part of a string and the rest will be suggested to me fine.
If a user types "smi" looking for "Smith, John" and then autocompletes the rest of the string by tabbing then the textbox contains "smith, John". But, if the user clicks on the name then the capitalisation is correct.
Is there a way I can get the autocomplete to re-capitalise the user inputted part of the string when the suggestion is accepted by tabbing?
Pressing tab leads to:
Clicking name leads to (this is what I want):
To handle this situation I handled the textbox Leave event. The idea is to split the text by comma, uppercase the first letter of the resulting strings, then join the strings back together.
private void textBox1_Leave(object sender, EventArgs e)
{
string[] strings = this.textBox1.Text.Split(new char[] { ',' });
for (int i = 0; i < strings.Length; i++)
{
strings[i] = string.Format("{0}{1}", char.ToUpper(strings[i][0]), strings[i].Substring(1));
}
this.textBox1.Text = string.Join(",", strings);
}
Here's the function I came up with the end, it replaces the textbox's content with a line from the AutoCompleteCustomSource of the textbox (sorted alphabetically).
So, this will still work for any case (e.g if user entered "aLLeN" it would still correct to "Allen,Charlie (ID:104)"
private void fixContent()
{
String text = txtAutoComplete.Text;
List<String> matchedResults = new List<String>();
//Iterate through textbox autocompletecustomsource
foreach (String ACLine in txtAutoComplete.AutoCompleteCustomSource)
{
//Check ACLine length is longer than text length or substring will raise exception
if (ACLine.Length >= text.Length)
{
//If the part of the ACLine with the same length as text is the same as text, it's a possible match
if (ACLine.Substring(0, text.Length).ToLower() == text.ToLower())
matchedResults.Add(ACLine);
}
}
//Sort results and set text to first result
matchedResults.Sort();
txtAutoComplete.Text = matchedResults[0]
}
Thanks to OhBeWise I attached this to the textbox leave event:
private void txtAutoComplete_Leave(object sender, EventArgs e)
{
fixContent();
}
But also I needed to cover situations when the autocomplete has been accepted which occur when enter, tab, left and right are pressed. Attaching this to the keydown event doesn't work because I think the autocomplete captures the event beforehand, so I attached to the previewkeydown event:
private void txtAutoComplete_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
Keys key = (Keys)e.KeyCode;
if (key == Keys.Enter || key == Keys.Tab || key == Keys.Left || key == Keys.Right)
{
fixContent();
}
}
simple ;
private void textbox_TextChanged(object sender, EventArgs e)
{
AutoCompleteStringCollection a = new AutoCompleteStringCollection();
a = textbox.AutoCompleteCustomSource;
for (int i = 0; i < a.Count; i++)
{
if (a[i].ToLower() == textbox.Text.ToLower())
{
textbox.Text= a[i].ToString();
break;
}
}
}

How do I copy certain rows from a csv file into a new file using C#?

I am using C# to make a small application that automates some manual processes. I have a CSV file, I must search the second column (which has the name "Status"), if the status is "clear" then I do not need this row, else I need to copy this row into another file and save the aggregated file. Additionally, I would also like to know how to delete (automatically) certain columns of a csv file in c#. Here is what I have thus far: (The first button is "Show Original" while the second is "Alter and Save"
namespace AppExcel
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static List<string[]> ReadAndParseData(string path, char separator )
{
var parsedData = new List<string[]>();
using (var sr = new StreamReader(path))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] row = line.Split(separator);
string[] column = line.Split('\n');
parsedData.Add(row);
}
}
return parsedData;
}
private void DrawGridView(List<string[]> parsedData)
{
dataGridView1.ColumnCount = 47;
for (int i = 0; i < 47; i++)
{
var sb = new StringBuilder(parsedData[0][i]);
sb.Replace('_', ' ');
sb.Replace("\"", "");
dataGridView1.Columns[i].Name = sb.ToString();
}
foreach (string[] row in parsedData)
{
dataGridView1.Rows.Add(row);
}
dataGridView1.Rows.Remove(dataGridView1.Rows[0]);
}
private void button1_Click(object sender, EventArgs e)
{
List<string[]> parsedData = ReadAndParseData(#"C:/Export Data.csv", ',');
DrawGridView(parsedData);
}
private void button2_Click(object sender, EventArgs e)
{
List<string[]> parsedData = ReadAndParseData(#"C:/Export Data.csv", ',');
foreach (string[] row in parsedData)
{
if (row != parsedData[0])
{
// What to insert here??
}
}
}
private void button3_Click(object sender, EventArgs e)
{
}
}
}
You can simply do (if your file is not really huge : in that case you'll have to work with a streamreader)
var retainedLines = File.ReadAllLines(#"C:/Export Data.csv")
.Skip(1) // if you have an header in your file and don't want it
.Where(x => x.Split(',')[1] != "clear");//don't take the lines with "clear" in second column
if you wanna keep the first line (headers), you may do
var retainedLines = File.ReadAllLines(#"C:/Export Data.csv")
.Where((x, i) => i == 0 || x.Split(',')[1] != "clear");//i is the index, so the first line will have i == 0
then save to another file
File.WriteAllLines(<targetPath>, retainedLines);
if you wanna remove lines in the same file, your targetPath must just be the existing one...
One liner to read file, go over lines, split into columns, check for Clear, and then write output.
File.WriteAllLines(outPath,
File
.ReadAllLines(inPath)
.Where(line => !line.Split(seperator)[colNum].Equals("clear")));

Categories