Having troubles with my math in the program - c#

When I am programming my forum, I am having troubles in differentiating the two digits of information on my csv file.
The issue is: If, there are 2 adults who are wanting to go to a place the price = less
However is it is a single adult the price will equal more.
PROBLEM: The problem that occurs is that ALL my segments think all Adults should get charged less, when some of the transaction charges should show more.
To be precise in information: The File that contains the HolidayTran.CSV has the array[3] that has the information of 1 or 2 adults in the party.
When I carry the function ref double adult is that I am carrying to the top.
Edited - This is the method that my professor at my university wants...yes slow and stupid, but its his practice final, so I am trying to figure out what I am missing.
Yes I understand i am suppose to do my own work, but I hope someone can tell me where my math is wrong in the programming.
Edited # 2 Changed the Variables to help make it clearer. I found the isolated problem, located at the If loop section, of my equation. It has been multiplying everything by two digits instead of 1. How can I create a function where if the message reads either a 1 or a 2, then the proper math would apply?
AdultPricing This function is suppose to choose the proper math, but I tend to lose concept of how to finish off the function proper. If you look at the If loop, you can see where I go wrong...Any Ideas guys?
I am trying to do a if statement bool function, but that is currently not working...I don't know what else is needed atm..
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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] myfile = File.ReadAllLines(#"C:\temp\customerinfo.csv");
var myquery = from mylines in myfile
let myfield = mylines.Split(',')
let names = myfield[1]
let lastname = myfield[2]
let id = myfield[0]
orderby lastname, names
select new { id, names, lastname };
foreach (var listing in myquery) { cmbcustomerinfo.Items.Add(listing.id + " " + listing.names + " " + listing.lastname); }
}
private void cmbcustomerinfo_SelectedIndexChanged(object sender, EventArgs e)
{
//recalling all private void information at the top of the combobox file, inorder to send information to the listbox.
string tempvariable = "";
string iddvariable = "";
string format1 = "{0,55}{1,5}";
string format2 = "{0,-5:d}{1,15:d}{2,20:c}{3,20:c}";
string format3 = "{0,-15}{1,35:c}{2,20:c}";
string format4 = "{0,-15}{1,72:c}";
getCustomerIDFirstName(out tempvariable, out iddvariable);
getcustomerinfo(iddvariable);
//set the required information to connect to the Holiday Transaction. Where we can connect if the ID found in Holiday Matchs the ID in CustomerInfo.CSV,
//then we can show the data of the dates and pricing of the information
string[] transaction = File.ReadAllLines(#"C:\temp\HolidayTrans.csv");
var TransactionQuery = from myLinesshown in transaction
let myfield2 = myLinesshown.Split(',')
let customerid = myfield2[0]
let datestart = myfield2[1]
let numofadults = byte.Parse(myfield2[2])
let numofkids = byte.Parse(myfield2[3])
where customerid == iddvariable
orderby datestart, customerid
select new
{
customerid,
datestart,
numofadults,
numofkids
};
foreach (var staff1 in TransactionQuery)
{
lstInvoice.Items.Clear();
lstInvoice.Items.Add("Purchase Date EndDate Adult Price Kid Price");
//set up all variables used or to be used.
string idgiven = "";
double KidsSubPricing = 0;
double AdultPricing = 0;
double singleddigit = 0;
double TwinAdultPricing = 0;
double totaladult = 0;
double subtotal = 0;
double subtotal1 = 0;
double kidpricing = 3300;
byte NumberOfDaysSpent = 0;
string EndofDays = "";
DateTime daybegin;
DateTime startthedate;
DateTime datebeginning = DateTime.Now;
//set the basic functionality to find the proper ID and date to be shown that corresponses to the person.
foreach (var transactionfound in TransactionQuery)
{
idgiven = transactionfound.customerid;
datebeginning = DateTime.Parse(transactionfound.datestart);
break;
}
//set the datetime interval to show the proper grouping later on
int xyy = datebeginning.Year;
//This is suppose to show where and how I can seperate the transaction of single and double pricing.
foreach (var transactionfound in TransactionQuery)
{
if (transactionfound.numofadults.ToString().Contains("1"))
{
singleddigit = transactionfound.numofadults;
}
if (transactionfound.numofadults.ToString().Contains("2"))
{
TwinAdultPricing = transactionfound.numofadults;
}
if (transactionfound.customerid == idgiven && DateTime.Parse(transactionfound.datestart).Year == xyy)
{
getpackagepriceinfo(transactionfound.datestart,ref singleddigit, ref TwinAdultPricing, ref NumberOfDaysSpent);
KidsSubPricing = transactionfound.numofkids * kidpricing;
//AdultPricing = transactionfound.numofadults * TwinAdultPricing;
subtotal += KidsSubPricing;
subtotal1 += AdultPricing;
daybegin = DateTime.Parse(transactionfound.datestart);
startthedate = daybegin.AddDays(NumberOfDaysSpent);
EndofDays = startthedate.ToString("d");
lstInvoice.Items.Add(string.Format(format2, daybegin, EndofDays, AdultPricing, KidsSubPricing));
}
else
{
lstInvoice.Items.Add(string.Format(format3, "Subtotal Amount",subtotal1, subtotal));
lstInvoice.Items.Add(" ");
getpackagepriceinfo(transactionfound.datestart,ref singleddigit, ref TwinAdultPricing, ref NumberOfDaysSpent);
KidsSubPricing = transactionfound.numofkids * kidpricing;
//AdultPricing = transactionfound.numofadults * singleddigit;
subtotal += KidsSubPricing;
subtotal1 += AdultPricing;
daybegin = DateTime.Parse(transactionfound.datestart);
startthedate = daybegin.AddDays(NumberOfDaysSpent);
EndofDays = startthedate.ToString("d");
lstInvoice.Items.Add(string.Format(format2, daybegin, EndofDays, AdultPricing, KidsSubPricing));
idgiven = transactionfound.customerid;
xyy = DateTime.Parse(transactionfound.datestart).Year;
}
if (idgiven == "")
{
lstInvoice.Items.Clear();
lstInvoice.Items.Add(string.Format(format1, "Sorry no Transaction Found For" + " ", tempvariable));
}
//else
//{
// lstInvoice.Items.Add(string.Format(format3, "Subtotal Amount", subtotal1, subtotal));
// lstInvoice.Items.Add("");
//}
}lstInvoice.Items.Add(string.Format(format3, "Subtotal Amount", subtotal1, subtotal));
}
}
private void getCustomerIDFirstName(out string tempp, out string idd)
{
string[] temp = cmbcustomerinfo.SelectedItem.ToString().Split(' ');
tempp = temp[1];
idd = temp[0];
}
private void getpackagepriceinfo(string date, ref double CostPerSingleAdult, ref double CostPerTwoAdults, ref byte numofdays1)
{
//set the information here, so we can recall the csv file into the main program.
string[] production = File.ReadAllLines(#"C:\temp\PackagePrice.csv");
var productQuery = from myLinesshown in production
let myfield1 = myLinesshown.Split(',')
let numofdays = byte.Parse(myfield1[0])
let startdateshown = myfield1[1]
let twinadult = myfield1[2]
let singlepricing = myfield1[3]
where startdateshown == date
select new
{
numofdays,
startdateshown,
twinadult,
singlepricing
};
//setting the factor of the private function doubles and bytes to be able to get recalled, back to the top.
foreach (var xyz in productQuery)
{
numofdays1 = xyz.numofdays;
CostPerTwoAdults = double.Parse(xyz.twinadult);
CostPerSingleAdult = double.Parse(xyz.singlepricing);
date = xyz.startdateshown;
break;
}
}
//redo the customer information, so we can recall the string of customer id inorder to recall proper functionality.
private void getcustomerinfo(string customerid){
string[] myfile = File.ReadAllLines(#"C:\temp\customerinfo.csv");
var myquery = from mylines in myfile
let myfield = mylines.Split(',')
let names = myfield[1]
let lastname = myfield[2]
let id = myfield[0]
where id == customerid
select new { id, names, lastname};}
}
}

Fix your variable names.
Refactor your code into smaller and tidier methods.
The problem becomes MUCH Clearer
You have a method called getpackagepriceinfo which takes the parameters
(string date, ref double adult, ref double single12, ref byte numofdays1)
where adult is costPerSingleAdult and single12 is costPerTwoAdults
When calling this method you have passed the variable singleddigit to the now renamed paramter costPerTwoAdults. What does that even mean? Did you realize you haven't used this variable within your code
Put code clarity first. When the code is easy to understand and working correctly, then you can start rewriting sections for speed/memory/reduced LoC/experimental language features/whatever other reason, when you do that write a comment showing the codes original intention so that when a bug gets written in to the new code you can find it quickly.
after edit
That's definitely an improvement. You can see now that you've got the number of adults for each transaction, but you've assigned this number into the variable used for pricing. I think you need to refer back to the specification, which I read as "if there are 2 adults and a two adult price, then charge the twin price. Else if there is no two adult price charge 2 * single adult price, else charge the adult price" your code should read the same.
Decimal adultPrice
if ( twoAdults && twinPrice > 0)
adultPrice = twinPrice;
else if ( twoAdults )
adultPrice = 2 * singlePrice;
else
adultPrice = singlePrice;
Note that this won't work if there are more than 2 adults. Not sure if that meets the specification

SO the new Coding is the following. Thanks to James Barrass I was able to properly fix the coding to work. The problem was the following
numberAdults = byte.Parse(Transaction.NumberofAdults);
if(numberAdults == 2)
adultpricing = AdultCost*2;
else
adultpricing = CostSingle;
Because of the following code above the entire coding is able to properly work now.
private void Form1_Load(object sender, EventArgs e)
{
string[] myfile = File.ReadAllLines(#"C:\temp\customerinfo.csv");
var myQuery = from mylines in myfile
let myfield = mylines.Split(',')
let CustomerID = myfield[0]
let CustomerFirstName = myfield[1]
let CustomerLastName = myfield[2]
orderby CustomerID, CustomerLastName, CustomerFirstName
select new {
CustomerID, CustomerFirstName, CustomerLastName
};
foreach (var customerinfo in myQuery) { cmbCustomer.Items.Add(customerinfo.CustomerID + " " + customerinfo.CustomerFirstName + " " + customerinfo.CustomerLastName); }
}
private void getCustomerFirstandID(out string customerfirst, out string idd)
{
string[] tempp = cmbCustomer.SelectedItem.ToString().Split(' ');
customerfirst = tempp[1];
idd = tempp[0];
}
private void getCustomerInfo(string StatedID)
{
string[] myfile = File.ReadAllLines(#"C:\temp\customerinfo.csv");
var myQuery = from mylines in myfile
let myfield = mylines.Split(',')
let CustomerID = myfield[0]
let CustomerFirstName = myfield[1]
let CustomerLastName = myfield[2]
where CustomerID == StatedID
select new
{
CustomerID,
CustomerFirstName,
CustomerLastName
};
}
private void getPackagePriceInfo(DateTime date, ref double CostofAdults, ref double CostofSingle, ref byte NumberofDaysShown)
{
string[] myGivenFile = File.ReadAllLines(#"C:\temp\PackagePrice.csv");
var myPackageTransaction = from myLinesGiven in myGivenFile
let myFieldShown = myLinesGiven.Split(',')
let NumberofDays = myFieldShown[0]
let StartDate = DateTime.Parse(myFieldShown[1])
let TwinAdult = myFieldShown[2]
let SingleAdult = myFieldShown[3]
where StartDate == date
select new {
NumberofDays, StartDate, TwinAdult, SingleAdult
};
foreach (var Package in myPackageTransaction) {
CostofSingle = double.Parse(Package.SingleAdult);
CostofAdults = double.Parse(Package.TwinAdult);
NumberofDaysShown = byte.Parse(Package.NumberofDays);
date = Package.StartDate;
break;
}
}
private void cmbCustomer_SelectedIndexChanged(object sender, EventArgs e)
{
string customerfirstvariable = "";
string iddvariable = "";
getCustomerFirstandID(out customerfirstvariable, out iddvariable);
getCustomerInfo(iddvariable);
string format1 = "{0,55}{1,5}";
string format2 = "{0,-5:d}{1,15:d}{2,20:c}{3,20:c}";
string format3 = "{0,25}{1,19:c}{2,20:c}";
string format4 = "{0,-15}{1,72:c}";
string[] myGivenFile1 = File.ReadAllLines(#"C:\temp\holidaytrans.csv");
var myHolidayTransaction = from myLinesGiven1 in myGivenFile1
let myFieldShown = myLinesGiven1.Split(',')
let CustomerGivenID = myFieldShown[0]
let PackageStartDate = DateTime.Parse(myFieldShown[1])
let NumberofAdults = myFieldShown[2]
let NumberofKids = myFieldShown[3]
where CustomerGivenID == iddvariable
orderby PackageStartDate
select new
{
CustomerGivenID, PackageStartDate, NumberofAdults, NumberofKids
};
lstInvoice.Items.Clear();
// foreach (var transactionfound in myHolidayTransaction) {
//set up all variables used or to be used.
string EndofDays = "";
DateTime daybegin;
DateTime startthedate;
DateTime datebeginning = DateTime.Now;
string idgiven = "";
double AdultCost = 0;
byte DaysUsed = 0;
double adultpricing = 0;
double KidsPricing = 0;
double KidsCost = 3300;
double subtotal = 0;
double totalamt = 0;
double subtotal1 = 0;
double total1 = 0;
double total = 0;
double CostSingle = 0;
byte numberAdults = 0;
double adultgiven = 0;
int xyz = 0;
foreach (var Transaction in myHolidayTransaction)
{
idgiven = Transaction.CustomerGivenID;
lstInvoice.Items.Add("Purchase Date EndDate Adult Price Kid Price");
datebeginning = Transaction.PackageStartDate;
xyz = datebeginning.Year;
break;
}
foreach (var Transaction in myHolidayTransaction)
{
if (Transaction.PackageStartDate.Year == xyz) {
getPackagePriceInfo(Transaction.PackageStartDate,ref AdultCost, ref CostSingle, ref DaysUsed);
KidsPricing = KidsCost * byte.Parse(Transaction.NumberofKids);
numberAdults = byte.Parse(Transaction.NumberofAdults);
if(numberAdults == 2)
adultpricing = AdultCost*2;
else
adultpricing = CostSingle;
subtotal += KidsPricing;
subtotal1 += adultpricing;
total += KidsPricing;
total1 += adultpricing;
daybegin = Transaction.PackageStartDate;
startthedate = daybegin.AddDays(DaysUsed);
EndofDays = startthedate.ToString("d");
lstInvoice.Items.Add(string.Format(format2, startthedate, EndofDays, adultpricing, KidsPricing));}
else
{
lstInvoice.Items.Add(string.Format(format3, "Subtotal Amount", subtotal1, subtotal));
lstInvoice.Items.Add(" ");
getPackagePriceInfo(Transaction.PackageStartDate, ref AdultCost, ref CostSingle, ref DaysUsed);
KidsPricing = KidsCost * byte.Parse(Transaction.NumberofKids);
numberAdults = byte.Parse(Transaction.NumberofAdults);
if (numberAdults == 2)
adultpricing = AdultCost * 2;
else
adultpricing = CostSingle;
subtotal = KidsPricing;
subtotal1 = adultpricing;
total += KidsPricing;
total1 += adultpricing;
daybegin =Transaction.PackageStartDate;
startthedate = daybegin.AddDays(DaysUsed);
EndofDays = startthedate.ToString("d");
lstInvoice.Items.Add(string.Format(format2, startthedate, EndofDays, adultpricing, KidsPricing));
idgiven = Transaction.CustomerGivenID;
xyz = Transaction.PackageStartDate.Year;
}}
if (idgiven == "")
{
lstInvoice.Items.Clear();
lstInvoice.Items.Add(string.Format(format1, "Sorry no Transaction Found For" + " ", customerfirstvariable));
}
else
lstInvoice.Items.Add(" ");
lstInvoice.Items.Add(string.Format(format3, "Subtotal Amount", subtotal1, subtotal));
lstInvoice.Items.Add(" ");
lstInvoice.Items.Add(string.Format(format3, "Total Amount", total1, total));
}
}
}

Related

read CSV file into a List of strings and then loop to identify an item

I'm just learning Windows Forms with C# and I'm having a lot of trouble rewriting my Console app into a window forms app. Here is my code in the Console App:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
const string FILENAME = #"C:\Users\annage\Desktop\SCHOOL\POS409\data.txt"; //path for CSV file
List<List<string>> EmployeesInfo = new List<List<string>>();
string inputLine = "";
StreamReader reader = new StreamReader(FILENAME);
int whileLoopRan = 0;
while ((inputLine = reader.ReadLine()) != null) //enters items into array
{
if (whileLoopRan == 0)
{
whileLoopRan++;
continue;
}
whileLoopRan = 1;
List<string> inputArray = inputLine.Split(new char[] { ',' }).ToList();//remove extra spaces
inputArray = inputArray.Select(x => x.Trim()).ToList();
EmployeesInfo.Add(inputArray);
}
List<EmployeeTaxes> EmployeeList = new List<EmployeeTaxes>();
foreach (List<string> EmployeeInfo in EmployeesInfo)
{
String employeeType;
employeeType = EmployeeInfo[5];
EmployeeTaxes employeeTaxType = new EmployeeTaxes();
employeeTaxType.GrossPay = double.Parse(EmployeeInfo[3]);
if (employeeType == ("W2"))
{
double taxes;
taxes = .07;
employeeTaxType.taxes = double.Parse(EmployeeInfo[3]) * .07;
employeeTaxType.totaltaxes = employeeTaxType.taxes * 12;
}
else if (employeeType == ("1099"))
{
}
EmployeeList.Add(employeeTaxType);
}
DisplayData(EmployeeList, EmployeesInfo);
Console.ReadLine();
}
private void DisplayData(List<EmployeeTaxes> employeeList, List<List<string>> employeesInfo)
{
for (int i = 0; i < employeeList.Count; i++)
{
List<string> Row = employeesInfo[i];
string fullName = Row[0];
string address = Row[1];
string employeeType = Row[5];
string developerType = Row[6];
EmployeeTaxes taxRow = employeeList[i];
double grossPay = taxRow.GrossPay;
double taxes = taxRow.taxes;
double totalGrossPay = taxRow.TotalGrossPay();
double annualTaxes = taxRow.totaltaxes;
double netPay = taxRow.Netpay();
Console.WriteLine("Welcome, !", fullName); // shows greeting and users name
Console.WriteLine("Address: ", address); //shows address entered
Console.WriteLine("Gross Pay: $", grossPay); // Shows gross pay entered
Console.WriteLine("Employee Type: ", employeeType);
Console.WriteLine("Monthly taxes are 7%"); ("Monthly Taxes Paid are: $" + taxes.ToString("N2")); // calculated the taxes paid monthly
Console.WriteLine("Annual Gross Pay: $" + totalGrossPay.ToString("N2")); // calulates gross pay * 12months
Console.WriteLine("Annual Taxes Paid: $" + annualTaxes.ToString("N2")); // calulates taxes * 12months
Console.WriteLine("NetPay: $" + netPay.ToString("N2"));
Console.WriteLine("Developer Type: ", developerType);
}
}
}
I am reading from a CSV .txt file and then I add it to a list of strings and I search for the "employee type" and then based on that value I loop it to do a calculation and then print out all the values.
I was able to read the csv file into a textbox in windows form, but I cannot figure out how to loop it and read the specific value and then continue with my calculation.
here is what I have for my console windows form:
public Form1()
{
InitializeComponent();
this.listBox3.SelectionMode = SelectionMode.MultiSimple;
ReadingCSVFile();
}
public void ReadingCSVFile()
{
List<List<string>> EmployeesInfo = new List<List<string>>();
string inputLine = "";
using (StreamReader sr = new StreamReader(#"C:\Users\annage\Desktop\SCHOOL\POS409\data.txt"))
{
string line;
while ((line = sr.ReadLine()) != null)
listBox3.Items.Add(line);
List<string> inputArray = inputLine.Split(new char[] { ',' }).ToList();
inputArray = inputArray.Select(x => x.Trim()).ToList();
EmployeesInfo.Add(inputArray);
}
}
private void DisplayData(List<EmployeeTaxes> employeeList, List<List<string>> EmployeesInfo)
{
for (int i = 0; i < employeeList.Count; i++)
{
List<string> Row = EmployeesInfo[i];
string fullName = Row[0];
string address = Row[1];
string employeeType = Row[5];
string developerType = Row[6];
EmployeeTaxes taxRow = employeeList[i];
double grossPay = taxRow.GrossPay;
double taxes = taxRow.taxes;
double totalGrossPay = taxRow.TotalGrossPay();
double annualTaxes = taxRow.totaltaxes;
double netPay = taxRow.Netpay();
}
}
Where can I add my loop? I tried using as much of my code in both formats, but I know console.writeline needs to be changed for windows form, but I haven't gotten that far yet.
Any assistance would be very much appreciated.
First of all it is easier to use Lambda Expressions.
So your code would look like this:
public void Test()
{
List<string> myList = new List<string>();
using (var reader = new StreamReader(#"2018-03-16.csv"))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
foreach (string item in values)
{
myList.Add(item);
}
}
}
this.FindItem(myList);
}
private void FindItem(List<string> myList)
{
// if you want the value
var match = myList.FirstOrDefault(stringToCheck => stringToCheck.Equals("your item to check"));
// if you just want to check if it exists
var match2 = myList.Any(stringToCheck => stringToCheck.Equals("your item to check"));
}

Set a string on a string referenced by string array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
string db;
ComboBox fieldBox = new ComboBox()
TextBox ValueBox = new TextBox()
ListBox dbValues = new ListBox()
private void LoadDB()
{
//Structure
string myStruct = "NAME\nAGE\nSEX\nSKILL
db = "John\t20\tMale\tNoob\n
Joe\t20\tMale\tMedium\n
Jessica\t27\tFemale\tExpert\n
John\t21\tMale\tMedium
";
//Load struct to combobox
string[] mbstr = myStruct.Split('\n');
for (int i = 0; i < mbstr.Length; i++)
{
fieldBox.Items.Add(mbstr[i]);
}
string[] db2 = db.Split('\n');
for (int i = 1; i < db2.Length - 1; i++)
{
//Display name and age in combobox
dbValues.Items.Add(db2[i].Split('\t')[0] + " - " + db2[i].Split('\t')[1]);
}
}
void ValueBoxKeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode != Keys.Enter)
return;
db.Split('\n')[dbValues.SelectedIndex].Split('\t')[fieldBox.SelectedIndex] = valueBox.Text;
MessageBox.Show("Value set: " +
db.Split('\n')[dbValues.SelectedIndex + 1].Split('\t')[fieldBox.SelectedIndex]
+ " to " + valueBox.Text + ".");
}
This is where it fails:
db.Split('\n')[dbValues.SelectedIndex].Split('\t')[fieldBox.SelectedIndex] = valueBox.Text;
I tried this, and tried to assign to db, but not working though. My original string is unchanged.
I do not want to convert to list and string back, i want to change directly.
How can i do this?
Your first problem is your string: unless you use # escaping you can't have your string cross multiple lines, and if you use # escaping you can't do \t or \n and retain their escaped meaning of tab and newline.
The second problem is a fundamental misunderstanding of the .NET string, string's are immutable. Split will create an array, there is no reference back to the original string, or the second array your splitting. You would need to do something like:
[TestClass]
public class StringTest
{
public TestContext TestContext { get; set; }
[TestMethod]
public void RewriteString()
{
var str = "Garry\t19\tMale\tNoob\n" +
"Joe\t25\tMale\tMedium\n" +
"Gary\t33\tFemale\tExpert";
var rows = str.Split('\n');
var columns = rows[0].Split('\t');
columns[0] = "Jerry";
rows[0] = string.Join("\t", columns);
str = string.Join("\n", rows);
TestContext.WriteLine(str);
}
}
Test Name: RewriteString
Test Outcome: Passed
Result StandardOutput: TestContext Messages:
Jerry 19 Male Noob
Joe 25 Male Medium
Gary 33 Female Expert
Would really hope there would be an easier way to do this, possibly with a Regex?
Now to really look at your (new) question. I have refactored exactly what you have, as I do not know your data situation I'm not entirely sure using a string as a database is a good idea: (this will compile without any references because of the use of dynamic).
public class SomeView
{
string db;
dynamic fieldBox = null;
dynamic valueBox = null;
dynamic dbValues = null;
dynamic MessageBox = null;
private void LoadDB()
{
//Structure
string myStruct = "NAME\nAGE\nSEX\nSKILL";
db = "John\t20\tMale\tNoob\n" +
"Joe\t20\tMale\tMedium\n" +
"Jessica\t27\tFemale\tExpert\n" +
"John\t21\tMale\tMedium";
//Load struct to combobox
string[] mbstr = myStruct.Split('\n');
for (int i = 0; i < mbstr.Length; i++)
{
fieldBox.Items.Add(mbstr[i]);
}
string[] db2 = db .Split('\n');
for (int i = 1; i < db2.Length - 1; i++)
{
var data = db2[i].Split('\t'); //expensive only do once
//Display name and age in combobox
dbValues.Items.Add(data[0] + " - " + data[1]);
}
}
protected string Transform(string value, int row, int column, string replacement, out string old)
{
var rows = value.Split('\n');
var columns = rows[row].Split('\t');
old = columns[column];
columns[column] = replacement;
rows[row] = string.Join("\t", columns);
return string.Join("\n", rows);
}
void ValueBoxKeyDown(object sender, dynamic e)
{
if (e.KeyCode != "enter")
return;
string old;
string newValue = this.Transform(db, dbValues.SelectedIndex, fieldBox.SelectedIndex, valueBox.Text, out old);
MessageBox.Show("Value set: " + old + " to " + valueBox.Text + ".");
}
}
So this is better:
public class SomeView
{
dynamic fieldBox = null;
dynamic valueBox = null;
dynamic dbValues = null;
dynamic MessageBox = null;
private List<Person> People = new List<Person>();
private void LoadDB()
{
//Structure
string myStruct = "NAME\nAGE\nSEX\nSKILL";
string db = "John\t20\tMale\tNoob\n" +
"Joe\t20\tMale\tMedium\n" +
"Jessica\t27\tFemale\tExpert\n" +
"John\t21\tMale\tMedium";
//Load struct to combobox
string[] mbstr = myStruct.Split('\n');
for (int i = 0; i < mbstr.Length; i++)
{
fieldBox.Items.Add(mbstr[i]);
}
People.Clear();
foreach(var row in db.Split('\n'))
{
var columns = row.Split('\t');
Person p = new Person();
p.Name = columns[0];
p.Age = int.Parse(columns[1]);
p.Sex = (Person.Sexs)Enum.Parse(typeof(Person.Sexs), columns[2]);
p.SkillLevel = (Person.SkillLevels)Enum.Parse(typeof(Person.SkillLevels), columns[2]);
People.Add(p);
dbValues.Items.Add(string.Format("{0}-{1}", p.Name, p.Age);
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public enum Sexs
{
Male,
Female
}
public Sexs Sex { get; set; }
public enum SkillLevels
{
Noob,
Medium,
Expert
}
public SkillLevels SkillLevel { get; set; }
}
void ValueBoxKeyDown(object sender, dynamic e)
{
if (e.KeyCode != "enter")
return;
Person p = this.People[dbValues.SelectedIndex];
switch((int)fieldBox.SelectedIndex)
{
case 0: p.Name = valueBox.Text; break;
case 1: p.Age = int.Parse(valueBox.Text); break;
case 2: p.Sex = (Person.Sexs)Enum.Parse(typeof(Person.Sexs), valueBox.Text); break;
case 3: p.SkillLevel = (Person.SkillLevels)Enum.Parse(typeof(Person.SkillLevels), valueBox.Text); break;
default: throw new NotImplementedException();
}
MessageBox.Show("Value set: " + old + " to " + valueBox.Text + ".");
}
}
However this is still garbage, since if you have a strongly typed data set you can actually bind this to form controls without directly manipulating the item.
https://msdn.microsoft.com/en-us/library/c8aebh9k(v=vs.110).aspx
You cannot change the return-value of a method returning a string as strings are immutable. What you can do instead is the following:
string myDatabase =
"Garry\t19\tMale\tNoob\n" +
"Joe\t25\tMale\tMedium\n" +
"Gary\t33\tFemale\tExpert";
var tmp = "";
foreach(var line in myString.Split('\n')) {
tmp = tmp + Regex.Replace(line, "^.*?(?=\\t)", myReplaceText);
}
myString = tmp;
This regex will search for everything before the very first tab within every line, replaces it by "Jerry"and and concatenates every so replaced line into myString.

Get the positions of unique elements in a string[]

I have an xml file that I am accessing to create a report of time spent on a project. I'm returning the unique dates to a label created dynamically on a winform and would like to compile the time spent on a project for each unique date. I have been able to return all of the projects under each date or only one project. Currently I'm stuck on only returning one project. Can anyone please help me?? This is what the data should look like if it's correct.
04/11/15
26820 2.25
27111 8.00
04/12/15
26820 8.00
04/13/15
01det 4.33
26820 1.33
27225 4.25
etc.
This is how I'm retrieving the data
string[] weekDateString = elementDateWeekstring();
string[] uniqueDates = null;
string[] weeklyJobNumber = elementJobNumWeek();
string[] weeklyTicks = elementTicksWeek();
This is how I'm getting the unique dates.
IEnumerable<string> distinctWeekDateIE = weekDateString.Distinct();
foreach (string d in distinctWeekDateIE)
{
uniqueDates = distinctWeekDateIE.ToArray();
}
And this is how I'm creating the labels.
try
{
int dateCount;
dateCount = uniqueDates.Length;
Label[] lblDate = new Label[dateCount];
int htDate = 1;
int padDate = 10;
for (int i = 0; i < dateCount; i++ )
{
lblDate[i] = new Label();
lblDate[i].Name = uniqueDates[i].Trim('\r');
lblDate[i].Text = uniqueDates[i];
lblDate[i].TabIndex = i;
lblDate[i].Bounds = new Rectangle(18, 275 + padDate + htDate, 75, 22);
targetForm.Controls.Add(lblDate[i]);
htDate += 22;
foreach (string x in uniqueDates)
{
int[] posJobNumber;
posJobNumber = weekDateString.Select((b, a) => b == uniqueDates[i].ToString() ? a : -1).Where(a => a != -1).ToArray();
for (int pjn = 0; pjn < posJobNumber.Length; pjn++)
{
if (x.Equals(lblDate[i].Text))
{
Label lblJobNum = new Label();
int htJobNum = 1;
int padJobNum = 10;
lblJobNum.Name = weeklyJobNumber[i];
lblJobNum.Text = weeklyJobNumber[i];
lblJobNum.Bounds = new Rectangle(100, 295 + padJobNum + htJobNum, 75, 22);
targetForm.Controls.Add(lblJobNum);
htJobNum += 22;
htDate += 22;
padJobNum += 22;
}
}
}
}
}
I've been stuck on this for about 3 months. Is there anyone that can describe to me why I'm not able to properly retrieve the job numbers that are associated with a particular date. I don't believe that these are specifically being returned as dates. Just a string that looks like a date.
I really appreciate any help I can get. I'm just completely baffled. Thank you for any responses in advance. I truly appreciate the assistance.
EDIT: #Sayka - Here is the xml sample.
<?xml version="1.0" encoding="utf-8"?>
<Form1>
<Name Key="4/21/2014 6:51:17 AM">
<Date>4/21/2014</Date>
<JobNum>26820</JobNum>
<RevNum>00000</RevNum>
<Task>Modeling Secondary</Task>
<Start>06:51 AM</Start>
<End>04:27 PM</End>
<TotalTime>345945089017</TotalTime>
</Name>
<Name Key="4/22/2014 5:44:22 AM">
<Date>4/22/2014</Date>
<JobNum>26820</JobNum>
<RevNum>00000</RevNum>
<Task>Modeling Secondary</Task>
<Start>05:44 AM</Start>
<End>06:56 AM</End>
<TotalTime>43514201221</TotalTime>
</Name>
<Name Key="4/22/2014 6:57:02 AM">
<Date>4/22/2014</Date>
<JobNum>02e-n-g</JobNum>
<RevNum>00000</RevNum>
<Task>NET Eng</Task>
<Start>06:57 AM</Start>
<End>07:16 AM</End>
<TotalTime>11706118875</TotalTime>
</Name>
....
</Form1>
This is how I'm getting the information out of the xml file and returning a string[].
public static string[] elementDateWeekstring()
{
//string datetxtWeek = "";
XmlDocument xmldoc = new XmlDocument();
fileExistsWeek(xmldoc);
XmlNodeList nodeDate = xmldoc.GetElementsByTagName("Date");
int countTicks = 0;
string[] dateTxtWeek = new string[nodeDate.Count];
for (int i = 0; i < nodeDate.Count; i++)
{
dateTxtWeek[i] = nodeDate[i].InnerText;
countTicks++;
}
return dateTxtWeek;
}
Job number and Ticks are returned in a similar fashion. I've been able to reuse these snippets throught out the code. This is a one dimensional xml file?? It will always return a position for a jobnumber that equates to a date or Ticks. I will never have more or less of any one element.
You can use Linq-to-XML to parse the XML file, and then use Linq-to-objects to group (and order) the data by job date and order each group by job name.
The code to parse the XML file is like so:
var doc = XDocument.Load(filename);
var jobs = doc.Descendants("Name");
// Extract the date, job number, and total time from each "Name" element.:
var data = jobs.Select(job => new
{
Date = (DateTime)job.Element("Date"),
Number = (string)job.Element("JobNum"),
Duration = TimeSpan.FromTicks((long)job.Element("TotalTime"))
});
The code to group and order the jobs by date and order the groups by job name is:
var result =
data.GroupBy(job => job.Date).OrderBy(g => g.Key)
.Select(g => new
{
Date = g.Key,
Jobs = g.OrderBy(item => item.Number)
});
Then you can access the data by iterating over each group in result and then iterate over each job in the group, like so:
foreach (var jobsOnDate in result)
{
Console.WriteLine("{0:d}", jobsOnDate.Date);
foreach (var job in jobsOnDate.Jobs)
Console.WriteLine(" {0} {1:hh\\:mm}", job.Number, job.Duration);
}
Putting this all together in a sample compilable console application (substitute the filename for the XML file as appropriate):
using System;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
private static void Main()
{
string filename = #"d:\test\test.xml"; // Substitute your own filename here.
// Open XML file and get a collection of each "Name" element.
var doc = XDocument.Load(filename);
var jobs = doc.Descendants("Name");
// Extract the date, job number, and total time from each "Name" element.:
var data = jobs.Select(job => new
{
Date = (DateTime)job.Element("Date"),
Number = (string)job.Element("JobNum"),
Duration = TimeSpan.FromTicks((long)job.Element("TotalTime"))
});
// Group the jobs by date, and order the groups by job name:
var result =
data.GroupBy(job => job.Date).OrderBy(g => g.Key)
.Select(g => new
{
Date = g.Key,
Jobs = g.OrderBy(item => item.Number)
});
// Print out the results:
foreach (var jobsOnDate in result)
{
Console.WriteLine("{0:d}", jobsOnDate.Date);
foreach (var job in jobsOnDate.Jobs)
Console.WriteLine(" {0} {1:hh\\:mm}", job.Number, job.Duration);
}
}
}
}
The output is like this
Create a new project
Set form size bigger.
Apply these codes.
Set the location for your XML file.
Namespaces
using System.Xml;
using System.IO;
Form Code
public partial class Form1 : Form
{
const string XML_FILE_NAME = "D:\\emps.txt";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
prepareDataGrid();
List<JOBS> jobsList = prepareXML(XML_FILE_NAME);
for (int i = 0; i < jobsList.Count; i++)
{
addDateRow(jobsList[i].jobDate.ToString("M'/'d'/'yyyy"));
for (int j = 0; j < jobsList[i].jobDetailsList.Count; j++)
dgv.Rows.Add(new string[] {
jobsList[i].jobDetailsList[j].JobNumber,
jobsList[i].jobDetailsList[j].JobHours
});
}
}
DataGridView dgv;
void prepareDataGrid()
{
dgv = new DataGridView();
dgv.BackgroundColor = Color.White;
dgv.GridColor = Color.White;
dgv.DefaultCellStyle.SelectionBackColor = Color.White;
dgv.DefaultCellStyle.SelectionForeColor = Color.Black;
dgv.DefaultCellStyle.ForeColor = Color.Black;
dgv.DefaultCellStyle.BackColor = Color.White;
dgv.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgv.Width = 600;
dgv.Dock = DockStyle.Left;
this.BackColor = Color.White;
dgv.Columns.Add("Col1", "Col1");
dgv.Columns.Add("Col2", "Col2");
dgv.Columns[0].Width = 110;
dgv.Columns[1].Width = 40;
dgv.DefaultCellStyle.Font = new System.Drawing.Font("Segoe UI", 10);
dgv.RowHeadersVisible = dgv.ColumnHeadersVisible = false;
dgv.AllowUserToAddRows =
dgv.AllowUserToDeleteRows =
dgv.AllowUserToOrderColumns =
dgv.AllowUserToResizeColumns =
dgv.AllowUserToResizeRows =
!(dgv.ReadOnly = true);
Controls.Add(dgv);
}
void addJobRow(string jobNum, string jobHours)
{
dgv.Rows.Add(new string[] {jobNum, jobHours });
}
void addDateRow(string date)
{
dgv.Rows.Add(new string[] { date, ""});
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.SelectionForeColor =
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.ForeColor = Color.Firebrick;
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.Font = new Font("Segoe UI Light", 13.5F);
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
dgv.Rows[dgv.Rows.Count - 1].Height = 25;
}
List<JOBS> prepareXML(string fileName)
{
string xmlContent = "";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs)) xmlContent = sr.ReadToEnd();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlContent);
List<JOBS> jobsList = new List<JOBS>();
XmlNode form1Node = doc.ChildNodes[1];
for (int i = 0; i < form1Node.ChildNodes.Count; i++)
{
XmlNode dateNode = form1Node.ChildNodes[i].ChildNodes[0].ChildNodes[0],
jobNumNode = form1Node.ChildNodes[i].ChildNodes[1].ChildNodes[0],
timeTicksNode = form1Node.ChildNodes[i].ChildNodes[6].ChildNodes[0];
bool foundDate = false;
for (int j = 0; j < jobsList.Count; j++) if (jobsList[j].compareDate(dateNode.Value))
{
jobsList[j].addJob(jobNumNode.Value, Math.Round(TimeSpan.FromTicks(
(long)Convert.ToDouble(timeTicksNode.Value)).TotalHours, 2).ToString());
foundDate = true;
break;
}
if (!foundDate)
{
JOBS job = new JOBS(dateNode.Value);
string jbnum = jobNumNode.Value;
string tbtck = timeTicksNode.Value;
long tktk = Convert.ToInt64(tbtck);
double tkdb = TimeSpan.FromTicks(tktk).TotalHours;
job.addJob(jobNumNode.Value, Math.Round(TimeSpan.FromTicks(
Convert.ToInt64(timeTicksNode.Value)).TotalHours, 2).ToString());
jobsList.Add(job);
}
}
jobsList.OrderByDescending(x => x.jobDate);
return jobsList;
}
class JOBS
{
public DateTime jobDate;
public List<JobDetails> jobDetailsList = new List<JobDetails>();
public void addJob(string jobNumber, string jobHours)
{
jobDetailsList.Add(new JobDetails() { JobHours = jobHours, JobNumber = jobNumber });
}
public JOBS(string dateString)
{
jobDate = getDateFromString(dateString);
}
public JOBS() { }
public bool compareDate(string dateString)
{
return getDateFromString(dateString) == jobDate;
}
private DateTime getDateFromString(string dateString)
{
string[] vals = dateString.Split('/');
return new DateTime(Convert.ToInt32(vals[2]), Convert.ToInt32(vals[0]), Convert.ToInt32(vals[1]));
}
}
class JobDetails
{
public string JobNumber { get; set; }
public string JobHours { get; set; }
}
}

Does anyone have c# code to use betfair api?

I am creating a c# windows app to display current sports market rates using betfair exchange webservice, I used the
getmarketpricescompressed()
method which returns a price string that looks like this:
106093239~GBP~ACTIVE~0~1~~true~5.0~1343114432333~~N:7337~1~6992.56~2.16~~~false~~~~|2.16~1036.19~L~1~2.14~97.18~L~2~2.12~5.0~L~3~|2.18~467.36~B~1~2.2~34.12~B~2~2.22~162.03~B~3~:414464~2~102181.96~1.86~~~false~~~~|1.85~2900.33~L~1~1.84~1831.59~L~2~1.83~1593.73~L~3~|1.86~58.83~B~1~1.87~1171.77~B~2~1.88~169.15~B~3~
i don't know how to properly unpack this string, for now i am using this code:
GetMarketPricesCompressedReq price_req1 = new GetMarketPricesCompressedReq();
price_req1.header = header2;
price_req1.marketId = marketid_temp;
price_req1.currencyCode = "GBP";
GetMarketPricesCompressedResp price_resp = new GetMarketPricesCompressedResp();
price_resp = bfg2.getMarketPricesCompressed(price_req1);
//MessageBox.Show(price_resp.errorCode.ToString());
//richTextBox1.Text = "";
//richTextBox1.Text = price_resp.marketPrices;
string prices = price_resp.marketPrices;
richTextBox1.Text = price_resp.marketPrices;
string[] ab1 = prices.Split('|');
string[] temp = ab1[1].Split('~');
textBox3.Text = temp[0];
textBox4.Text = temp[4];
textBox5.Text = temp[8];
temp = ab1[2].Split('~');
textBox6.Text = temp[0];
textBox7.Text = temp[4];
textBox8.Text = temp[8];
temp = ab1[3].Split('~');
textBox9.Text = temp[0];
textBox10.Text = temp[4];
textBox11.Text = temp[8];
temp = ab1[4].Split('~');
textBox12.Text = temp[0];
textBox13.Text = temp[4];
textBox14.Text = temp[8];
if (ab1.Length >5)
{
temp = ab1[5].Split('~');
textBox15.Text = temp[0];
textBox16.Text = temp[4];
textBox17.Text = temp[8];
temp = ab1[6].Split('~');
textBox18.Text = temp[0];
textBox19.Text = temp[4];
textBox20.Text = temp[8];
}
It works fine for a few matches, but i observed the string changes for a few other matches and it thus generates exceptions,
Can any1 help me with a proper code to unpack this string, i've googled it and found a vb code, which was not very usefull,
and btw, i want to arrange the data in something like this:
Consider the following:
a|b|c|d
In this, you have four chunks. But it doesn't necessarily have to be only four. It can be two, it can be six.
Try going at it by iterating the string-array you get as a result of the
string[] ab1 = prices.Split('|');
Something like
foreach(var stringChunk in ab1)
{
string[] temp = stringChunk.Split('~');
// use the strings here as you please
}
Consider using a more dynamic approach in presenting your data as well, using a row-based, repeating control instead of static textboxes. =)
The full documentation for the compressed data is available here: https://docs.developer.betfair.com/betfair/#!page=00008360-MC.00008307-MC
Just guessing, I think the data is organised like this
first delimited by : then | we get
106093239~GBP~ACTIVE~0~1~~true~5.0~1343114432333~~N
7337~1~6992.56~2.16~~~false~~~~
2.16~1036.19~L~1~2.14~97.18~L~2~2.12~5.0~L~3~
2.18~467.36~B~1~2.2~34.12~B~2~2.22~162.03~B~3~
414464~2~102181.96~1.86~~~false~~~~
1.85~2900.33~L~1~1.84~1831.59~L~2~1.83~1593.73~L~3~
1.86~58.83~B~1~1.87~1171.77~B~2~1.88~169.15~B~3~
I think that first row is clearly a header, that first number being the market ID perhaps.
Likewise, the first part of each subsequent section is a row identifier. Delimited by ~ something like
(SelectionId)7337 (Order)1 (TotalMatched?)6992.56 (EvenPoint)2.16 (???)false
I think the price rows are delimited by ~ in tuples of 4, like this
(Price)2.16 (MatchAvailable)1036.19 (Type)L (Order)1
(Price)2.14 (MatchAvailable)0097.18 (Type)L (Order)2
(Price)2.12 (MatchAvailable)0005.00 (Type)L (Order)3
for example.
To test my guesses I'd have to compare with the BetFair rendering on thier web site.
I converted the vb code to c# myself, if anyone might find it useful, I am posting it here:
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
namespace stock
{
class UnpackMarketPricesCompressed : stock.BFExchangeService.MarketPrices
{
//The substitute code for "\:"
private const string ColonCode = "&%^#";
//Unpack the string
public UnpackMarketPricesCompressed(string MarketPrices)
{
string[] Mprices = null;
string[] Part = null;
string[] Field = null;
int n = 0;
Mprices = MarketPrices.Replace("\\:", ColonCode).Split(':');
//Split header and runner data
Field = Mprices[0].Replace("\\~", "-").Split('~');
//Split market data fields
marketId = Convert.ToInt32(Field[0]);
//Assign the market data
currencyCode = Field[1];
marketStatus = (stock.BFExchangeService.MarketStatusEnum)Enum.Parse(typeof(stock.BFExchangeService.MarketStatusEnum), Field[2], true);
delay = Convert.ToInt32(Field[3]);
numberOfWinners = Convert.ToInt32(Field[4]);
marketInfo = Field[5].Replace(ColonCode, ":");
discountAllowed = (Field[6].ToLower() == "true");
marketBaseRate = float.Parse(Field[7]);
lastRefresh = long.Parse(Field[8]);
removedRunners = Field[9].Replace(ColonCode, ":");
bspMarket = (Field[10] == "Y");
n = Mprices.Length - 1;
// ERROR: Not supported in C#: ReDimStatement
//For each runner
for (int i = 0; i <= n; i++)
{
Part = Mprices[i + 1].Split('|');
//Split runner string into 3 parts
Field = Part[0].Split('~');
//Split runner data fields
runnerPrices[i] = new stock.BFExchangeService.RunnerPrices();
var _with1 = runnerPrices[i];
//Assign the runner data
_with1.selectionId = Convert.ToInt32(Field[0]);
_with1.sortOrder = Convert.ToInt32(Field[1]);
_with1.totalAmountMatched = Convert.ToDouble(Field[2]);
_with1.lastPriceMatched = Convert.ToDouble(Field[3]);
_with1.handicap = Convert.ToDouble(Field[4]);
_with1.reductionFactor = Convert.ToDouble(Field[5]);
_with1.vacant = (Field[6].ToLower() == "true");
_with1.farBSP = Convert.ToDouble(Field[7]);
_with1.nearBSP = Convert.ToDouble(Field[8]);
_with1.actualBSP = Convert.ToDouble(Field[9]);
_with1.bestPricesToBack = Prices(Part[1]);
_with1.bestPricesToLay = Prices(Part[2]);
}
}
private stock.BFExchangeService.Price[] Prices(string PriceString)
{
string[] Field = null;
stock.BFExchangeService.Price[] Price = null;
int k = 0;
int m = 0;
Field = PriceString.Split('~');
//Split price fields
m = (Field.Length / 4) - 1;
//m = number of prices - 1
// ERROR: Not supported in C#: ReDimStatement
for (int i = 0; i <= m; i++)
{
Price[i] = new stock.BFExchangeService.Price();
var _with2 = Price[i];
_with2.price = Convert.ToInt32(Field[k + 0]);
//Assign price data
_with2.amountAvailable = Convert.ToInt32(Field[k + 1]);
_with2.betType = (stock.BFExchangeService.BetTypeEnum)Enum.Parse(typeof(stock.BFExchangeService.BetTypeEnum), Field[k + 2], true);
_with2.depth = Convert.ToInt32(Field[k + 3]);
k += 4;
}
return Price;
//Return the array of prices
}
}
}

I have a CSV file where the Date and the time are into 2 fields. How can I use FileHelpers to aggregate the 2 fields into the same DateTime data?

I have a CSV file where the Date and the time are into 2 fields.
How can I use FileHelpers to aggregate the 2 fields into the same DateTime data ?
Thanks,
2011.01.07,09:56,1.2985,1.2986,1.2979,1.2981,103
2011.01.07,09:57,1.2981,1.2982,1.2979,1.2982,75
2011.01.07,09:58,1.2982,1.2982,1.2976,1.2977,83
2011.01.07,09:59,1.2977,1.2981,1.2977,1.2980,97
2011.01.07,10:00,1.2980,1.2980,1.2978,1.2979,101
2011.01.07,10:01,1.2980,1.2981,1.2978,1.2978,57
2011.01.07,10:02,1.2978,1.2979,1.2977,1.2978,86
2011.01.07,10:03,1.2978,1.2978,1.2973,1.2973,84
2011.01.07,10:04,1.2973,1.2976,1.2973,1.2975,71
2011.01.07,10:05,1.2974,1.2977,1.2974,1.2977,53
2011.01.07,10:06,1.2977,1.2979,1.2976,1.2978,57
2011.01.07,10:07,1.2978,1.2978,1.2976,1.2976,53
2011.01.07,10:08,1.2976,1.2980,1.2976,1.2980,58
2011.01.07,10:09,1.2979,1.2985,1.2979,1.2980,63
var file = #"2011.01.07,09:56,1.2985,1.2986,1.2979,1.2981,103
2011.01.08,09:57,1.2981,1.2982,1.2979,1.2982,75
2011.01.09,09:58,1.2982,1.2982,1.2976,1.2977,83
2011.01.07,09:59,1.2977,1.2981,1.2977,1.2980,97
2011.01.07,10:00,1.2980,1.2980,1.2978,1.2979,101
2011.01.07,10:01,1.2980,1.2981,1.2978,1.2978,57
2011.01.07,10:02,1.2978,1.2979,1.2977,1.2978,86
2011.01.07,10:03,1.2978,1.2978,1.2973,1.2973,84
2011.01.07,10:04,1.2973,1.2976,1.2973,1.2975,71
2011.01.07,10:05,1.2974,1.2977,1.2974,1.2977,53
2011.01.07,10:06,1.2977,1.2979,1.2976,1.2978,57
2011.01.07,10:07,1.2978,1.2978,1.2976,1.2976,53
2011.01.07,10:08,1.2976,1.2980,1.2976,1.2980,58
2011.01.07,10:09,1.2979,1.2985,1.2979,1.2980,63";
var rows = file.Split('\n');
foreach(var row in rows){
var cols = row.Split(',');
var col1 = new DateTime();
foreach(var col in cols){
if (col == cols[0]) // first col
{
var dateParts = col.Split('.');
col1 = new DateTime(int.Parse(dateParts[0]), int.Parse(dateParts[1]), int.Parse(dateParts[2]));
}
else if (col == cols[1]) // second col
{
var timeParts = col.Split(':');
col1 = col1.AddHours(int.Parse(timeParts[0]));
col1 = col1.AddMinutes(int.Parse(timeParts[1]));
//col1.Dump();
}
else {
// all other columns here
}
}
}
I answer my own question.
Because my need have change, I dont really answer my own question.
My question have evolve to :
I have a CSV file where the Date and the time are into 2 fields. How can I use FileHelpers to aggregate the 2 fields into the same XLDate data ?
Here the full projet where I use this code :
enter link description here
private void CreateGraphic(ZedGraphControl zgc)
{
// référence vers le "canevas"
GraphPane pane = zgc.GraphPane;
pane.Title.Text = "Japanese Candlestick Chart Demo";
pane.XAxis.Title.Text = "Trading Date";
pane.YAxis.Title.Text = "Share Price, $US";
FileHelperEngine<MetaTrader4> engine = new FileHelperEngine<MetaTrader4>();
engine.ErrorManager.ErrorMode = ErrorMode.SaveAndContinue;
MetaTrader4[] res = engine.ReadFile(#"..\..\Data\EURUSD240.csv");
if (engine.ErrorManager.ErrorCount > 0)
engine.ErrorManager.SaveErrors("Errors.txt");
StockPointList spl = new StockPointList();
foreach (MetaTrader4 quotes in res)
{
DateTime dateTime = new DateTime();
dateTime = DateTime.ParseExact(quotes.Date + "-" + quotes.Time, "yyyy.MM.dd-HH:mm",
null);
XDate xDate = new XDate(dateTime);
StockPt pt = new StockPt(xDate, quotes.Hight, quotes.Low, quotes.Open, quotes.Close, quotes.Volume);
spl.Add(pt);
}
JapaneseCandleStickItem myCurve = pane.AddJapaneseCandleStick("trades", spl);
myCurve.Stick.IsAutoSize = true;
myCurve.Stick.Color = Color.Blue;
// Use DateAsOrdinal to skip weekend gaps
pane.XAxis.Type = AxisType.DateAsOrdinal;
// pretty it up a little
pane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45.0f);
pane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45.0f);
zgc.AxisChange();
}
You do this by listening to the engine.BeforeReadRecord event.
As you (engine) read each line, you'll need to remove the delimiter between the date and time so that it fits the expected date time format you specified in the FieldConverter attribute.
Here's is a linqpad snippet to demonstrate.
void Main()
{
string reading = "2011.01.07,09:56,1.2985,1.2986,1.2979,1.2981,103";
var engine = new FileHelperEngine<Reading>();
//engine.Options.Fields.Dump();
char delimiter = ((DelimitedRecordOptions)engine.Options).Delimiter.ToCharArray().First();
int expectedDelimiterCount = engine.Options.Fields.Sum(field => field.FieldType == typeof(DateTime) ? 2 : field.ArrayMinLength == 0 ? 1 : field.ArrayMinLength);
expectedDelimiterCount--; // no ending delimiter
engine.BeforeReadRecord += (ngin, e) => {
int fieldCount = e.RecordLine.Count(c => c == delimiter);
if (fieldCount == expectedDelimiterCount)
{
int delimiterIndex = e.RecordLine.IndexOf(delimiter);
if (delimiterIndex > NOT_FOUND)
{
e.RecordLine = e.RecordLine.Remove(delimiterIndex, 1);
}
}
};
var readings = engine.ReadString(reading);
readings.Dump();
}
const int NOT_FOUND = -1;
// Define other methods and classes here
[DelimitedRecord(",")]
class Reading
{
[FieldOrder(1)]
[FieldConverter(ConverterKind.Date, "yyyy.MM.ddHH:mm")]
public DateTime CollectionDate { get; set; }
[FieldOrder(2)]
[FieldArrayLength(4)]
public decimal[] Data;
[FieldOrder(3)]
public int CollectorID { get; set; }
}
Writing out the DateTime property into two fields is left as an exercise for the reader.

Categories