从MSFT Project中同步数据到PSA

最近在做dynamics 365 PSA 模块的开发. 

其中的module功能的确是非常好用.  微软已经在project中有plugin可以直接使用. 这个plugin的好处是可以无缝和PSA关联,并且数据都可以导入进去.

缺点也非常明显, 就是现在只支持11个字段(WBS, category 和 description 在途中没有显示出来)

那如果project中有自定义的字段,则我们需要额外想办法导入. 

有两种方法:

1. 使用代码导入

2. 使用flow + project online

今天我们讲解用C#代码导入

因为微软没有提供官方的SDK, 我们只能用三方的SDK.

我们首先进nuget package中下载 net.sf.mpxj.

这是三方的插件, 通过Java实现的.

首先,我们在dynamics 中创建一个open web resource的 js绑定在ribbon button中, 当我们点upload按钮之后, 会激活下面的C# 代码.

这里只判断了三层关系. 超过三层关系则不做更多的判断.

        [HttpPost]
        [AllowAnonymous]
        [Route("api/project/uploadproject")]
        public JObject UploadProjects()
        {
            var back = new ProjectBack();
            try
            {
                LogHelper.WriteLog("Entered UploadProjects");
                HttpFileCollection filelist = HttpContext.Current.Request.Files;
                NameValueCollection form = HttpContext.Current.Request.Form;
                string rootFolder = form.Get("rootFolder");
                ProjectId = form.Get("projectId");
                LogHelper.WriteLog("Upload MPP" + rootFolder);
                if (filelist.Count < 1)
                {
                    back.status = "error";
                    back.errors.Add("cannot find file");
                    return JObject.Parse(JsonConvert.SerializeObject(back));
                }

                var file = filelist[0];
                byte[] fileData = null;
                using (var binaryReader = new BinaryReader(file.InputStream))
                {
                    fileData = binaryReader.ReadBytes(file.ContentLength);
                }

                // TODO: 
                // 删除当前project的所有projecttasks
                // 导入数据到project中 
                var result = DeleteRecord(ProjectId);
                if (result == false)
                {
                    var retryDeleteResult = false;
                    for (int i = 0; i < 5; i++)
                    {
                        retryDeleteResult = DeleteRecord(ProjectId);
                        if (retryDeleteResult)
                        {
                            break;
                        }
                    }
                    if (!retryDeleteResult)
                    {
                        back.status = "error";
                        back.errors.Add("delete error");
                        return JObject.Parse(JsonConvert.SerializeObject(back));
                    }

                }
                var reader = new net.sf.mpxj.reader.UniversalProjectReader();
                var project = reader.Read(new java.io.ByteArrayInputStream(fileData));
                var tasks = project.Tasks;
                var isRootItem = true;
                var previousOutlineLevel = 1;
                // initinal WbsLevel
                WbsLevel = new WbsLevel();
                foreach (net.sf.mpxj.Task task in tasks)
                {
                    // 判断不要第0行数据
                    //if (isRootItem)
                    //{
                    //    isRootItem = false;
                    //    continue;
                    //}

                    // 赋值guid
                    CurrentItemGuid = Guid.NewGuid();
                    // 判断父子层级关系
                    var wbs = task.WBS;
                    var wbsSplit = wbs.Split('.');
                    switch (wbsSplit.Count())
                    {
                        case 1:
                            WbsLevel.FirstLevelGuid = CurrentItemGuid;
                            HasParentLvl = false;
                            break;
                        case 2:
                            WbsLevel.SecondLevelGuid = CurrentItemGuid;
                            HasParentLvl = true;
                            ParentLvlGuid = WbsLevel.FirstLevelGuid;
                            break;
                        case 3:
                            WbsLevel.ThirdLevelGuid = CurrentItemGuid;
                            HasParentLvl = true;
                            ParentLvlGuid = WbsLevel.SecondLevelGuid;
                            break;
                        case 4:
                            HasParentLvl = true;
                            ParentLvlGuid = WbsLevel.ThirdLevelGuid;
                            break;
                    }


                    //int.TryParse(task.OutlineLevel.ToString(), out int currentOutlineLevel);
                    //if (currentOutlineLevel >= previousOutlineLevel)
                    //{
                    //    HasParentLvl = true;
                    //}
                    //else
                    //{
                    //    HasParentLvl = false;
                    //    // TODO: 不应该是上个 而是上级
                    //    ParentLvlGuid = CurrentItemGuid;
                    //}


                    var dependency = task.Predecessors.ToString();
                    var splitResult = dependency.Split('>');

                    if (splitResult.Count() >= 2)
                    {
                        var splitValue = splitResult[1];
                        dependency = splitValue.Substring(10, 2);
                    }
                    else
                    {
                        dependency = "";
                    }


                    var calStart = java.util.Calendar.getInstance();
                    calStart.setTime(task.Start);
                    // note that the Month component of java.util.Date  
                    // from 0-11 (i.e. Jan == 0)
                    var plannedStart = new DateTime(calStart.get(java.util.Calendar.YEAR),
                              calStart.get(java.util.Calendar.MONTH) + 1,
                              calStart.get(java.util.Calendar.DAY_OF_MONTH),
                              calStart.get(java.util.Calendar.HOUR_OF_DAY),
                              calStart.get(java.util.Calendar.MINUTE),
                              calStart.get(java.util.Calendar.SECOND));
                    var calEnd = java.util.Calendar.getInstance();
                    calEnd.setTime(task.Start);
                    // note that the Month component of java.util.Date  
                    // from 0-11 (i.e. Jan == 0)
                    var plannedEnd = new DateTime(calEnd.get(java.util.Calendar.YEAR),
                              calEnd.get(java.util.Calendar.MONTH) + 1,
                              calEnd.get(java.util.Calendar.DAY_OF_MONTH),
                              calEnd.get(java.util.Calendar.HOUR_OF_DAY),
                              calEnd.get(java.util.Calendar.MINUTE),
                              calEnd.get(java.util.Calendar.SECOND));

                    double.TryParse(task.PercentageComplete.toString(), out double complete);

                    MsProject = new MsProjectValues
                    {
                        task = task.Name,
                        responsible = task.ResourceNames,
                        totaldays = task.Duration.Duration,
                        plannedstart = plannedStart,
                        plannedend = plannedEnd,
                        complete = complete,
                        dependency = dependency,
                        wbsid = task.WBS
                    };
                    CreateProjectRecord(MsProject, ProjectId);
                    int.TryParse(task.OutlineLevel.toString(), out previousOutlineLevel);
                }

                back.status = "success";
                back.errors.Add("delete error");
                return JObject.Parse(JsonConvert.SerializeObject(back));
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("error=upload=====>" + ex.Message);
                back.status = "error";
                back.errors.Add("delete error");
                return JObject.Parse(JsonConvert.SerializeObject(back));
            }
        }
原文地址:https://www.cnblogs.com/TheMiao/p/12600746.html