Makale Özeti

Bu makalemde bir MS Project dosyasından verilerin nasıl import edilebileceğini inceleyeceğiz. Bildiğiniz gibi proje planlarını oluştururken sıklıkla kullandığımız bir uygulama olan MS Project'in bize sunduğu özellikler hepimizin çok işine yaramaktadır. İhtiyaç duyulan uygulamalarda MS Project'te girilen ve kaydedilen bilgileri kendi uygulamalarımıza aktararak kullanıcının aynı bilgiyi iki yere girmemesi'ni sağlamak ise biz yazılımcılara düşmektedir. Bu aktarımı yapmak için project dosyasından gerekli bilgileri okumak gerekmektedir. Bunu ise MSProject ve MSOffice Interop dll'lerini kullanarak yapabiliriz. Tüm bu dll kullanım mantığında olduğu gibi Project uygulamamızı açacağız, arkasından import etmek istediğimiz project dosyasını açacağız, daha sonra gerekli verileri okuduktan sonra dosyayı kapayacağız.

Makale

        Merhabalar

        Bu makalemde bir MS Project dosyasından verilerin nasıl import edilebileceğini inceleyeceğiz. Bildiğiniz gibi proje planlarını oluştururken sıklıkla kullandığımız bir uygulama olan MS Project'in bize sunduğu özellikler hepimizin çok işine yaramaktadır. İhtiyaç duyulan uygulamalarda MS Project'te girilen ve kaydedilen bilgileri kendi uygulamalarımıza aktararak kullanıcının aynı bilgiyi iki yere girmemesi'ni sağlamak ise biz yazılımcılara düşmektedir. Bu aktarımı yapmak için project dosyasından gerekli bilgileri okumak gerekmektedir. Bunu ise MSProject ve MSOffice Interop dll'lerini kullanarak yapabiliriz. Tüm bu dll kullanım mantığında olduğu gibi Project uygulamamızı açacağız, arkasından import etmek istediğimiz project dosyasını açacağız, daha sonra gerekli verileri okuduktan sonra dosyayı kapayacağız.

        Bu örneği geliştirmek için öncelikle bir tane windows uygulaması açalım. Ve referans ekleme kısmından Com sekmesinden Microsoft Project 11.0 Type Library dll'ini ekleyelim. Bilgisayarınızda farklı versiyonlarda Office kurulu ise buradaki versiyon numarası değişecektir. Project dosyasından veri alırken tüm işlemlerimizi eklediğimiz bu assembly üzerinden yapacağız.

        Peki import işlemini nasıl yapacağız ve project dosyasında bulunan verilere nasıl erişeceğiz şimdi bunu inceleyelim. Öncelikle Microsoft.Office.Interop.MSProject.Application tipindeki nesnenin instance'ını almalıyız. Daha sonrasında ise instance aldığımız nesneye verdiğimiz değişken ismini kullanarak nesnenin FileOpen metodunu kullanarak açmak istediğimiz project dosyasının yolunu vermeliyiz. Sonrasında ise Bu nesne içinde bulunan Projects propertysi sayesinde gerekli bilgilere ulaşabiliriz. Şimdi isterseniz bu anlattıklarımı pekiştirmek için örnek bir uygulama yapalım.

        Microsoft.Office.Interop.MSProject.Application app = new Microsoft.Office.Interop.MSProject.Application();
        Microsoft.Office.Interop.MSProject.ject.Project p = null;

        Yukarıda da bahsettiğimiz gibi uygulamamızda öncelikle class level MSProject.Application ve MSProject.Project tipinde değikenlerimizi tanımlıyoruz. Burda tanimladığımız app nesnesi MSProject uygulamasını, p nesnesi ise Project dosyasını temsil etmektedir.

 

        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            if (p != null)
            {
                app.FileClose(Microsoft.Office.Interop.MSProject.PjSaveType.pjDoNotSave, Type.Missing);
            }
            ofd.ShowDialog();
            if (ofd.FileName != "")
            {
                app.Visible = false;
                app.FileOpen(ofd.FileName, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.MSProject.PjPoolOpen.pjPoolReadOnly, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                p = app.Projects[1];
                DataTable dt = new DataTable();
                dt.Columns.Add("Id", typeof(int));
                dt.Columns.Add("Name", typeof(string));
                dt.Columns.Add("ParentId", typeof(int));
                dt.Columns.Add("Index", typeof(int));
 
                foreach (Microsoft.Office.Interop.MSProject.Task t in p.Tasks)
                {
                    DataRow dr = dt.NewRow();
                    dr["Id"] = t.ID;
                    dr["Name"] = t.Name;
                    dr["ParentId"] = t.OutlineParent.ID;
                    dr["Index"] = t.UniqueID;
                    dt.Rows.Add(dr);
                }
                FillTreeView(dt, null, null);
            }
        }

        Bu kısımda ise öncelikle bir open file dialog nesnesi ile kullanıcıya açmak istediği dosyayı seçtiriyoruz. Daha sonrasında app.Visible kodu ile çalıştıracağımız Project Application nesnesinin kullanıcı tarafında gösterilmemesini sağlıyoruz.  FileOpen metodu ile seçilmiş olan dosyayı uygulama tarafında açtırtıyoruz. Bir sonraki adımda ise açılan dosya sayesinde Project uygulamasında açık olan Project dosyasının taşıdığı bilgileri alarak p değişkenine atıyoruz. Daha sonrasında gerekli verileri saklayabileceğimiz bir datatable şeması oluşturuyor ve proje değişkeni içinde bulunan Task'larda bir döngü ile dönerek bu taskların bazı bilgilerinin oluşturduğumuz datatable'a atanmasını sağlıyoruz. Daha sonrasında ise taskların bir hiyerarşide treeview üzerinde gösterilmesini sağlayacak reccursive metodumuz olan FillTreeView'i çağırıyoruz. Şimdi Project nesnesinin property'lerini biraz daha detaylı inceleyelim.

        Project Nesnesi Önemli Özellikleri.
Resources Project dosyasında tanımlanmış olan resource'ları bir collection olarak veren property'dir.
Tasks Project dosyasında girilmiş olan taskları bir collection olarak veren property'dir.
Application Project dosyasının içinde açık olduğu MSProject uygulamasını veren property'dir.
Calendar Proje için tanımlanmış çalışma takvimini veren property'dir.
    Bu belli başlı özelliklerin yanısıra project nesnesinde ActualStart, ActualFinish, RemainingCost, RemainingDuration gibi değişkenlerde bulunmaktadır ve birçoğu isminden rahat bir şekilde anlaşılabilmektedir.

    Task Nesnesi Önemli Özellikleri
ActualCost Bu property bize bu taskın maliyet rakamını verecektir.
Name Bu property'de ise taskın kullanıcılara gösterilen adı saklanmaktadır.
Notes Task hakkında saklanan notlara bu property'den ulaşabiliriz.
PercentComplete Task'ın % kaçının bittiği bilgisine ulaşılabilecek alandır.
Resources Bu task'a atanmış olan resource'lara Resource nesnesinin bir collection'ı olarak ulaşabileceğimiz property'dir.
ResourceNames Bir önceki property'de bulunan değerlerin Resource Name lerinin yan yana yazılmış halde ulaşabileceğimiz property'dir.
UniqueID Bu task'a ait benzersiz bir id'dir.
Parent Bu task'ın parent'ına yani hangi task'ın altında olduğuna ulaşabileceğimiz property'dir.
OutlineParent Outline demek project dosyasında oluşturduğumuz indent outdent hiyerarşisinin bir yansımasıdır. Dolayısıyla bu property'de hangi taskların hangi tasklar altında tutulduğuna veya bu taskın outline'da hangi task altında olduğuna olaşabiliriz.
OutlineNumber Bir önce bahsettiğim property'nin numaralandırılmış halidir. 4.1.2 gibi değerler vermektedir.
Milestone Task'ın bir milestone olarak işsaretlenip işaretlenmediğine burdan ulaşabilirsiniz.
Assignments Task'ın resource'lara assign edilme bilgilerinin tutulduğu property'dir Assignment tipinin bir collection'u tipindedir.
       
        Assignment Nesnesi Önemli Özellikleri
ResourceName Atamanın yapıldığı resource'ın adının bulunduğu property'dir.
Start Atamanın başlangıç tarihinin tutulduğu property'dir.
Finish Atamanın bitiş tarihinin tutulduğu proeprty'dir.
TaskName Atanan task'ın adının tutulduğu property'dir.

        Resource Nesnesi Önemli Özellikleri
ActualCost Resource'un olan maliyetinin tutulduğu property'dir
Assignments Resource'a yapılmış atamalara ulaşılabilecek property'dir. Assignment tipinde bir collection tipindedir.
Name Resource'un adının tutulduğu değişkendir.
WindowsUserAccount Kullanıcı bir windows account'u ile ilişkilendirilmişse bu property'den ulaşılabilir.

        Bu kısımda belli başlı property'leri inceledik. Project uygulamasında girilen her tür veriye ulaşmamız mümkündür. Şimdi uygulamamızı yazmaya devam edelim.

        private void FillTreeView(DataTable dt, int? Id,TreeNode parTreeNode)
        {
            if (Id.HasValue)
            {
                foreach (DataRow dr in dt.Select("ParentID=" + Id.Value.ToString()))
                {
                    TreeNode tn = new TreeNode();
                    tn.Text = dr["Name"].ToString();
                    FillTreeView(dt, Convert.ToInt32(dr["Id"]), tn);
                    tn.Tag = GetTaskByUniqueId(Convert.ToInt32(dr["Index"]));
                    parTreeNode.Nodes.Add(tn);
                   
                }
            }
            else
            {
                foreach (DataRow dr in dt.Select("ParentID=0"))
                {
                    TreeNode tn = new TreeNode();
                    tn.Text = dr["Name"].ToString();
                    FillTreeView(dt, Convert.ToInt32(dr["Id"]), tn);
                    tn.Tag =GetTaskByUniqueId(Convert.ToInt32(dr["Index"]));
                    trvProject.Nodes.Add(tn);
                }
            }
        }

        FillTreeView metodu ise kendisine parametre olarak verilen DataTable'da Id'si parametrik Id  değişkeni altında bulunan tüm taskları bulup bu task'ın adını yeni oluşturulan TreeNode'un text'ine Task'ın kendisini ise tag propertysine atıyor ve sonrasında bu treenode'u yine parametre olarak gelen TreeNode değişkeninin altında yeralacak şekilde yerleştiriyor. Bu işlem en alt kırılıma inene kadar recursive bir şekilde devam ediyor. Daha Öncesinde her task'ın bir uniqueId'si olduğunu söylemiştik. GetTaskByUniqueId metodu ise taskların arasından bu task'ı getiren bir metoddur.

        private Task GetTaskByUniqueId(int uniqueId)
        {
            foreach (Task t in p.Tasks)
            {
                if (t.UniqueID == uniqueId)
                {
                    return t;
                }
            }
            return null;
        }
 
        private void trvProject_AfterSelect(object sender, TreeViewEventArgs e)
        {
            propertyGrid1.SelectedObject = (Task)e.Node.Tag;
           
        }
        private void frmProjectImport_FormClosing(object sender, FormClosingEventArgs e)
        {
            app.FileClose(Microsoft.Office.Interop.MSProject.PjSaveType.pjDoNotSave, Type.Missing);
        }

        Bu metod yukarıda gözüktüğü gibi döngüde tüm taskları dolaşarak uniqueId si verilen değere eşit olanı bulduğunda bu task'ı döndüren basit bir metoddur. Bir diğer noktas ise treeview'da bir node seçildiğinde bu node'un barındırdığı task'a ait bilgileri bir property grid penceresinde görebilmektir. Bu işlemi sağlayabilecek kod parçası TreeView'in AfterSelect event'ına yazılmıştır.  


        Bu makalemde Office Interop kullanarak project dosyasından nasıl import işlemi yapabileceğimizi inceledik. Umarım faydalı bir makale olmuştur.

         oztamer@hotmail.com
         tamer.oz@yazgelistir.com
         oztamer@hotmail.com
Ornek Uygulama