Thursday, March 29, 2012

C# Converting PT0H0M0S to TimeSpan


I was working on importing Microsoft Project data into one of my projects when I encountered a problem where the MSP's TimePhasedData value is using the format PT0H0M0S to represent date values. I needed to convert the PT0H0M0S string to a double representing the total hours. I'm posting this code just in case someone is looking for something similar.

public static double StringToTimeSpan(string source)
   int hours = 0; int minutes = 0; int seconds =0;
   string number = string.Empty ;
   for (int index = 0; index < source.Length; index++) {
      char current = source[index];

      if ("1234567890".Contains(current)) number += current;

      else
{
         if (current.Equals ('H')) hours += int.Parse(number);
         if (current.Equals ('M')) minutes += int.Parse(number);
         if (current.Equals ('S')) seconds += int.Parse(number);
         number = string.Empty ;
      }
   }
   return new TimeSpan (hours, minutes, seconds).TotalHours;

}

Tuesday, March 20, 2012

ComponentOne FlexGrid columns with checkboxes

When working with ComponentOne's FlexGrid bounded to a boolean column, setting the Editor property of that boolean column will make it difficult to change the value of the column.

DataTable table = new DataTable();
table.Columns.Add("Selected", typeof(bool));
table.Columns.Add("Name", typeof(string));
table.Rows.Add(false, "Row 1");
flexGrid.DataSource = table;Column column = flexGrid.Cols[0];
column.Editor = new CheckBox();

In the example above, once the editor property of the column is set to an instance of a checkbox, changing the value of the selected column will take several tries.

I just skipped the setting the editor for boolean columns as a result and let C1FlexGrid manage it. If anyone knows of an explanation or a better way to set an editor of a C1FlexGrid column, just send me a message.


Friday, February 3, 2012

Ideablade License Exceptions when running Applications using DevForce


When running code in Visual Studio which uses Ideablade Devforce, you might encounter the following exception.


An error occurred while processing your product license: This product is not registered or the key may no longer be valid. Please contact your IdeaBlade representative to obtain a new key or email sales@ideablade.com.
Check the messages in the debuglog preceding this error for more information, since this error can occur in some high-security configurations. If your product key is no longer valid or you cannot resolve the problem, please contact IdeaBlade.

The three most common causes of this error include:
  1. An Invalid License key. When this occurs, contact ideablade and make sure that the license key is valid for the version of DevForce you have installed.
  2. The probing assembly is invalid. Check the Ideblade.config file and ensure that the probing assembly points to the assembly that contains your entity model.

  3. A change in one of the files that is used by the Ideablade license logic. When this occurs, simply regenerate the model. That is, open the Ideablade Object Mapper and save.
    The Ideablade license information is found in EntityRelations.cs. If the Ideblade Devforce assemblies are recently upgraded, regenerating the model ensures that this file contains the valid license information.
    [assembly: IdeaBladeLicense("aseriesofcharacters")] 
These findings are found with help from Ideablade support.

Thursday, January 12, 2012

Aspose.Tasks and Task Types


Task dates may be automatically calculated by the MSP's scheduling engine which may cause a task's start and finish dates to shift depending on the task type setting.


Task task = new Task("Name");
task.Type = TaskType.FixedUnits ;

The following is a very useful post by Chris Woodill explaining each of the TaskTypes:
http://chriswoodill.blogspot.com/2009/03/how-to-use-microsoft-project-task-type.html

Aspose.Tasks in MS Project Resource Uids


When using Aspose.Tasks to generate an XML file for Microsoft Project, if one of the resource’s uid is set to 0 and it has been used on an assignment, the assignment will not be shown once the xml file is opened in Microsoft Project. To prevent this, always set the resource.uid to a positive non zero integer value.
Aspose.Tasks.Resource resource = new Aspose.Tasks.Resource("Name");      
resource.Uid = resourceIDCounter++;

Note that a function call to CalcResourceUids of the Aspose.Tasks.Project will reset the Uid value.
_project.CalcResourceUids();

Booking individual periods in TimePhaseData in MS Project using Aspose.Tasks


The following code will allow booking of individual periods in the TimePhaseDetail of MSP.
I've used the following tools/languages for this demo.
  • Aspose.Tasks version: 4.0.0.0
  • Microsoft Visual Studio 2010 C#
  • Microsoft Project 2007
The _tasks and _resources is just a collection of Tasks and Resources respectively.
In the example below, all resources are being assigned to each task and are given a 1 or 2 value depending on the flag variable.

foreach (Task task in _tasks.Values) {
   foreach (Aspose.Tasks.Resource resource in _resources.Values) {

      ResourceAssignment resourceAssignment = new
      ResourceAssignment();
      resourceAssignment.Task = task;
      resourceAssignment.Resource = resource;

      resourceAssignment.Start = task.ActualStart;
      resourceAssignment.Finish = task.ActualFinish;
      resourceAssignment.Units = 1;
      resourceAssignment.HasFixedRateUnits = true;
      resourceAssignment.LevelingDelayFormat = TimeUnitType.ElapsedHour;
      resourceAssignment.Uid = _project.NextResourceAssignmentUid;
      resourceAssignment.WorkContour = WorkContourType.Contoured;
     
      DateTime date = task.ActualStart;
      bool flag = true;
      while (date < task.ActualFinish) {

         TimephasedData timephaseData = new TimephasedData();
         timephaseData.Start = date;
         timephaseData.Unit = TimeUnitType.Hour;
         date = date.AddDays(1);
         timephaseData.Finish = date;
         timephaseData.Uid = _project.ResourceAssignments.Count ;

         timephaseData.TimephasedDataType = TimephasedDataType.AssignmentActualWork ;

         if (flag) timephaseData.Value = "PT1H0M0S";

         else timephaseData.Value = "PT2H0M0S";
         flag = !flag;
         resourceAssignment.TimephasedData.Add(timephaseData);
      }
      _project.ResourceAssignments.Add(resourceAssignment);
   }
}


This is the resource usage view in MSP 2007. Notice that the resource Alien 1 is assigned to all projects with an alternating value.




I needed this requirement in the task I was working on and found that there were no existing examples on how to do it yet so this is just from my research.

Thursday, December 8, 2011

Unit test tips

Automated unit tests provide a safety net to enhance application so that we wont be afraid to make a change without introducing defects and it also makes an application more maintainable.
Unit test names must be robust; They should be named after the functionality that they are testing. A recommended way to name unit tests is to use the Noun+should+verb pattern.

A body of a test method should be arranged using the AAA pattern (arrange, act, assert).
-          Arrange: This section contains code that sets up the variables that will be used by the unit test.
-          Act : This section execercises the unit under testing and capture the results.
-          Assert: This section verifies the results of the unit test against expectations.

Avoid tests that do too much. Verify only a single concept to make it easier to pinpoint the cause of failures.

A good point is to have only a single assert statement in a test method. If you have multiple asserts, make sure that they are verifying the same concept.

Unit testing with a real database brings a number of challenges:
1.       It significantly slows down the execution time of unit tests.The longer it takes to run the tests, the less likely you will run them frequently. Ideally you would want unit tests to run in seconds- something you do naturally as compiling the project.
2.       It complicates the setup and cleanup logic within the tests. You want each unit test to be isolated and independent of the others with no side effects or dependencies. When working against a real database, you have to be also mindful of state and reset the values between the tests.
To overcome this challenge, it is recommended to use the dependency injection design pattern.

Dependency Injection
Dependencies, like repository classes are no longer implicitly created within the classes that use them. This will allow us to test specific scenarios without requiring a connection to the database.