Hello I posted a few days ago a similar question and I was told to use a dataset filter to filter my datagridview. I've had a go but I'm struggling to work out how to do it.
I'm trying to filter a deadline column in a datagridview by 2 datetimepickers - startDate and endDate.
datagridview is TaskTable2, datetimepicker1 is startSchedule, datetimepicker2 is endSchedule and deadline in datagridview is deadlineRow
TaskDataSet in the underlying datasource.
So far I have got the following code which is successfully making the rows invisible which are not between the selected start and end date.
private void scheduleButton_Click(object sender, EventArgs e)
{
DateTime startSchedule = startDate.Value.Date;
DateTime endSchedule = endDate.Value.Date;
if (startSchedule <= endSchedule)// runs foreach loop if startdate and enddate are valid
{
foreach (DataGridViewRow dr in TaskTable2.Rows)// loops through rows of datagridview
{
string deadline = dr.Cells["Deadline"].Value.ToString(); // gets deadline values
DateTime deadlineRow = Convert.ToDateTime(deadline); // converts deadline string to datetime and stores in deadlineRow variable
if (startSchedule <= deadlineRow && deadlineRow <= endSchedule) // filters deadlines that are => startDate and <= endDate
{
dr.Visible = true; // display filtered rows here.
}
else
{
dr.Visible = false; // hide rows that are not beteen start and end date.
TaskTable2.CurrentCell = null;
}
}
}
else
{
MessageBox.Show("Please ensure Start Date is set before End Date."); // ensures user selects an end date after the start date.
}
}
However, I have a few existing problems:
Using the visible property is the wrong approach, I need to filter the dataset using something like the following (not sure how to do it)
TaskDataSet.Filter = "startSchedule <= Deadline AND Deadline <= endSchedule";
I have a print button that is supposed to print the filtered
results. However, it is printing all data stored in the
datagridview, even if some rows are visible=false from pressing the
schedule button so this is why I need to filter the dataset and then
use that in the print event.
The datagridview is bound to an XML file so data can be removed from the datagridview for filtering and printing aslong as they remain in the XML file.
If someone could amend my code with a dataset filter rather than using the visible property it would be greatly appreciated.
Thanks!
You filter code could be:
DateTime startSchedule = startDate.Value.Date;
DateTime endSchedule = endDate.Value.Date;
TaskDataSet.Filter = "Deadline >='" + startSchedule + "' AND Deadline <= '" + endSchedule + "'";
As far as your second issue with the printing of the filtered results - found this link online in VB.NET but you could convert it to C#
Print DataSet or DataTable contents from VB.NET
You can also try the DataSet.Clone() and loop through the rows to remove the filtered items then print the remaining records.
DataGridView Printing by Selecting Columns/Rows
How can I print data from a DataGridView in C#?
suppose that your dataset is named 'ds' and the data is stored in the first table, you could do this:
ds.Tables[0].DefaultView.RowFilter =
string.Format("Deadline between ( {0}, {1})",startSchedule,endSchedule );
Note that I didn't test this.
Related
[This is solved, i have added the answer at the bottom]
[Original Question]
How do I automate adding a date to be inserted into a datagridview?
The datagridview is not binded or sourced to any SQL server as anything that user will write into the DataGridView will then be extracted and converted into a pdf table. However the dates inside the DataGridView is to be fixed with a value of today's date.
My end result should be as per picture below :
I tried using code below to automate adding dates into new rows but it didnt work.
dt.Rows.Add("CurrentDate",System.Type.GetType("System.DateTime"));
Note - i did add a datatable.
I also changed the method from CellContentClick to CellContentDoubleClick.
Edit 1 :
I updated the DGV as apparently i still require a datatable to assign as a source to make this work.
Here's my code :
pretable = new DataTable();
pretable.Columns.Add("NO", typeof(int));
pretable.Columns.Add("ID", typeof(string));
pretable.Columns.Add("LO", typeof(string));
pretable.Columns.Add("QT", typeof(string));
pretable.Columns.Add("DA", typeof(DateTime));
pretable.Columns["DA"].DefaultValue = DateTime.Now;
pretable.Columns.Add("ER", typeof(string));
pretable.Columns.Add("RE", typeof(string));
DataRow row = pretable.NewRow();
row["DA"] = DateTime.Now;
pretable.Rows.Add(row);
dataGridView1.DataSource = pretable;
dataGridView1.Rows[5].Cells["DACL"].Value = DateTime.Now;
DA = Date Column in DataTable
DACL = the name of the Date Column in DGV
However , my results added only an empty row as per picture below.
.
.
[ANSWER]
Previously on Form_Load, i added a DataTable, however i found out that this DataTable does not need to be bounded to the DGV as a Source for the date to work.
so instead on Form_Load i added this code
dataGridView1.Rows[0].Cells["DACL"].Value = DateTime.Now.ToString("dd/MM/yyyy");
dataGridView1.Rows[0].Cells["NOCL"].Value = totalRowsN;
This will work as my first Row Numbering and Date insertion.
Thanks to ZedLepplin below for providing the base answer.
I found out that DataGridView1_CellContentDoubleClick takes way too much click for the event to happen so instead i did DataGridView1_CellClick where insertion now takes less effort.
The code i used is :
private void DataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
totalRowsC = dataGridView1.Rows.Count-1;
totalRowsN = dataGridView1.Rows.Count;
dataGridView1.Rows[totalRowsC].Cells["DACL"].Value = DateTime.Now.ToString("dd/MM/yyyy");
dataGridView1.Rows[totalRowsC].Cells["NOCL"].Value = totalRowsN;
}
What this does is that TotalRowsC will be the value of Index for the code
dataGridView.Rows[Index].Cells[ColumnName]
So that it fits programming index. Programming indexes starts with 0 even though the row we see is 1. If i do not minus one in TotalRowsC , an error will prompt stating that we need to insert a value that fits the existing index.
Problem solved for Date automation.
Thank you everyone for the assistance.
To add a date to a column the row you want to add the date to must already exist.
So assuming the row exists and the date column is a text column then this just worked for me: -
yourDgvName.Rows[0].Cells["yourColumnName"].Value = DateTime.Today.ToShortDateString();
Replace yourDgvName with the name of your DataGridView control.
Replace yourColumnName withe the name of your date column, or just use an index number instead of a string column name.
This will add today's date to the date column in the first row of your DataGridView control.
Alternatively, your could create a DataGridView row, add today's date to that row data and then add the row to the DataGridView control.
I have this table called EVENT_ANNOUNCE. Currently I only know how to display every data from the database which is the EVENTNAME column field into the 3 labels. I only want to have maximum 3 events on the form so I created 3 labels, one label for each record.
But I want to display the data only if today date matches the date for that record. Since today date is 31/03/2014, only record 1 and 2 should display only because record 1 is 31/03/2014 to 01/04/2014 and record 2 is 31/03/2014 to 31/03/2014.
If i make 4 records that have today's date. The third label doesn't come out anything. I still will want the label 3 to display IT fair at Atrium tho. If I make 3 records that have today's date(that means without the fourth record which is test). those 3 labels will display as respectively Sales at Cheers, 50% all item and IT fair at Atrium no problem.
public partial class number2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string strConnString = ConfigurationManager.ConnectionStrings["ProjectConnectionString"].ConnectionString;
string str;
SqlCommand com;
SqlConnection con = new SqlConnection(strConnString);
con.Open();
str = "select * from EVENT_ANNOUNCE";
com = new SqlCommand(str, con);
SqlDataReader reader = com.ExecuteReader();
reader.Read();
lblEvent1.Text = reader["EVENTNAME"].ToString();
reader.Read();
lblEvent2.Text = reader["EVENTNAME"].ToString();
reader.Read();
lblEvent3.Text = reader["EVENTNAME"].ToString();
reader.Close();
con.Close();
}
}
You can filter the records by the current date. This should only get records where the current date falls within the start / end date range.
select * from EVENT_ANNOUNCE
where getdate() >= STARTDATE
and cast(getdate() as Date) <= ENDDATE
The time portion of your startdate and enddate values is 00:00:00.000, so using current date to filter results will not return the second record, unless you happen to run this at exactly midnight, down to the millisecond.
So call cast to drop the time portion of the current date, and that should get you both records.
Also, to avoid errors if your query returns no records, make use of the HasRows property:
var events = new List<string>();
if (reader.HasRows)
{
while (reader.Read())
events.Add(reader["EVENTNAME"].ToString());
}
if (events.Count >= 1)
lblEvent1.Text = events[0];
if (events.Count >= 2)
lblEvent2.Text = events[1];
if (events.Count == 3)
lblEvent3.Text = events[2];
How can I check the date I pick from a DateTimePicker control exists in a SQL table?
I have a DateTimePicker on my ASP.NET page where I can select a date. I need to check if this selected date exists in a SQL table (in a table called blockdate). If the selected date does exist, I need to enter the corresponding values from the date and reason columns in the blockdate table into a DataGridView.
Can anybody tell me how I can do this?
This is the code I have so far to check if the selected date is a weekend.
DatePicker.SelectedDate.ToString("dd-MM-yyyy");
DateTime date = DatePicker.SelectedDate.Date;
DateTime weekend;
if (date.DayOfWeek == DayOfWeek.Saturday)
{
weekend = date.AddDays(+2);
}
if (date.DayOfWeek == DayOfWeek.Sunday)
{
weekend = date.AddDays(+1);
}
else
{
weekend = date;
}
I think calling the database on every time when the DatePicker values change not going to be an ideal solution.
You can select all the dates from you sql table to a list in pageload.
var dateList = new List<DateTime>();
dateList = //all the dates from you sql table
Then when the DatePicker value changed, you can match the value against your list.
Hope this helps
I'm trying to filter a deadline column in a datagridview by 2 datetimepickers - startDate and endDate.
datagridview is TaskTable2,
datetimepicker1 is startSchedule,
datetimepicker2 is endSchedule and
deadline in datagridview is deadlineRow
So far I have got the following code which is successfully making the rows invisible which are not between the selected start and end date.
private void scheduleButton_Click(object sender, EventArgs e)
{
DateTime startSchedule = startDate.Value.Date;
DateTime endSchedule = endDate.Value.Date;
if (startSchedule <= endSchedule)// runs foreach loop if startdate and enddate are valid
{
foreach (DataGridViewRow dr in TaskTable2.Rows)// loops through rows of datagridview
{
string deadline = dr.Cells["Deadline"].Value.ToString(); // gets deadline values
DateTime deadlineRow = Convert.ToDateTime(deadline); // converts deadline string to datetime and stores in deadlineRow variable
if (startSchedule <= deadlineRow && deadlineRow <= endSchedule) // filters deadlines that are => startDate and <= endDate
{
dr.Visible = true; // display filtered rows here.
}
else
{
dr.Visible = false; // hide rows that are not beteen start and end date.
}
}
}
else
{
MessageBox.Show("Please ensure Start Date is set before End Date."); // ensures user selects an end date after the start date.
}
}
However, I have a few existing problems:
The application crashes and I get the following error when I select a date range that will display no tasks:
'Row associated with the currency manager's position cannot be made invisible'
I have a print button that is supposed to print the filtered results.
However, it is printing all data stored in the datagridview, even if some rows are visible=false from pressing the schedule button so I'm guessing I need to use a different approach to remove the rows rather than hide them.
The datagridview is bound to an XML file so data can be removed from the datagridview for filtering and printing aslong as they remain in the XML file.
Any help would be greatly appreciated!
Thankyou
I would use the Filter property on the bindingsource for the datagridview. The Filter property allows you to view a subset of the DataSource.
Example from MSDN:
private void PopulateDataViewAndFilter()
{
DataSet set1 = new DataSet();
// Some xml data to populate the DataSet with.
string musicXml =
"<?xml version='1.0' encoding='UTF-8'?>" +
"<music>" +
"<recording><artist>Coldplay</artist><cd>X&Y</cd></recording>" +
"<recording><artist>Dave Matthews</artist><cd>Under the Table and Dreaming</cd></recording>" +
"<recording><artist>Dave Matthews</artist><cd>Live at Red Rocks</cd></recording>" +
"<recording><artist>Natalie Merchant</artist><cd>Tigerlily</cd></recording>" +
"<recording><artist>U2</artist><cd>How to Dismantle an Atomic Bomb</cd></recording>" +
"</music>";
// Read the xml.
StringReader reader = new StringReader(musicXml);
set1.ReadXml(reader);
// Get a DataView of the table contained in the dataset.
DataTableCollection tables = set1.Tables;
DataView view1 = new DataView(tables[0]);
// Create a DataGridView control and add it to the form.
DataGridView datagridview1 = new DataGridView();
datagridview1.AutoGenerateColumns = true;
this.Controls.Add(datagridview1);
// Create a BindingSource and set its DataSource property to
// the DataView.
BindingSource source1 = new BindingSource();
source1.DataSource = view1;
// Set the data source for the DataGridView.
datagridview1.DataSource = source1;
//The Filter string can include Boolean expressions.
source1.Filter = "artist = 'Dave Matthews' OR cd = 'Tigerlily'";
}
I use this type of Filter to show data based on account. For an account, I have a textbox when the user places the account number and I use the TextChanged Event to apply the filter. Then I have a button that is used to remove the Filter from the binding source.
If you want to filter by date you can following instructions in this SO question:
BindingSource Filter by date
Using the filter on a date that is not present should not crash the app, it will just display nothing.
Found a solution to the exception here:
http://discuss.itacumens.com/index.php?topic=16375.0
I added this to my code directly before I attempt to set the row to be not visible. row is my ForEach loop variable. I check to see if its selected and if it is attempt to clear the row and cell selection before setting the visible property.
If gridItems.SelectedRows.Count > 0 AndAlso row.Index = gridItems.SelectedRows(0).Index Then
'fixes dumb exception with row.visible = false
gridItems.ClearSelection()
gridItems.CurrentCell = Nothing
End If
It seems the issue is with making the current row or cell not visible.
I faced exact same problem with exception 'Row associated with the currency manager's position cannot be made invisible'.
dgridView.CurrentCell = null;
dgridView.Rows[i].Visible = false;
Just setting the CurrentCell to null fixed it for me. I haven't checked it further, if it breaks something.
I have a list of data in a data table, I also have a button that when clicked Will Show the Rows that have been completed in the last week.
However, I cant get the table to update after the modifications for some reason
I get the date of 7 days ago, and for every row that has a completed date greater than it in the source DataTable, I delete that row. That should leave me with only rows completed in the last week, but for some reason every row remains after my method is done. Can anyone spot a problem here?
Thanks in advance for any help!
protected void btnShowLastWeek_OnClick(Object sender, EventArgs e)
{
DateTime current = DateTime.Today;
DateTime lastWeek = current.AddDays(-7);
DataTable temp = compDV.Table;
for(int i = 0; i < temp.Rows.Count; i ++)
{
DateTime completed = (DateTime)temp.Rows[i]["DateCompleted"];
if (completed.CompareTo(lastWeek.Date) <= 0)
{
temp.Rows.RemoveAt(i);
}
}
dgCompletedRequests.DataSource = temp;
dgCompletedRequests.DataBind();
}
You should bind to a DataView instead:
dgCompletedRequests.DataSource =
new DataView(compDV.Table, "DateCompleted > #" + lastWeek + "#");
I would follow SLaks' advice from the comments, but when it comes down to it, I would also consider punting and just rewrite the code to query the datatable without modifying the original.
dgCompletedRequests.DataSource =
temp.AsEnumerable()
.Where(row => row.Field<Datetime>("DateCompleted") >= lastWeek)
.AsDataView(); // or .CopyToDataTable(); if you need it
Was dgCompletedRequests.DataSource already set before this code executes? I'm not sure if this will work for you but it has for me in the past, you might give this a try. Set your dgCompletedRequests.DataSource = null; then set it to temp after. Somehow I think this will "reset" the databinding.