MyChartWebPart.cs // Standard SharePoint web part includes using System; using System.ComponentModel; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls; // Includes for chart libraries and related classes using System.Web.UI.DataVisualization; using System.Web.UI.DataVisualization.Charting; using System.Web.UI.DataVisualization.Charting.ChartTypes; using System.Drawing; // For SortList using System.Collections.Generic; using System.Collections; // For DataTable using System.Data; namespace MyChartWebPart.MyChartWebPart.cs [ToolboxItemAttribute(false)] public class MyChartWebPart : WebPart // The following define the properties that may // be set through the web part property sheet // 1. User selectable chart type public enum mycharttype Area, Bar, Column, Pie, Pyramid private mycharttype _mycharttype = mycharttype.bar; [WebDisplayName("Chart Type")] public mycharttype ChartType get return _mycharttype; set _mycharttype = value; // 2. Option of displaying a data table under the chart private bool _displaydatatable = false; [WebDisplayName("Display Data Table?")] public bool DisplayDataTable get return _displaydatatable; set _displaydatatable = value; // 3. Indicate whether clicking on the chart should apply // a filter to any list on the page private bool _setfilter = false; 1
[WebDisplayName("Click on Chart to Apply Filter?")] public bool SetFilter get return _setfilter; set _setfilter = value; // 4. Indicate whether chart should be in 3D private bool _is3d = false; [WebDisplayName("Display Chart in 3D?")] public bool Is3D get return _is3d; set _is3d = value; // 5. Select the list containing the chart data private string _listname = ""; [WebDisplayName("List Name")] public string ListName get return _listname; set _listname = value; // 6. Select the display field from the list private string _displayfield = ""; [WebDisplayName("Display Field")] public string DisplayField get return _displayfield; set _displayfield = value; // 7. Indicates whether the chart should SUM a numeric field, // or simply COUNT the instances of the display field private string _sumfield = ""; [WebDisplayName("Field to Sum (leave blank to COUNT instead)")] public string SumField get return _sumfield; set _sumfield = value; // This is where the chart and optional data table // are placed within the web part protected override void CreateChildControls() try // Create an empty chart and empty data series Chart mychart = new Chart(); mychart.chartareas.add("chart"); 2
Series series = new Series("Series"); mychart.series.add(series); // Center the chart within the web part zone this.horizontalalign = System.Web.UI.WebControls.HorizontalAlign.Center; // If user requested 3D, set chart accordingly if (_is3d) mychart.chartareas["chart"].area3dstyle.enable3d = true; // Set the chart type based on user-selected value switch (_mycharttype) case mycharttype.bar: series.charttype = SeriesChartType.Bar; case mycharttype.pie: series.charttype = SeriesChartType.Pie; case mycharttype.pyramid: series.charttype = SeriesChartType.Pyramid; case mycharttype.column: series.charttype = SeriesChartType.Column; case mycharttype.area: series.charttype = SeriesChartType.Area; default: // Get handle to current web site and selected list SPWeb web = SPControl.GetContextWeb(Context); SPList list = web.lists[_listname]; // Populated a sorted list with the data for the // chart System.Collections.SortedList chartdata = new SortedList(); foreach (SPListItem item in list.items) // It's possible that some items will not have // a value in the _displayfield, in that case // use a value of "[Empty]" string key; if (item[_displayfield]!= null) key = CleanUpFieldValue(item[_displayField].ToString()); key = "[Empty]"; // If user has specified a value field to be // summed, get its value, otherwise simply add // 1 to the counter double value = 0; if (_sumfield!= null && _sumfield!= "") try 3
value = double.parse(item[_sumfield].tostring()); catch value = 1; // If a row has already been added for this _displayfield // value in the list, simply add the value to that, // otherwise, add a new entry for the new _displayfield // value. if (!chartdata.containskey(key)) chartdata.add(key, value); chartdata[key] = double.parse(chartdata[key].tostring()) + value; // Set chart title mychart.titles.add("title"); Title title = new Title(_displayField, Docking.Top, new Font(myChart.Titles[0].Font.FontFamily, mychart.titles[0].font.size + 1, FontStyle.Bold), Color.Black); mychart.titles[0] = title; // Here's where the data in the chartdata sorted // list created above gets placed on the chart for (int i = 0; i < chartdata.count; i++) string key = chartdata.getkey(i).tostring(); string value = chartdata.getbyindex(i).tostring(); // Optional, this changes the bars from 2D to 3D series["drawingstyle"] = "Cylinder"; // Add the data point series.points.addxy(key, value); // Add the point label if this is a pie or pyramid chart, // because those two chart types do not contain legends if (series.charttype == SeriesChartType.Pie series.charttype == SeriesChartType.Pyramid) series.points[series.points.count - 1].Label = key; series.points[series.points.count - 1].LabelBackColor = Color.White; series.points[series.points.count - 1].LabelBorderColor = Color.Gray; series.points[series.points.count - 1].LabelBorderWidth = 1; // If user wants chart to filter list data, add SharePoint filter // elements to the Url querystring if (_setfilter) string baseurl = Context.Request.Url.ToString().Split('?')[0]; string filter = string.format("?filterfield1=0&filtervalue1=1", list.fields.getfield(_displayfield).internalname, iif(key == "[Empty]", "", key)); 4
series.points[series.points.count - 1].ToolTip = "Filter on: " + key; series.points[series.points.count - 1].Url = baseurl + filter; // Place the chart contstructed above on the web part this.controls.add(mychart); // Now add the data table if requested by user if (_displaydatatable) // Define data table to hold data from sorted list. // The GridView control created below will bind // to this data table DataTable dtchartdata = new DataTable(); dtchartdata.columns.add(_displayfield); if (_sumfield!= null && _sumfield!= "") dtchartdata.columns.add("sum of " + _sumfield); dtchartdata.columns.add("count"); // Copy data from sorted list into the new // data table for (int i = 0; i < chartdata.count; i++) string key = chartdata.getkey(i).tostring(); string value = chartdata.getbyindex(i).tostring(); DataRow drchartdata = dtchartdata.newrow(); drchartdata[0] = key; drchartdata[1] = value; dtchartdata.rows.add(drchartdata); dtchartdata.acceptchanges(); // Create and format the grid view GridView gvchartdata = new GridView(); gvchartdata.borderstyle = System.Web.UI.WebControls.BorderStyle.Solid; gvchartdata.borderwidth = Unit.Pixel(1); gvchartdata.bordercolor = Color.Gray; gvchartdata.cellpadding = 3; // Fill the grid view with data gvchartdata.horizontalalign = System.Web.UI.WebControls.HorizontalAlign.Center; gvchartdata.datasource = dtchartdata; gvchartdata.databind(); // Align columns gvchartdata.headerrow.cells[0].horizontalalign = System.Web.UI.WebControls.HorizontalAlign.Left; gvchartdata.headerrow.cells[1].horizontalalign = System.Web.UI.WebControls.HorizontalAlign.Right; foreach (GridViewRow row in gvchartdata.rows) row.cells[0].horizontalalign = System.Web.UI.WebControls.HorizontalAlign.Left; row.cells[1].horizontalalign = System.Web.UI.WebControls.HorizontalAlign.Right; // If user wants chart to filter list data, add that too if (_setfilter) string baseurl = Context.Request.Url.ToString().Split('?')[0]; string filter = string.format("?filterfield1=0&filtervalue1=1", 5
list.fields.getfield(_displayfield).internalname, iif(row.cells[0].text == "[Empty]", "", row.cells[0].text)); // Create new hyperlink to replace plane // text in first column of table HyperLink hl = new HyperLink(); hl.text = row.cells[0].text; hl.tooltip = "Filter on: " + row.cells[0].text; hl.navigateurl = baseurl + filter; // Clear out the first column and add the new // hyperlink row.cells[0].controls.clear(); row.cells[0].controls.add(hl); // Add the report to the web part this.controls.add(gvchartdata); catch (Exception ex) Label lblerrmsg = new Label(); lblerrmsg.text = "Error: " + ex.message; lblerrmsg.forecolor = System.Drawing.Color.Red; this.controls.add(lblerrmsg); // In SharePoint, person and lookup fields are in the format // <ID#>#<Display value>. We only want the display value, // so extract it here private string CleanUpFieldValue(string value) if (value.indexof("#")!= -1) value = value.split('#')[1]; return value; // This is a handy helper function private object iif(bool logicalexpression, object truevalue, object falsevalue) if (logicalexpression) return truevalue; return falsevalue; You may find more detailed instruction on how to compile and deploy the above web part in Mark Gerow s book "SharePoint 2007 Development Recipes," or one of the numerous web postings (such as http://msdn.microsoft.com/enus/library/bb153523(v=office.12).aspx) describing the process. 6