InvalidArgument=Value of '1' is not valid for 'index' - c#

I have an error in my C# application that interacts with MDB access DB.
The error is:
InvalidArgument=Value of '1' is not valid for 'index'.
My code:
objConn.Open();
listView1.Items.Clear();
OleDbCommand cmd = new OleDbCommand("select a.bill_Id,a.bill_Number,a.bill_Date,c.sup_Name,Sum(b.de_NetPrice),a.bill_Note from (suppliers c right JOIN bills a on c.sup_Id = a.bill_From) LEFT JOIN bill_Details b on a.bill_Id = b.bill_Id where a.bill_Id like '%" + txbSearch.Text + "%' or a.bill_Number like '%" + txbSearch.Text + "%' or c.sup_Name like '%" + txbSearch.Text + "%' or a.bill_Note like '%" + txbSearch.Text + "%' group by a.bill_Id,a.bill_Number,a.bill_Date,c.sup_Name,a.bill_Note order by a.bill_Date desc", objConn);
OleDbDataReader dataReader = cmd.ExecuteReader();
int i = 0;
while (dataReader.Read())
{
DateTime dt0 = DateTime.Parse(dataReader.GetValue(2).ToString());
int Date1 = DateTime.Compare(DateTime.Parse(dt0.ToShortDateString()), DateTime.Parse(txbFrom.Value.ToShortDateString()));
int Date2 = DateTime.Compare(DateTime.Parse(dt0.ToShortDateString()), DateTime.Parse(txbTo.Value.ToShortDateString()));
if (Date1 >= 0 && Date2 <= 0)
{
listView1.Items.Add(dataReader.GetValue(0).ToString());
// The error happens on the following line
listView1.Items[i].SubItems.Add(dataReader.GetValue(1).ToString());
listView1.Items[i].SubItems.Add(dt0.ToShortDateString());
listView1.Items[i].SubItems.Add(dataReader.IsDBNull(3) ? "0" : dataReader.GetString(3));
listView1.Items[i].SubItems.Add(dataReader.IsDBNull(4) ? "0" : dataReader.GetDouble(4).ToString("n2"));
listView1.Items[i].SubItems.Add(dataReader.IsDBNull(5) ? "-" : dataReader.GetString(5));
}
i++;
}
objConn.Close();
The listview has these columns:
ID -- Number -- BillDate -- Supplier -- total -- Note

I may have found the issue.
If first time around the 'if (Date1 >= 0 && Date2 <= 0)' statemant evaluates to false, the i index will still get incremented. And then on the second iteration the if statement might evaluate to true, and then your index will be off-by-one, as there is just one Item in the ListView, but you try to get at using listView1.Items[1], instead of listView1.Items[0], which would be correct.
Solution would be to change the code to:
if (Date1 >= 0 && Date2 <= 0)
{
listView1.Items.Add(dataReader.GetValue(0).ToString());
listView1.Items[i].SubItems.Add(dataReader.GetValue(1).ToString());// The error appears on this line
listView1.Items[i].SubItems.Add(dt0.ToShortDateString());
listView1.Items[i].SubItems.Add(dataReader.IsDBNull(3) ? "0" : dataReader.GetString(3));
listView1.Items[i].SubItems.Add(dataReader.IsDBNull(4) ? "0" : dataReader.GetDouble(4).ToString("n2"));
listView1.Items[i].SubItems.Add(dataReader.IsDBNull(5) ? "-" : dataReader.GetString(5));
i++;
}

Related

How to get 30 days from today including the month january

My sql table contains date of birth of many people.dates are in mm/dd/yyyy format. I want select the persons details whose birth day in next 30days. And i use the following query for that,
SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE
ltrim(str(year(GETDATE()))) + -' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND
ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' +
ltrim(str(day(Mem_DOB))) <= getdate() + 30
And full code is
public List<MemberData> GetThisMonthBirthday()
{
List<MemberData> MD = new List<MemberData>();
using (SqlConnection con = new SqlConnection(Config.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SELECT Mem_FirstNA, Mem_LastNA, Mem_DOB FROM MemberDetails WHERE ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) >= getdate() - 1 AND ltrim(str(year(GETDATE()))) + '-' + ltrim(str(month(Mem_DOB))) + '-' + ltrim(str(day(Mem_DOB))) <= getdate() + 30", con))
{
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
MemberData mb = new MemberData();
mb.Mem_NA = (string)reader["Mem_FirstNA"];
mb.Mem_LastNA =(string)reader["Mem_LastNA"];
mb.Mem_DOB = (Convert.ToDateTime(reader["Mem_DOB"]));
MD.Add(mb);
}
}
catch (Exception e) { throw e; }
finally { if (con.State == System.Data.ConnectionState.Open) con.Close(); }
return MD;
}
}
The problem is that this check only till December 31, if the persons birthday in 01/01/1987 , the query is not selected that details. Please help me to solve this problem. Thank you
There are lots of ways to do this, you need conditional logic depending on whether or not you are within 30 days of the end of the year. If you're using SQL Server, I'd wrap the logic in a function to make it more readable, e.g.:
CREATE FUNCTION [dbo].[IsBirthdayInRange]
(
#Birthday DATETIME,
#StartDate DATETIME,
#EndDate DATETIME
)
RETURNS BIT
AS
BEGIN
DECLARE #StartMonthDay INT
DECLARE #EndMonthDay INT
DECLARE #BirthdayMonthDay INT
SET #StartMonthDay = MONTH(#StartDate) * 100 + DAY(#StartDate)
SET #EndMonthDay = MONTH(#EndDate) * 100 + DAY(#EndDate)
SET #BirthdayMonthDay = MONTH(#Birthday) * 100 + DAY(#Birthday)
IF YEAR(#StartDate) <> YEAR(#EndDate)
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay OR #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
ELSE
BEGIN
IF #BirthdayMonthDay >= #StartMonthDay AND #BirthdayMonthDay <= #EndMonthDay
BEGIN
RETURN 1
END
END
RETURN 0
END
You can then use it as:
...
WHERE IsBirthdayInRange(Mem_DOB, GETDATE(), GETDATE() + 30)

Filter WinForms DataGridView by date range

I would like to filter my DataGridView by a date range which is listed below.
I have a ListBox with 2 items with start and end date. Start date on top, end date below in listbox.
ListBox
DataGridView with date column named 'DATE'
Note: all DateTime formats in my DataGridView and ListBox are dd/MM/yyyy, example: 05/23/2013
Filter = "(DATE >= '" + lbSearchByTime.Items[0].ToString().Trim() +
"and DATE <= '" + lbSearchByTime.Items[1].ToString().Trim() + "')";
Filter = "(DATE >= '" + Convert.ToDateTime(lbSearchByTime.Items[0].ToString().Trim()) +
and "DATE <= '" + Convert.ToDateTime(lbSearchByTime.Items[1].ToString().Trim()) + "')";
These 2 codes does not work for me. Is it wrong format or something else?
It does not have any change when perform filter by button_click.
if (lbSearchByTime.Items.Count == 2)
{
DateTime start = stringToDateTime(lbSearchByTime.Items[0].ToString().Trim());
DateTime end = stringToDateTime(lbSearchByTime.Items[1].ToString().Trim());
Filter = "(DATE101 >= #" + start + "# and DATE101 <= #" + end + "#)";
}

Query upcoming birthdays

I'd like to query my customers for the ones, whose birthdays are yet to come.
I've tried this query, and it - of course - has failed breathtakingly:
Addresses.Where(adr => adr.DateOfBirth != null && adr.DateOfBirth.Value >
DateTime.Now).Take(15).ToList();
Of course this can't work properly (not if you're born in the future) and I'd like to know how I can query my Nullable<DateTime> without a year?
You can do it in one line like this:
context.Addresses.Where(adr => adr.DateOfBirth != null).OrderBy(adr => EntityFunctions.DiffDays(DateTime.Today, EntityFunctions.AddYears(adr.DateOfBirth, EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today) + ((adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month)) ? 1 : 0)))).Take(15).ToList();
Or in a more readable format:
var query = from adr in context.Addresses
where adr.DateOfBirth != null
let diffYears = EntityFunctions.DiffYears(adr.DateOfBirth, DateTime.Today)
let birthdayOccurred = adr.DateOfBirth.Month < DateTime.Today.Month || (adr.DateOfBirth.Day <= DateTime.Today.Day && adr.DateOfBirth.Month == DateTime.Today.Month)
let nextBirthdate = EntityFunctions.AddYears(adr.DateOfBirth, diffYears + (birthdayOccurred ? 1 : 0))
let daysToBirthdate = EntityFunctions.DiffDays(DateTime.Today, nextBirthdate)
orderby daysToBirthdate
select adr;
var result = query.Take(15).ToList();
I'm not sure you can do this as a one-liner. Certainly not with any degree of clarity.
The needed steps are:
Create an ordered list containing only the birthdates where the
month/day comes after today.
Create an ordered list containing only the birthdates where the month/day is before today.
Append the second list to the first one, you now have a single list, sorted in
birthday order.
Take the first 15.
I think the C# code would look something like this (You might need to add a List or two.)
var list1 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month > DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day >= DateTime.Today.Day))).ToList();
var list2 = Addresses.Where(adr => adr.DateOfBirth != null && (adr.DateOfBirth.Value.Month < DateTime.Today.Month || (adr.DateOfBirth.Value.Month == DateTime.Today.Month && adr.DateOfBirth.Value.Day < DateTime.Today.Day))).ToList();
var fullList = list1.Add(list2);
Im not familiar with Linq, I'll try to help with some pseudocode.
Most important condition should look like this:
Date(CurrentDate.Year, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate
|| ' OR
Date(CurrentDate.Year + 1, DateOfBirth.Month, DateOfBirth.Day) >= CurrentDate
This will work 31 December too.
Alternative:
// consider this as pseudocode, I didnt tested that in C#
function GetNextBirthday(DateTime DateOfBirth)
{
int yearOfNextBirthday;
int birthdayMMDD = DateOfBirth.Month*100 + DateOfBirth.Day;
int todayMMDD = CurrentDate.Month*100 + CurrentDate.Day;
if (birthdayMMDD >= todayMMDD)
{
yearOfNextBirthday = CurrentDate.Year; // this year
}
else
{
yearOfNextBirthday = CurrentDate.Year + 1; // next year
}
DateTime nextBirthday;
// you have to write this line yourself, i dont remember how to make date from Y, M, D
nextBirthday = DateFromYMD(yearOfNextBirthday, DateOfBirth.Month, DateOfBirth.Day);
return nextBirthday;
}
Here is my entry for "one liner":
DateTime now = DateTime.Now;
var next15 =
from a in db.Addresses
where a.DateOfBirth != null
let diff = EntityFunctions.DiffSeconds(
EntityFunctions.AddYears(now, -EntityFunctions.DiffYears(a.DateOfBirth, now)),
a.DateOfBirth)
orderby diff >= 0 ? diff : diff + 366*24*60*60
select new a;
var res = next15.Take(15).ToList();
Just tested with SQL Database - and it works like charm ;)
Try something like this; (this is working - I've tested)
//A mock up value for comparison (as DayOfYear not supported in Linq)
int doy = DateTime.Today.Month * 31 + DateTime.Today.Day;
var results = Addresses.Where(a => a.DateOfBirth != null)
.OrderBy( a =>
(a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day) +
(a.DateOfBirth.Value.Month * 31 + a.DateOfBirth.Value.Day > doy ? 0 : 400 ))
.Take(15).ToList();
Here's the same solution as #Aducci but with nullable date and the DBFunctions, as EntityFunctions became deprecated.
pacientes = from paciente in pacientes
where paciente.Nascimento != null
let diffYears = DbFunctions.DiffYears(paciente.Nascimento, DateTime.Today)
let birthdayOccurred = paciente.Nascimento.Value.Month < DateTime.Today.Month
|| (paciente.Nascimento.Value.Day <= DateTime.Today.Day && paciente.Nascimento.Value.Month == DateTime.Today.Month)
let nextBirthdate = DbFunctions.AddYears(paciente.Nascimento, diffYears + (birthdayOccurred ? 1 : 0))
let daysToBirthdate = DbFunctions.DiffDays(DateTime.Today, nextBirthdate)
orderby daysToBirthdate
select paciente;

How to check if for example 30 min have passed?

i have the following Code:
if (v != null && DateTime.Now > v.Besetzt_Von)
{
Debug.WriteLine("Hallo, das ist die Ausgabe! : " + v.Thema + v.Besetzt_Von + v.Besetzt_Bis);
string clientId = GetClientId(req);
DateTime TimeCheck = v.Besetzt_Von;
if (TimeCheck.AddMinutes(30) > v.Besetzt_Von)
{
String hql = "UPDATE Buchung as b " +
"set STORNO = :Storno " +
"where ID IN (SELECT rr.Buchung FROM Raumreservierung rr " +
"where BESETZT_VON = :Von and Raum IN (SELECT r.ID FROM Raum r " +
"join r.Panel pl where pl.ID = :PanelId))";
IQuery query = CurrentSession.CreateQuery(hql);
query.SetParameter("Storno", DateTime.Now);
query.SetParameter("Von", v.Besetzt_Von);
query.SetParameter("PanelId", clientId);
int result = query.ExecuteUpdate();
Debug.WriteLine("Rows affected: " + result);
}
}
I want that if for example Besetzt_Von = 14:00 o'clock, the Query only gets executed if 30 minutes have passed (14:30). I did that with the if clause, but it does not work. The Query is always executing. What iam doing wrong?
change
if (TimeCheck.AddMinutes(30) > v.Besetzt_Von)
which doesn't do anything (this means if v.Besetz_von < v.BesetzVon + 30 minutes, which is of course always true)
to
if (DateTime.Now > v.Besezt_Von.AddMinutes(30))
// DateTime TimeCheck = v.Besetzt_Von; <-- you don't need this
if (DateTime.Now > v.Besetzt_Von.AddMinutes(30))
{
// ...
}

C# date and time comparing

I have a table which contains a two column(start_time and end_time).I am getting the information of start and end time from the user and adding it to the table.Once the user enters the next start and end time I have to compare it with the database.
Suppose in table one row has start time as 2011-08-10 16:00:00 and end time is 2011-08-10 16:30:00.
Suppose the user enter value 2011-08-10 16:05:00.000 (start_time) and 2011-08-10 16:25:00 (end_time) I am able to capture the by using
String getConflictTimeInBetween = string.Format("select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where start_time<='{0}' and end_time>='{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);//
com = new SqlCommand(getConflictTimeInBetween, myConnection);
dr = com.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
//Assign to your textbox here
conflictQuestionIdAtBetween = dr["question_id"].ToString();
conflictQuestionTextAtBetween=dr["question_text"].ToString();
}
}
Here are some sample overlaps that I want to prevent
start_time from 2011-08-10 15:55:00 and end_time 2011-08-10 16:05:00 (five minutes overlap with already existing data)
start_time from 2011-08-10 16:25:00 and end_time 2011-08-10 17:00:00 (five minutes overlap with already existing data)
start_time from 2011-08-10 15:00:00 and end_time 2011-08-10 17:00:00 (30 minutes overlap with already existing data)
Can anyone help me how to solve these three issues.
None of the 3 overlapping scenarios you mentioned will show up with the query you're using now. It's not clear from your post what you mean to achieve, but I can give you the queries that will show each scenario:
1) "select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where start_time>'{0}' and start_time<'{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);
2) "select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where end_time>'{0}' and end_time<'{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);
3) "select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + " where start_time>'{0}' and end_time<'{1}'", start_full, end_full);//question_text='DFS'"2011-06-23 14:55);
Since you seem to have the SQL part, here's the algorithm that finds the overlap in ticks between the input time and the row time.
public long GetTimeOverlap(long inputStart, long inputEnd)
{
// I assume you can get the data yourself so heres only the algorithm.
long rowStart = new DateTime().Ticks, rowEnd = new DateTime().Ticks;
if (inputStart < rowStart)
if (inputEnd >= rowEnd)
// case 3
return rowEnd - rowStart;
else if (inputEnd > rowStart)
// case 1
return inputEnd - rowStart;
// Input time is before row time.
else return 0;
else if (inputStart >= rowEnd)
// Input time is after row time.
return 0;
else if (inputEnd >= rowEnd)
// case 2
return rowEnd - inputStart;
// case 0
else return inputEnd - inputStart;
}
Not sure what you mean in your question, however here is much better code:
String getConflictTimeInBetween = string.Format("select question_id,question_text from {0} where start_time<=#start and end_time>=#end", data_variables.RES_TXT_STRING_QUESTION_TABLE);
using (com = new SqlCommand(getConflictTimeInBetween, myConnection))
{
com.Parameters.AddWithValue("#start", Convert.ToDateTime(start_full));
com.Parameters.AddWithValue("#end", Convert.ToDateTime(end_full));
using (dr = com.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
//Assign to your textbox here
conflictQuestionIdAtBetween = dr["question_id"].ToString();
conflictQuestionTextAtBetween=dr["question_text"].ToString();
}
}
}
}
It's doing the same thing plus:
Prevent possible SQL Injection attacks by using Parameters instead of directly injecting the text.
Dispose the objects (command and reader) after using them to prevent connections from remaining open and crashing your database. This is done by the using blocks.
I believe what you want to do to intersect the date ranges correctly is something like:
String getConflictTimeInBetween = string.Format("select question_id,question_text from " + data_variables.RES_TXT_STRING_QUESTION_TABLE + "where (start_time<='{0}' and end_time>='{0}') or ((start_time<='{1}' and end_time>='{1}')", start_full, end_full);

Categories