【问题标题】:Displaying yearly totals in ListView control在 ListView 控件中显示年度总计
【发布时间】:2018-07-13 21:28:42
【问题描述】:

我正在测试一个示例应用程序,该应用程序添加了许多个人,即“人”,并为每个人记录了一年中每个月的时间度量,即“minTime”一个十进制值,“auxTime”一个十进制值。

在我的代码中,我遍历了一个 SQL 数据库表,以计算每个人小时数的十进制值。 “person”是一个 nvarchar,“yearTotal”是一个小数。

我想在 ListView 屏幕中显示总数。

出于测试目的,我添加了 2 人。每个人都有一个为 12 个月中的每一个输入的时间度量。

我遇到了两个问题。

1) 尝试将“yearTotal”添加到 ListView 控件,最终显示 每个月 的 12 个月价值数据中的每个人

例如:John Smith 50 小时、John Smith 75 小时等,而不是 John Smith 的总数,这适用于所有人。

2) 一旦“yearTotal”达到第一个人的正确总数,它就会保持这个值并为下一个人增加它,为所有后续人提供一个错误的值。

我需要知道如何(以及在​​何处)将每个人的年度总计添加到 ListView 控件的一个条目中,而不是同一个人的多个条目。

例如:John Smith 840 小时,Sally Jones 750 小时。

这里是一个下载“testDB”的链接,其中包含一个名为“timeRecord”的表。 请记住,我需要一种方法来完全总计每个人的值,总计他们从 1 月到 12 月的值,并在 ListView 控件中显示该人的总计。

当我尝试在 minTime 和 auxTime 列(带有别名)上使用 SUM 时,SQL 仍会显示各个月份的总计,但不会显示每个人的单个总计。 sample database

【问题讨论】:

  • 不要使用 for 循环,只需将命令更改为:SELECT PEOPLE, SUM(MINTIME) FROM TIEMTABLE ORDER BY PEOPLE ASC GROUP BY PEOPLE 它将解决所有问题
  • 你好,Aleksa。我尝试了您的建议,但我相信 ORDER BY 子句必须是您在查询中指定的最后一个子句。但是,当我将 GROUP BY 人放在 ORDER BY 人之后,我在“minTime”上不断收到错误消息。当我深入研究错误时,它会在“minTime”上报告 System.IndexOutOfRangeException,尽管 SQL Server Management Studio 显示所有人都有 minTime 数据。不确定为什么会发生此错误。

标签: c# winforms sql-server-2012-express


【解决方案1】:

我不会解释它,只是写完成的代码。

class String_String
{
    public _string1 { get; set; }
    public _string2 { get; set; }
}


try
{
    using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\TimeKeeping.mdf;Integrated Security=True;User Instance=False"))
    {
        conn.Open();

        using (SqlCommand cmd = new SqlCommand(
        "SELECT people, SUM(minTime) FROM timeTable ASC GROUP BY PEOPLE ORDER BY people", conn))
        {
            SqlDataReader dr = cmd.ExecuteReader();

            List<String_String> list = new List<String_String>();

            while(dr.Read())
            {
                list.Add(new List<String_String> { _string1 = dr[0].ToString(), _string2 = dr[1].ToString() });
            }


            lstVwPeopleTime.DataSource = list;
            lstVwPeopleTime.DisplayMember = "_string2";
            lstVwPeopleTime.ValueMember = "_string1";
        }
    }
}
catch (SqlException ex) { MessageBox.Show(ex.Message); }
catch (System.Exception ex) { MessageBox.Show(ex.Message); }

代码未经测试,因此可能会出错。

【讨论】:

  • Aleksa,我无法让您的代码正常工作。但是,在尝试对我的列求和时,我注意到了一个明显的问题。例如,如果我这样编写代码:使用 (SqlDataAdapter adap = new SqlDataAdapter("SELECT people, SUM(minTime) FROM timeTable ORDER BY people ASC", conn)),那么它会抛出错误“列不属于桌子。”当我单步执行代码时,它显示 [0] {people}, [1] {Column 1} 而不是 {minTime}。为什么对列执行 SUM 会阻止查询识别实际的列名?
  • 试试SUM(minTime) as TIME
  • 你好,Aleksa。这更正了引发的错误。但是,它仍然没有给我每个人的总数。无论我在代码中还是在 SQL Server Management Studio 中尝试,它仍然会显示每个人的十进制值列表。因此,我将尝试将 Decimal 值读入一个数组,然后对它们进行 SUM。
  • @CodeMann 你能给我提供你的表结构吗,里面只有几行
  • Aleksa,请查看我在上面编辑过的 cmets,即提供所请求的附加数据库结构和解释性信息。
【解决方案2】:

我终于想出了如何解决我遇到的问题。 我创建了一个单独的方法,即 private void GetTotals(string name),其中我传递了每个人的姓名。我从表名中查询了人,minTime,auxTime,其中 person = @person。然后在 SQL 数据读取器循环中,我递增 minTime 和 auxTime 值并将这些值传递给 ListViewItem 以在我的 ListView 控件中显示。

while (reader.Read())
{
    yearTotal += Convert.ToDecimal(reader["minTime"].ToString(), CultureInfo.InvariantCulture) + 0.00M;
    auxTotal += Convert.ToDecimal(reader["auxTime"].ToString(), CultureInfo.InvariantCulture) + 0.00M;
}
ListViewItem listItem = new ListViewItem(name);
listItem.SubItems.Add(yearTotal.ToString());
listItem.SubItems.Add(auxTotal.ToString());
lstVwPeopleTime.Items.Add(listItem);
name = "";
return;

在我以前的方法中,我只是创建和实例化一个 ArrayList,查询表中所有人员的姓名并将它们添加到 ArrayList。然后在 foreach 循环中,我将每个人的姓名传递给 GetTotals 方法。此方法成功汇总并在 ListView 控件中显示每个人的 12 个月值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    相关资源
    最近更新 更多