C# WinForm error import from excel to database - c#

Hei. I need to understand why I receive an error like that :
C# windows form import from excel error
I can't separe the year from string (year time). Or, can I renounce at split and import directly the string as "date"? Sorry, I'm too beginner in c#, but I need this help, is a task for me.
Here is my code :
for (int i = 0; i < dvColumns.Count; i++)
{
string columnName = string.Empty;
string columnField = string.Empty;
if ((dvColumns[i]["Header"] != null) && (!Convert.IsDBNull(dvColumns[i]["Header"])))
{
columnName = dvColumns[i]["Header"].ToString();
}
if ((dvColumns[i]["Field"] != null) && (!Convert.IsDBNull(dvColumns[i]["Field"])))
{
columnField = dvColumns[i]["Field"].ToString();
}
rangeObject = cellsObject.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, cellsObject, new object[] { row, i + 1 });
object valueObject = rangeObject.GetType().InvokeMember("Value", BindingFlags.GetProperty, null, rangeObject, null);
if (columnName == "FiscalCode" && columnField == "PartnerId")
{
string fiscalCode = Erp.Core.Utils.GetStringFromObject(valueObject);
partnerId = p.GetPartnerIdByFiscalCode(fiscalCode);
eventRow["PartnerId"] = partnerId;
}
else if (columnField == "StartDate" || columnField == "EndDate")
{
string date = Erp.Core.Utils.GetStringFromObject(valueObject);
DateTime columnDate = DateTime.Now;
string[] dateComponents = null;
int year = 0;
int month = 0;
int day = 0;
if (date.Contains("."))
{
dateComponents = date.Split('.');
}
if (date.Contains("/"))
{
dateComponents = date.Split('/');
}
if (date.Contains(":"))
{
dateComponents = date.Split(':');
}
if (dateComponents.Length > 1)
{
string s = dateComponents[0];
day = Erp.Core.Utils.GetIntFromObject(s);
s = dateComponents[1];
month = Erp.Core.Utils.GetIntFromObject(s);
s = dateComponents[2];
year = Erp.Core.Utils.GetIntFromObject(s);
columnDate = new DateTime(year, month, day, 9, 0, 0);
}
eventRow[columnField] = columnDate;
}
else if (columnField != "PartnerId" && columnField != "StartDate" && columnField != "EndDate")
{
eventRow[columnField] = valueObject;
}
}

I tried to keep in excel same format as in database table : 'yyyy/mm/dd hh:mm:ss.000'.
The line date = Erp.Core.Utils.GetStringFromObject(valueObject); get my date from first excel cell.
ds.Tables["Events"] is all time empty.
I know this line eventRow[columnField] = date; must add the dates in DB, really? After split, day is ok (receive an int by s[0]), month is ok (receive an int by s[1], but s[2] for year is something like 2017 19:06:22 .... year plus time). I tried to split again by space, but without results, to keep the number (2017) in year variable.

Best way is to use DateTime.ParseExact method. In your case, if original format is 'yyyy/mm/dd hh:mm:ss.000', you can convert it to DateTime like this:
//string date = Erp.Core.Utils.GetStringFromObject(valueObject);
string date = "2017/08/15 10:20:30.000";
DateTime columnDate = DateTime.ParseExact(date, "yyyy/MM/dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
This way you can skip parsing excel string.
In your example, usage will be like this:
//...snip...
else if (columnField == "StartDate" || columnField == "EndDate")
{
string date = Erp.Core.Utils.GetStringFromObject(valueObject);
//parsing date string
DateTime columnDate = DateTime.ParseExact(date, "yyyy/MM/dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
eventRow[columnField] = columnDate;
}
else if (columnField != "PartnerId" && columnField != "StartDate" && columnField != "EndDate")
{
eventRow[columnField] = valueObject;
}
if hours are in 12-hour format, use lowercase hh, like this "yyyy/MM/dd hh:mm:ss.fff"

Related

Copy last value to other cells till we see a filled cell

I have a list like below :
2016-10-05 00:00:00.000
NULL
NULL
NULL
2016-08-12 07:46:00.000
NULL
NULL
Which I need to convert to
2016-10-05 00:00:00.000
2016-10-05 00:00:00.000
2016-10-05 00:00:00.000
2016-10-05 00:00:00.000
2016-08-12 07:46:00.000
2016-08-12 07:46:00.000
2016-08-12 07:46:00.000
Basically, I need to capture the last occurrence date and copy it to next rows till i see a filled row.
Here is how I see it working now
foreach (var date in dates)
{
var lastValue = null;
if(date != null)
{
lastValue = date;
}
if(date == null)
{
date = lastValue;
}
else
{
lastValue = date;
}
}
I would use a simple for-loop for this
List<DateTime?> dates = new List<DateTime?>()
{
new DateTime( 2016,10,05,00,00,00),
null,
null,
null,
new DateTime( 2016, 08, 12 ,07,46,00),
null,
null
};
DateTime? latest = null;
for (int i = 0; i < dates.Count; i++)
{
if (dates[i].HasValue)
{
latest = dates[i];
}
else
{
dates[i] = latest;
}
}
https://dotnetfiddle.net/qqDaMf
//input
List<DateTime?> dates = new List<DateTime?> { DateTime.Now, null, DateTime.Parse("2019-10-01"), null };
DateTime? lastPresentDate = dates.FirstOrDefault();
if (lastPresentDate.HasValue)
{
dates = dates.Select(d => d.HasValue ? lastPresentDate = d : lastPresentDate).ToList();
}
//output
7/23/2019 7:15:48 AM
7/23/2019 7:15:48 AM
10/1/2019 12:00:00 AM
10/1/2019 12:00:00 AM
This will only correct the dates if the first date is present and otherwise leave the list as is.
Assuming you actually have a class (let's say Product) with some other properties:
DateTime? lastDate = null;
var result = products.Select(
p =>
new {
Id = p.Id,
CreateDate = (p.CreateDate.HasValue ? (lastDate = p.CreateDate) : lastDate)
//Other properties..
}
);
If not and you have just the dates:
DateTime? lastDate = null;
var result = dates.Select(d => (d.HasValue ? (lastDate = d.Value) : lastDate));
You can add .ToList() if you like or not.
Change String class for whatever class u are using.
String lastValue = null;
foreach(var value in ValuesList){
if(value == null)
value = lastValue;
else
lastValue = value;
}

pairing and calculating the hours of checkTypes

Continuing from here, I have a table named Attendancelogs which has all the sorted logs CHeckTypes In and Out accordingly. (Thanks to #StephenMuecke the previous question was pretty much resolved) However, what I am trying to achieve next is to make a pairList of all the In and Out in a particular period (StartDate and EndDate) and then calculate the total hours of the employee.
Different Cases, already been taken care of in the previous question
I have two method, one called getSingleDevicePairs(int EnrollNumber, DateTime StartDate, DateTime EndDate) which creates the pairList and the second method getTimeSpentEachDay(List<Pair> pairList) which calculates the total hours of each day.
Pair.cs
public class Pair {
public int id { get; set; }
public int RegisterationId { get; set; }
public int EmpID { get; set; }
public DateTime InnDateTime { get; set; }
public DateTime OutDateTime { get; set; }
}
public List<Pair> getSingleDevicePairs(int EnrollNumber, DateTime StartDate, DateTime EndDate) {
DateTime today = DateTime.Now;
List<Pair> pairList = new List<Pair>();
var logs = db.AttendanceLogs.Where(x => x.RegisterationId == EnrollNumber && x.Date >= StartDate &&
x.Date <= EndDate && x.isIgnore != true && (x.CheckType == "In" || x.CheckType == "Out")).Distinct().ToList();
int loopEnd = 0;
bool oddLogs = false;
if (logs.Count % 2 == 0) {
loopEnd = logs.Count;
} else {
loopEnd = logs.Count - 1;
oddLogs = true;
}
bool inn = true;
if (loopEnd > 1) {
Pair pair = new Pair();
for (int v = 0; v < loopEnd; v++) {
if (inn) {
pair.InnDateTime = logs[v].DateTime;
inn = false;
} else {
pair.OutDateTime = logs[v].DateTime;
inn = true;
pairList.Add(pair);
pair = new Pair();
}
}
}
Bogus bogus = new Bogus();
DateTime bogusDate = new DateTime();
if (oddLogs) {
bogus.MachineNum = logs[logs.Count - 1].DeviceID;
bogus.RegisterationId = logs[logs.Count - 1].RegisterationId;
bogus.DateTime = logs[logs.Count - 1].DateTime;
bogusDate = logs[logs.Count - 1].DateTime;
}
return pairList;
}
^I changed the above method with different approach, since the above approach would mess up with Case 1 shown in the link above.
public List<Pair> getSingleDevicePairs(int EnrollNumber, DateTime StartDate, DateTime EndDate) {
DateTime today = DateTime.Now;
List<Pair> pairList = new List<Pair>();
var logs = db.AttendanceLogs.Where(x => x.RegisterationId == EnrollNumber && x.Date >= StartDate &&
x.Date <= EndDate && x.isIgnore != true && (x.CheckType == "In" || x.CheckType == "Out")).Distinct().ToList();
bool isCheck = false;
Pair pair = new Pair();
DateTime previous = logs.FirstOrDefault().DateTime;
foreach (var log in logs) {
if (!isCheck) {
pair.InnDateTime = log.DateTime;
isCheck = true;
} else {
pair.OutDateTime = log.DateTime;
isCheck = false;
}
pairList.Add(pair);
pair = new Pair();
}
return pairList;
}
^This approach again will fail at Case 1 as it is sequentially adding In and Out in the pairList.
public List<DateAndTime> getTimeSpentEachDay(List<Pair> pairList) {
List<DateAndTime> list = new List<DateAndTime>();
if (pairList.Count > 0) {
for (int i = 0; i < pairList.Count; i++) {
TimeSpan span = TimeSpan.Zero;
// bool flag = false;
int result = -1;
do {
span = span + (pairList[i].OutDateTime - pairList[i].InnDateTime);
result = -1;
if (i < pairList.Count - 1) {
DateTime p = (DateTime)pairList[i].InnDateTime;
DateTime q = (DateTime)pairList[i + 1].InnDateTime;
result = DateTime.Compare(p.Date, q.Date);
}
if (result == 0) {
i++;
// flag = true;
}
} while (result == 0);
//if (i == pairList.Count - 1)
//{
// span = span + (pairList[i].OutDateTime - pairList[i].InnDateTime) ?? TimeSpan.Zero;
//}
DateAndTime dnt = new DateAndTime();
dnt.date = ((DateTime)pairList[i].InnDateTime).ToString("yyyy-MM-dd");
dnt.Time = span;
list.Add(dnt);
}
}
return list.ToList();
}
I am trying to get total hours for each pair as well as a way to take the odd In's together which I can display on the calendar.
Below is an image of the calendar view for an employee which displays only the paired hours, I even want to show a In that would indicate the employee that he either forgot to check out or a missing entry was made.
*Lets say he had a checkin for 9th April of around 08:00 PM that had no Check out on that day and also in the NightersLimit (12 AM - 7 AM) then there should be a single line displayed on the calendar which can only happen if I bring the bogus record for a day from previous method.
There is nothing wrong with the getTimeSpentEachDay(); just a little changes in the getSingleDevicePairs(); method, your first approach fails since it eliminates the last entry of the logs in case of an odd number and your second approach fails since it is not taking account of the sequence the logs are stored in the table.
public List<Pair> getSingleDevicePairs(int EnrollNumber, DateTime StartDate, DateTime EndDate, int? missingEntry)
{
var logs = db.AttendanceLogs.Where(x => x.RegisterationId == EnrollNumber &&
x.Date >= StartDate && x.Date <= EndDate && x.isIgnore != true
&& (x.CheckType == "In" || x.CheckType == "Out")).Distinct().ToList();
if (logs.Count > 0)
{
bool isCheck = false;
Pair pair = new Pair();
DateTime previous = logs.FirstOrDefault().DateTime;
foreach (var log in logs)
{
if (!isCheck)
{
if (log.CheckType == "In")
{
pair.InnDateTime = log.DateTime;
isCheck = true;
}
}
else
{
if (log.CheckType == "Out")
{
pair.OutDateTime = log.DateTime;
isCheck = false;
pairList.Add(pair);
pair = new Pair();
}
if (pair.OutDateTime == DateTime.MinValue)
{
pair.InnDateTime = log.DateTime;
}
}
}
}
return pairList;
}
This completes the pair only when there is an Out for an In.

How to determine if the value of datetime is valid(full date) or it is in year only?

DATETIME Value 1980
I have this code to retrieve a DateTime from sql
string startDate = ed.IDAFrom != null ? Convert.ToDateTime(ed.IDAFrom).ToShortDateString() : "";
EDIT
Note: The Date here is Year Graduated (must be in full date)
I have a datepicker in my view(so the date is in full date right?).. What if the user forgot the date when he graduate so the user will be edit the datepicker to year only.
What I want to achieve here is if the user encode full date or year I want to get the value of YEAR if the user encode full date.
Hope it clears.
Thanks.
Code
foreach (var ed in exams)
{
int rowId = i;
string startDate = ed.IDAFrom != null ?Convert.ToDateTime(ed.IDAFrom).ToShortDateString() : "";
string endDate = ed.IDATo != null ? Convert.ToDateTime(ed.IDATo).ToShortDateString() : "";
string InclusiveDates = startDate + " - " + endDate;
rowsObj[i] = new { id = rowId, cell = new object[] { rowId, InclusiveDates } };
i++;
}
I want to display the year only if it is in full date.
DateTime value;
if(DateTime.TryParse(ed.IDAFrom, out value))
{
Int year = value.Year;
}
If you care about culture:
CultureInfo = CultureInfo.CreateSpecificCulture("en-US"); // Or whichever culture you need
if (DateTime.TryParse(ed.IDAFrom, culture, DateTimeStyles.None, out value))
{
int year = value.Year;
}
If the user has the option to either enter year only or a full date, use this method:
public static string GetDateTime(string value)
{
DateTime date;
string dateString = ""; // Empty by default
// If full date is given, this will succeed
if (DateTime.TryParse(value, out date))
{
dateString = date.ToShortDateString();
}
// If only year is given then this will succeed
else if (DateTime.TryParseExact(value,
"yyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date))
{
dateString = date.ToShortDateString();
}
return dateString;
}
EDIT
Now that you have added some more code to your question, here is how to do it using Linq:
int i = 0;
int j = 0;
var rows = list.Select(exam =>
{
string inclusiveDates = string.Format("{0} - {1}", GetDateTime(exam.IDAFrom), GetDateTime(exam.IDATo));
return new
{
Id = ++i,
Cell = new object[] { ++j, inclusiveDates }
};
})
.ToList();
And here is an example usage
class Program
{
public class Exam
{
public string IDAFrom { get; set; }
public string IDATo { get; set; }
}
public static string GetDateTime(string value)
{
DateTime date;
string dateString = ""; // Empty by default
// If full date is given, this will succeed
if (DateTime.TryParse(value, out date))
{
dateString = date.ToShortDateString();
}
// If only year is given then this will succeed
else if (DateTime.TryParseExact(value,
"yyyy",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out date))
{
dateString = date.ToShortDateString();
}
return dateString;
}
static void Main(string[] args)
{
var list = new List<Exam> { new Exam { IDAFrom = "1999", IDATo = null },
new Exam { IDAFrom = DateTime.Now.ToShortDateString(), IDATo = DateTime.Now.AddDays(5).ToShortDateString() } };
int i = 0;
int j = 0;
var rows = list.Select(exam =>
{
string inclusiveDates = string.Format("{0} - {1}", GetDateTime(exam.IDAFrom), GetDateTime(exam.IDATo));
return new
{
Id = ++i,
Cell = new object[] { ++j, inclusiveDates }
};
})
.ToList();
foreach (var item in rows)
{
Console.WriteLine("{0}\t{1}\t{2}", item.Id.ToString(), item.Cell[0], item.Cell[1]);
}
Console.Read();
}
}

Why won't my Monthcalendar accept today's date?

This question might sound very vague but I do not know how to phrase it in a better fashion.
I've been working on a month calendar that checks if the 2 selected dates are correct. There is 1 calender that uses to following code to figure out who called the event (The startdate textbox or enddate textbox)
MaskedTextBox b = (MaskedTextBox)sender;
currentSelectedDateBox = b.Name;
The startdate must be sooner than the enddate, both startdate and enddate can't be a date that already has a reservation(it shows a reservation by making the date bold), and the selected period can not have a reservation in it.
This is all working fine, although I have one problem: When I open the calendar and click on today, it closes, meaning the user has selected a date, although no date shows up and when I try to print the selected date: it won't print anything. If I select a different date, though, it will print that date, meaning that all dates can be selected except today.
If I click on a different day and then select today, it will work. This is really weird and I'm stuck.
Here's my code:
private void monthCalendar_DateChanged(object sender, DateRangeEventArgs e)
{
ErrorStartDateLabel.Visible = false;
ErrorEndDateLabel.Visible = false;
startdateLabel.ForeColor = Color.Black;
enddateLabel.ForeColor = Color.Black;
string day = monthCalendar.SelectionStart.Day.ToString();
string month = monthCalendar.SelectionStart.Month.ToString();
if (day.Length == 1) //part of the stringbuilder
{
day = "0" + day;
}
if (month.Length == 1) //part of the stringbuilder
{
month = "0" + month;
}
string date = day + "-" + month + "-" + monthCalendar.SelectionStart.Year.ToString(); //Date selected
if (startdateTextbox.Name == currentSelectedDateBox) //If the StartDate Calendar has been selected
{
startdateTextbox.Text = date;
startdate = monthCalendar.SelectionStart.Date;
}
else if (enddateTextbox.Name == currentSelectedDateBox)//If the EndDate Calendar has been selected
{
enddateTextbox.Text = date;
enddate = monthCalendar.SelectionStart.Date;
secondDateChecked = true;
}
if (secondDateChecked) //if the enddate textbox has data
{
if (enddate < startdate) //if enddate is smaller than the startdate
{
enddateTextbox.Text = "";
ErrorEndDateLabel.Text = "Uw gekozen huurperiode klopt niet!";
ErrorEndDateLabel.ForeColor = Color.Red;
enddateLabel.ForeColor = Color.Red;
ErrorEndDateLabel.Visible = true;
}
}
if (carHasReservation == true) //If there is a reservation
{
foreach (var bolddate in bolddates) //loop through all bolded dates
{
if (startdate == bolddate || enddate == bolddate)//if the startdate OR enddate is a bolded date
{
if (startdate == bolddate)
{
startdateTextbox.Text = "";
ErrorStartDateLabel.Text = "Deze startdatum is al gereserveerd!";
ErrorStartDateLabel.ForeColor = Color.Red;
ErrorStartDateLabel.Visible = true;
}
else
{
enddateTextbox.Text = "";
ErrorEndDateLabel.Text = "Deze einddatum is al gereserveerd!";
ErrorEndDateLabel.ForeColor = Color.Red;
ErrorEndDateLabel.Visible = true;
}
}
if (startdate <= enddate)
{
TimeSpan tisp = enddate - startdate;
int dateDiffer = tisp.Days;
for (int i = 0; i <= dateDiffer; i++) //Count the amount of days between the startdate and the enddate. For every day, check if one of those days is a bolded(reservation) date
{
if (startdate.AddDays(i) == bolddate)
{
reservationCollision = true;
}
}
}
}
}
else
{
//No reservation, do nothing!
}
if (reservationCollision) //if there is a boldeddate between the selected dates
{
ErrorStartDateLabel.Text = "Tijdens uw geselecteerde periode";
ErrorEndDateLabel.Text = " is er al een reservering geplaatst!";
ErrorStartDateLabel.ForeColor = Color.Red;
ErrorEndDateLabel.ForeColor = Color.Red;
startdateLabel.ForeColor = Color.Red;
enddateLabel.ForeColor = Color.Red;
ErrorStartDateLabel.Visible = true;
ErrorEndDateLabel.Visible = true;
enddateTextbox.Text = "";
reservationCollision = false;
}
}
My explanation and code might be a bit vague, I'm sorry for that. I thought it would be better to add more information than necessary instead of giving a bad explanation of my problem and code.

How to Compare two date without timeline in C#

I want to compare two dates. In pseudo-code:
If the dueDate > now or dueDate = now
Then Fine Amount = something.
Else Fine Amount = 0
I wrote below code:
DateTime dueDate = Convert.ToDateTime(Reader1[3].ToString());
DateTime now = DateTime.Now;
int result = DateTime.Compare(dueDate, now);
if ((result < 0) || (result == 1))
{
row["Fine_Amount"] = Convert.ToDouble(Reader1[4].ToString());
}
else
{
row["Fine_Amount"] = 0;
}
This code gives wrong value, when
dueDate = 23-12-2011 AM 12:00:00
now = 23-12-2011 PM 05:26:54
I want to Compare:
dueDate = 23-12-2011
now = 23-12-2011
How do I remove the time in that?.
Adding below code is given result. But its to lengthy code.: -
DateTime dueDate = Convert.ToDateTime(Reader1[3].ToString());
DateTime now = DateTime.Now;
if (dueDate.Year < now.Year)
{
row["Fine_Amount"] = Convert.ToDouble(Reader1[4].ToString());
}
else if (dueDate.Year > now.Year)
{
row["Fine_Amount"] = 0;
}
else if (dueDate.Year == now.Year)
{
if (dueDate.Month < now.Month)
{
row["Fine_Amount"] = Convert.ToDouble(Reader1[4].ToString();
}
else if(dueDate.Month > now.Month)
{
row["Fine_Amount"] = 0;
}
else if(dueDate.Month == now.Month)
{
if(dueDate.Day < now.Day)
{
row["Fine_Amount"] = Convert.ToDouble(Reader1[4].ToString();
}
else
{
row["Fine_Amount"] = 0;
}
}
}
Is there any way to short this code?.
Answer For this Question is
if (dueDate.Date >= now.Date)
{
row["Fine_Amount"] = 0;
}
else
{
row["Fine_Amount"] = Convert.ToDouble(Reader1[4].ToString());
}
This datetime.date is gives
dueDate = 23-12-2011 AM 12:00:00 to 23-12-2011 AM 12:00:00
now = 23-12-2011 PM 05:26:54 to 23-12-2011 AM 12:00:00
You can use DateTime.Now.Date
According to docs, Date property returns: A new object with the same date as this instance, and the time value set to 12:00:00 midnight (00:00:00).
The DateTime class in C# supports comparison by simply using <, >, and == operators. Do it like your above written pseudo code.
dueDate.Date >= DateTime.Now.Date
Although you could use the .Date property of DateTime it is generally a good practice to compare a certain date to a date range:
startDate <= someDate && someDate < endDate
You can use the DateTime.Date Property to gets the date component of a DateTime value:
if (dueDate.Date >= DateTime.Now.Date)
use the Date property of DateTime object for comparison

Categories