Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » .NET - Все статьи »

Обсудить на форуме Обсудить на форуме

Сложные графики и диаграммы в ASP.NET. Часть первая - OWC.

Решив написать статью про построение графиков в ASP.NET, я понял, что одной статьи не хватит и запланировал серию из трёх статей. Данная статья, первая из серии, предлагает решение через OWC и генератор клиентского скрипта, так сказать введение в OWC. Здесь мы рассмотрим 2 типа графиков (круговая диаграмма и столбчато-линейная :)).

В запланированной второй статье будет показан пример более сложных диаграмм и будет добавлен слой бизнес-логики и class-wrapper для графиков. В третьей статье будет предложено решение построения сложной диаграммы с помощью System.Drawing и отображения с помощью HttpHandler - средствами чистого .NET.

OWC - Office Web Component это компонент windows для построения диаграмм в web. Даже во времена ASP он находился в тени, а свет в основном падал на компоненты сторонних разработчиков, которые в большинстве случаев не превосходили OWC по возможностям. Главное его достоинство в том что он позволяет очень быстро и сравнительно легко построить диаграммы для всего приложения. Бесплатен. Узнаваем юзерами, пользующимися MS-Office.

Недостатки - такие же как у любого клиентского компонента. Ограничен. Нужно, чтобы присутствовал на машине. Хотя наличие офиса у юзера необязательно - достаточно чтобы был windows. Поэтому лично я предпочитаю построение диаграмм средствами чистого .NET, об этом мы поговорим в другой статье.

Итак, допустим, есть фирма, в фирме агенты, которые заключают контракты на определённые суммы, требуется: нарисовать диаграмму, которая показывает, кто сколько контрактов заключил:

Процедура, которая принесёт нужные данные:

CREATE procedure P_GET_ALL_PERCENTS  

as

select 
   A.AGENT_NAME, 
   count(C.CONTRACT_ID) 
from  
   T_AGENT A join T_CONTRACT C on 
   A.AGENT_ID = C.AGENT_ID
group by 
   A.AGENT_NAME
GO

Рассмотрим, как выглядит страница:

    /// 
	/// PieChart
	/// 
	public class PieChart : Page
	{
		private void Page_Load(object sender, System.EventArgs e)
		{
            // ##################################################
            // получим данные по-умолчанию из web.config
            #region GetFromConfig 
            string sDefaultFont = ConfigurationSettings.AppSettings["DefaultFont"].ToString();
            string sDefaultFontSize = ConfigurationSettings.AppSettings["DefaultFontSize"].ToString();
            string sDefaultLegendFontSize = ConfigurationSettings.AppSettings["DefaultLegendFontSize"].ToString();
            string sDefaultAxisFontSize = ConfigurationSettings.AppSettings["DefaultAxisFontSize"].ToString();
            string sInnerFontSize = ConfigurationSettings.AppSettings["InnerFontSize"].ToString();
            #endregion


            // ##################################################
            // получим данные из базы для PIE CHART
            // используем для этого класс DataLayer, 
            // который осуществляет работу с базой 
            SqlDataReader reader = null;
            DataLayer data = new DataLayer();
            data.RunProc("P_GET_ALL_PERCENTS", out reader);

            // кладём DataReader в ArrayList
            #region PutReaderInArrayList
            ArrayList rowList = new ArrayList();
            while (reader.Read()) {
                object[] values = new object[ reader.FieldCount];
                reader.GetValues( values);
                rowList.Add(values);
            }
            reader.Close();
            #endregion

            // здесь преобразуем ArrayList в delimited strings
            // которые несут в себе данные
            string strNames = "";
            string strValues = "";
            foreach (object[] row in rowList) 
            {
                strNames += String.Format("\"{0}\",", row[0].ToString());
                strValues += String.Format("{0},", row[1].ToString());
            }
            
            // legend and data
            strNames = strNames.Remove(strNames.Length - 1, 1);
            strValues = strValues.Remove(strValues.Length - 1, 1);

            
            // генерация клиентского скрипта 
            // ##################################################
            // ##################################################
            // StringBuilder 
            StringBuilder sb = new StringBuilder(""); 
            sb.Append("<script language=\"VBScript\">\n");            
            sb.Append("Sub Window_OnLoad()\n");
            sb.Append("call Show_ChartSpacePie\n");
            sb.Append("End Sub\n");
         
            // генерируем код клиентской функции, которая
            // работает с графиком
            // ##################################################
            #region GeneratePieChart             
            sb.Append("Sub Show_ChartSpacePie()\n");
            sb.Append("dim oChart\n");
            sb.Append("dim oSeries1, oSeries2, oSeries3\n");
            sb.Append("dim oAxis1, oAxis2\n");
            sb.Append("dim oConst\n");
            sb.Append("ChartSpacePie.Clear\n");
            sb.Append("Set oConst = ChartSpacePie.Constants\n");
            sb.Append("' Create a new chart in the ChartSpace.\n");
            sb.Append("Set oChart = ChartSpacePie.Charts.Add\n");
            sb.Append("oChart.Type = oConst.chChartTypePie\n");
            sb.Append("' Add a series of type Column.\n");
            sb.Append("Set oSeries1 = oChart.SeriesCollection.Add\n");
            sb.Append("oSeries1.Caption = \"C\"\n");
            
            // наши данные
            sb.Append("oSeries1.SetData oConst.chDimCategories, oConst.chDataLiteral, Array(" + strNames + ")\n");
            sb.Append("oSeries1.SetData oConst.chDimValues, oConst.chDataLiteral, Array(" + strValues + ")\n");
            
            sb.Append("With oSeries1.DataLabelsCollection.Add\n");
            sb.Append(".Position = 1\n");
            sb.Append(".Font.Name = \"" + sDefaultFont + "\"\n");
            sb.Append(".Font.Size = " + sInnerFontSize + "\n");
            sb.Append(".HasValue = False\n");
            sb.Append(".HasPercentage = True\n");
            sb.Append("End With\n");
            sb.Append("' Display the legend.\n");
            sb.Append("oChart.HasLegend = True\n");
            sb.Append("oChart.Legend.Font.Size = " + sDefaultLegendFontSize + "\n");
            sb.Append("oChart.Legend.Position = oConst.chLegendPositionRight\n");
            sb.Append("' Display the title for the chart.\n");
            sb.Append("oChart.HasTitle = True\n");
            sb.Append("oChart.Title.Font.Name = \"" + sDefaultFont + "\"\n");
            sb.Append("oChart.Title.Font.Size = " + sDefaultFontSize + "\n");
            sb.Append("oChart.Title.Caption = \"Agents Contracts\"\n");
            sb.Append("End Sub\n");
            #endregion
            
            // регистрируем скрипт
            sb.Append("</script>\n");
            if (!Page.IsClientScriptBlockRegistered("PieChart")) 
                Page.RegisterClientScriptBlock("PieChart", sb.ToString()); 
        }
	}

Вот и вся диаграмма.

Более сложный пример. Надо показать, на какую сумму определённый агент заключал контрактов каждый месяц и средняя сумма одного контракта в месяц.

Процедура, которая принесёт нужные данные:

CREATE procedure P_GET_AVG_BY_ID 
(
   @p_agent_id int
)
as

select
   A.AGENT_ID, 
   A.AGENT_NAME, 
   C.MONTH_ID, 
   sum(C.CONTRACT_VALUE),
   avg(C.CONTRACT_VALUE)
from  
   T_AGENT A join T_CONTRACT C on 
   A.AGENT_ID = C.AGENT_ID
where 
   A.AGENT_ID = @p_agent_id 
group by
   A.AGENT_ID,
   A.AGENT_NAME,
   C.MONTH_ID
order by 
   A.AGENT_ID,
   C.MONTH_ID

Рассмотрим, как выглядит страница:

    /// 
	/// BarAvgChart
	/// 
	public class BarAvgChart : Page
	{
		private void Page_Load(object sender, System.EventArgs e)
		{
            // ##################################################
           // получим данные по-умолчанию из web.config
            #region GetFromConfig 
            string sDefaultFont = ConfigurationSettings.AppSettings["DefaultFont"].ToString();
            string sDefaultFontSize = ConfigurationSettings.AppSettings["DefaultFontSize"].ToString();
            string sDefaultLegendFontSize = ConfigurationSettings.AppSettings["DefaultLegendFontSize"].ToString();
            string sDefaultAxisFontSize = ConfigurationSettings.AppSettings["DefaultAxisFontSize"].ToString();
            string sInnerFontSize = ConfigurationSettings.AppSettings["InnerFontSize"].ToString();
            #endregion


            // ##################################################
            // получим данные из базы для BAR AVG CHART
            SqlDataReader reader = null;
            DataLayer data = new DataLayer();
            SqlParameter[] prams = { data.MakeInParam("@p_agent_id", SqlDbType.Int, 4, 1) };
            data.RunProc("P_GET_AVG_BY_ID", prams, out reader);
            
            // кладём DataReader в ArrayList
            ArrayList rowList = new ArrayList();
            while (reader.Read()) 
            {
                object[] values = new object[ reader.FieldCount];
                reader.GetValues( values);
                rowList.Add(values);
            }
            reader.Close();
            #endregion


            // здесь преобразуем ArrayList в delimited strings
            // которые несут в себе данные
            string strMonths = "";
            string strValuesTotal = "";
            string strValuesAvg = "";
            string strNameAgent = "";
            foreach (object[] row in rowList) 
            {
                strMonths += String.Format("\"{0}\",", row[2].ToString());
                strValuesTotal += String.Format("{0},", row[3].ToString());
                strValuesAvg += String.Format("{0},", row[4].ToString());
                strNameAgent = row[1].ToString(); 
            }
            
            // legend and data
            strMonths = strMonths.Remove(strMonths.Length - 1, 1);
            strValuesTotal = strValuesTotal.Remove(strValuesTotal.Length - 1, 1);
            strValuesAvg = strValuesAvg.Remove(strValuesAvg.Length - 1, 1);
         

            // ##################################################
            // ##################################################
            // StringBuilder 
            StringBuilder sb = new StringBuilder(""); 
            sb.Append("<script language=\"VBScript\">\n");            
            sb.Append("Sub Window_OnLoad()\n");
            sb.Append("call Show_ChartSpaceBarAvg\n");
            sb.Append("End Sub\n");
           
            

            // ##################################################
            // генерируем код клиентской функции, которая
            // работает с графиком
            #region GenerateBarAvgChart
            sb.Append("Sub Show_ChartSpaceBarAvg()\n");
            sb.Append("dim oChart\n");
            sb.Append("dim oSeries1, oSeries2, oSeries3\n");
            sb.Append("dim oAxis1, oAxis2\n");
            sb.Append("dim oConst\n");
            sb.Append("ChartSpaceBarAvg.Clear\n");
            sb.Append("Set oConst = ChartSpaceBarAvg.Constants\n");
            sb.Append("'Create a new chart in the ChartSpace.\n");
            sb.Append("Set oChart = ChartSpaceBarAvg.Charts.Add\n");
            sb.Append("'Add a series of type Column.\n");
            sb.Append("Set oSeries1 = oChart.SeriesCollection.Add\n");
            sb.Append("oSeries1.Caption = \"Total\"\n");
            
            // наши данные для суммы
            sb.Append("oSeries1.SetData oConst.chDimCategories, oConst.chDataLiteral, Array(" + strMonths + ")\n");
            sb.Append("oSeries1.SetData oConst.chDimValues, oConst.chDataLiteral, Array(" + strValuesTotal + ")\n");
            
            sb.Append("oSeries1.Type = oConst.chChartTypeColumnStacked\n");
            sb.Append("oSeries1.Interior.Color = RGB(176,196,222)\n");
            sb.Append("With oSeries1.DataLabelsCollection.Add\n");
            sb.Append(".Position = 1\n");
            sb.Append(".HasValue = True\n");
            sb.Append(".Font.Size = " + sDefaultAxisFontSize + "\n");
            sb.Append("End With\n");
            sb.Append("' Add a second series of type Line.\n");
            sb.Append("Set oSeries2 = oChart.SeriesCollection.Add\n");
            sb.Append("oSeries2.Caption = \"Average\"\n");
            
            // наши данные для среднего арифметического
            sb.Append("oSeries2.SetData oConst.chDimCategories, oConst.chDataLiteral, Array(" + strMonths + ")\n");
            sb.Append("oSeries2.SetData oConst.chDimValues, oConst.chDataLiteral, Array(" + strValuesAvg + ")\n");
            
            sb.Append("oSeries2.Type = oConst.chChartTypeLine\n");
            sb.Append("oSeries2.Line.Color = RGB(178,38,38)\n");
            sb.Append("With oSeries2.DataLabelsCollection.Add\n");
            sb.Append(".Position = 1\n");
            sb.Append(".HasValue = True\n");
            sb.Append(".Font.Size = " + sDefaultAxisFontSize + "\n");
            sb.Append("End With\n");
            sb.Append("' Change the Min/Max, Numberformat and Gridlines for the value-axis of the first series.\n");
            sb.Append("Set oAxis1 = oChart.Axes(oConst.chAxisPositionLeft)\n");
            sb.Append("oAxis1.Scaling.Maximum = 50000\n");
            sb.Append("oAxis1.Scaling.Minimum = 0\n");
            sb.Append("oAxis1.NumberFormat = \"0\"\n");
            sb.Append("oAxis1.Font.Size = " + sDefaultAxisFontSize + "\n");
            sb.Append("Set oAxis2 = oChart.Axes(oConst.chAxisPositionBottom)\n");
            sb.Append("oAxis2.Font.Size = " + sDefaultAxisFontSize + "\n");
            sb.Append("oAxis1.HasMajorGridlines = False\n");
            sb.Append("' Ungroup the series so that they can have separate value-axis scaling.\n");
            sb.Append("' Display the legend.\n");
            sb.Append("oChart.HasLegend = True\n");
            sb.Append("oChart.Legend.Font.Size = " + sDefaultLegendFontSize + "\n");
            sb.Append("oChart.Legend.Position = oConst.chLegendPositionRight\n");
            sb.Append("' Display the title for the chart.\n");
            sb.Append("oChart.HasTitle = True\n");
            sb.Append("oChart.Title.Font.Size = " + sDefaultFontSize + "\n");
            sb.Append("oChart.Title.Caption = \"" + strNameAgent + "\"\n");
            sb.Append("End Sub\n");
            #endregion 
            
            // регистрируем скрипт
            sb.Append("</script>\n");
            if (!Page.IsClientScriptBlockRegistered("BarAvgChart")) 
                Page.RegisterClientScriptBlock("BarAvgChart", sb.ToString()); 
        }
	}

Вот и всё. Легко и очень быстро.

Добавим в web.config:

   <appsettings>
      <add key="ConnectionString"      value="server=localhost;database=DB_OWC;uid=sa;pwd=" />
      <add key="DefaultFont"           value="Verdana" />
      <add key="DefaultFontSize"       value="10" />
      <add key="InnerFontSize"         value="8" />
      <add key="DefaultLegendFontSize" value="7" />
      <add key="DefaultAxisFontSize"   value="6" />
   </appsettings>

В следующей статье я повышу уровень сложности для OWC. Ну а потом рассмотрим построение диаграмм средствами чистого .NET.

Код и database скрипты прилагаются.


Текст примеров данной статьи можно выкачать здесь


Может пригодится:


Автор: Anatoly Lubarsky
Прочитано: 7734
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (0)

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру