Gantt Chart Trick: How To Visualize Operations With Short Durations

Posted by Alfred Göhlich on Jan 28, 2015 1:30:00 PM

Does this sound familiar? You have to visualize plenty of operations with short durations and have to cover both a short-term and a long-term planning horizon with one view in your Gantt scheduling appplication? There are two options of how to display the time scale. You could choose between

  1. A very detailed time scale, offering the advantage of making the single operations clearly visible but, on the other hand only showing a very short period, thus losing the overview.
  2. A rough time scale offering a good overview of a longer period, while however affecting the accuracy of details.

In our series of Gantt chart tricks we describe how to create advanced planning and scheduling charts with our .NET Gantt control VARCHART XGantt. Read in this blog post how to enhance the time scale function to realize a magnifiying glass letting you keep track of the longer period while at the same time zooming into a selected time window to show every detail of the operations.

Time Scale with Magnifying Glass Function

Define a rough time scale, select a group of operations and switch to a detailed time scale only for the period containing the selected operations. The following steps are needed:

Step 1) Initial situation: The time scale lies within a planning horizon of several days.

 Gantt chart trick for operations with short term duration

 

The operations circled in red could lead the planner to the assumption that they consist only of three operations. 

Gantt chart trick: operations with very short duration

 

Step 2) To check this, the planner selects these operations with the so called rectangle rubber band

Gantt Chart trick: select a timeframe when working with operations with short durations

In the background, VARCHART XGantt switches to a detailed time resolution for the selected period and it becomes immediately clear that there are lots of operations located within this time window:

Gantt best practice: Timescale with zoom functions for operations with short durations 

 

Step 3) Clicking in the white area of the diagram switches off the time scale magnifying glass and the planner sees the former overview again.

 

Hands-on step-by-step-guide how to achieve this with VARCHART XGantt

Create a time scale with three sections:

VARCHART XGantt Trick: Magnifiying glass for time scale; step 1

 

The labeling of the time scale section DetailedArea has to be more detailed than those of the other two, e.g., markings every ten minutes in contrast to hourly markings for the other time scale sections.

Layers with two filters are needed for displaying operations in the detailed time scale section and in the other two sections:

VARCHART XGantt Trick: Magnifiying glass for time scale; step 2

 

VARCHART XGantt Trick: Magnifiying glass for time scale; step 3

Add the data field Tasks:NodeZoomed to your node data table. It will be set at runtime.

Create two date lines to use as optical divider of the three time scale sections:

VARCHART XGantt Trick: Magnifiying glass for time scale; step 4

 

The following code is needed:

  

      //Global variables

      List<stringzoomedNodesIDs = new List<string>();

 

      DateTime earliestStart;

      DateTime latestEnd;

 

      double oldUnitWidthEx0;

      double oldUnitWidthEx1;

      double oldUnitWidthEx2;

 

      bool diagramLeftClicked = false;

 

      VcDateLine dateLine1;

      VcDateLine dateLine2;

 

      int sectionIndex;

 

      private void Form1_Load(object sender, EventArgs e)
      {
         //Add the following code after you have loaded your data into XGantt:
         ts.get_Section(1).StartDate = vcGantt1.TimeScaleStart;
         ts.get_Section(2).StartDate = vcGantt1.TimeScaleStart;
 
         dateLine1 = vcGantt1.DateLineCollection.DateLineByName("DateLine1");
         dateLine2 = vcGantt1.DateLineCollection.DateLineByName("DateLine2");
 
         oldUnitWidthEx0 = ts.get_Section(0).UnitWidthEx;
         oldUnitWidthEx1 = ts.get_Section(1).UnitWidthEx;
         oldUnitWidthEx2 = ts.get_Section(2).UnitWidthEx;
      }
 
 
      private void vcGantt1_VcNodesMarking(object sender, VcNodesMarkingEventArgs e)
      {
         if (e.NodeCollection.Count > 0)
         {
            DateTime startDate;
            DateTime endDate;
 
            VcCalendar cal = vcGantt1.CalendarCollection.Active;
            VcTimeScale ts = vcGantt1.TimeScaleCollection.Active;
 
            earliestStart = DateTime.MaxValue;
            latestEnd = DateTime.MinValue;
 
            //Reset all
            ts.get_Section(1).StartDate = vcGantt1.TimeScaleStart;
            ts.get_Section(2).StartDate = vcGantt1.TimeScaleStart;
            ts.get_Section(0).UnitWidthEx = oldUnitWidthEx0;
            ts.get_Section(1).UnitWidthEx = oldUnitWidthEx1;
            ts.get_Section(2).UnitWidthEx = oldUnitWidthEx2;
 
            //Compute start and end date for zoomed timescale section
            foreach (VcNode node in e.NodeCollection)
            {
               startDate = (DateTime)node.get_DataField(eTasks.Start);
               endDate = (DateTime)node.get_DataField(eTasks.End);
 
               if (startDate < earliestStart)
                  earliestStart = startDate;
 
               if (endDate > latestEnd)
                  latestEnd = endDate;
            }
 
            //Round to hours
            earliestStart = earliestStart.AddMinutes(-1 * earliestStart.Minute);
            latestEnd = latestEnd.AddMinutes(-1 * latestEnd.Minute).AddHours(1);
 
            //Set new section start dates
            ts.get_Section(2).StartDate = latestEnd;
            ts.get_Section(1).StartDate = earliestStart;
 
            vcGantt1.FitRangeIntoView(earliestStart, latestEnd, 120);
            ts.get_Section(0).UnitWidthEx = oldUnitWidthEx0;
            ts.get_Section(2).UnitWidthEx = oldUnitWidthEx2;
 
            vcGantt1.ScrollToDate(earliestStart, VcHorizontalAlignment.vcLeftAligned, 120);
 
            dateLine1.Date = earliestStart;
            dateLine1.Visible = true;
            dateLine2.Date = latestEnd;
            dateLine2.Visible = true;
         }
      }
 
 
      private void vcGantt1_VcNodesMarked(object sender, VcNodesMarkedEventArgs e)
      {
         UnmarkAllNodes();
         MarkNodesInTimeRange();
      }
 
 
      private void UnmarkAllNodes()
      {
         vcGantt1.SuspendUpdate(true);
         foreach (string nodeID in zoomedNodesIDs)
         {
            VcNode node = vcGantt1.GetNodeByID(nodeID);
            node.set_DataField(eTasks.NodeZoomed, 0);
            node.Update();
         }
         vcGantt1.SuspendUpdate(false);
 
         zoomedNodesIDs.Clear();
      }
 
 
      private void MarkNodesInTimeRange()
      {
         //Set "NodeZoomed" datafield for all nodes in zoomed timescale section
         DateTime startDate;
         DateTime endDate;
 
         if (!diagramLeftClicked)
         {
            vcGantt1.SuspendUpdate(true);
            foreach (VcNode node in vcGantt1.NodeCollection)
            {
               startDate = (DateTime)node.get_DataField(eTasks.Start);
               endDate = (DateTime)node.get_DataField(eTasks.End);
 
               if (startDate >= earliestStart && startDate < latestEnd || endDate > earliestStart && endDate <= latestEnd)
               {
                  node.set_DataField(eTasks.NodeZoomed, 1);
                  node.Update();
 
                  zoomedNodesIDs.Add(node.get_DataField(eTasks.ID).ToString());
               }
            }
            vcGantt1.SuspendUpdate(false);
         }
         diagramLeftClicked = false;
      }
 
 
      private void vcGantt1_VcDiagramLeftClicking(object sender, VcDiagramClickingEventArgs e)
      {
         //Reset the timescale so that only section 2 is visible
         VcTimeScale ts = vcGantt1.TimeScaleCollection.Active;
         ts.get_Section(1).StartDate = vcGantt1.TimeScaleStart;
         ts.get_Section(2).StartDate = vcGantt1.TimeScaleStart;
 
         ts.get_Section(0).UnitWidthEx = oldUnitWidthEx0;
         ts.get_Section(1).UnitWidthEx = oldUnitWidthEx1;
         ts.get_Section(2).UnitWidthEx = oldUnitWidthEx2;
 
         UnmarkAllNodes();
 
         dateLine1.Visible = false;
         dateLine2.Visible = false;
 
         diagramLeftClicked = true;
      }

 VARCHART XGantt free trial - Gantt chart control .NET

 

Do you want to learn how to integrate a shift calendar into timescale? See this blog post.

Topics: Windows Forms Gantt Control, XGantt development tricks, Gantt Chart Controls