Introduction
Due to various issues, this version was rewritten. The article for it can be found here.
Many organizations (or sub organizations, such as departments, teams, etc.) have Intranet sites which supply details regarding the specific organization.
It is usually required to display an organization chart. There are a few solutions:
- Use a static image, from PowerPoint, etc. - any change will require regeneration of image
- Use a commercial product - these cost money
- Design your own product - this is what I did
The article discusses a DLL, which accepts a datatable and returns an image with the organization chart.
The DLL can be called from Windows Forms or ASP.NET.
Most of the parameters (sizes, colors) can be controlled by the developer using the DLL - they are exposed as properties.
A Personal Note: As this is my first article, I would greatly appreciate comments on both the article and the code itself. I realize that the code still needs to be optimized. When I do so, I'll update the article.
Using the Code
The download zip file contains the C# solution, which has two projects:
OrgChartGenerator
, which contains the code for the DLL that generates the Org Chart.
TestOrgchart
, which contains a Windows Forms application that demonstrates the abilities of OrgChartGenerator
and its usage.
Constructor
The OrgChartGenerator
accepts a Typed DataSet
in the constructor, with the employee list, in order to generate the Org Chart. The OrgChartGenerator.OrgData.OrgDetailsDataTable
is the DataTable
that the class will accept in the constructor. It can contain the whole organization structure or just parts of it. If it contains the whole organization, multiple Org Charts can be created from the same instance of the object. The structure of the DataTable
is as follows:
string EmployeeID
- Primary Key - the ID of the employee - employee number, email, login code or anything else that uniquely identifies the employee
string EmployeeName
- The employee name
string BossEmployeeID
- The employee ID of this Employees' Boss. This defines the organization structure.
string EmployeeTitle
- The title/Job description for the current employee.
Methods
There is just one method - GenerateOrgChart
, which is overloaded. The difference between the overloads is that one method accepts as parameters the required size of the resulting image and resizes it before returning it. The other returns it in the size as determined by calculation - the number of boxes (both x & y) times the number of employees.
This method returns a System.IO.Stream
, which can be used to display an image, save to file, or any other activity. Another important parameter for this method is the BossEmployeeID
. This parameter determines which employee will be at the top of the Org Chart.
This class/DLL can be used from a Windows Forms application in the following way:
private void TestForm_Load(object sender, EventArgs e)
{
OrgChartGenerator.OrgData.OrgDetailsDataTable myOrgData =
new OrgChartGenerator.OrgData.OrgDetailsDataTable();
myOrgData.AddOrgDetailsRow("1111", "Alon", "", "Manager");
myOrgData.AddOrgDetailsRow("1112", "Yoram", "1111", "Team Leader");
myOrgData.AddOrgDetailsRow("1113", "Dana", "1111", "Team Leader");
myOrgData.AddOrgDetailsRow("1114", "Moshe", "1113", "SW Engineer");
myOrgData.AddOrgDetailsRow("1115", "Oren", "1113", "SW Engineer");
myOrgData.AddOrgDetailsRow("1116", "Noa", "1113", "SW Engineer");
myOrgData.AddOrgDetailsRow("1117", "Mor", "1112", "Consultant");
myOrgData.AddOrgDetailsRow("1118", "Omer", "1112", "Consultant");
myOrgChart = new OrgChartGenerator.OrgChart(myOrgData);
}
private void ShowChart()
{
picOrgChart.Image =
Image.FromStream(
myOrgChart.GenerateOrgChart("1111",
System.Drawing.Imaging.ImageFormat.Bmp));
}
Properties
The image that is returned has default properties. In order to control the sizes and colors of the Org Chart, these properties are can be changed (all sizes are in pixels):
BoxFillColor
- Which color will fill the boxes
BoxWidth
- The width of each box
BoxHeight
- The height of each box
Margin
- The margin from the edges of the image to the boxes
HorizontalSpace
- The space between the 2 employee boxes on the same level
VerticalSpace
- The space between 2 levels of employees
FontSize
- The font size for the employee details
LineColor
- The color of both the box line and the connecting line
LineWidth
- The width of both the box line and the connecting line
BGColor
- The color in the Background of the image
FontColor
- The font color
EmployeeData
- A SortedDictionary
, which contains data regarding the position of each employee on the chart. This can be used for checking if a specific Employee
was clicked.
Changing these properties could generate weird results, so care should be taken by the user. For example - it would not look good if both the BoxFillColor
and the FontColor
were the same.
ASP.NET Usage
In order to use the DLL in ASP.NET, create a Web form which returns the response as a stream. Let's call it OrgChartImage.aspx. The codebehind file should look like this:
protected void Page_Load(object sender, EventArgs e)
{
this.Response.Clear();
this.Response.ContentType = "image/jpeg";
OrgChartGenerator.OrgChart myOrgChart;
OrgChartGenerator.OrgData.OrgDetailsDataTable myOrgData =
new OrgChartGenerator.OrgData.OrgDetailsDataTable();
myOrgData.AddOrgDetailsRow("1111", "Alon", "", "Manager");
myOrgData.AddOrgDetailsRow("1112", "Yoram", "1111", "Team Leader");
myOrgData.AddOrgDetailsRow("1113", "Dana", "1111", "Team Leader");
myOrgData.AddOrgDetailsRow("1114", "Moshe", "1113", "SW Engineer");
myOrgData.AddOrgDetailsRow("1115", "Oren", "1113", "SW Engineer");
myOrgData.AddOrgDetailsRow("1116", "Noa", "1113", "SW Engineer");
myOrgData.AddOrgDetailsRow("1117", "Mor", "1112", "Consultant");
myOrgData.AddOrgDetailsRow("1118", "Omer", "1112", "Consultant");
myOrgChart = new OrgChartGenerator.OrgChart(myOrgData);
System.Drawing.Image OC =
System.Drawing.Image.FromStream(myOrgChart.GenerateOrgChart("1111",
System.Drawing.Imaging.ImageFormat.Bmp));
OC.Save(this.Response.OutputStream, ImageFormat.Jpeg);
OC.Dispose();
}
Calling the OrgChartImage.aspx can be done from any IMG
tag:
<img src="OrgChartImage.aspx"/>
Trapping MouseClick Events
The DLL exposes the EmployeeData
property, which is a System.Collections.Generic.SortedDictionary
. The code calling the DLL can use this property in order to see if a specific employee was clicked. This can be used for various purposes, such as linking to an employee image, showing other employee data or showing the next level of the organization chart. In ASP.NET, this can be done by defining an ImageMap
control. Here's an example of how it is used in the WinFroms sample application:
private void picOrgChart_MouseClick(object sender, MouseEventArgs e)
{
string SelectedEmployee = "No employee";
foreach (OrgChartGenerator.OrgChartRecord EmpRec in
myOrgChart.EmployeeData.Values)
{
if (e.X >= EmpRec.EmployeePos.Left &&
e.X <= EmpRec.EmployeePos.Right &&
e.Y >= EmpRec.EmployeePos.Top &&
e.Y <= EmpRec.EmployeePos.Bottom)
{
SelectedEmployee = EmpRec.EmployeeData.EmployeeName;
break;
}
}
MessageBox.Show(SelectedEmployee);
}
Inside the Black Box
OrgChart.cs includes the main functionality for the application. The first method, BuildTree
, is used recursively to build an XmlDocument
of employee IDs and calculate the box positions. Another recursive method, DrawChart()
, draws the boxes and writes the texts inside them. Then it draws the lines connecting all the boxes and completes the organization chart. If necessary, the image is then resized and a stream
is returned to the caller.
History
- April 12, 2007
- April 18, 2007
- Fixed a bug in the calculation of image size
- Added functionality for exposing the location of each employee, thus enabling to trap clicks on specific employees
- April 19, 2007
- Fixed some more bugs in location calculation
- April 28, 2007
- Following the great tips of Seishin#, rebuilt part of the mechanism. Now using an
XmlDocument
as a tree and drawing the tree recursively. This also fixed the overlapping box bugs that were reported.
- April 30, 2007
- Another small box positioning issue fixed
- September 16, 2007
- Due to various issues, this version was rewritten. The article for it can be found here.