波斯马BOSSMA Information Technology

多级子项目(任务)计算项目进度的方法

发布时间:2010年5月15日 / 分类:DOTNET, WinForm / 12,887 次浏览 / 评论

现实中遇到这样一个问题:有一个项目,下边有多级任务,我们想获取项目和每一级任务的进度。很多人第一反应就是使用递归,这里先不着急探讨好不好实现。我们先来构建一个例子:

一个项目,有很多子项目(或任务),每个子项目下的子项目数和级次都是不固定的,实际的操作中,我们只需要手工录入最底层的子项目(也就是无下级子项目的项目)的进度,然后能够自动计算各个上级项目的进度,最后获取整体项目的进度。如下图所示树结构:

1、项目实体类

我们可以把这每一个项目抽出来,用一个类来表示:

一个项目包含的属性包括:项目ID、项目名称、项目权重、所属项目ID、项目进度、项目等级。

/// <summary>
??? /// 项目实体类
??? /// </summary>
??? public class Project
??? {
??????? /// <summary>
??????? /// 获取或设置项目的ID
??????? /// </summary>
??????? /// <value>The project ID.</value>
??????? public int ProjectID { get; set; }
??????? /// <summary>
??????? /// 获取或设置项目的名称
??????? /// </summary>
??????? /// <value>The name of the project.</value>
??????? public string ProjectName { get; set; }
??????? /// <summary>
??????? ///获取或设置项目的权重
??????? /// </summary>
??????? /// <value>The project weights.</value>
??????? public decimal ProjectWeights { get; set; }
??????? /// <summary>
??????? /// 获取或设置项目的所属项目ID
??????? /// </summary>
??????? /// <value>The parent ID.</value>
??????? public int ParentID { get; set; }
??????? /// <summary>
??????? /// 获取或设置项目进度
??????? /// </summary>
??????? /// <value>The project progress.</value>
??????? public decimal ProjectProgress { get; set; }
??????? /// <summary>
??????? /// 获取或设置项目的等级
??????? /// </summary>
??????? /// <value>The project progress.</value>
??????? public decimal ProjectGrade { get; set; }
??? }

2、项目数据结构

将上边图中的数据初始化到一个List中:

?projectList = new List<Project>();
??????????? projectList.Add(new Project(1, "我的项目", 1, 0, 0, 1));
??????????? projectList.Add(new Project(2, "子项目1", new decimal(0.50), 1, 0, 2));
??????????? projectList.Add(new Project(3, "子项目2", new decimal(0.50), 1, 0, 2));
??????????? projectList.Add(new Project(4, "子项目11", new decimal(0.40), 2, 0, 3));
??????????? projectList.Add(new Project(5, "子项目12", new decimal(0.60), 2, 0, 3));
??????????? projectList.Add(new Project(6, "子项目121", new decimal(0.50), 5, 0, 4));
??????????? projectList.Add(new Project(7, "子项目122", new decimal(0.50), 5, 0, 4));
??????????? projectList.Add(new Project(8, "子项目1221", new decimal(0.20), 7, 0, 5));
??????????? projectList.Add(new Project(9, "子项目1222", new decimal(0.80), 7, 0, 5));
??????????? projectList.Add(new Project(10, "子项目21", new decimal(0.20), 3, 0, 3));
??????????? projectList.Add(new Project(11, "子项目22", new decimal(0.40), 3, 0, 3));
??????????? projectList.Add(new Project(12, "子项目23", new decimal(0.20), 3, 0, 3));
??????????? projectList.Add(new Project(13, "子项目231", new decimal(0.50), 12, 0, 4));
??????????? projectList.Add(new Project(14, "子项目232", new decimal(0.50), 12, 0, 4));

3、设置无下级项目的进度值

检查是否有下级子项目:

private bool IsProjectHasSubProject(int projectID)
??????? {
??????????? foreach (Project objProject in parojectList)
??????????? {
??????????????? if (objProject.ParentID == projectID)
??????????????? {
??????????????????? return true;
??????????????? }
??????????? }
??????????? return false;
??????? }

遍历每个项目,如果没有下级项目,则设置一个百分值。

Random ro = new Random();
??????????? foreach (Project objProject in projectList)
??????????? {
??????????????? if (!IsProjectHasSubProject(objProject.ProjectID))
??????????????? {

??????????????????? objProject.ProjectProgress = new decimal(ro.Next(0, 100));
??????????????? }
??????????? }

递归添加到Treeview,显示出来看看:

private void ShowTreeView()
??????? {
??????????? treeView1.Nodes.Clear();
??????????? InitTreeView(treeView1.Nodes, 0);
??????????? treeView1.ExpandAll();
??????? }

private void InitTreeView(TreeNodeCollection collection, int parentID)
??????? {
??????????? foreach (Project objProject in projectList)
??????????? {
??????????????? if (objProject.ParentID == parentID)
??????????????? {

??????????????????? TreeNode node = new TreeNode(objProject.ProjectName + " [权重:" + objProject.ProjectWeights + " 进度:" + objProject.ProjectProgress + "%]");
??????????????????? collection.Add(node);

??????????????????? InitTreeView(node.Nodes, objProject.ProjectID);
??????????????? }
??????????? }
??????? }

4、计算项目进度

很多人想到的都是递归,这里先用递归试试:

private void FormTopToBottomRecursiveProgressCal(Project parentProject)
??????? {
??????????? decimal progressCount = 0;
??????????? foreach (Project objProject in projectList)
??????????? {
??????????????? if (objProject.ParentID == parentProject.ProjectID)
??????????????? {
??????????????????? if (objProject.ProjectProgress == 0)
??????????????????? {
??????????????????????? FormTopToBottomRecursiveProgressCal(objProject);
??????????????????? }

??????????????????? progressCount += objProject.ProjectProgress * objProject.ProjectWeights;
??????????????? }
??????????? }
??????????? progressCount = decimal.Round(progressCount, 2);
??????????? parentProject.ProjectProgress = progressCount;
??????? }

?看起来不错,代码挺简洁。

这里再提供一种方法:按照级次计算,从最低的级次开始计算:

首先实现一个类,用来项目级次排序:

/// <summary>
??? /// 排序项目级次
??? /// </summary>
??? public class SortProjectGrade : IComparer<Project>
??? {
??????? /// <summary>
??????? /// Compares the specified project1.
??????? /// </summary>
??????? /// <param name="project1">The project1.</param>
??????? /// <param name="project2">The project2.</param>
??????? /// <returns></returns>
??????? public int Compare(Project project1, Project project2)
??????? {
??????????? if (project1 != null && project2 != null)
??????????? {
??????????????? if (project1.ProjectGrade == project2.ProjectGrade)
??????????????????? return 0;
??????????????? else
??????????????????? return project1.ProjectGrade > project2.ProjectGrade ? 1 : -1;

??????????? }

??????????? return -1;
??????? }
??? }

下边是用来计算进度的方法:

private void FromBottomToTopGradeCalProgress()
??????? {
??????????? //获取项目级次
??????????? SortProjectGrade objSortProjectGrade = new SortProjectGrade();
??????????? projectList.Sort(objSortProjectGrade);

??????????? int grade = projectList[projectList.Count - 1].ProjectGrade;

??????????? //遍历每个级次
??????????? for (int i = grade - 1; i > 0; i--)
??????????? {
??????????????? //遍历项目列表,获取当前级次
??????????????? foreach (Project project in projectList)
??????????????? {
??????????????????? if (project.ProjectGrade == i)
??????????????????? {
??????????????????????? //获取项目的下级,求和
??????????????????????? int count = 0;
??????????????????????? decimal progressCount = 0;
??????????????????????? foreach (Project subproject in projectList)
??????????????????????? {
??????????????????????????? if (subproject.ParentID == project.ProjectID)
??????????????????????????? {
??????????????????????????????? progressCount += subproject.ProjectProgress * subproject.ProjectWeights;
??????????????????????????????? count++;
??????????????????????????? }
??????????????????????? }

??????????????????????? if (count != 0)
??????????????????????? {
??????????????????????????? progressCount = decimal.Round(progressCount, 2);
??????????????????????????? project.ProjectProgress = progressCount;
??????????????????????? }
??????????????????? }
??????????????? }
??????????? }
??????? }

使用两种方法都可以准确的计算进度,如图计算结果:

使用递归或者根据级次循环计算,可能有时候选择会不一样。

本文仅提供参考,欢迎就此问题与我交流。

本博客所有文章如无特别注明均为原创。
复制或转载请以超链接形式注明转自波斯马,原文地址《多级子项目(任务)计算项目进度的方法

关键字:

建议订阅本站,及时阅读最新文章!
【上一篇】 【下一篇】

发表评论