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.
Related
I have used a database to populate Data-grids on many occasions.
However, in this instance, i can't seem to get the desired result.
I am trying to display only the people who have a birthday on the day.
i already have the dates, and the Birthday, but i can't seem to get teh rows to add to the datagridview.
here is how far i have got. But he "BirthdayGrdVw.DataSource" i can't seem to figure out.
i have been googling for 2 days.
I am new to this, and would really appreciate some assistance.
private void Tasks_VisibleChanged(object sender, EventArgs e)
{
Clients = Controller.DBQueries.GetPolicyList();
if(Clients != null)
{
foreach(DataRow row in Clients.Rows)
{
string ClientID = Clients.Rows[0]["ClientID"].ToString();
DateTime Birthdate = Controller.GetBirthdate(ClientID);
DateTime now = DateTime.Now;
if (Birthdate.Day == now.Day && Birthdate.Month == now.Month)
{
}
}
}
}
There appears to be things left out you your code, but without all of the information here is what I suggest you try if you are sure that your datatable has been populated.
Add a bindingsource object to your Windows Form by dragging it from the toolbox onto the form.
Set the it will be called bindingsource1. Set it's DataSource to the datatable like this:
BindingSource1.DataSource = "your data table name here";
And then set the DataGridView's DataSource to bindingsource1.
"Your DataGridView".DataSource = BindingSource1;
Or if you don't need some of the extra functionality that a BindingSource provides like "Filter" etc... You could bind the datatable directly to the DataGridView like:
DataGridView.DataSource = "your data table name here";
If Clients is a DataTable and you know what filtering you want to apply then why not use Filter on datatable as :
DataView dv = new DataView(Clients);
dv.RowFilter = "month(of your Birthday Col)="+now.Month+" and day(of your BirthDay Col)="+now.Day;
yourGridView.DataSource = dv.ToTable();
yourGridView.DataBind();
instead of all Foreach loop and all?
I have a MySQL database with comments, and I've already filled in my dataGridView_flaggedComments with flagged comments using this function:
private void button_Search1_Click(object sender, EventArgs e)
{
commentCount = 0;
//comboBox_stockIndex.SelectedIndex = 0;
richTextBox_flaggedComments.Clear();
dataGridView_flaggedComments.Refresh();
DataTable flaggedcomments = new DataTable("flaggedcomments");
using (MySqlConnection sqlConn = new MySqlConnection(strProvider))
{
using (MySqlDataAdapter da = new MySqlDataAdapter("SELECT Comment_ID, Comments_Date, Author, Title, Comments_Comment, Tickers_Ticker_ID FROM comments ORDER BY Comments_Date ASC", sqlConn))
{
da.Fill(flaggedcomments);
}
}
StringBuilder sb = new StringBuilder();
string[] words = File.ReadAllLines(sourceDirTemp + comboBox_crimeKeywords.SelectedItem.ToString() + ".txt");
var query = flaggedcomments.AsEnumerable().Where(r =>
words.Any(wordOrPhrase => Regex.IsMatch(r.Field<string>("Comments_Comment"), #"\b" + Regex.Escape(wordOrPhrase) + #"\b",
RegexOptions.IgnoreCase)));
dataGridView_flaggedComments.DataSource = query.AsDataView();
}
The flagged comments appear in dataGridView_flaggedComments are belong to different stock prices (each stock has its unique symbol and its Ticker_ID). I am trying to filter the current dataGridView_flaggedComments so that it only shows what I selected from comboBox_stockIndex.
However, my code will somehow retrieve all comments for this particular symbol from database rather than filtering what's in the dataGridView_flaggedComments. Can anyone point out what went wrong?
I've went through quite a number of questions at SO, but couldn't really relate it. Here's my code and it would be much appreciated if I could get some help! Thank you!
private void comboBox_stockIndex_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable link_stockIndex = new DataTable("link_stockIndex");
using (MySqlConnection sqlConn = new MySqlConnection(strProvider))
{
using (MySqlDataAdapter da = new MySqlDataAdapter("SELECT Ticker_ID, Symbol FROM tickers", sqlConn))
{
da.Fill(link_stockIndex);
}
}
foreach (DataRow da in link_stockIndex.Rows)
{
for (int i = 0; i < dataGridView_flaggedComments.Rows.Count - 1; i++)
{
if (dataGridView_flaggedComments.Rows[i].Cells["Tickers_Ticker_ID"].Value.ToString() != "" && comboBox_stockIndex.SelectedItem.ToString() == da["Symbol"].ToString())
{
(dataGridView_flaggedComments.DataSource as DataView).RowFilter = string.Format("Tickers_Ticker_ID = '{0}'", da["Ticker_ID"]);
}
}
}
}
You have a very strange code in your comboBox_stockIndex_SelectedIndexChanged handler.
Just have a look: on every index change of combobox you're quering database with always the same query and later in the code you actually doesn't use results of this query. What for is it?
Let's go further. You are iterating over your dataGridView_flaggedComments rows and setting your RowFilter multiple times. Looks pretty unnecessary, as only the last filter will take place.
It looks like your code should be something like this:
Query database for SELECT Ticker_ID, Symbol FROM tickers as you have made, but outside SelectedIndexChanged handler, and store it into datatable.
In SelectedIndexChanged handler iterate over that datatable, and find a row having "Symbol" equal to your comboBox_stockIndex.SelectedItem.
Set RowFilter like "Tickers_Ticker_ID = Ticker_ID from row you've found in previous point. And return, don't set multiple filters.
Remark: I don't know how frequently your tickers database table being changed, so maybe suggestion about query it outside of SelectedIndexChanged is wrong if it changes very frequently.
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.
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 some Excel file reading code that uses the OLEDB (Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=Excel 8.0;) which works well but I keep encountering an issue whereby certain dates are returned as DBNull.
In the original XLS document, the format of dates that work (en-GB locale) are:
"02/04/2009 17:00:00" // returned as a System.DateTime
And the following style fails:
"08/Jan/09 11:24 AM" // returned as DBNull
Excel knows they're both dates (although I can't force them to style correctly) as the following correctly shows a date:
=DATE(YEAR(c),MONTH(c),DAY(c)) // where c = cell reference.
Is there a way, without altering the auto-generated original, to get the data?
EDIT for reference, here is my read-data method (assuming a dbAdapter is set up already -- note the DBNull doesn't come from the catch which isn't fired at all):
public List<List<string>> GetData(string tableName, int maxColumns)
{
List<List<string>> rows = new List<List<string>>();
DataSet ExcelDataSet = new DataSet();
dbCommand.CommandText = #"SELECT * FROM [" + tableName + "]";
dbAdapter.Fill(ExcelDataSet);
DataTable table = ExcelDataSet.Tables[0];
foreach (DataRow row in table.Rows)
{
List<string> data = new List<string>();
for (int column = 0; column < maxColumns; column++)
{
try
{
data.Add(row[column].ToString());
}
catch (Exception)
{
data.Add(null);
}
}
// Stop processing at first blank row
if ( string.IsNullOrEmpty(data[0]) ) break;
rows.Add(data);
}
return rows;
}
I don't know if this will be helpful or not, but I have run into issues with Excel OLEDB code returning NULLs where I expected data and it almost always came back to a data type inference issue. Excel determines the datatype of a column based on the first x rows of data (I think x=10, could be wrong). I know you don't want to alter the file, but it might be worth trying to put the problem date style in the first 10 rows and see if it alters the behavior of your application.
Obviously if it does fix it, then that doesn't solve your problem. The only fixes in that case that I know of are to alter the file (put something in the first 10 rows that forces it to use the correct datatype). Sorry I can't offer a better solution, but hopefully at least I am helping you figure out what's causing your issue.