I am trying to write a c# program to make a Bank system with users creating bank accounts. And I want to be able to save these accounts given through the console to an excel file so it can retrieve them later if needed.
I followed a tutorial on how to do that and made minor adjustments to the code but when I try to run the program with some test accounts it writes them as blank accounts with no data and I can't see why it would do this.
public class Account
{
protected static int count = 1;
protected int accountNum;
protected string fName;
protected string lName;
protected int idNumber;
protected string address;
protected DateOnly birthday = new();
protected bool flag;
Savings.SpendingRef = Spendings(accountNum);
public Account(string fn, string ln, int idnum, string add, DateOnly bd)
{
//System.Threading.Interlocked.Increment(ref count);
this.accountNum = count++;
fName = fn;
lName = ln;
idNumber = idnum;
address = add;
birthday = bd;
flag = false;
}
public int AccountNum{get;}
public string FName{get; set;}
public string LName{get; set;}
public int IdNumber{get; set;}
public string Address{get; set;}
public DateOnly Birthday{get;}
public bool Flag{get; set;}
public string GetAccount(){
string s = "--------------------------------\n";
s += "Account Number :" + accountNum + "\nAccount belonging to :" + fName + " " + LName + "\nID Number :" + IdNumber + "\nAddress :" + address + "\nBirthday : " + birthday + "\nAccount blocked? :" + flag;
s += "\n--------------------------------\n";
Console.WriteLine(s);
return s;
}
}
Here is how the account class is implemented
static async Task Main(string[] args)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
var file = new FileInfo(#"..\..\..\SavedAccounts.XLSX");
//Other code not important
var Accounts = GetSetupData();
await SaveExcelFile(Accounts, file);
}
private static List<Account> GetSetupData()
{
List<Account> output = new()
{
new Account("Jerome", "Dupret", 42069, "68 rue des ecoles", new DateOnly(1999, 08, 10)),
new Account("Deborah", "Pierre", 69420, "68 rue des ecoles", new DateOnly(2000, 02, 18)),
};
return output;
}
Here are the test accounts I want to be inserted.
private static async Task SaveExcelFile(List<Account> accounts, FileInfo file)
{
DeleteIfExists(file);
using var package = new ExcelPackage(file);//basically a Dispose method to get rid of any useless data
var ws = package.Workbook.Worksheets.Add("AccountData");
var range = ws.Cells["A1"].LoadFromCollection(accounts, true);
range.AutoFitColumns();
await package.SaveAsync();
}
And this is where the call and the write function itself happen.
I used console Writes at every step to check if the accounts lose info at any time but they never do, I'm confused as to why it isn't sent properly.
It looks like you never set your public properties such as Fname, either you need to set them in the constructor or make the getter get the protected field.
for example
protected string fName;
public string FName
{
get
{
return fName;
}
set
{
fName = value;
}
}
This needs to be done on all the public fields so they all get the field that gets set in the constructor.
The set is not required but if you dont use it FName and fName can become diffrent values since fName is only set in the constructor.
Related
I am using the following Code
public class GetTabelRealizari : ControllerBase
{
public class Realizare
{
String user;
String denumire;
String incasari;
public Realizare(String user, String denumire, String incasari)
{
this.user = user;
this.denumire = denumire;
this.incasari = incasari;
}
public String getUser()
{
return user;
}
public void setUser(String user)
{
this.user = user;
}
public String getDenumire()
{
return denumire;
}
public void setDenumire(String denumire)
{
this.denumire = denumire;
}
public String getIncasari()
{
return incasari;
}
public void setIncasari(String incasari)
{
this.incasari = incasari;
}
}
[HttpPost]
public string Post([FromBody] string[] value)
{
//SSMS connection
string connectionString = "Data Source=DESKTOP-QKC0G7V;Initial Catalog=Restaurant_gest;Integrated Security=True";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
List<Realizare> realizari = new List<Realizare>();
double incasari;
String incasariString;
SqlCommand command = new SqlCommand("SELECT Users.Username," +
" Tip_Nota_Plata.Denumire," +
" sum(Nota_plata.Suma) as Incasari" +
" from Users" +
" INNER JOIN Nota_plata" +
" INNER JOIN Comandas" +
" ON Nota_plata.Id_comanda = Comandas.Id" +
" ON Comandas.User_Id = Users.Id" +
" INNER JOIN Tip_Nota_Plata" +
" ON Tip_Nota_Plata.Id = Nota_plata.Id_tip_nota" +
" Group by Username, Tip_Nota_Plata.Denumire", connection);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
incasari = (double)reader["Incasari"];
incasariString = incasari.ToString("#.##");
realizari.Add(new Realizare(reader["Username"].ToString(), reader["Denumire"].ToString(), incasariString));
}
}
return JsonConvert.SerializeObject(realizari);
//return "salut";
}
}
And I am receiving an empty JsonObject. Why?
[{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}]
I keep trying to make it work and I cannot. The list has the objects, i can test it with Console.Writeline(realizari[0].getDenumire()) and it works. I can also serialize a list of strings, it just doesn`t work for objects.
Because the object has no serializable properties.
I'm going to guess you are a Java developer based on this:
String user;
public String getUser()
{
return user;
}
public void setUser(String user)
{
this.user = user;
}
C# has "properties" which, while they compile down to methods very similar to this, the syntax in C# is a bit different. All of the above code can be simplified to a property:
public String User { get; set; }
The usage then becomes simpler as well, allowing for assignments instead of calling a method:
someObject.User = someUser;
In cases where you want to add logic to your getter/setter, you can expand the "auto implemented property" above into a manual one:
private string user;
public string User
{
get { return user; }
set { user = value; }
}
The get and set syntax still tells the compiler that this is a property, but within those blocks you can write any method logic you like. (In the setter value is a keyword for the value being assigned to the property.)
I'm accessing a value object as follows: accounts[accountNum]
I want to do some minor manipulation on this object, ie: increase it by something, etc. Rather than typing "accounts[accountNum] += something" I'd rather do something like this:
MemberData account = accounts[accountNum];
account.balance += something;
Ie: "account" should be a direct pointer, reference, or somehow "be equivalent to" typing "accounts[accountNum]". But since this is a value type and not a reference type, it makes a copy and I cannot manipulate that object directly.
All my research on using "ref" seems to talk about using it within method parameters and return types, not in variables. Is there a simple way to shortcut a long variable name whilst still referencing the same object?
UPDATE:
Full source code - Please see specifically Line 46 & 51
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
/* * Description of the project:
* To implement an ATM machine which accepts deposits, withdrawals
* DEPOSIT / WITHDRAWAL:
* Account, Amount, Timestamp, TransactionID, Location
* Keep record of all accounts in TXT file, which is updated after each transaction. Of course in live system DB would be used.
* Keep another file that logs all transactions. Make it possible to LINQ the log associated with account, to show transaction history.
* TXT Accounts in form of:
* Account #, Name, Balance
* */
namespace ATMProject
{
class Program
{
static void Main(string[] args)
{
// Globals.DisplayAccounts();
// Deposit.MakeDeposit(1000009, 500, "sydney");
}
}
static class Deposit
{
//TODO Deposit: * Account #, Amount, Timestamp, TransactionID, Location
public static void MakeDeposit(long accountNum, long amount, string location)
{
string timestamp;
string transactionID;
timestamp = DateTime.Now.ToString("yyyyMMddhhmm");
transactionID = Globals.GenerateValidTransactionID();
using (StreamWriter sr = new StreamWriter(Globals.transactions, true))
{
string transactString = $"DEPOSIT| {accountNum}| {amount}| {timestamp}| {transactionID}| {location}";
sr.WriteLine(transactString);
}
Globals.WriteTransactionID(transactionID);
Dictionary<long, MemberData> accounts = Globals.GenerateAccounts();
try
{
//WORKS
MemberData account = accounts[accountNum];
account.balance += amount;
accounts[accountNum] = account;
//DOESN'T BUILD
//ref MemberData account = ref accounts[accountNum];
}
catch (KeyNotFoundException)
{
Console.WriteLine("Deposit failed, selected account number does not exist in accounts.txt");
}
}
}
static class Withdraw
{
}
static class CreateAccount
{
public static void Create(string name, long StartDeposit)
{
long accountNumber;
using (StreamReader sr = new StreamReader(Globals.accountIter))
{
accountNumber = Convert.ToInt64(sr.ReadLine());
sr.Close();
}
using (StreamWriter sr = new StreamWriter(Globals.accounts, true))
{
string accountAdd = $"{accountNumber}| {name}| {StartDeposit}";
sr.WriteLine(accountAdd);
Globals.SetNextAccountNumber();
Console.WriteLine("Successfully created account #" + accountNumber);
sr.Close();
}
}
}
struct MemberData
{
public long accountNum;
public string name;
public long balance;
public MemberData(long accountNum, string name, long balance)
{
this.accountNum = accountNum;
this.name = name;
this.balance = balance;
}
public override string ToString()
{
string thisStr = $"Account #: {accountNum}, Name: {name}, Balance: {balance}";
return thisStr;
}
}
static class Globals
{
public static string basepath = "C:\\Users\\root\\RiderProjects\\ConsoleApp1\\ATMProject\\";
public static string accounts = basepath + "accounts.txt"; //path to all accounts
public static string transactions = basepath + "transactions.txt"; //path to all accounts
public static string accountIter = basepath + "accountIter.txt"; //path to the current account iter
public static string transactIter = basepath + "transactIter.txt"; //path to the current account iter
//class values
public static long GetNextAccountNumber() //returns the next available account #
{
try
{
using (StreamReader sr = new StreamReader(accountIter))
{
long currAccountIter = Convert.ToInt64(sr.ReadLine());
sr.Close();
return currAccountIter;
}
}
catch (IOException e)
{
Console.WriteLine(e.Message);
return -1;
}
}
public static void SetNextAccountNumber() //increments the account #
{
long currAccountIter = GetNextAccountNumber();
if (currAccountIter == -1)
{
Console.WriteLine("Could not SetNextAccountNumber");
return;
}
using (StreamWriter sr = new StreamWriter(accountIter, false))
{
currAccountIter += 1;
sr.WriteLine(currAccountIter);
sr.Close();
}
}
public static Dictionary<long, MemberData> GenerateAccounts() //Returns Dictionary in form of <Account Number, MemberData>
{
Dictionary<long, MemberData> memberList = new Dictionary<long, MemberData>();
using (StreamReader sr = new StreamReader(accounts))
{
while (!sr.EndOfStream)
{
var memberSplit = sr.ReadLine().Split("| ", StringSplitOptions.RemoveEmptyEntries);
long accountNum = Convert.ToInt64(memberSplit[0]);
string name = memberSplit[1];
long balance = Convert.ToInt64(memberSplit[2]);
MemberData member = new MemberData(accountNum, name, balance);
memberList.Add(accountNum, member);
}
}
return memberList;
}
public static void DisplayAccounts()
{
Console.WriteLine("List of all Accounts:\n===========");
foreach (var member in GenerateAccounts())
{
Console.WriteLine(member.Value);
}
}
public static string GetTimestamp()
{
string timestamp = DateTime.Now.ToString("yyyyMMddhhmmss");
return timestamp;
}
private static string GetTransactionIter()
{
using (StreamReader sr = new StreamReader(transactIter))
{
string transactionID = sr.ReadLine();
sr.Close();
return transactionID;
}
}
public static string GenerateValidTransactionID()
{
string IDPart;
string timestamp = GetTimestamp();
string transactionID = GetTransactionIter();
string numberSlice = transactionID.Substring(14);
string timestampSlice = transactionID.Substring(0, 14);
if (timestamp == timestampSlice)
{
IDPart = Convert.ToString(Convert.ToInt64(numberSlice) + 1);
transactionID = timestamp + IDPart;
}
else
{
transactionID = timestamp + 0;
}
return transactionID;
}
public static void WriteTransactionID(string transactionID) //overwrite and write current transactionID to iter
{
using (StreamWriter sr = new StreamWriter(transactIter, false))
{
sr.WriteLine(transactionID);
sr.Close();
}
}
public static void GenereateAndWriteTransactionID()
{
WriteTransactionID(GenerateValidTransactionID());
}
}
}
Since C# 7 you can use local ref variables:
ref int niceName = ref localVariable.Values.SubArray.Here;
niceName += 20;
Note that you can not use this in async methods. And it does neither work with properties nor indexers (except for arrays).
I am looking for the solution to save and reload what I enter into my text boxes or what I filled in my ComboBoxes. Here is the code I current have, but I am not 100% sure it is all correct. I am only posting the code I need help with. If you need the entire batch of code I can post it, but I did not think it was relevant to what I am asking for. This is what I have done so far, which I am not sure it will actually save the info that is typed in, and I am completely unsure as to what to put in the loadLastBtn method. I Just want it to be saved to memory even when the textbox texts have changed and then I want to be able to retrieve that from memory when I hit the loatLastbtn.
private void submitBtn_Click(object sender, EventArgs e)
{
List<Members> lstMembers = new List<Members>();
if (string.IsNullOrEmpty(firstNameTxt.Text) || string.IsNullOrEmpty(lastNameTxt.Text)
|| string.IsNullOrEmpty(userNameTxt.Text) ||
string.IsNullOrEmpty(passwordTxt.Text) || string.IsNullOrEmpty(confPassTxt.Text)
|| string.IsNullOrEmpty(majorBox.Text) || string.IsNullOrEmpty(specialtyBox.Text))
{
MessageBox.Show("You must enter in all fields before moving forward");
}
else
{
//would this save my data to the array and how can I reload this?
Members m1 = new Members(firstNameTxt.Text, lastNameTxt.Text, userNameTxt.Text,
passwordTxt.Text, confPassTxt.Text, majorBox.Text,
specialtyBox.Text);
lstMembers.Add(m1);
}
}
private void loadLastBtn_Click(object sender, EventArgs e)
{
for(int i = 0; i < lstMembers.Count; i++)
{
firstNameTxt.Text = lstMembers[i].FirstName;
lastNameTxt.Text = lstMembers[i].LastName;
userNameTxt.Text = lstMembers[i].UserName;
passwordTxt.Text = lstMembers[i].Password;
confPassTxt.Text = lstMembers[i].ConfPassword;
majorBox.Text = lstMembers[i].Major;
specialtyBox.Text = lstMembers[i].Specialty;
}
}
Here is the user object I created. I am just unsure how to call it now when I want to save and reload.
class Members
{
private string firstName;
private string lastName;
private string userName;
private string password;
private string confPassword;
private string major;
private string specialty;
public Members(string firstName, string lastName, string userName, string password,
string confPassword, string major, string specialty)
{
this.firstName = firstName;
this.lastName = lastName;
this.userName = userName;
this.password = password;
this.confPassword = confPassword;
this.major = major;
this.specialty = specialty;
}
public string FirstName
{
get
{
return firstName;
}
set
{
FirstName = firstName;
}
}
public string LastName
{
get
{
return lastName;
}
set
{
LastName = lastName;
}
}
public string UserName
{
get
{
return userName;
}
set
{
UserName = userName;
}
}
public string Password
{
get
{
return password;
}
set
{
Password = password;
}
}
public string ConfPassword
{
get
{
return confPassword;
}
set
{
ConfPassword = confPassword;
}
}
public string Major
{
get
{
return major;
}
set
{
Major = major;
}
}
public string Specialty
{
get
{
return specialty;
}
set
{
Specialty = specialty;
}
}
I would suggest creating a 'POCO' (Plain old c# object) or struct that will hold your data.
When you want to save it, just serialize it to disk (either using MS Serialization (more here, or by using JSON serialize method (more here).
This way, you don't worry about what the user might have entered (less worries about sanitizing the data and making sure he didn't use your escape character).
Well, most common way to do it without any hard implementation would be writing all of your variables with ';' between them within a file. Then read it from file and re-assign it into your form elements when user press down a button.Check this guide to how to write into file:
https://msdn.microsoft.com/en-us/library/8bh11f1k.aspx
I'll give an simple example:
For example my form consist of username and password TextFields. After user entered them and pressed login, I save them into file for next time user logs in, this method will save it.
public void save(){
String username = txtUsername.Text;
String password = txtPassword.Text;
File.WriteAllText(path, username + ";" + password);
}
public void load(){
String parameters = File.ReadAllText(path);
String[] splitted = parameters.split(';');
txtUsername.Text = splitted[0];
txtPassword.Text = splitted[1];
}
I am creating a program with two forms(register and view).
The view form will read a single record from a table(database), and then you can edit or delete the record. I am creating a class for this program, and for one of the constructors it will get the search ID, First name and last name from the view form and then there is a method which will search through the table for the record(using search ID, OR firstname and lastname) and will assign the variables inside the class, and I want to use THOSE variables for my edit and delete methods, but the problem is when I try to create a public object of the class which would be used across all my events, using 'this' keyword, it says that this doesn't exist in the current context, but whenever I create an object in each event it will recognize 'this' keyword, but I won't be able to use the class variables assigned from the search method. This is my constructor and search method for the class
public ASystem(searchSHD search)
{
searchHID = search.searchHID;
search_FName = search.searchFName;
search_LName = search.searchLName;
}
public String searchHID;
public String search_FName;
public String search_LName;
public String HID;
public String First_Name;
public String Full_Name;
public String query;
public String Last_Name;
public String PhoneNum;
public String Country;
public String DOB;
public String Experience;
public void Search()
{
using (OleDbConnection db_connection = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\KAZEM\Documents\Hairsalon\employees.accdb;
Persist Security Info=False;"))
{
if (searchHID == "")
{
query = "SELECT * FROM Hairdresser where First_Name = #FName AND Last_Name = #LName";
}
else
{
query = "SELECT * FROM Hairdresser where HID = #HID";
}
using (OleDbCommand db_command = new OleDbCommand(query, db_connection))
{
db_command.Parameters.Add("#HID", searchHID);
db_command.Parameters.Add("#FName", search_FName);
db_command.Parameters.Add("#LName", search_LName);
db_connection.Open();
OleDbDataReader reader = db_command.ExecuteReader();
reader.Read();
HID = reader.GetValue(0).ToString();
First_Name = reader.GetString(1);
Last_Name = reader.GetString(2);
Full_Name = First_Name + " " + Last_Name;
Country = reader.GetString(4);
PhoneNum = reader.GetString(5);
DOB = (Convert.ToDateTime(reader.GetValue(3))).ToString();
Experience = reader.GetValue(6).ToString();
}
}
}
you can create your own event through creating a class which is derived of EventArgs, that like:
class yourEventArgs:EventArgs
{
public yourEventArgs(object yourValues)
{
Value = yourValues;
}
//Create your properties like below
public object Value { get; set; }
}
after that you need to create an eventhandler:
public event EventHandler<yourEventArgs> YourEventName;
for raising the event you use:
if(YourEventName!=null)
{YourEventName(this,new yourEventArgs(yourValue));}
then you can add to your eventhandler your method through (the code which should be executed if you raise the event)
YourEventName+=((object o,yourEventArgs e)=> {/*-Insert Code here-*/});
//or
YourEventName+=on_yourEvent;
private void on_yourEvent(object o,yourEventArgs e)
{
/*-Insert your Code here- */
}
I hope that's what you want.
I am relatively new to C# (WinForms), and had a question regarding combo boxes. I have a combo box of Reviewer objects (it is a custom class with an overridden ToString method) and am currently attempting to go through all the checked items and use them to generate a setup file.
Here is how the combo box is populated (populated on form load). Parameters is just a collection of linked lists and parsing code.
for (int i = 0; i < parameters.GetUsers().Count; i++)
{
UserList.Items.Add(parameters.GetUsersArray()[i], parameters.GetUsersArray()[i].isSelected());
}
Here is how I am trying to read it. setup is a StringBuilder. The problem is that GetID is not defined. Does the add function above cast the Reviewer object to a Object object? It looks a little funny since it creates a file fed into a Perl script. A sample desired output line looks like this: inspector0 => "chg0306",
for (int i = 0; i < UserList.CheckedItems.Count; i++)
{
setup.AppendLine("inspector" + i.ToString() + " => \t \"" +
UserList.CheckedItems[i].GetID() + "\",");
}
Here is the users class: (Sample User is ID = aaa0000 name: Bob Joe)
public class Reviewer
{
private string name;
private string id;
private bool selected;
public Reviewer(string newName, string newID, bool newSelected)
{
name = newName;
id = newID;
selected = newSelected;
}
public string GetName()
{
return name;
}
public override string ToString()
{
//string retVal = new string(' ', id.Length + name.Length + 1);
string retVal = id + '\t' + name;
return retVal;
}
public string GetID()
{
return id;
}
public bool isSelected()
{
return selected;
}
}
For posterity, here is the Parameters class:
public class ParameterLists
{
public ParameterLists()
{
projects = new LinkedList<string>();
reviewers = new LinkedList<Reviewer>();
}
public enum FileContents {
PROJECT_LIST,
USERS_LIST,
}
public LinkedList<Reviewer> GetUsers()
{
return reviewers;
}
public LinkedList<string> GetProjects()
{
return projects;
}
public Reviewer[] GetUsersArray()
{
Reviewer[] userArray = new Reviewer[reviewers.Count];
reviewers.CopyTo(userArray, 0);
return userArray;
}
public string[] GetProjectsArray()
{
String[] projectArray = new String[projects.Count];
projects.CopyTo(projectArray, 0);
return projectArray;
}
public void LoadParameters(string fileName)
{
//Reads the parameters from the input file.
}
private void CreateDefaultFile(string fileName)
{
// Create the file from the defaultfile , if it exists.
// Otherwise create a blank default file.
}
private LinkedList <string> projects;
private LinkedList <Reviewer> reviewers;
}
I am probably missing something simple, coming from embedded C++. Any help would be appreciated.
You have to cast that object:
((Reviewer)UserList.CheckedItems[i]).GetID()