簡單工程項目管理系統

 我是背後那一束模糊的影子,只爲襯托前面那個美麗……圖片

        實現這個“簡單”的管理系統其實不是那麼簡單!
        其中總結我所遇到的幾個大問題:
                其一:對於一個界面型的管理系統,用我所熟悉的MFC實現,也不斷的碰見控件操作和數據交換問題;
                其二:數據庫操作,對於MFC的CRecordset類來說,還是需要研究一下才能加入這個系統的使用中來的;
                其三:生成項目報表,這就需要利用MFC來操作word,用MFC提供的庫文件來形成word文檔的報表;
        下面就來一 一介紹我克服這幾個問題的過程吧!

        第一個,控件操作與數據交換!
        首先給大家看一下該系統所涉及的幾個界面:
圖片
            登陸界面
 
            經營部管理主界面
 
            綜合部、生產部、總工辦管理主界面類似
 
            用戶信息更改界面
 
            項目信息查詢界面
 
            用戶信息註冊界面

        該系統流程大致是:經營部接到項目,填寫項目信息和項目安排,交由下一級總工辦;總工辦登陸顯示該項目信息,填寫項目安排後交由下一級生產部;生產部登陸顯示該項目信息,填寫項目安排後交由下一級綜合部;綜合部登陸顯示該項目信息,填寫項目安排後提交下一級返回經營部,此項目完成整個流程。經營部再次登陸,可填寫新項目信息和安排。每個部門都可以查看之前所有項目的信息。

        之前說的關於控件的操作問題主要就是由於經營部、綜合部、生產部、總工辦的管理界面相似度很大,我不想做四個Dialog,所以就想着這四個部門共用一個對話框。還有就是不同的用戶登陸,所屬部門不同,對這個界面的操作權限就不同,如上圖所示,還有經營部可以編輯項目信息和安排,而其他3個部門的用戶就只能編輯安排那一部分,而已經發送下一級的項目,都變爲不可編輯狀態。我在資源里加入一個綜合部樣式的對話框,想到控件有可以隱藏和禁用的操作,所以這個控件的問題應該不算太難……

        但是這個所謂的不太難,難度還不太小。
        我用管理界面的對話框類ManagementMain 生成對話框: ManagementMain dlg;        dlg.DoModal(); 
        這樣的結果就是,我設計的對話框是怎樣,它出來就是怎樣……那要在哪裏判斷用戶後做不同的顯示呢? 那我就給ManagementMain 添加一個成員變量,int m_flg;    然後再在構造函數裏給它初始化m_flg=0;    如果是經營部登陸,那麼ManagementMain dlg;    dlg.m_flg=1;//隱藏部分控件    dlg.DoModal();     然後在構造函數裏判斷做不同的顯示:
 if(m_flg==1)//爲經營部登陸,則隱藏歸檔要求那兩個控件,否則禁用項目信息的控件
 {
  m_CtrFileRequire.ShowWindow(false);
  m_CtrFilingRequire.ShowWindow(false);
 }
 else
 {
  GetDlgItem(IDC_ProjectNum)->EnableWindow(FALSE);
  GetDlgItem(IDC_ProjectName)->EnableWindow(FALSE);
  GetDlgItem(IDC_ProjectAddr)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientAddr)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientPerson)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientPhone)->EnableWindow(FALSE);
  GetDlgItem(IDC_ClientRequire)->EnableWindow(FALSE);
 }
這裏保存後編譯鏈接沒問題,運行執行文件登陸過後,就出現下圖的運行錯誤: 
圖片
        多次百度查找錯誤的原因,也沒有弄明白個究竟,只知道不能在構造函數裏對對話框控件進行操作,要初始化對話框的佈局,需要在virtual void DoDataExchange(CDataExchange* pDX);這個函數裏進行改變。而且放在構造函數裏的判斷m_flg始終未0,這是由於構造函數先於 dlg.m_flg=1;//隱藏部分控件 這一句執行,構造裏初始化爲0,所以構造裏判斷過後m_flg纔會被賦值爲1。
        那麼將上面改變控件的代碼Ctrl+X,Ctrl+V到 DoDataExchange()函數中,編譯鏈接後運行登陸果然可以實現同一個對話框佈局的不同顯示了!
 
        控件操作的問題解決了,還有一個就是數據交換了。
        比如在經營部登陸後,對話框一出來,就顯示該用戶信息,項目信息的編號處顯示一個新生成的項目編號;綜合部、生產部、總工辦登陸後,對話框上就顯示用戶信息,顯示上一級發過來的項目信息。 
        這個問題應該可以不用再對話框上再加一個按鈕,點擊按鈕過後才更新各對話框的信息,應該有另外的方法……我百度查了一下對話框的初始化相關的消息,也翻看以前一些寫了界面的程序,偶然發現平時忽略的生成對話框的步驟  ManagementMain dlg; dlg.DoModal(); 太簡單了,百度有在這兩句話之間對類成員變量賦值的例子,效果就是DoModal()對話框可以初始顯示控件內容。於是乎,經營部DoModal()之前加上   dlg.m_projectnum=buf;爲項目編號的顯示內容,用戶信息的成員變量依次賦值;另外3個部門DoModal()之前爲用戶信息、項目信息的成員變量賦值。

        至此,第一個大問題控件操作和數據交換得以解決!

        第二個大問題,MFC的CRecordset類對數據庫的操作問題。
        
        之前照着課本寫了一個簡單的QQ聊天系統,其中有涉及到數據庫的操作,記得是重寫了一個數據庫類,代碼還不少,當然是針對那個系統專寫的數據庫操作。我也沒時間再去看那裏的代碼,找出可用於這個管理系統的數據庫操作,再自己重寫了,所以我就百度搜索可以直接操作數據庫的類的使用。 找到MFC的CDataBase類和CRecordset類結合使用可以直接對數據庫進行讀寫操作。
        在對數據庫進行讀寫操作之前,需要先動態註冊數據源,即告訴應用程序所需要的數據庫文件和對應的數據庫驅動: 
SQLConfigDataSource(NULL,  ODBC_ADD_DSN,
  "Microsoft Access Driver (*.mdb)",//Access數據庫的驅動驅動程序,其他數據庫可在電腦的數據源(ODBC)裏查看哪些可用
  "DSN=projectinfo\0" "DBQ=dbf\\projectinfo.mdb\0" "DEFAULTDIR=dbf\0"); //註冊本地數據庫數據源,projectinfo爲數據庫文件名稱
 CoInitialize(NULL);
其中 SQLConfigDataSource()爲註冊數據源,具體參數可百度瞭解,CoInitialize(NULL)爲初始化com庫。這兩句可以放在需要使用數據庫的類的構造函數裏。先編譯鏈接運行一下,使其在用戶DSN註冊一個數據庫文件。
        數據源註冊完過後,需要自定義一個數據庫記錄集的類,使該類與需要讀寫的數據庫關聯。在類嚮導裏添加一個新類,類名定義爲MyProjectSet,選擇基類時選擇CRecordset,點擊OK後彈出對話框選擇數據源,完成後就會建成一個與數據庫文件相關聯的類MyProjectSet:
 long m_ID;
 CString m_projectnum;
 CString m_projectname;
 CString m_projectaddr;
 CString m_clientaddr;
 CString m_clientperson;
 CString m_clientphone;
 CString m_clientrequire;
……………

 RFX_Long(pFX, _T("[ID]"), m_ID);
 RFX_Text(pFX, _T("[projectnum]"), m_projectnum);
 RFX_Text(pFX, _T("[projectname]"), m_projectname);
 RFX_Text(pFX, _T("[projectaddr]"), m_projectaddr);
 RFX_Text(pFX, _T("[clientaddr]"), m_clientaddr);
 RFX_Text(pFX, _T("[clientperson]"), m_clientperson);
 RFX_Text(pFX, _T("[clientphone]"), m_clientphone);
 RFX_Text(pFX, _T("[clientrequire]"), m_clientrequire);
………… 

        接下來,我們就可以通過MyProjectSet類來對數據庫進行讀寫操作了。我在這個管理系統中,就只用到數據庫的查詢、修改、添加3個操作。 
        數據庫的查詢操作如下: 
 CDatabase m_db;
 MyProjectSet myset(&m_db);
 CString strSQL1="select * from projectinfo where projectnum=  '00001'  ";
 if(!myset.Open(CRecordset::dynaset,strSQL1))
  return;
如果沒有打開失敗返回,則myset裏存放的就是數據文件中projectnum爲00001的所有記錄。可以做如下判斷:
if(myset.GetRecordCount()!=0)
{//有projectnum爲00001的記錄,定義操作
…………}
        數據庫的修改操作如下: 
  //更新項目信息
  myset.Edit();
  myset.m_projectname=m_projectname;//需要修改的數據項
…………
  myset.Update();
  myset.Requery();
  myset.Close();
        數據庫添加操作如下: 
  //項目信息加入數據庫信息表
  myset.AddNew();
  myset.SetFieldNull(NULL);
  myset.m_projectnum=m_projectnum;//需要添加的數據項
…………
  myset.Update();
  myset.Requery();
  myset.Close();

        至此,第二個大問題數據庫的操作也可以得到解決。

        最後一個大問題就是MFC操作word生成報表。
        在這之前,我所接觸的MFC操作文檔就只限於讀寫txt文件,而要讀寫word並生成表格樣式的doc文檔,就不是那麼簡單了。百度MFC讀寫word,發現網上也沒有說得非常明白的應用文檔,最終讓我找到一篇比較好的應用說明文檔http://wenku.baidu.com/view/e62b610c52d380eb62946d5a.html,其中說到在word中創建一個表格,然後爲單元格賦值,還有合併單元格等操作的使用。當然,這篇文檔裏沒有說得那麼完整,需要先使用MFC提供的wor庫文件添加幾個操作類。具體方法爲:

按下快捷鍵Ctrl+W,彈出MFC ClassWizard對話框,單擊Add Class,選擇From a type library,彈出Import from Type Library對話框,找到你OFFICE軟件的安裝文件夾(默認是在C盤的Program Files中),在其中找到MSWORD.OLB,單擊打開。在Confirm Classes中按下Ctrl鍵選中_Application,Documents,_Document,Cell,Cells,Paragraph,Paragraphs,Shading,Table,Tables,InlineShapesSelection,單擊OK。之後會發現類視圖下多了之前添加的那幾個文檔操作類,在需要生成word表格的Cpp文件頭部添加幾個頭文件:
#include "MyProjectSet.h"
#include "msword.h"
#include <atlbase.h>
然後就可以創建生成word的表格了: 
 COleVariant bTRUE((short)TRUE);
 COleVariant bFALSE((short)FALSE);
 COleVariant OPTION((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
 _Application WordApp;
 if(!WordApp.CreateDispatch("Word.Application",NULL))
 {
  AfxMessageBox("CreateDispatch falied.",MB_OK|MB_SETFOREGROUND);
  return;
 }
 Documents Docs;
 _Document Doc;
 Docs=WordApp.GetDocuments();
 Doc=Docs.Add(OPTION,OPTION,OPTION,OPTION);
 Selection Select;
 Select=WordApp.GetSelection();
 _Document ActiveDoc;
 ActiveDoc=WordApp.GetActiveDocument();
 Tables tables=ActiveDoc.GetTables();
 CComVariant defaultBehavior(1);
 CComVariant AutoFitBehavior(1);
 tables.Add(Select.GetRange(),16,6,&defaultBehavior,&AutoFitBehavior);//添加一個7行11列的空表格
 Table table=tables.Item(1);
 Cell c,c1;
 Cells cs;
//以上就是創建一個表格,並定義單元格對象
c=table.Cell(1,1);
 c1=table.Cell(1,6);
 c.Merge(c1);//合併(1,1)到(1,6)的單元格
 c.Select();
 cs=Select.GetCells();
 cs.SetVerticalAlignment(1);
 Select.TypeText("項目信息");
//這是將第一行前6個單元格合併,並設置該合併後的單元格顯示字符"項目信息"
   c=table.Cell(i,j);
   c.Select();
   cs=Select.GetCells();
   cs.SetVerticalAlignment(1);
   Select.TypeText("字符"); 
//這裏是選定第i行第j列的單元格,並設置字符"字符"

 Select.ReleaseDispatch();
 c.ReleaseDispatch();//釋放文檔操作類的對象
 ActiveDoc.SaveAs(COleVariant(filename),COleVariant((short)0),
bFALSE,COleVariant(""),bTRUE,COleVariant(""),
  bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE,bFALSE);
//保存該word文檔
 WordApp.Quit(OPTION,OPTION,OPTION);
 

         以上就是對於最後一個大問題的解決方法。

        至此,我的一個“簡單”的工程項目管理系統的實踐的過程說明就完成了,至於心得體會以及收穫,那就只有重複研究該系統,精益求精,才能將這個“簡單”的系統變爲一份不簡單的編程財富!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章