2009年7月26日 星期日

PDM/PLM (SmarTeam) 二次開發 - Lesson Five - 進階功能 - 建立專案時預建資料夾

在 SmarTeam 中所有物件的使用是非常彈性的,意思是端看使用者想怎麼增刪改,就決定其呈現的樣貌,這樣容易造成不同專案內所建立的文件或分類結果迥異,導致搜尋及閱讀上的困難

然而幾乎所有公司對專案所需的文件都會有一定的定義及分類,故在新增專案時若能自動建立對應的資料夾來管理分類,不僅可以節省 SmarTeam 使用者的時間,同時也能達到標準化

例如 ##CONTINUE##


所以在使用建立專案時同時也在文件樹建立幾個預設資料夾的功能幾乎是 SmarTeam 的標準二次開發要求

那為何 SmarTeam 不把他列入標準功能呢?因為每間公司的分類結構不同,所以也無法寫成標準功能,所以就需要二次開發

P.S. 其實上面的畫面是由在使用 R19 + SDE 後就有的功能,但 SDE 產生那五個資料夾是固定無法更改的,所以還是要自己寫

以下就來介紹如何如何開發此功能,包含有階層的資料夾結構,同時在新增資料夾時 SmarTeam 不會一直問你是否要當專案子階

  1. 首先當然一樣是建立一個 Script 檔,跟之前都一樣,所以只列重要的 function name
    Function CreateProjectFoldersTest(ApplHndl As Long,OpStr As String,FirstPar As Long,SecondPar As Long,ThirdPar As Long) As Integer
     ...略...

     Set MyDll = CreateObject("MirdcPDMTool.Tools")
     sRet = MyDll.CreateProjectFoldersTest(SmSession, SmOp, RecListIn1, RecListIn2, RecListOut)

     ...略...
    End Function

  2. 在新增專案後加上 Hook




  3. 在 Visual Studio 新增 CreateProjectFoldersTest 方法
    之前有說過要建立具階層型的資料夾,第一層資料夾是與專案連結並新增於桌面(Desktop),第二層資料夾則是當成第一層的子階,兩種的 link 是不同的,故再寫兩個 function 來新增這兩種 link,分別是
    CreateProjectSubfolderTest() 與 CreateSubfolderTest()

    Function CreateProjectFoldersTest(ByVal SmSession As SmApplic.SmSession, ByVal Operation As SmApplic.ISmOperation, ByVal FirstPar As SmRecList.SmRecordList, ByVal SecondPar As SmRecList.SmRecordList, ByVal ThirdPar As SmRecList.SmRecordList) As String

     Dim Project As ISmObject
     Dim smObject As ISmObject
     Dim sRetObjectID As String

     Project = SmSession.ObjectStore.ObjectFromData(FirstPar.GetRecord(0), False)

     Dim retObject As ISmObject
     Dim tmpObject As ISmObject
     Dim sProjectID As String = Project.Value("TDMX_ID").ToString()

     '如果是第一層就呼叫
    CreateProjectSubfolderTest()
     retObject = CreateProjectSubfolderTest(SmSession, "My Folder 1", Project)
     tmpObject = CreateProjectSubfolderTest(SmSession, "My Folder 2", Project)
     '把第一層的 Folder Object 傳回給
    tmpObject ,並傳給 CreateSubfolderTest() 當成第二層的 parent
     retObject = CreateSubfolderTest(SmSession, "My Folder 2-1", tmpObject)
     retObject = CreateSubfolderTest(SmSession, "My Folder 2-2", tmpObject)
     retObject = CreateProjectSubfolderTest(SmSession, "My Folder 3", Project)

     Return sRetObjectID
    End Function


    Function CreateProjectSubfolderTest(ByVal SmSession As SmApplic.SmSession, ByVal sFolderName As String, ByVal parentObject As ISmObject) As ISmObject

     Dim smObject As ISmObject
     Dim sRetObjectID As String
     Dim SessionUtil As SmarTeam.Std.Interop.SmarTeam.SmUtil.SmSessionUtil  'main SmarTeam service object

     Dim folderClass As ISmClass
     folderClass = SmSession.MetaInfo.SmClassByName("Folder")
     Dim MainClassId As Integer 'class id for Sm main class
     Dim SmClassAttributes As SmApplic.ISmClassAttributes 'Sm object attributes
     Dim SmClassAttribute As SmApplic.ISmClassAttribute 'Sm object attribute
     Dim StartMask As String 'start mask for attribute
     Dim NextMask As String 'next mask for attribute

     MainClassId = folderClass.ClassId
     SmClassAttributes = folderClass.Attributes
     SmClassAttribute = SmClassAttributes.ItemByName("TDMX_ID")
     SessionUtil = SmSession.GetService("SmUtil.SmSessionUtil")

     StartMask = SessionUtil.RetrieveStartMaskValue(SmClassAttribute)
     NextMask = SessionUtil.RetrieveNextMask(SmClassAttribute, StartMask)

     smObject = SmSession.ObjectStore.NewObject(folderClass.ClassId)
     smObject.AddAllAttributes()
     smObject.AddAttributes("TDMX_ID")
     smObject.AddAttributes("TDM_DESCRIPTION")
     smObject.Value("TDMX_ID") = NextMask
      smObject.Value("TDM_DESCRIPTION") = sFolderName
     '讓 SmarTeam 在產生 link 不一直彈出視窗問是否當子階的關鍵,把 Behavior 設成 Silent
     Dim Silent As ISmBehavior
     Silent = SmSession.ObjectStore.DefaultBehavior.Clone
     Silent.ConfirmOperations = ConfirmOperationEnum.coYesToAll
    'Silent.InvokeScripts = True
    smObject.InsertEx(Silent)

     Dim retObject As ISmObject = smObject.Clone()

     ' Adds object to desktop tree
     Dim smLinkObject As ISmObject
     Dim smLinkClassId As Integer = 0
     smObject.AddToDesktopEx(parentObject, smLinkClassId, Silent, smLinkObject, smObject)

     Return retObject
    End Function


    Function CreateSubfolderTest(ByVal SmSession As SmApplic.SmSession, ByVal sFolderName As String, ByVal parentObject As ISmObject) As ISmObject

     Dim smObject As ISmObject
     Dim sRetObjectID As String
     Dim SessionUtil As SmarTeam.Std.Interop.SmarTeam.SmUtil.SmSessionUtil 'main SmarTeam service object

     Dim folderClass As ISmClass
     folderClass = SmSession.MetaInfo.SmClassByName("Folder")
     Dim MainClassId As Integer 'class id for Sm main class
     Dim SmClassAttributes As SmApplic.ISmClassAttributes 'Sm object attributes
     Dim SmClassAttribute As SmApplic.ISmClassAttribute 'Sm object attribute
     Dim StartMask As String 'start mask for attribute
     Dim NextMask As String 'next mask for attribute

     MainClassId = folderClass.ClassId
     SmClassAttributes = folderClass.Attributes
     SmClassAttribute = SmClassAttributes.ItemByName("TDMX_ID")
     SessionUtil = SmSession.GetService("SmUtil.SmSessionUtil")
     StartMask = SessionUtil.RetrieveStartMaskValue(SmClassAttribute)

     NextMask = SessionUtil.RetrieveNextMask(SmClassAttribute, StartMask)

     smObject = SmSession.ObjectStore.NewObject(folderClass.ClassId)
     smObject.AddAllAttributes()
     smObject.AddAttributes("TDMX_ID")
     smObject.AddAttributes("TDM_DESCRIPTION")
     smObject.Value("TDMX_ID") = NextMask
     smObject.Value("TDM_DESCRIPTION") = sFolderName

     Dim Silent As ISmBehavior
     Silent = SmSession.ObjectStore.DefaultBehavior.Clone
     Silent.ConfirmOperations = ConfirmOperationEnum.coYesToAll
    'Silent.InvokeScripts = True
    smObject.InsertEx(Silent)

     Dim retObject As ISmObject = smObject.Clone()

     ' Add as Child
     Dim LinkObject As ISmObject
     Dim LinkClassId As Integer
     LinkClassId = SmSession.MetaInfo.HierarchicalLinkClassByClasses(folderClass.ClassId, smObject.ClassId)
     LinkObject = smObject.NewLinkToParent(LinkClassId, parentObject)
     LinkObject.InsertEx(Silent)

     Return retObject
    End Function



  4. 測試看看,成果如下

以上就完成簡單但實用的一個功能,本篇的資料夾數目及結構是寫在程式當中,維護上較困難,更新時亦需一一去更新每個 User 端
故下篇會介紹一資料庫來管理資料夾的內容及階層關係,如此一來就可輕易調整

沒有留言:

張貼留言