我在SqlServer中有一个表,其中包含:(ID,项目名称,添加的日期时间)
我想创建一个C#代码,首先:在datagridview中查看(ID,item_name,date_time_added)列,然后计算(date_time_NOW-date_time_added),并在同一datagridview中的新列(名为:expire's in :)中查看结果。 ..
注意:结果将计算到期前一天的剩余时间
到目前为止我已经尝试过的:
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Expire's in:", typeof(int)));
int countrow = dataGridView1.RowCount;
for (int i = 0; i < countrow; i++)
{
string dateAsString = dataGridView1.Rows[dataGridView1.SelectedRows[0].Index].Cells[3].Value.ToString();
DateTime.TryParseExact(dateAsString , "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AssumeLocal, out DateTime dateAsString);
dateTimePicker3.Text = dateAsString;
DateTime expire_date = dateTimePicker3.Value;
TimeSpan span = expire_date - DateTime.Now;
int days = span.Days;
dataGridView1.Rows[dataGridView1.SelectedRows[0].Index].Cells[4].Value = days;
}
注意:代码已更新... 任何帮助将不胜感激..
答案 0 :(得分:0)
根据我的发现,您尝试在此处将字符串放入DateTime值:
DateTime str;
str=dataGridView1.Rows[dataGridView1.SelectedRows[0].Index].Cells[3].Value.ToString();
如果要将字符串解析为DateTime,代码应如下所示:
string dateAsString = dataGridView1.Rows[dataGridView1.SelectedRows[0].Index].Cells[3].Value.ToString();
DateTime.TryParseExact(dateAsString, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AssumeLocal, out DateTime dateAsDateTime);
然后您可以从DateTime中减去该日期。现在:
TimeSpan span = dateAsDateTime - DateTime.Now;
最后从跨度中提取日期:
int days = span.Days;
或者只需一行完成所有操作:
int days = (DateTime.Now - dataGridView1.Rows[dataGridView1.SelectedRows[0].Index].Cells[3].Value).Days;
答案 1 :(得分:0)
我将假定从sql查询返回的“ ExpireDate”字段是DateTime
对象。如果是这种情况,那么似乎没有必要将“日期”转换为字符串。例如,给定一个“未来”日期,那么今天的日期和“未来”日期之间的差可以实现为……
TimeSpan dif = futureDate.Subtract(DateTime.Now);
使用DataTable
可以使用Expression
列,但是,我认为这不适用于日期和时间。幸运的是,如果网格DataSource
是DataTable
,则实现起来并不难。使用“类”将是另一种选择。本示例使用DataTable
作为网格的DataSource
。
鉴于此,为了简化起见,似乎很方便的方法是从数据表中获取DataRow
,并添加此TimeSpan
差异。可能看起来像下面的样子……
private void SetDifCol(DataRow row) {
TimeSpan dif = ((DateTime)row["ExpireDate"]).Subtract(DateTime.Now);
row["TimeToExpire"] = dif.Days + " days " + dif.Hours + " hours " + dif.Minutes + " minutes";
}
鉴于DataTable
已经被数据填充了,代码将不得不“添加”该差异列,然后遍历每一行并计算日期之间的差异。因此,仅添加此列的一个小方法可能如下所示……
private void AddDifferenceColumn(DataTable dt) {
dt.Columns.Add("TimeToExpire", typeof(string));
}
下一步是遍历DataTable
中所有行的循环,只需在每一行上调用SetDifCol
方法。
private void CalculateDateDif(DataTable dt) {
foreach (DataRow row in dt.Rows) {
SetDifCol(row);
}
}
这将在加载数据时按预期工作,但是,如果用户“更改”网格中的“ ExpireDate”值之一怎么办?在这种情况下,我们需要连接一个网格单元更改事件。特别是网格CellValueChanged
事件。如果该行中的“ ExpireDate”值发生更改,则此事件将调用SetDifCol
方法。
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
if (dataGridView1.Columns[e.ColumnIndex].Name == "ExpireDate") {
if (e.RowIndex >= 0 && dataGridView1.Rows[e.RowIndex].Cells["ExpireDate"].Value != null) {
DataRowView row = (DataRowView)dataGridView1.Rows[e.RowIndex].DataBoundItem;
SetDifCol(row.Row);
}
}
}
将所有内容放在一起可能如下所示……
DataTable GridTable;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
GridTable = GetTable();
FillTable(GridTable);
AddDifferenceColumn(GridTable);
CalculateDateDif(GridTable);
dataGridView1.DataSource = GridTable;
dataGridView1.Columns[3].Width = 180;
}
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(string));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("ExpireDate", typeof(DateTime));
return dt;
}
private void AddDifferenceColumn(DataTable dt) {
dt.Columns.Add("TimeToExpire", typeof(string));
}
private void FillTable(DataTable dt) {
dt.Rows.Add("ID1", "Name1", new DateTime(2019, 12, 31));
dt.Rows.Add("ID2", "Name2", new DateTime(2019, 8, 31));
dt.Rows.Add("ID3", "Name3", new DateTime(2019, 4, 30));
dt.Rows.Add("ID4", "Name4", new DateTime(2019, 1, 31));
dt.Rows.Add("ID5", "Name5", new DateTime(2019, 4, 12, 21, 38, 00));
}
private void CalculateDateDif(DataTable dt) {
foreach (DataRow row in dt.Rows) {
SetDifCol(row);
}
}
private void SetDifCol(DataRow row) {
TimeSpan dif = ((DateTime)row["ExpireDate"]).Subtract(DateTime.Now);
row["TimeToExpire"] = dif.Days + " days " + dif.Hours + " hours " + dif.Minutes + " minutes";
}
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
if (dataGridView1.Columns[e.ColumnIndex].Name == "ExpireDate") {
if (e.RowIndex >= 0 && dataGridView1.Rows[e.RowIndex].Cells["ExpireDate"].Value != null) {
DataRowView row = (DataRowView)dataGridView1.Rows[e.RowIndex].DataBoundItem;
SetDifCol(row.Row);
}
}
}
我希望这会有所帮助。
编辑:
将列类型从string
更改为int
以进行数字排序。
关于您发布的其他问题,您评论说“我想根据我的数据库表中的内容进行计算” …此问题中没有任何代码或显示的其他问题一个数据库。您如何开始获取数据?
在此问题中似乎出现了一个新的DataTable
dt
,并向其中添加了一个列,但是从未使用过它。代码中的循环只是将差异列添加到“ GRID”而不是DataTable.
我的答案是将差异列添加到DataTable
(您应该这样做)。我建议您说明如何从数据库中获取数据。
关于对列进行排序,您已经注意到string
个数字不能正确地按数字排序。这是因为它们是字符串...解决方案...使它们为ints
。使用我的答案,对此需要两个更改。首先,列的创建需要为int
类型…
private void AddDifferenceColumn(DataTable dt) {
dt.Columns.Add("TimeToExpire", typeof(int));
}
第二个SetDifCol
方法需要更改。由于您只希望日差,并且任何小于零的值都应显示为零(0),因此以下更改应符合此要求。
private void SetDifCol(DataRow row) {
TimeSpan dif = ((DateTime)row["ExpireDate"]).Subtract(DateTime.Now);
if (dif.Days >= 0) {
row["TimeToExpire"] = dif.Days;
}
else {
row["TimeToExpire"] = 0;
}
}
这两个更改应按预期对列进行数字排序。
最后,应该清楚的是,如果您希望此“差异”列反映在数据库中……那么您将不得不将差异列添加到数据库表中,然后,您将需要发出更新命令到数据库表。