雪連,李家
(遼寧師范大學(xué) 城市與環(huán)境學(xué)院, 遼寧 大連 116029)
摘要:針對B/S模式下甘特圖交互操作性差、傳統(tǒng)的單線條甘特圖不便于對比分析項目的計劃和實施情況等問題,提出了利用列模板技術(shù)實現(xiàn)雙線條甘特圖的解決方案。甘特圖中包含上下兩根線條,分別代表項目的進度計劃和實施情況。用戶通過簡單地點擊甘特圖可以對計劃進行微調(diào),對實施進行記錄。使用結(jié)果表明,這種雙線條甘特圖擴展了甘特圖的使用方式,可以直觀地對比檢查計劃和實施情況;交互操作性好,易于掌握和使用;基于通用的列模板技術(shù),易于開發(fā)。
關(guān)鍵詞:項目進度管理;甘特圖;列模板;DevExpress ASPxGridView
0引言
項目進度控制是項目計劃控制的中心任務(wù)和重要內(nèi)容,它直接關(guān)系到項目能否按期完成,并最終影響項目的成功[1]。甘特圖是進行工期計劃和控制的有效工具,它以橫坐標表示時間,縱坐標表示項目分解的各項工作任務(wù), 清楚地表達了活動的開始時間、結(jié)束時間和持續(xù)時間[2]。目前已經(jīng)可以基于B/S模式繪制甘特圖[25]。
以往所見的甘特圖是一條線條圖,表示在整個期間上計劃或?qū)嵤┣闆r。這種方式不能直觀表達計劃方案與實際完成情況的對比,不便于檢查和大數(shù)據(jù)挖掘。另外,受計算機軟件技術(shù)發(fā)展所限,有些以Web方式實現(xiàn)的甘特圖只能將數(shù)據(jù)顯示為圖形,不能與圖形進行直觀的互操作,反作用于數(shù)據(jù);有些甘特圖軟件的開發(fā)方法過于復(fù)雜,不易實現(xiàn)。
由于在使用甘特圖進行項目管理系統(tǒng)開發(fā)時遇到了上述問題,因此在工作中以提高甘特圖的互操作性和直觀對比計劃和實施情況為研究目的,基于B/S模式以常用的列模板技術(shù)實現(xiàn)了甘特圖。系統(tǒng)中采用上下兩根線條表示一項任務(wù)的計劃和實施情況,如圖1所示。上面的計劃條如為灰色表示該時段有這項任務(wù)的計劃,下面的實施條如為黑色表示該時段的任務(wù)已實施。在計劃階段,用戶可以通過選擇起止日期對整個區(qū)間設(shè)定計劃,可以點擊某個時間段的任務(wù)塊進行微調(diào),取消或設(shè)定該時間段的計劃。在實施階段,用戶可以在完成某個時間段的任務(wù)后點擊該時間段的任務(wù)塊,使該任務(wù)塊中下面的實施條從灰變紅,表示實施了該時段的任務(wù)。系統(tǒng)擴展了甘特圖的使用方式,提供了較好的交互操作功能和用戶體驗,同時因采用了常用的模板技術(shù)開發(fā)而易于實現(xiàn)。
1系統(tǒng)設(shè)計與實現(xiàn)
系統(tǒng)的實現(xiàn)方法如下:
(1)確定計劃和實施值在數(shù)據(jù)庫中存儲方式。因時間段很多,不能為每個時間段建立一個字段,各時間段的計劃和實施值在數(shù)據(jù)庫要分別合并存儲為一個字符串;
?。?)將數(shù)據(jù)庫中的表取到程序中后,自動增加各時間段的字段,以便用戶可以對每一個時間段中的任務(wù)塊進行交互處理;
(3)將數(shù)據(jù)表每條記錄中的計劃和實施值轉(zhuǎn)換為各時間段字段的值;
(4)將步驟(2)~(3)改造后的數(shù)據(jù)表綁定到ASPxGridView后,將各時間字段的值表現(xiàn)為任務(wù)塊圖片;
(5)為每個任務(wù)塊圖片的鼠標點擊事件給出客戶端響應(yīng)函數(shù),改變圖片的顏色。
1.1計劃、實施數(shù)據(jù)在數(shù)據(jù)庫中的存儲
系統(tǒng)中需將每項任務(wù)的起止日期、計劃、實施情況記錄到數(shù)據(jù)庫中。本系統(tǒng)中以半天作為最小時間段,為節(jié)省存儲空間,沒有為每個時間段建立一個字段,而是將所有時間段的計劃值和實施值分別記錄在一個字符串字段中,用“1”或“0”表示該時間段是否有值,每個字符在串中的位置隱含了其代表的時間段。例如,圖2中,第一條記錄中,計劃字段中的第一個字符“1”表示9月6日上午有方案制定任務(wù),實施字段中的第三個字符“1”表示9月7日上午實施了方案制定任務(wù)。
程序中制定計劃并存儲的主要代碼為:
string plan = "", real = "";
for (DateTime date1 = (DateTime)newValues["起始日期"]; date1 <= (DateTime)newValues["截止日期"]; date1 = date1.AddDays(1))
{
plan += "11";
real += "00";
}
row["計劃"] = plan;
row["實施"] = real;
代碼中newValues["起始日期"]和newValues["截止日期"]為用戶在為某項任務(wù)制定計劃界面上輸入的起止日期,row為在數(shù)據(jù)表中為該任務(wù)新增的一條記錄,制定計劃時每天的計劃值為“11”,實施值為“00”,將其累加后賦給row中對應(yīng)的字段值,更新到數(shù)據(jù)庫中。
1.2增加時間段字段
圖2中的數(shù)據(jù)的前兩行在系統(tǒng)中的顯示結(jié)果如圖1所示。圖1中各時間段字段不是數(shù)據(jù)庫中已有字段,而是將數(shù)據(jù)取到程序中后,根據(jù)起止日期為數(shù)據(jù)表中增加的字段。主要代碼如下:
TimeSpan ts = date2 - date1;
string[] fields = new string[(ts.Days + 1) * 2];
for (int i = 0; i < fields.Length; date1 = date1.AddHours(12), i++)
{
string s = date1.Year.ToString().Substring(2) + "-" + date1.Month + "-" + date1.Day;
if (date1.Hour < 12)
s += "上午";
else
s += "下午";
fields[i] = s;
table.Columns.Add(s);
}
代碼中date1、date2為要顯示的時間段的起止日期,fields為根據(jù)起止日期建立的時間字段名數(shù)組,循環(huán)中根據(jù)起止日期生成每個時間段字段的名稱,最后增加到數(shù)據(jù)表table的列中。
1.3確定記錄中時間段字段的值
時間段字段中的值是在程序中根據(jù)計劃、實施字段值生成的,代碼為:
row[s1] = "" + row["計劃"].ToString()[k] + row["實施"].ToString()[k];
代碼中row為某一條任務(wù)記錄,s1為某一個時間段的字段名,row["計劃"].ToString()[k]為計劃字段中從起始日期開始第k個半天的值,row["實施"].ToString()[k]為實施字段中第k個半天的值,row[s1]為計算后得到的s1字段的值,它可能的值為:“00”、“01”、“10”、“11”。以其中兩例說明:“10”值采用列模板技術(shù)顯示在界面中時對應(yīng)的任務(wù)塊圖片名稱為 “10.png”,該圖片的計劃條為灰色,實施條為淺灰色;“11”對應(yīng)的任務(wù)塊圖片名稱為 “11.png”,該圖片的計劃條灰色,實施條為黑色。
1.4利用列模板將時間字段值表現(xiàn)為任務(wù)塊圖片
ASP.NET為了更精確地控制列的內(nèi)容和布局,在DataGrid中支持綁定列和模板列的定義,該模板列可創(chuàng)建HTML文本和服務(wù)器控件的組合,以便為列設(shè)計自定義布局[6]。這種列模板技術(shù)易于掌握,為表現(xiàn)復(fù)雜的頁面提供了方便的工具。本系統(tǒng)利用DevExpress 的ASP.NET 控件庫ASPxGridView中的列模板表現(xiàn)甘特圖。
程序中取到數(shù)據(jù)表增加時間段字段并為每條記錄的時間段字段賦值后,綁定到ASPxGridView中,利用ASPxGridView的列模板將表中每行中每個時間段字段列顯示為與該列字段值對應(yīng)的任務(wù)塊圖片。代碼為:
(ASPxGridView1.Columns[i]as GridViewDataColumn). DataItemTemplate = new scheduleItemTemplateG( ASPxGridView1.Columns[i].FieldName);
代碼中Columns[i]為某一時間段列,DataItemTemplate為該列的數(shù)據(jù)模板屬性,scheduleItemTemplateG為自定義的模板類,在該類中為每行每列的值顯示相應(yīng)的圖片。主要代碼如下:
public class scheduleItemTemplateG : System.Web.UI.Page, ITemplate
{
string field;
public scheduleItemTemplateG(string field)
{
this.field = field;
}
public void InstantiateIn(Control container)
{
…
GridViewDataItemTemplateContainer gridContainer = (GridViewDataItem TemplateContainer)container;
ASPxHyperLink link = new ASPxHyperLink();
link.ImageUrl = imgPath + gridContainer.Text + ".png";
…//為超鏈增加客戶端點擊事件處理函數(shù)
gridContainer.Controls.Add(link);
}
}
代碼中在該類的構(gòu)造函數(shù)中傳入了該列時間字段的名稱,記錄在field成員中。InstantiateIn函數(shù)在該行該列顯示時自動調(diào)用,傳來了該行該列中的控件容器。函數(shù)中imgPath為圖片所在路徑,gridContainer.Text為控件中顯示的字符串,其值為該列的計劃字符+實施字符,imgPath + gridContainer.Text + ".png"為包含路徑在內(nèi)的圖片名稱,將其賦給新建超鏈link的ImageUrl屬性,以便在超鏈中顯示該圖片。最后將超鏈加入到該控件容器中,顯示為圖片。
1.5處理任務(wù)塊圖片的鼠標點擊事件
在計劃制定時可以進行微調(diào),如圖3所示,用戶點擊“微調(diào)”按鈕,然后點擊某個時段的任務(wù)塊,就能取消或設(shè)定該時段的計劃。類似地,點擊“執(zhí)行任務(wù)”按鈕可以在實施時標識某個時段的任務(wù)已執(zhí)行,如圖4所示。這需要對每個任務(wù)塊超鏈的客戶端點擊事件給出響應(yīng)函數(shù),以便在客戶端改動任務(wù)塊圖片的計劃條或?qū)嵤l的顏色,同時改動該任務(wù)塊對應(yīng)于計劃字段或?qū)嵤┳侄巫址械哪莻€字符的值。
為此,在上述代碼“為超鏈增加客戶端點擊事件處理函數(shù)”注釋處增加以下代碼:
DateTime startDate = (DateTime)gridContainer.Grid.GetRowValues(gridContainer. VisibleIndex, "起始日期");
DateTime date = Convert.ToDateTime("20" + field.Replace("上午?", "").Replace("下午", ""));
int indexInValueArray = (date - startDate).Days*2 + (field.IndexOf("上午") > 0 ? 0 : 1);
link.ClientSideEvents.Click = "function(s,e){onLinkClick(e," + gridContainer. VisibleIndex + "," + indexInValueArray + ")}";
代碼中startDate為表中該行任務(wù)的起始日期,date為該列字段名(某天的上午或下午)代表的日期,indexInValueArray為該時間字段列在時間字段數(shù)組中的序數(shù),也就是該列在計劃和實施字段中對應(yīng)字符的下標。onLinkClick為超鏈的客戶端Click事件的響應(yīng)函數(shù),響應(yīng)函數(shù)中傳入了該列所在的行數(shù)和該列在計劃和實施字段中對應(yīng)字符的下標。JavaScript中onLinkClick函數(shù)的主要代碼如下:
function onLinkClick(e, rowIndex, indexInValueArray)
{
if (document.getElementById("rowIndex_button").value.indexOf("微調(diào)") > 0)
var w = -2;
else
var w = -1;
var n = e.htmlElement.innerHTML.indexOf(".png");
var s = e.htmlElement.innerHTML.substring(0, n + w) + s1 + e.htmlElement.innerHTML. substring(n + w + 1);
e.htmlElement.innerHTML = s;
…
var value = document.getElementById("valueArray").value;
document.getElementById("valueArray").value = value.substring(0, indexInValueArray) + s1 + value.substring(indexInValueArray + 1);
}
代碼中e.htmlElement為事件中鼠標所點超鏈,n為擴展名“.png”在該超鏈的innerHTML中的位置。如果在計劃階段點擊“微調(diào)”按鈕修改計劃(見圖3),則w=-2,s1對應(yīng)圖片名中的第一個字符即計劃字符;如果點擊“執(zhí)行任務(wù)”或“結(jié)束任務(wù)”按鈕(見圖4),則w=-1,s1對應(yīng)圖片名的第二個字符即實施字符。s1 的值為跟頭鍵值,原來為“0”則變?yōu)椤?”,原來為“1”則變?yōu)椤?”。改動了e.htmlElement.innerHTML中圖片名后,相應(yīng)的任務(wù)塊中的計劃條或?qū)嵤l也就改變了顏色。
document.getElementById("valueArray").value為鼠標所在行中計劃列或?qū)嵤┝械淖址担斢脩酎c擊“微調(diào)”、“執(zhí)行任務(wù)”或“結(jié)束任務(wù)”按鈕時取得,保存在客戶端hidden標簽valueArray中。在鼠標點擊事件中,該值中鼠標所點時間段對應(yīng)的字符也要相應(yīng)地改為s1的值,臨時記錄在客戶端,點擊“更新”按鈕時再一起更新到數(shù)據(jù)庫中。
2結(jié)論
本系統(tǒng)基于DevExpress ASPxGridView控件的列模板技術(shù)實現(xiàn),已用于房地產(chǎn)評估項目管理系統(tǒng)中。使用結(jié)果表明,這種雙線條甘特圖可以直觀地對比檢查計劃和實施情況,打破了傳統(tǒng)的單線條甘特圖的使用方式,表現(xiàn)力更豐富;通過簡單點擊就可以對每個任務(wù)塊進行交互操作,克服了以往B/S模式下的甘特圖只能看不能交互操作的弊病;根據(jù)本文給出的實現(xiàn)方法,可以很容易地采用ASP.NET 中的Gridview中的模板技術(shù)實現(xiàn),或利用其他開發(fā)平臺中的相關(guān)技術(shù)實現(xiàn)。
參考文獻
?。?] 肖偉,趙嵩正. 基于OLE技術(shù)的項目甘特圖設(shè)計與實現(xiàn)[J]. 微型電腦應(yīng)用, 2003,19(10):20-22.
[2] 梁海燕,趙嵩正. 基于JSP技術(shù)工程項目甘特圖的設(shè)計與實現(xiàn)[J]. 計算機應(yīng)用與軟件, 2006,23(8):43-44,59.
?。?] 夏臻,陳建勛. 基于SVG技術(shù)的甘特圖繪制組件設(shè)計與實現(xiàn)[J]. 計算機工程與設(shè)計, 2010,31(10):2354-2357.
?。?] 王俊,楊濤. 基于JSP技術(shù)的項目甘特圖設(shè)計與實現(xiàn)[J]. 現(xiàn)代制造工程,2008(2):80-83.
[5] 安思,張菹,葉鑫. 基于AMT算法的時間序列數(shù)據(jù)在甘特圖中的應(yīng)用[J]. 計算機與數(shù)字工程, 2011,39(6):146-149.
?。?] 李林靜. 基于DataGrid模板列的分析及應(yīng)用[J].計算機系統(tǒng)應(yīng)用,2009,18(3):57-61.