Вопрос

Возникло сразу несколько вопросов по графикам:

1. Можно ли показатель поделить на какое-то число перед отображением? Например, сумму выводить в миллионах рублей, а не в единицах рублей? Огромные числа не информативны!

2. Можно ли в горизонтальной гистограмме выводить top 5, 10 или 20 линий в сортировке по убыванию?

3. Как настроить подписи по оси Х, чтобы они были развернуты на 90%, т.е. вертикально? Тогда они перестанут наезжать друг на друга.

У меня такой же вопрос

3 комментария

Здравствуйте, Алексей!

1. На данный момент, к сожалению, данные на графиках отображаются в том же виде, в котором заполнены соответствующие поля на страницах разделов. Мы зафиксировали Ваше пожелание и передали его аналитикам продукта. Они рассмотрят возможность реализации настройки отображения данных на дашбордах в будущих релизах продукта

2. Индивидуально для каждого графика такой возможности нет, но можно ограничить количество выводимых на дашборд данных в системной настройке "Ограничение запроса данных графика". Тогда на графике будет отображаться только топ-N категорий согласно сортировке (работает начиная с версии 7.11.2, только с графиками, где настроена одна серия данных). Также можем предложить устанавливать дополнительные фильтры, чтоб уменьшить количество выводимых данных

3. К сожалению, пользовательскими средствами данную настройку выполнить возможности нет. Данная проблема находится в работе у аналитиков продукта с высоким приоритетом. Мы обязательно уведомим Вас, когда оно будет включено в релиз. В качестве обходного решения можем предложить устанавливать дополнительные фильтры в графиках, которые будут ограничивать количество выводимых на график данных. Также можно изменять высоту графика или, например, сделать один график большого размера на отдельной вкладке.

Мы передали все Ваши пожелания аналитикам продукта. Спасибо, что помогаете улучшать наши продукты!

Посмотрел в 7.11.2 как работает эта настройка.

Во-первых, она выдает на 1 значение больше, чем указано. Т.е. я указал значение 2 в настройке, а увидел 3 столбца-значения на графике.

Во-вторых, такая настройка нужна в каждом графике, но это и так, надеюсь, очевидно. Взять и обрезать данные во всех графиках и во всех разделах - идея странная и выглядит как заплатка.

Алексей, необходимая Вам настройка количества выводимых значений на график находится в работе у аналитиков продукта. На данный момент, к сожалению, настраивать количество выводимых значений индивидуально для блока итогов можно только для дашбордов с типом "Список".

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день! Возник вопрос по изменению графика в дашборде - можно ли изменить шаг вертикальной и горизонтальной оси, как добавить подписи с линейчатым графикам, можно ли добавить линию тренда (или просто пороговую горизонтальную линию), можно ли добавить больше цветов отображения серий графика?

У меня такой же вопрос

1 комментарий

Александр, здравствуйте!

По вопросам:

- можно ли изменить шаг вертикальной и горизонтальной оси,

- можно ли добавить линию тренда (или просто пороговую горизонтальную линию),

- можно ли добавить больше цветов отображения серий графика.

На данный момент такой возможности нет. Мы передали инфомацию в департамент разработки есть для анализа и возможной реализации в будущих версиях приложения.

По поводу "подписи с линейчатым графикам", то пописи появляются, когда Вы наводите курсор на саму линию.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Здравствуйте.
Как решить следующий бизнес-кейс?

Клиент понял, что необходимо работать над улучшением показателя "Длительность сделки".
Первым шагом является построение системы, которая позволит видеть значение средней длительности сделок за период и производить drill down до конкретного списка(представления).

Цель: вывести показатель "Средняя длительность сделок за период", Построить график "Распределение сделок по длительности".

Предлагаемое решение: в карточке "Продажа" есть показатель "Дней в воронке". Необходимо как-то выделить его в отдельные записи, выбрав по периоду.
И вывести среднеарифметическое за период.
Плюс построить график с распределением.

У меня такой же вопрос

2 комментария

Здравствуйте!

Показатель "Дней в воронке" считается "на лету" при открытии страницы редактирования "Продажи". Код, который отвечает за отображение дней в воронке:

updateDaysInFunnelValue: function(dueDate) {
	dueDate = dueDate || new Date();
	var createdOnValue = this.get("CreatedOn") || new Date();
	var dateNow = Terrasoft.clearTime(dueDate);
	createdOnValue = Terrasoft.clearTime(createdOnValue);
	var days = Terrasoft.dateDiffDays(createdOnValue, dateNow);
	days = Terrasoft.getFormattedNumberValue(days,
			{type: Terrasoft.DataValueType.INTEGER});
	this.set("DaysInFunnel", days > 0 ? days : "0");
},

В базовой версии, работая с объектом "Продажа" отобразить нужную аналитику не получится.

Что нужно сделать:
1) Создать объект VwOpportunityAnalitic, унаследовавшись от базового объекта и указав в свойствах объекта "Представление".
2) В объект добавить поля:

  • Дней в воронке - тип "Целое число" (DueDate)
    • Дата закрытия - тип "Дата/время" (DaysInFunnel)

        3) Опубликовать объект
        4) Создать представление в БД скриптом:

        create VwOpportunityAnalitic
        as
        (select Id, createdOn, DueDate, max(DueDate-createdOn, 0)) as DaysInFunnel

        В результате аналитику нужно будет строить по объекту VwOpportunityAnalitic, который будет содержать в себе все значения.

        Ограничить период вы сможете фильтрами, например:
        Дата создания >= [#Начало периода#] И Дата создания <= [#Завершение периода#]
        ИЛИ
        Дата завершения>= [#Начало периода#] И Дата завершения <= [#Завершение периода#]

    Спасибо, будем пробовать.

    "Демьяник Алексей" написал:

    Здравствуйте!

    Показатель "Дней в воронке" считается "на лету" при открытии страницы редактирования "Продажи". Код, который отвечает за отображение дней в воронке:

    updateDaysInFunnelValue: function(dueDate) {
            dueDate = dueDate || new Date();
            var createdOnValue = this.get("CreatedOn") || new Date();
            var dateNow = Terrasoft.clearTime(dueDate);
            createdOnValue = Terrasoft.clearTime(createdOnValue);
            var days = Terrasoft.dateDiffDays(createdOnValue, dateNow);
            days = Terrasoft.getFormattedNumberValue(days,
                            {type: Terrasoft.DataValueType.INTEGER});
            this.set("DaysInFunnel", days > 0 ? days : "0");
    },
    В базовой версии, работая с объектом "Продажа" отобразить нужную аналитику не получится.

    Что нужно сделать:
    1) Создать объект VwOpportunityAnalitic, унаследовавшись от базового объекта и указав в свойствах объекта "Представление".
    2) В объект добавить поля:

    • Дней в воронке - тип "Целое число" (DueDate)
      • Дата закрытия - тип "Дата/время" (DaysInFunnel)

          3) Опубликовать объект
          4) Создать представление в БД скриптом:

          CREATE VwOpportunityAnalitic
          AS
          (SELECT Id, createdOn, DueDate, max(DueDate-createdOn, 0)) AS DaysInFunnel

          В результате аналитику нужно будет строить по объекту VwOpportunityAnalitic, который будет содержать в себе все значения.

          Ограничить период вы сможете фильтрами, например:
          Дата создания >= [#Начало периода#] И Дата создания <= [#Завершение периода#]
          ИЛИ
          Дата завершения>= [#Начало периода#] И Дата завершения <= [#Завершение периода#]

      Войдите или зарегистрируйтесь, чтобы комментировать
      Вопрос

      Добрый день!
      Столкнулись с таким поведением системы:
      В замещающий объект "Продажа" добавлены несколько полей цифровых типов.
      В графиках пытаемся вывести сумму этих полей по определенным условиям, но после выбора способа агрегации (сумма, среднее, мин-макс), в списке возможных для выбора полей не появляются наши поля. Видны поля только из родительского объекта.
      Лечится ли это штатными способами, и, если нет, куда копать?

      У меня такой же вопрос

      2 комментария

      Перезайдите в систему, должна появиться.
      Если не поможет, чистим кэш браузера.

      Эм, да.. после полной чистки браузера, появилось. :confused:

      Войдите или зарегистрируйтесь, чтобы комментировать
      Идея
      C 7.5 реально появилась возможность настраивать dashboard'ы. Например, по активностям.Правда бывает, что нулевые показатели тоже нужны, а они не отображаются. Например, кол-во выполненных активностей за месяц по ответственным в гистограмме. Добавить бы чек-бокс-показывать нулевые значения. Чтобы видеть, у кого нули.
      Реализована
      1 комментарий

      Спасибо, что помогаете нам развивать и улучшать наши продукты. Ваша идея принята для анализа и будет рассмотрена возможность ее реализации в одной из последующих версий программного продукта.

      Войдите или зарегистрируйтесь, чтобы комментировать
      Вопрос

      Terrasoft XRM 3.4.0.168:
      1. Как сделать график с осями более двух: X и Y? Z может и т.д.
      2. Как сделать график с данными более двух колонок (X,Y)?
      3. Может есть где-то внешняя компонента с более удобными средствами построения графиков и визуализации вообще?

      У меня такой же вопрос

      1 комментарий

      Здравствуйте.

      В целом, FastReport умеет строить графики лучше. В нем есть Chart Editor, который позволяет добавлять трехмерные графики/диаграммы.

      Войдите или зарегистрируйтесь, чтобы комментировать
      Вопрос

      Добрый день, Коллеги.

      Стоит задача разработать модуль для отображения информации в реальном времени в графическом виде по сущностям нашей системы:
      -Обращения абонентов;
      -Звонки абонентов.

      Планируется разработать 2 вкладки:
      Отображение обращений по тематикам;
      Отображение звонков абонентов по типам.

      Похожих задач я не реализовывал, поэтому хотелось бы услышать от Вас рекомендаций:
      -какие объекты для этого лучше всего использовать
      -как построить процесс обновления данных

      У меня такой же вопрос

      5 комментариев

      Точно на 2.8?

      Форумом ошибся, спасибо за замечание.

      Интересует реализация на базе платформы Terrasoft CRM в версии 3.X

      Алексей, уточните, пожалуйста, точную версию продукта(к примеру 3.4.1 ...т.п) и СУБД.

      Версия продукта - Terrasoft 3.4.0.138

      Есть мысли использовать блоки из модуля - Graphs

      Алексей, прежде всего рекомендую обратить внимание на элемент Timer в невизуальных элемента сервиса окна wnd_Main - в обоаботчике таймера OnTimer можно реализовать необходимое Вам обновление окна или графика.

      Рализация обновления элементов окон и графиков реализованы также в Dashboard\General\DashboardView\wnd_DashboardView, Dashboard\General\DashboardView\wnd_DashboardViewScript

      Войдите или зарегистрируйтесь, чтобы комментировать
      Вопрос

      Добрый день!
      Господа подскажите , пожалуйста, как построить сложный график. Чтоб сравнение шло по 3 параметра, тип графика : линия.

      Пробовал по ссылке, http://www.community.terrasoft.ru/forum/topic/5608
      но воссоздать так и не получилось, может кто проделывал такое?
      Желательно подробнейшее описание.
      За ранее благодарен.
      Примерно вот такого вида

      У меня такой же вопрос

      16 комментариев

      Здравствуйте,
      Как обходное решение, вы можете построить график в FastReport, подробнее вы можете прочитать в теме "FastReport- график с несколькими линиями"
      http://www.community.terrasoft.ru/forum/topic/6703

      Алексей, вот такой вопросик, мне просто в самом террасофте построить этот график , в графиках, Олег рассказал как это сделать, но я никак не могу понять, он рисует график, но продолжает линию, а мне надо чтоб она отдельной была.я добавил параметры,вот сам скрипт wnd_GraphEditScript

      //-----------------------------------------------------------------------------
      // wnd_GraphEditScript
      //-----------------------------------------------------------------------------
       
      var GraphEditScript = new Object();
       
      function Initialize(Window) {
      	if (Assigned(edtWorkspaceCode.Enum)) {
      	    return;
      	}
      	edtWorkspaceCode.Enum = scr_GraphUtils.GetWorkspacesEnum();  
      	edtFieldX.CaptionColor = LayoutLookAndFeelRequiredItemColor;    	
      	edtFieldY.CaptionColor = LayoutLookAndFeelRequiredItemColor;
       
      }
       
      function EnableQueryControls(IsEnabled) {	
      	edtFieldX.IsEnabled = IsEnabled;
      	edtFieldY.IsEnabled = IsEnabled;
      	edtFieldLink.IsEnabled = IsEnabled;
      	amiQueryEdit.IsEnabled = IsEnabled;
      }
       
      function CheckGraphControls() {	  
      	var IsEnabled = Boolean(        
      		(edtName.DataField) && (edtName.DataField.Value) &&
      		(edtType.DataField) && (!IsEmptyValue(edtType.DataField.Value)) &&
      		(edtQuery.DataField) && (edtQuery.DataField.Value) &&
      		GetEnumControlValue(edtFieldX) &&
      		GetEnumControlValue(edtFieldY) 
      		//&&	GetEnumControlValue(edtFieldY1) //BobkovPN
      		);
      	btnPreview.IsEnabled = IsEnabled;
      	btnOK.IsEnabled = IsEnabled;
      }
       
      function SetFieldEnum(Control, Enum) {
      	var OldValueCode;
      	if (Control.Value) {
      		OldValueCode = Control.Value.Code;
      	}
      	Control.Enum = Enum;
      	if (OldValueCode) {
      		SetEnumControlValue(Control, OldValueCode);
      	} else {
      		Control.Value = System.EmptyValue; 
      	}
      }
       
      function GetUniqueCaption(Enum, Caption, Iter) {
      	if (Iter > 1) {
      		Caption = Caption + '(' + Iter + ')';
      	} 
      	if (Enum.ItemsByCaption(Caption)) {	
      		return GetUniqueCaption(Enum, Caption, Iter + 1) 
      	} else {
      		return Caption;	
      	}
      }
       
      function CreateEnumItemCheck(Enum, Code, Caption) {
      	Caption = GetUniqueCaption(Enum, Caption, 1);
      	return CreateEnumItem(Enum, Code, Caption);
      }
       
      function PrepareDiagramFields(Dataset) {
      	var enmFieldX = Services.CreateItem(EnumObjectName);
      	var enmFieldY = Services.CreateItem(EnumObjectName);
      	var enmFieldY1 = Services.CreateItem(EnumObjectName); //BobkovPN
      	var enmFieldLink = Services.CreateItem(EnumObjectName);
      	var Name;
      	var Caption;
      	for (var i = 0; i < Dataset.DataFields.Count; i++) {		
      	    var Field = Dataset.DataFields.Items(i);		
      		Caption = Field.Caption;	    
      	    if (Caption == '__ID__') {
      	    	continue;
      	    }   
      	    Name = Field.Name;
          	if (GraphEditScript.DisplayFilterFields(Field.Tag)) {
          		CreateEnumItemCheck(enmFieldLink, Name, Caption);
          	}
      	    if (Field.IsEnabled) {
      		    switch (Field.FieldType) {	    	
      	    	case dftInteger:
      			case dftFloat:
      			case dftBool:
      				CreateEnumItemCheck(enmFieldY, Name, Caption);
      				break;
      			case dftDateTime:
      				CreateEnumItemCheck(enmFieldX, Name, Caption);
      				break;                                       			
      			default: 
      				CreateEnumItemCheck(enmFieldX, Name, Caption);
      		    }   
      		}
      	}	 debugger;
      	SetFieldEnum(edtFieldX, enmFieldX);
      	SetFieldEnum(edtFieldY, enmFieldY);
      	SetFieldEnum(edtFieldY1, enmFieldY1);//BobkovPN
      	SetFieldEnum(edtFieldLink, enmFieldLink);
      }                                 
       
      function LoadQueryInfo(QueryID) {
          GraphEditScript.Query = GetQueryDataset(QueryID, GraphEditScript);
          if (!GraphEditScript.Query) {
          	return false;
          }    
          if (!dlData.Dataset.Values('Name')) {
      		dlData.Dataset.Values('Name') = GraphEditScript.QueryName;
      	}
          PrepareDiagramFields(GraphEditScript.Query);
          return true;
      }
       
      function InitializeContolValuesByDataset() {
      	var Dataset = dlData.Dataset;
      	edtWorkspaceCode.Value = System.EmptyValue;
      	var WorkspaceCode = Dataset.ValAsStr('WorkspaceCode');
      	SetEnumControlValue(edtWorkspaceCode, WorkspaceCode);	
      	var QueryLoaded = LoadQueryInfo(Dataset.Values('QueryID'));
      	EnableQueryControls(QueryLoaded);
      	SetEnumControlValue(edtFieldX, Dataset.ValAsStr('FieldX'));
      	SetEnumControlValue(edtFieldY, Dataset.ValAsStr('FieldY'));
      	SetEnumControlValue(edtFieldY1, Dataset.ValAsStr('FieldY1')); //BobkovPN
      	SetEnumControlValue(edtFieldLink, Dataset.ValAsStr('FieldLink'));
      	CheckGraphControls();
      }
       
      function SaveControlValuesToDatasetWithCheck() {
      	var Dataset = dlData.Dataset;
      	if ((Dataset.State != dstEdit) & (Dataset.State != dstInsert)) { 
      		return false;
      	} 	
      	var WorkspaceCode = GetEnumControlValue(edtWorkspaceCode);	
      	Dataset.Values('WorkspaceCode') = WorkspaceCode;	
      	var FieldXCode = GetEnumControlValue(edtFieldX);
      	if (!CheckRequiredControlCondition(edtFieldX, FieldXCode, 
      		Dataset.DataFields('FieldX').Caption)) {
      		return false;
      	}
      	Dataset.Values('FieldX') = FieldXCode; 	
      	var FieldYCode = GetEnumControlValue(edtFieldY);	
      	if (!CheckRequiredControlCondition(edtFieldY, FieldYCode, 
      		Dataset.DataFields('FieldY').Caption)) {
      		return false;
      	}
      	Dataset.Values('FieldY') = FieldYCode;
      	////////////BobkovPN
      	if (!CheckRequiredControlCondition(edtFieldY1, FieldY1Code, 
      		Dataset.DataFields('FieldY1').Caption)) {
      		return false;
      	}
      	Dataset.Values('FieldY1') = FieldY1Code;
      	//////***************
      	var FieldLinkCode = GetEnumControlValue(edtFieldLink);	
      	Dataset.Values('FieldLink') = FieldLinkCode;
      	return true;
      }
       
      function ShowPreview() {
      	if (!GraphEditScript.Query) {
      		ShowInformationDialog("Выберите запрос");
      		return;
      	}              	
      	var PreviewAttributes = GetNewDictionary(); 	
      	PreviewAttributes('Dataset') = GraphEditScript.Query;
      	PreviewAttributes('FieldX') = GetEnumControlValue(edtFieldX);
      	PreviewAttributes('FieldY') = GetEnumControlValue(edtFieldY);
      	PreviewAttributes('FieldY1') = GetEnumControlValue(edtFieldY1); //BobkovPN
      	PreviewAttributes('FieldLink') = GetEnumControlValue(edtFieldLink);
      	PreviewAttributes('GraphType') = edtType.DataField.Value;	
      	PreviewAttributes('GraphName') = edtName.DataField.Value;	
      	var Attributes = GetNewDictionary();                 
      	Attributes(NotifyObjectAttrName) = Self; 	
      	Attributes('PreviewMode') = 'Edit';       	
      	Attributes('PreviewAttributes') = PreviewAttributes; 	
      	ShowEditWindowEx('wnd_GraphPreview', Attributes);   	
      }
      //////////////BobkovPN
      function  ActiveAdvancedGraph () {
      	var Dataset = dlData.Dataset;
      	var FastLine = GetDatasetFieldValue(Dataset,'TypeID');
      	if (FastLine == gt_FastLine){
      			 	fgExtendedGraph.IsEnabled = true;
      			 	cbAdvancedGraphik.IsEnabled = true;
      		 }else{
      			 	 cbAdvancedGraphik.IsChecked=false;
      				 fgExtendedGraph.IsEnabled = false;
       
      		}
      }
       
      function UpdateDataControlsByParams() {
      	Self.BeginUpdate();
      	try {      
      		var Window = Self;
       
      		if (cbAdvancedGraphik.IsChecked == true) {
      			edtFieldY1.IsVisible = true;
      			edtFieldY2.IsVisible = true;
      			edtFieldY3.IsVisible = true;
      			edtFieldY4.IsVisible = true;
      			edtFieldY5.IsVisible = true;
      			edtFieldY6.IsVisible = true;
      			edtFieldY7.IsVisible = true;
      			edtFieldY8.IsVisible = true;
      			edtFieldY9.IsVisible = true;
      		}else{
      		    edtFieldY1.IsVisible = false;
      			edtFieldY2.IsVisible = false;
      			edtFieldY3.IsVisible = false;
      			edtFieldY4.IsVisible = false;
      			edtFieldY5.IsVisible = false;
      			edtFieldY6.IsVisible = false;
      			edtFieldY7.IsVisible = false;
      			edtFieldY8.IsVisible = false;
      			edtFieldY9.IsVisible = false;
      		 }
      		Window.Height = GetFrameHeight(Window);
       
      	} finally {
      	Self.EndUpdate();
      	} 
      }
      ////////////////********************
      //-----------------------------------------------------------------------------
      // Event handlers
      //-----------------------------------------------------------------------------
       
      function wnd_GraphEditOnPrepare(Window) {
      	Initialize(Window);
      	wnd_BaseDBEditOnPrepare(Window);
      	UpdateDataControlsByParams();
      	ActiveAdvancedGraph (); 
      	InitializeContolValuesByDataset();
      }
       
      function btnOKOnClick(Control) {
      	if (!SaveControlValuesToDatasetWithCheck()) {
      		return;	
      	} 
      	scr_BaseDBEdit.btnOKOnClick(Control);
      }
       
      function dlDataOnDatasetDataChange(DataField) {
      	switch (DataField.Name) {
      		case 'QueryID':
      			var QueryLoaded = LoadQueryInfo(DataField.Value);	
      			EnableQueryControls(QueryLoaded);
      		case 'TypeID':
      		//////////////////BobkovPN
      		ActiveAdvancedGraph();
      		//////////////////////////
      		case 'Name':
      			CheckGraphControls();
      	}
       
      }
       
      function btnPreviewOnClick(Control) {
      	ShowPreview();
      }
       
      function wnd_GraphEditOnShow(Window) {
      }
       
      function amiShowFullCaptionOnExecute(ActionMenuItem, Sender) {
      	switch (Sender.Name) {
      		case 'edtFieldX':
      			var FieldCode = GetEnumControlValue(edtFieldX);
      			break;
      		case 'edtFieldY':
      			var FieldCode = GetEnumControlValue(edtFieldY);
      			break;
      		//////BobkovPN	
      		case 'edtFieldY1':
      			var FieldCode = GetEnumControlValue(edtFieldY1);
      			break;
      		//////***********
      		case 'edtFieldLink':
      			var FieldCode = GetEnumControlValue(edtFieldLink);
      			break;
      	}	 	
      	if (!FieldCode) {
      		return;
      	}
      	var Field = GraphEditScript.Query.DataFields.ItemsByName(FieldCode);
      	var FieldCaption = GraphEditScript.Columns(Field.Tag);
      	ShowInformationDialog(FieldCaption);
      }
       
      function amiQueryEditOnExecute(ActionMenuItem, Sender) {
      	var QueryID = edtQuery.DataField.Value;
      	if (!QueryID) {
      		return;
      	}
      	ShowQueryEditWindow(QueryID, Self);
      }
       
      function wnd_GraphEditOnNotify(ScriptableService, Sender, Message, Data) {
      	if (Message == 'MSG_OK') {
      		var Dataset = dlData.Dataset;
      		var QueryID = Dataset.Values('QueryID');
      		LoadQueryInfo(QueryID);
      		edtQuery.DataField.Value = GUID_NULL;
      		edtQuery.DataField.Value = QueryID;
      		return;
      	} 
      	wnd_BaseGridAreaOnNotify(ScriptableService, Sender, Message, Data);
      }
       
      function edtNameOnClick(Control) {
      	CheckGraphControls();
      }
       
      function edtFieldXOnChange(EnumControl) {
      	CheckGraphControls();
      }
       
      function edtFieldYOnChange(EnumControl) {
      	CheckGraphControls();
      }
       
      ////////BobkovPN
      function cbAdvancedGraphikOnClick(Control) {
      	UpdateDataControlsByParams();
      }
       
      function edtFieldY1OnChange(EnumControl) {
      	CheckGraphControls();
      }
      ////////************

      а вот scr_GraphUtils

      //-----------------------------------------------------------------------------
      // scr_GraphUtils
      //----------------------------------------------------------------------------
       
      var GraphUtils = new Object();
       
      function GetWorkspacesEnum() {
      	if (GraphUtils.WorkspacesEnum) {
      	    return GraphUtils.WorkspacesEnum;
      	}
      	var WorkspaceCodes = GetNewDictionary();
      	/* MODULE ACCOUNTS */
      	WorkspaceCodes("Контрагенты") = 'wnd_AccountsWorkspace';
      	/* ENDMODULE ACCOUNTS */	
      	/* MODULE CONTACTS */
      	WorkspaceCodes("Контакты") = 'wnd_ContactsWorkspace';
      	/* ENDMODULE CONTACTS */
      	/* MODULE TASKS */
      	WorkspaceCodes("Задачи") = 'wnd_TasksWorkspace';
      	/* ENDMODULE TASKS */
      	/* MODULE MAIL */
      	WorkspaceCodes("E-mail") = 'wnd_MailWorkspace';
      	WorkspaceCodes("Шаблоны сообщений") = 'wnd_MailTemplatesWorkspace';
      	/* ENDMODULE MAIL */
      	/* MODULE WORKFLOW */
      	WorkspaceCodes("Процессы") = 'wnd_WorkflowWorkspace';
      	/* ENDMODULE WORKFLOW */
      	/* MODULE LIBRARY */
      	WorkspaceCodes("Библиотека") = 'wnd_LibraryWorkspace';
      	/* ENDMODULE LIBRARY */
         	/* MODULE OPPORTUNITIES */
      	WorkspaceCodes("Продажи") = 'wnd_OpportunitiesWorkspace';
         	/* ENDMODULE OPPORTUNITIES */
       
         	/* MODULE CONTRACTS */
      	WorkspaceCodes("Договоры") = 'wnd_ContractsWorkspace';
         	/* ENDMODULE CONTRACTS */
         	/* MODULE DOCUMENTS */
      	WorkspaceCodes("Документы") = 'wnd_DocumentsWorkspace';
         	/* ENDMODULE DOCUMENTS */
         	/* MODULE OFFERINGS */
      	WorkspaceCodes("Продукты") = 'wnd_OfferingsWorkspace';
      	/* ENDMODULE OFFERINGS */
         	/* MODULE INVOICES */
      	WorkspaceCodes("Счета") = 'wnd_InvoicesWorkspace';
         	/* ENDMODULE INVOICES */
         	/* MODULE CAMPAIGNS */
      	WorkspaceCodes("Воздействия") = 'wnd_CampaignsWorkspace';
         	/* ENDMODULE CAMPAIGNS */
       
      	/* MODULE MASSMAIL */
      	WorkspaceCodes("Рассылка") = 'wnd_MassMailWorkspace';
      	/* ENDMODULE MASSMAIL */
      	/* MODULE QUERIES */
      	WorkspaceCodes("Запросы") = 'wnd_QueryWorkspace';
      	/* ENDMODULE QUERIES */
      	/* MODULE REPORTS */
      	WorkspaceCodes("Отчеты") = 'wnd_ReportsWorkspace';
      	/* ENDMODULE REPORTS */  	
       
      	WorkspaceCodes("Журнал изменений БД") = 'wnd_DatabaseLogWorkspace';
      	WorkspaceCodes("Интеграции") = 'wnd_DataflowsWorkspace';
       
      	WorkspaceCodes("Звонки") = 'wnd_CallWorkspace';
      	/* MODULE PLANNING */
      	WorkspaceCodes("Настройка планирования") = 'wnd_PlanningWorkspace';
      	/* ENDMODULE PLANNING */
       
      	WorkspaceCodes("Графики") = 'wnd_GraphsWorkspace';
      	WorkspaceCodes("Настройка итогов") = 'wnd_DashboardWorkspace';
      	/* MODULE PIPELINES */
      	WorkspaceCodes("Воронка продаж") = 'wnd_PipeLineWorkspace';   
      	/* ENDMODULE PIPELINES */	
      	WorkspaceCodes("Контрагенты") = 'wnd_AccountsWorkspace';
      	WorkspaceCodes("Воздействия") = 'wnd_CampaignsWorkspace';
      	WorkspaceCodes("Контакты") = 'wnd_ContactsWorkspace';
      	WorkspaceCodes("Акции поставщика") = 'wnd_ActionManufakturWorkspace';
       
      /* CUSTOM MODULE BOOKMARK */
      	var Keys = (new VBArray(WorkspaceCodes.Keys())).toArray();
      	Keys.sort();
      	var Enum = Services.CreateItem(EnumObjectName);
      	for (var i in Keys) {
      	    var Caption = Keys[i];
      	    var Code = WorkspaceCodes(Caption);
      	   	CreateEnumItem(Enum, Code, Caption);
      	}
         	GraphUtils.WorkspacesEnum = Enum;
         	return Enum;
      }
       
      function GetGraphDataset(GraphID) {
      	var Dataset = GetSingleItemByCode('ds_Graph', 'GraphUtils'); 
      	ApplyDatasetIDFilter(Dataset, GraphID, true);
          return Dataset;
      }
       
      function GetField(FieldPath) {
      	var SegmentsArray = FieldPath.split(snpSegment); 
          var Segment = SegmentsArray[0];
          var FieldsArray = Segment.split(jtLeft);
      	var Field = GetTableFieldByUIDCode(FieldsArray[0]);
      	return Field;
      }
       
      function GetTableFieldByUIDCode(FieldUIDCode) {
          FieldUIDCodeArray = FieldUIDCode.split(snpFields);
      	var TableUID = FieldUIDCodeArray[0];
      	var FieldUID = FieldUIDCodeArray[1];
      	var Table = Services.GetSingleItemByID(TableUID);
      	var Field = Table.Fields.CoreItemsByUID(FieldUID);
      	return Field;
      }
       
      function GetTableIDFieldByUIDCode(FieldUIDCode) {
          FieldUIDCodeArray = FieldUIDCode.split(snpFields);
      	var TableUID = FieldUIDCodeArray[0];
      	var Table = Services.GetSingleItemByID(TableUID);
      	var Field = Table.Fields.ItemsByName('ID');
      	return Field;
      }
       
      function GetFilterField(FieldPath) {
      	var SegmentsArray = FieldPath.split(snpSegment);
      	if (SegmentsArray.length > 1) {
      		var Segment = SegmentsArray[SegmentsArray.length -2];
      	    var FieldsArray = Segment.split(jtLeft);
      		var Field = GetTableFieldByUIDCode(FieldsArray[0]);
      	} else 
      	if (SegmentsArray.length == 1) {
      		var Segment = SegmentsArray[0];
      		var FieldsArray = Segment.split(jtLeft);       
      		var Field = GetTableIDFieldByUIDCode(FieldsArray[FieldsArray.length -1]);	    
      	} else {
      		return null;
      	}
      	return Field;
      }
       
      function GetDisplayFilterField(FieldPath) {
      	var SegmentsArray = FieldPath.split(snpSegment); 
          var Segment = SegmentsArray[SegmentsArray.length -1];
          var FieldsArray = Segment.split(jtLeft);
      	var Field = GetTableFieldByUIDCode(FieldsArray[FieldsArray.length -1]);
      	return Field;
      }
       
      function IsPrimaryDisplayField(Field) {
      	var Result = false;
      	try {
      		var ParentTable = Field.ParentFields.ParentTable;
      		if (ParentTable.PrimaryDisplayTableField) {
      			Result = (Field.UID == ParentTable.PrimaryDisplayTableField.UID); 			
      		}
      		Result = Result || (Field.KeyValue == 'ID');
      	} finally {
      		return Result;
      	}
      }
       
      function GetQueryDataset(QueryID, GraphPreview) { 	
      	if (IsEmptyValue(QueryID)) {
      		return null;
      	}
      	var QueryDataset = GetSingleItemByCode('ds_Query', 'GraphUtils');
          ApplyDatasetIDFilter(QueryDataset, QueryID, true);
          QueryDataset.Open();   
      	try {     
      	    var XMLStorage = GetNewXMLStorage();
      	    XMLStorage.LoadFromDataset(QueryDataset, rdfnQueryData);
      	    var UserReportData = new Object();
      	    var ReadXMLResult = DeserializeXMLData(UserReportData, XMLStorage);
      	    if (!ReadXMLResult) {
      	        return null;
      	    }
      		var RootSection = GetRootSection(ReadXMLResult);
      		if (!RootSection) {
      	        return null;
      	    }    	
       
      		var Dataset = GetDatasetBySectionAndSetupDatasetLink(RootSection, 
      			UserReportData.Sections);
      		if (!Dataset) {
      			return null;
      		}  
      		Dataset.Attributes('QueryFilterData') = 
      			UserReportData['QueryFilterData'];   	         
      		SetSectionUserFilters(RootSection);
       
      		if (Assigned(GraphPreview)) {
      	    	if (Assigned(GraphPreview)) {
      				GraphPreview.QueryName = QueryDataset.Values('Name');
      			}
      			var ColumnDict = GetNewDictionary();	
      			var FieldsDict = GetNewDictionary();		
      			var FilterFieldsDict = GetNewDictionary();		
      			var DisplayFilterFieldsDict = GetNewDictionary();
      		    var Columns = new VBArray(RootSection.Columns.Keys()).toArray();
      			var Length = Columns.length;
      			var Column;
      			var FieldPath;
      			var Field;
      			var FilterField;
      			var DisplayFilterField;
      			for (var i = 0; i < Length; i++) {
      				Column = RootSection.Columns(Columns[i]);
      				FieldPath = GetFieldPathString(Column.FieldPath);
      				ColumnDict.Add(Column.ID, FieldPath);
      				Field = GetField(Column.FieldPath);
      				FieldsDict.Add(Column.ID, Field);
      				DisplayFilterField = GetDisplayFilterField(Column.FieldPath);
      				if (IsPrimaryDisplayField(DisplayFilterField)) {
      					FilterField = GetFilterField(Column.FieldPath);
      					FilterFieldsDict.Add(Column.ID, FilterField);
      					DisplayFilterFieldsDict.Add(Column.ID, DisplayFilterField);
      				}
      			}
      			GraphPreview.Columns = ColumnDict;
      			GraphPreview.Fields = FieldsDict;
      			GraphPreview.DisplayFilterFields = DisplayFilterFieldsDict;
      			GraphPreview.FilterFields = FilterFieldsDict;
      		}
      	} finally {
      		QueryDataset.Close();	
      	}
      	return Dataset;
      }
       
      function FullScreenPreview(Graph) {
      	var Attributes = GetNewDictionary();
      	Attributes('Graph') = Graph;	
      	ShowEditWindowEx('wnd_GraphPreview', Attributes);   	
      }
       
      function ShowPreview(GraphID, NotifyObject) {
      	if (IsEmptyGUID(GraphID)) {
      		ShowInformationDialog("Выберите запрос");
      		return false;
      	}                        	
      	var Attributes = GetNewDictionary();
      	Attributes('GraphID') = GraphID;	
      	Attributes(NotifyObjectAttrName) = NotifyObject; 
      	ShowEditWindowEx('wnd_GraphPreview', Attributes);   	
      	return true;
      }
       
      function ApplyDatasetIDsFilter(Dataset, FilterName, ParamName, ParamValue, 
      	Enabled) {
      	var Select = GetSelectQueryPrimarySelect(Dataset.SelectQuery);
      	var Filters = Select.Filters;
      	Filter = Filters.ItemsByCode(FilterName);
      	if (!Assigned(Filter)) {
      	    Filter = Filters.CreateIncludeFilter();
      	    Filter.Code = FilterName;
      	    Filters.Add(Filter);
      		Filter.TestExpression =
      			Filter.CreateFieldFilterExpression();
      		Filter.TestExpression.TableAlias =
      			Select.FromTableAlias;
      		Filter.TestExpression.Field =
      			Select.FromTable.Fields.ItemsByName(ParamName);
      	}
      	ApplyDatasetIncludeFilter(Dataset, FilterName, ParamValue, Enabled);
      }
       
      function FilterGraphDataset(Dataset, IsWorkspace, GridDataset, 
      	FieldLinkName, GraphPreview) {
      	Dataset.Close();      	
      	var FieldLink = Dataset.DataFields.ItemsByName(FieldLinkName);
      	var Field = GraphPreview.FilterFields(FieldLink.Tag); 
      	if (!Field) { 
      		return false;
      	}
      	var Table = Field.ParentFields.ParentTable; 
      	var SelectQuery = Dataset.SelectQuery;
      	var Select = SelectQuery.Items(0);	
      	var Filters = Select.Filters;
      	var TableAlias = Select.FromTableAlias;
      	var Join = Select.Columns.ItemsByAlias(FieldLink.KeyValue).ParentJoin;		
      	if (Join) {
      		if (Join.ParentJoin) {
      			TableAlias = Join.ParentJoin.LeftTableAlias;
      		}
      	}				
      	if (IsWorkspace) {    			  		
      		var GridSelect = GridDataset.SelectQuery.Items(0).CreateCopy();
      		GridSelect.Top = -1;
      		var GridTable = GridSelect.FromTable; 
      		// Add exist filter
      		var ExistFilter = Filters.CreateExistsFilter();
      	    ExistFilter.KeyValue = 
      			GenNewKeyValueFromCollection(Filters, 'ExistFilter');
      		var FilterExpression = ExistFilter.CreateSelectFilterExpression();
      		FilterExpression.ExpressionSelectQuery.Add(GridSelect); 					
      		ExistFilter.TestExpression = FilterExpression;	
      		ExistFilter.IsEnabled = true;		
      	    Filters.Add(ExistFilter);  		    
      	    // Add compare filter to new exist filter
      	    var ExpressionSelectQuery =	FilterExpression.ExpressionSelectQuery;
      		var ExpressionSelect = ExpressionSelectQuery.Items(0);
      		var FieldLinkFilter = AddFieldFieldCompareFilter(
      			ExpressionSelect.Filters, 
      			GridTable.Fields.ItemsByName('ID'), GridSelect.FromTableAlias,
      			Field, TableAlias, cotEqual)
      	    FieldLinkFilter.IsEnabled = true;  	    
      	    // Reassign parameters
      	    var Parameters = GridDataset.SelectQuery.Parameters;
      	    for (var i = 0; i < Parameters.Count; i++) {
      	    	var Parameter = Parameters.Items(i).CreateCopy();
      	    	SelectQuery.Parameters.Add(Parameter);
      	    }
      	    // Disable all columns for select from main grid
      	    DisableAllColumns(GridSelect.Columns, true);   
      	} else {		
      		var ID = GridDataset.Values('ID');	
      		var FieldLinkParameter = 
      			AddParameter(SelectQuery.Parameters, Field.SQLDataType, ID); 		
      		var FieldLinkFilter = AddFieldParamCompareFilter(Filters, Field,
      			TableAlias, FieldLinkParameter, cotEqual);  	
      		FieldLinkFilter.IsEnabled = true; 				
      	}	
      	return true;
      }
       
      function BuildGraph(Window, GraphID) {
      	var edtGraphPreview = Window.ComponentsByName('edtGraphPreview');
      	var Graph = edtGraphPreview.ActiveXObject;
      	if (!Graph) {
      		return
      	}
      	if (Window.Attributes('PreviewMode') == 'Edit') {
      		// Предпросмотр из карточки графика
      		var PreviewAttributes = Window.Attributes('PreviewAttributes');	
      		var Dataset = PreviewAttributes('Dataset');	
      		var FieldXName = PreviewAttributes('FieldX');	
      		var FieldYName = PreviewAttributes('FieldY');	
      		var FieldY1Name = PreviewAttributes('FieldY1'); //BobkovPN
      		var FieldLinkName = PreviewAttributes('FieldLink');
      		RemoveNonGraphColumns(Dataset, FieldXName, FieldYName);
      		var GraphType = PreviewAttributes('GraphType');
      		var GraphName = PreviewAttributes('GraphName');
      		return DrawGraphByDataset(Dataset, Graph, FieldXName, 
      			FieldYName, GraphType, GraphName, edtGraphPreview);	
      	}       	
      	if (IsEmptyGUID(GraphID)) {					
      		return false;
      	}	
      	if (Window.Attributes('PreviewMode') != 'Workspace') {
      	    var IsWorkspace = GetAttribute(Window, 'IsWorkspace');
      		var GridDataset = GetAttribute(Window, 'GridDataset');
      		if (!GridDataset) {
      			return false;
      		}  
      	}    	
      	var GraphDataset = GetGraphDataset(GraphID);	
      	if (!GraphDataset) {
      		return false;
      	}			
      	GraphDataset.Open();
      	try {
      		var Attributes = GetNewDictionary();	
      		var QueryID = GraphDataset.Values('QueryID');
      		if (!QueryID) {
      			return false;
      		}
      		var GraphPreview = new Object();
      		var Dataset = GetQueryDataset(QueryID, GraphPreview);
      		if (!Dataset) {
      			return false;
      		}
      		Window.Attributes('QueryFilterData') = 
      			Dataset.Attributes('QueryFilterData');
      		var FieldXName = GraphDataset.Values('FieldX');		
      		var FieldYName = GraphDataset.Values('FieldY');		
      		var FieldY1Name = GraphDataset.Values('FieldY1');//BobkovPN
      		//var FieldZName = GraphDataset.Values('FieldZ');	
      		var GraphType = GraphDataset.Values('TypeID');
      		if ((!FieldXName) || (!FieldYName) || (GraphType == null)
      		|| (!FieldY1Name) //BobkovPN
      		) {
      			return false;
      		}
      		var GraphName = GraphDataset.Values('Name');		
      		var FieldLinkName = GraphDataset.Values('FieldLink');
      		if (!Window.Attributes('PreviewMode')) {			
      			if (FieldLinkName) {
      				if (!FilterGraphDataset(Dataset, IsWorkspace, GridDataset, 
      					FieldLinkName, GraphPreview)) {
      					return false;
      				}
      			} else 
      			if (GetAttribute(Window, 'LastGraphID') == GraphID) {
              		return true;
                 	}   
      		}
      		RemoveNonGraphColumns(Dataset, FieldXName, FieldYName,
      		FieldY1Name //BobkovPN
      		);
      		return DrawGraphByDataset(Dataset, Graph, FieldXName, 
      			FieldYName, 
      			FieldY1Name,//BobkovPN
      			GraphType, GraphName, edtGraphPreview);	
      	} finally {
      		SetAttribute(Window, 'LastGraphID', GraphID);
      		GraphDataset.Close();
      	}
      }	
       
      function RemoveNonGraphColumns(Dataset) {
      	var SelectColumns = Dataset.SelectQuery.Items(0).Columns; 	
      	var GraphFields = ArgumentsToArray(arguments, 1);
      	var IsGraphField;
         	for (var i = SelectColumns.Count-1; i >= 0; i--) {
         		if (!SelectColumns.Items(i).IsEnabled) {
         			continue;
         		}
         		IsGraphField = false;
         		for (var j = 0; ((j < GraphFields.length) && (!IsGraphField)); j++) {
      			IsGraphField = (GraphFields[j] == SelectColumns.Items(i).ColumnAlias);
      		}  		
      		if (!IsGraphField) {					
      			SelectColumns.Remove(SelectColumns.Items(i));
      		} 				
      	}     	    	
      }       
       
      function DrawGraphByDataset(Dataset, Graph, 
      			FieldXName, FieldYName, 
      			FieldY1Name,//BobkovPN
      			GraphType, GraphName, edtGraphPreview) {	
      	Graph.Environment.IEPrintWithPage = true;
      	Graph.ClearChart();	
      	var FieldX = Dataset.DataFields.ItemsByName(FieldXName);
      	var FieldY = Dataset.DataFields.ItemsByName(FieldYName);
      	var FieldY1 = Dataset.DataFields.ItemsByName(FieldY1Name);//BobkovPN
      	if ((!FieldX) || (!FieldY) 
      	||  (!FieldY1) //BobkovPN
      	) {
      		return false;
      	} 	
      	var FieldXCaption = FieldX.Caption;
      	var FieldYCaption = FieldY.Caption;
      	var FieldY1Caption = FieldY1.Caption;                       	
      	if ((GraphType == gt_HorizontalBar) ||
      		(GraphType == gt_HorizontalLine) ||
      		(GraphType == gt_HorizontalArea)) {
      		// Меняем местами
      		FieldXCaption = FieldY.Caption;
      		FieldYCaption = FieldX.Caption;		
      	}  
          Graph.AddSeries(GraphType);     
          var Series = Graph.Series(0);
          var Series1 = Graph.Series(0); //BobkovPN
          Series.Clear();
      	Series1.Clear(); //BobkovPN   
       
      	SetGraphHeader(Graph, GraphName);
       
      	Graph.ApplyPalette(7); 
      	Graph.Footer.Visible = false;
      	Graph.SubFooter.Visible = false;
      	Graph.SubHeader.Visible = false;
       
      	var FontName = 'Tahoma';
      	Graph.Axis.Bottom.Labels.Font.Name = FontName;
      	Graph.Axis.Bottom.Ticks.Color = 13145800;
      	Graph.Axis.Bottom.Ticks.Width = 2;
      	Graph.Axis.Bottom.Title.Font.Name = FontName;
      	Graph.Axis.Bottom.Title.Caption = FieldXCaption;
       
      	Graph.Axis.Depth.Labels.Font.Name = FontName;
      	Graph.Axis.Depth.Title.Font.Name = FontName;
       
      	Graph.Axis.DepthTop.Labels.Font.Name = FontName;
      	Graph.Axis.DepthTop.Title.Font.Name = FontName;
       
      	Graph.Axis.Left.Labels.Font.Name = FontName;
      	Graph.Axis.Left.Title.Caption = FieldYCaption;
      	Graph.Axis.Left.Title.Font.Name = FontName;	
       
      	Graph.Legend.Alignment = 3; //laBottom
      	Graph.Legend.CheckBoxesStyle = 1; //cbsRadio
      	Graph.Legend.Font.Name = FontName;
      	Graph.Legend.LeftPercent = 10;
      	Graph.Legend.PositionUnits = 0; //muPercent
          Graph.Legend.Shadow.Color = clSilver;
          Graph.Legend.Shadow.HorizSize = 1;
          Graph.Legend.Shadow.Smooth = false;
          Graph.Legend.Shadow.VertSize = 1;
          Graph.Legend.Shadow.Visible = false;
          Graph.Legend.Title.Font.Name = FontName;
          Graph.Legend.TopPercent = 90;
          Graph.Legend.Transparent = true;
          Graph.Legend.ResizeChart = true;
       
          Graph.Axis.Right.Labels.Font.Name = FontName;
          Graph.Axis.Right.Title.Font.Name = FontName;
       
      	Graph.Axis.Top.Labels.Font.Name = FontName;
      	Graph.Axis.Top.Title.Font.Name = FontName;
       
      	Graph.Aspect.Elevation = 315;
      	Graph.Aspect.Perspective = 0;
      	Graph.Aspect.Rotation = 360;
       
      	Graph.Walls.Visible = false;
       
      	Graph.Panel.BevelOuter = 0; //bvNone  	
      	Graph.Panel.Color = 16314602;
      	Graph.Panel.MarginBottom = 1;
      	Graph.Panel.MarginTop = 1;
      	Graph.Panel.MarginRight = 2;
      	Graph.Panel.MarginLeft = 2;
       
      	Graph.Header.Alignment = 0; // Left
       
      	Graph.Zoom.Enable = true;
      	Graph.Zoom.Animated = true;
      	Graph.Zoom.Direction = 2; //tzdBoth
      	Graph.Zoom.Pen.Color = clBlack;
      	Graph.Zoom.Pen.Style = 7; //psSmallDots
       
          Graph.Cursor = -3; //Cross
       
      	if (GraphType == gt_Pie) {
      		Series.Marks.Arrow.Color = clBlack;
      		Series.Marks.Arrow.Visible = true;
      		Series.Marks.Callout.Brush.Color = clBlack;
      		Series.Marks.Callout.Arrow.Color = clBlack;
      		Series.Marks.Callout.Arrow.Visible = true;
      		Series.Marks.Callout.ArrowHeadSize = 0;
      		Series.Marks.Callout.Distance = 25;
      		Series.Marks.Callout.Length = 10;
      		Series.Marks.Font.Name = FontName;	
      		Series.Marks.Multiline = true;
      		Series.Marks.Shadow.Smooth = false;
      		Series.Marks.Style = 3; // smsLabelPercent
      	    Series.Marks.Transparent = true;
      	    Series.Marks.Visible = true;
      		Series.asPie.Gradient.Direction = 7; //gdRadial
      		Series.asPie.OtherSlice.Legend.Font.Name = FontName;
      		Series.asPie.OtherSlice.Legend.Visible = false;
      		Series.asPie.PieValues.Name = 'Pie';
      		Series.asPie.PieValues.Order = 0; //loNone	
      		Series.ColorEachPoint = true;
      		Graph.Legend.Visible = true;
      		Graph.Cursor = 0;
      	} else  
      	if ((GraphType == gt_Bar) || 
      		(GraphType == gt_HorizontalBar)) {
      		Series.Marks.Visible = false;                   
      		Series.ColorEachPoint = true;
      		Graph.Legend.Visible = false;
      	} else 
      	if ((GraphType == gt_HorizontalLine) ||
      		(GraphType == gt_HorizontalArea) || 
      		(GraphType == gt_FastLine) ||
      		(GraphType == gt_Line) ||
      		(GraphType == gt_Area)) {
      		Series.ColorEachPoint = false;
      		Graph.Legend.Visible = false;
      	} 
       
      	if ((GraphType == gt_HorizontalBar) ||
      		(GraphType == gt_HorizontalLine) ||
      		(GraphType == gt_HorizontalArea)) {
      		Graph.Axis.Bottom.MaximumOffset = 50;		
      	} else {
      		Graph.Axis.Left.MaximumOffset = 50;
      	}   	
      	if (GraphType == gt_FastLine) {
      		Graph.Aspect.View3D = false;	
      		Series.asFastLine.LinePen.Width = 2;	
      	}    
          var clTeeColor = 536870912;
          var ValueX;
          var ValueY;
           try {
          	try {
      	    	Dataset.Open();
      		    while (!Dataset.IsEOF) {       		 
      				ValueX = FieldX.DisplayValue;
      		    	ValueX = !IsEmptyValue(ValueX)?Trim(ValueX):'';
      		    	ValueY = FieldY.Value*1;
      		    	Series.Add(ValueY, ValueX, clTeeColor);				
      		    	Dataset.GotoNext();
      		    }   
      		} catch(e) {
      			return false;	
      	    }
      	} finally {
      		Dataset.Close();            
      	} 
      	//////////////////BobkovPN
      	var ValueY1; //BobkovPN
      	try {
          	try {
      	    	Dataset.Open();
      		    while (!Dataset.IsEOF) {       		 
      				ValueX = FieldX.DisplayValue;
      		    	ValueX = !IsEmptyValue(ValueX)?Trim(ValueX):'';
      		    	ValueY1 = FieldY1.Value*1;
      		    	Series1.Add(ValueY1, ValueX, clTeeColor);				
      		    	Dataset.GotoNext();
      		    }   
      		} catch(e) {
      			return false;	
      	    }
      	} finally {
      		Dataset.Close();            
      	}
      	/////////////*************   
      	if (FieldX.FieldType == dftDateTime) {	
      		var Column = FieldX.ParentDataFields.ParentDataset.SelectQuery.Columns.
      			ItemsByAlias(FieldX.Name);			
      		if (IsUndefined(Column.ExtractDateTimeKind)) {		
      			Series.XValues.DateTime = true;
      		} else {
      			switch (Column.ExtractDateTimeKind) {
      				case (edtkTime):
      				case (edtkDate):
      				case (edtkNone):			
      					Series.XValues.DateTime = true;
      					break;
      				default: 
      					Series.XValues.DateTime = false;
      			}
      		}
      	}
      	if (FieldY.FieldType == dftDateTime) {
      		Series.YValues.DateTime = true;
      	} else 
      	if (FieldY.FieldType != dftFloat) {
      		if ((GraphType == gt_HorizontalBar) ||
      			(GraphType == gt_HorizontalLine) ||
      			(GraphType == gt_HorizontalArea)) {		
      			Graph.Axis.Bottom.Increment = 1;
      		} else {		
      			Graph.Axis.Left.Increment = 1;
      		}   
      	}	
       
      	edtGraphPreview.SubscribeForEvent('OnMouseDown', 'ChartOnMouseDown'); 	
      	return true;
      }
       
      function Trim(s) {
      	return (s.length > 30)?(s.substr(0,30)+'...'):s;
      }
       
      function SetGraphHeader(Graph, Text) {
      	if (!Assigned(Graph)) {
      		return;
      	}
      	Graph.Header.Text.Clear();
      	Graph.Header.Font.Name = 'Tahoma';
      	Graph.Header.Font.Size = 14;
      	Graph.Header.Font.Color = 0x0080FF;
      	Graph.Header.Text.Add(Graph.Environment.CodeUTF8String(Text, true)); 		
      }
       
      function GetGraphParamsObjectByGraphID(GraphID) {
      	var GraphParamsObject = new Object();
      	var GraphDataset = GetGraphDataset(GraphID);
      	GraphDataset.Open();
      	if (GraphDataset.IsEmptyPage) {
      		return null;
      	}
      	GraphParamsObject.GraphID = GraphID;
      	GraphParamsObject.FieldXName = GraphDataset.Values('FieldX');	
      	GraphParamsObject.FieldYName = GraphDataset.Values('FieldY');
      	GraphParamsObject.FieldYName = GraphDataset.Values('FieldY1'); //BobkovPN	
      	GraphParamsObject.GraphType = GraphDataset.Values('TypeID');
      	GraphParamsObject.GraphName = GraphDataset.Values('Name');
      	GraphParamsObject.QueryID = GraphDataset.Values('QueryID');
      	return GraphParamsObject;
      }       
       
      function DoGraphSaveToFile(Graph, ExportFormat, FileName) {		
      	var Result = false;
      	try {
      		switch (ExportFormat) {
      		case ('WMF'):
      		    Graph.Export.SaveToMetafileEnh(FileName);
      			break;
      		case ('JPG'):
      			Graph.Export.asJPEG.SaveToFile(FileName);
      		    break;
      		case ('BMP'):
      			Graph.Export.SaveToBitmapFile(FileName);
      		    break;
      		}   
      		Result = true;
      	} finally {
      		return Result;
      	}
      }   
       
      function GetExtension(ExportFormat) {
      	var Result = '';
      	switch (ExportFormat) {
      	case ('WMF'):
      	    Result = '.wmf';
      		break;
      	case ('JPG'):
      		Result = '.jpg';
      	    break;
      	case ('BMP'):
      		Result = '.bmp';
      	    break;
      	}    	
      	return Result;
      }
       
      function DoGraphExport(Graph, ExportFormat) {
      	var FileName = GetNewValue();
      	var Filter = '';
      	var DefaultExt = GetExtension(ExportFormat);
      	switch (ExportFormat) {
      	case ('WMF'):
      	    Filter = "Файлы изображений Windows Meta (*.wmf)|*.wmf";
      		break;
      	case ('JPG'):
      		Filter = "Файлы JPEG формата (*.jpg)|*.jpg";
      	    break;
      	case ('BMP'):
      		Filter = "Файлы растровых изображений (*.bmp)|*.bmp";
      	    break;
      	default:
      		return false;
      	}
      	var GraphName = Graph.Header.Caption;
         	GraphName = GraphName.replace(/[\n,\r]/gi,'');
         	GraphName = PrepareFileName(GraphName);
      	var DialogCaption = FormatStr("Экспорт графика '%1'", GraphName);
      	FileName.Value = PrepareFileName(GraphName);
      	if (!System.PromptForFileName(FileName, Filter, DefaultExt,
      		DialogCaption, Connector.WorkingDirectory, true)) {    	
      		return false;
          }       	
          DoGraphSaveToFile(Graph, ExportFormat, FileName.Value);
          return true;
      }
       
      function DoGraphSendByMail(Graph, ExportFormat) {
      	if (!GetCanCreateMessage(true)){
      		return;
      	}
         	var TempFileName;
         	var GraphName = Graph.Header.Caption;
         	GraphName = GraphName.replace(/[\n,\r]/gi,'');
         	GraphName = PrepareFileName(GraphName);
      	var FileNameStr = PrepareFileName(GraphName);
      	var Extension = GetExtension(ExportFormat);	
      	TempFileName = GetTemporaryFileName(FileNameStr + Extension, true);
      	DoGraphSaveToFile(Graph, ExportFormat, TempFileName);
       
      	SendEmail({Subject: FormatStr("График: %1", GraphName),
      		BodyFormat: 1, Attachments: [TempFileName]});
      }
       
      function DoGraphZoomIn(Graph) {
      	Graph.Aspect.Zoom = Graph.Aspect.Zoom + 5;
      }
       
      function DoGraphZoomOut(Graph) {
      	Graph.Aspect.Zoom = Graph.Aspect.Zoom - 5;
      }

      Ну так все же, как вручную добавить новую серию,для прорисовки графиков?

      Чтобы реализовать отрисовку нескольких линий (например, двух), необходимо внести следующие изменения в сервис scr_GraphUtils:

      1. Найти функцию function BuildGraph(Window, GraphID), модифицировать ее подобным образом (выделено):

      function BuildGraph(Window, GraphID) {
      var edtGraphPreview = Window.ComponentsByName('edtGraphPreview');
      var Graph = edtGraphPreview.ActiveXObject;
      if (!Graph) {
      return
      }
      if (Window.Attributes('PreviewMode') == 'Edit') {
      // Предпросмотр из карточки графика
      var PreviewAttributes = Window.Attributes('PreviewAttributes');
      var Dataset = PreviewAttributes('Dataset');
      var FieldXName = PreviewAttributes('FieldX');
      var FieldYName = PreviewAttributes('FieldY');
      var FieldY1Name = PreviewAttributes('FieldY1');
      var FieldLinkName = PreviewAttributes('FieldLink');
      RemoveNonGraphColumns(Dataset, FieldXName, FieldYName,
      FieldY1Name );
      var GraphType = PreviewAttributes('GraphType');
      var GraphName = PreviewAttributes('GraphName');
      return DrawGraphByDataset(Dataset, Graph, FieldXName,
      FieldYName,
      FieldY1Name,
      GraphType, GraphName, edtGraphPreview);
      }
      if (IsEmptyGUID(GraphID)) {
      return false;
      }
      if (Window.Attributes('PreviewMode') != 'Workspace') {
      var IsWorkspace = GetAttribute(Window, 'IsWorkspace');
      var GridDataset = GetAttribute(Window, 'GridDataset');
      if (!GridDataset) {
      return false;
      }
      }
      var GraphDataset = GetGraphDataset(GraphID);
      if (!GraphDataset) {
      return false;
      }
      GraphDataset.Open();
      try {
      var Attributes = GetNewDictionary();
      var QueryID = GraphDataset.Values('QueryID');
      if (!QueryID) {
      return false;
      }
      var GraphPreview = new Object();
      var Dataset = GetQueryDataset(QueryID, GraphPreview);
      if (!Dataset) {
      return false;
      }
      Window.Attributes('QueryFilterData') =
      Dataset.Attributes('QueryFilterData');
      var FieldXName = GraphDataset.Values('FieldX');
      var FieldYName = GraphDataset.Values('FieldY');
      var FieldY1Name = GraphDataset.Values('FieldY1');
      var GraphType = GraphDataset.Values('TypeID');
      if ((!FieldXName) || (!FieldYName) || (GraphType == null)) {
      return false;
      }
      var GraphName = GraphDataset.Values('Name');
      var FieldLinkName = GraphDataset.Values('FieldLink');
      if (!Window.Attributes('PreviewMode')) {
      if (FieldLinkName) {
      if (!FilterGraphDataset(Dataset, IsWorkspace, GridDataset,
      FieldLinkName, GraphPreview)) {
      return false;
      }
      } else
      if (GetAttribute(Window, 'LastGraphID') == GraphID) {
      return true;
      }
      }
      RemoveNonGraphColumns(Dataset, FieldXName, FieldYName, FieldY1Name ); return DrawGraphByDataset(Dataset, Graph, FieldXName, FieldYName,
      FieldY1Name,
      GraphType, GraphName, edtGraphPreview);
      } finally {
      SetAttribute(Window, 'LastGraphID', GraphID);
      GraphDataset.Close();
      }
      }

      2. Изменить функцию function DrawGraphByDataset, как отображено ниже (выделено):

      function DrawGraphByDataset(Dataset, Graph, FieldXName, FieldYName,
      FieldY1Name,
      GraphType, GraphName, edtGraphPreview) {
      Graph.Environment.IEPrintWithPage = true;
      Graph.ClearChart();
      var FieldX = Dataset.DataFields.ItemsByName(FieldXName);
      var FieldY = Dataset.DataFields.ItemsByName(FieldYName);
      var IsR = !!FieldY1Name;
      var FieldY1 = Dataset.DataFields.ItemsByName(FieldY1Name);
      if ((!FieldX) || (!FieldY)) {
      return false;
      }

      var FieldXCaption = FieldX.Caption;
      var FieldYCaption = FieldY.Caption;
      var FieldY1Caption = FieldY1.Caption;
      if ((GraphType == gt_HorizontalBar) ||
      (GraphType == gt_HorizontalLine) ||
      (GraphType == gt_HorizontalArea)) {
      // Меняем местами
      FieldXCaption = FieldY.Caption;
      FieldYCaption = FieldX.Caption;
      }
      Graph.AddSeries(GraphType);
      var Series = Graph.Series(0);
      Series.Clear();

      Graph.AddSeries(GraphType);
      var Series1 = Graph.Series(1);
      Series1.Active=true;
      Series1.Clear();

      SetGraphHeader(Graph, GraphName);

      Graph.ApplyPalette(7);
      Graph.Footer.Visible = false;
      Graph.SubFooter.Visible = false;
      Graph.SubHeader.Visible = false;

      var FontName = 'Tahoma';
      Graph.Axis.Bottom.Labels.Font.Name = FontName;
      Graph.Axis.Bottom.Ticks.Color = 13145800;
      Graph.Axis.Bottom.Ticks.Width = 2;
      Graph.Axis.Bottom.Title.Font.Name = FontName;
      Graph.Axis.Bottom.Title.Caption = FieldXCaption;

      Graph.Axis.Depth.Labels.Font.Name = FontName;
      Graph.Axis.Depth.Title.Font.Name = FontName;

      Graph.Axis.DepthTop.Labels.Font.Name = FontName;
      Graph.Axis.DepthTop.Title.Font.Name = FontName;

      Graph.Axis.Left.Labels.Font.Name = FontName;
      Graph.Axis.Left.Title.Caption = FieldYCaption;
      Graph.Axis.Left.Title.Font.Name = FontName;

      if (!IsR) {
      Graph.Legend.Alignment = 3; //laBottom
      Graph.Legend.CheckBoxesStyle = 1; //cbsRadio
      Graph.Legend.Font.Name = FontName;
      Graph.Legend.LeftPercent = 10;
      Graph.Legend.PositionUnits = 0; //muPercent
      Graph.Legend.Shadow.Color = clSilver;
      Graph.Legend.Shadow.HorizSize = 1;
      Graph.Legend.Shadow.Smooth = false;
      Graph.Legend.Shadow.VertSize = 1;
      Graph.Legend.Shadow.Visible = false;
      Graph.Legend.Title.Font.Name = FontName;
      Graph.Legend.TopPercent = 90;
      Graph.Legend.Transparent = true;
      Graph.Legend.ResizeChart = true;
      }

      Graph.Axis.Right.Labels.Font.Name = FontName;
      Graph.Axis.Right.Title.Font.Name = FontName;

      Graph.Axis.Top.Labels.Font.Name = FontName;
      Graph.Axis.Top.Title.Font.Name = FontName;

      Graph.Aspect.Elevation = 315;
      Graph.Aspect.Perspective = 0;
      Graph.Aspect.Rotation = 360;

      Graph.Walls.Visible = false;

      Graph.Panel.BevelOuter = 0; //bvNone
      Graph.Panel.Color = 16314602;
      Graph.Panel.MarginBottom = 1;
      Graph.Panel.MarginTop = 1;
      Graph.Panel.MarginRight = 2;
      Graph.Panel.MarginLeft = 2;

      Graph.Header.Alignment = 0; // Left

      Graph.Zoom.Enable = true;
      Graph.Zoom.Animated = true;
      Graph.Zoom.Direction = 2; //tzdBoth
      Graph.Zoom.Pen.Color = clBlack;
      Graph.Zoom.Pen.Style = 7; //psSmallDots

      Graph.Cursor = -3; //Cross

      if (GraphType == gt_Pie) {
      Series.Marks.Arrow.Color = clBlack;
      Series.Marks.Arrow.Visible = true;
      Series.Marks.Callout.Brush.Color = clBlack;
      Series.Marks.Callout.Arrow.Color = clBlack;
      Series.Marks.Callout.Arrow.Visible = true;
      Series.Marks.Callout.ArrowHeadSize = 0;
      Series.Marks.Callout.Distance = 25;
      Series.Marks.Callout.Length = 10;
      Series.Marks.Font.Name = FontName;
      Series.Marks.Multiline = true;
      Series.Marks.Shadow.Smooth = false;
      Series.Marks.Style = 3; // smsLabelPercent
      Series.Marks.Transparent = true;
      Series.Marks.Visible = true;
      Series.asPie.Gradient.Direction = 7; //gdRadial
      Series.asPie.OtherSlice.Legend.Font.Name = FontName;
      Series.asPie.OtherSlice.Legend.Visible = false;
      Series.asPie.PieValues.Name = 'Pie';
      Series.asPie.PieValues.Order = 0; //loNone
      Series.ColorEachPoint = true;
      Graph.Legend.Visible = true;
      Graph.Cursor = 0;
      } else
      if ((GraphType == gt_Bar) ||
      (GraphType == gt_HorizontalBar)) {
      Series.Marks.Visible = false;
      Series.ColorEachPoint = true;
      Graph.Legend.Visible = false;
      } else
      if ((GraphType == gt_HorizontalLine) ||
      (GraphType == gt_HorizontalArea) ||
      (GraphType == gt_FastLine) ||
      (GraphType == gt_Line) ||
      (GraphType == gt_Area)) {
      Series.ColorEachPoint = true;
      Series1.ColorEachPoint = true;

      Graph.Legend.Visible = false;
      }

      if ((GraphType == gt_HorizontalBar) ||
      (GraphType == gt_HorizontalLine) ||
      (GraphType == gt_HorizontalArea)) {
      Graph.Axis.Bottom.MaximumOffset = 50;
      } else {
      Graph.Axis.Left.MaximumOffset = 50;
      }
      if (GraphType == gt_FastLine) {
      Graph.Aspect.View3D = false;
      Series.asFastLine.LinePen.Width = 2;
      Series1.asFastLine.LinePen.Width = 2;

      }
      //var clTeeColor = 536870912;
      var ValueX;
      var ValueY;
      var ValueY1;

      try {
      try {
      Dataset.Open();
      while (!Dataset.IsEOF) {
      ValueX = FieldX.DisplayValue;
      ValueX = !IsEmptyValue(ValueX)?Trim(ValueX):'';
      ValueY = FieldY.Value*1;
      Series.Add(ValueY, ValueX, clBlack);
      ValueY1 = FieldY1.Value * 1;
      Series1.Add(ValueY1, ValueX, clRed);

      Dataset.GotoNext();
      }
      } catch(e) {
      return false;
      }
      } finally {
      Dataset.Close();
      }
      Series.Color = clBlack;
      Series1.Color = clRed;

      if (FieldX.FieldType == dftDateTime) {
      var Column = FieldX.ParentDataFields.ParentDataset.SelectQuery.Columns.
      ItemsByAlias(FieldX.Name);
      if (IsUndefined(Column.ExtractDateTimeKind)) {
      Series.XValues.DateTime = true;
      } else {
      switch (Column.ExtractDateTimeKind) {
      case (edtkTime):
      case (edtkDate):
      case (edtkNone):
      Series.XValues.DateTime = true;
      break;
      default:
      Series.XValues.DateTime = false;
      }
      }
      }
      if (FieldY.FieldType == dftDateTime) {
      Series.YValues.DateTime = true;
      } else
      if (FieldY.FieldType != dftFloat) {
      if ((GraphType == gt_HorizontalBar) ||
      (GraphType == gt_HorizontalLine) ||
      (GraphType == gt_HorizontalArea)) {
      Graph.Axis.Bottom.Increment = 1;
      } else {
      Graph.Axis.Left.Increment = 1;
      }
      }

      edtGraphPreview.SubscribeForEvent('OnMouseDown', 'ChartOnMouseDown');
      return true;
      }

      3. Модифицировать function GetGraphParamsObjectByGraphID подобным образом (выделено):

      function GetGraphParamsObjectByGraphID(GraphID) {
      var GraphParamsObject = new Object();
      var GraphDataset = GetGraphDataset(GraphID);
      GraphDataset.Open();
      if (GraphDataset.IsEmptyPage) {
      return null;
      }
      GraphParamsObject.GraphID = GraphID;
      GraphParamsObject.FieldXName = GraphDataset.Values('FieldX');
      GraphParamsObject.FieldYName = GraphDataset.Values('FieldY');
      GraphParamsObject.FieldY1Name = GraphDataset.Values('FieldY1');
      GraphParamsObject.GraphType = GraphDataset.Values('TypeID');
      GraphParamsObject.GraphName = GraphDataset.Values('Name');
      GraphParamsObject.QueryID = GraphDataset.Values('QueryID');
      return GraphParamsObject;
      }

      Спасибо Наталья, скажите пожалуйста, как в гистограмме отключить заполнение фигуры, то есть оставить ее границы и сделать бесцветную внутреннюю часть!

      Сделать бесцветную внутреннюю часть гистограммы (рис1) можно записью вида:
      Series.Brush.Style = 1;

      function DrawGraphByDataset(Dataset, Graph, FieldXName, FieldYName,
      		......
      		    while (!Dataset.IsEOF) {       		 
      				ValueX = FieldX.DisplayValue;
      		    	ValueX = !IsEmptyValue(ValueX)?Trim(ValueX):'';
      		    	ValueY = FieldY.Value*1;
      		    	Series.Add(ValueY, ValueX, clWhite);			
      		    	ValueY1 = FieldY1.Value * 1;
      		    	Series1.Add(ValueY1, ValueX, clRed);
       
      				Dataset.GotoNext();
      		    }
      		} catch(e) {
      			return false;	
      	    }
      	} finally {
      		Dataset.Close();            
      	}                
      	Series.Color = clBlack;
      	Series.Brush.Style = 1;
      	Series1.Color = clRed;
      	....
      }

      Спасибо Наталия!!!

      Наталья , скажите пожалуйста как в легенду добавить цвет серии?

      Добавить легенду с цветом серии можно таким образом:

      Graph.Legend.Visible = true; 
      Graph.Legend.FontSeriesColor = true;


      Наталья таким образом он нарисует, мне тем же цветом Название этих серий!
      см. Приложенный скрин

      	Series.Color = clBlack;
          Series1.Color = clRed;
          Series2.Color = clBlue;
          Series3.Color = clGreen;
          Series4.Color = clFuchsia;                                                                       	
          Series5.Color = clMoneyGreen;
          Series6.Color = clGridSelected;
      	Series.Title=FieldY.Caption;
      	Series.asFastLine.Stairs = true;
      	Series3.asFastLine.Stairs = true;
      	Graph.Legend.Font.Name = FontName;
      	Graph.Legend.Title.Font.Name = FontName;
      //	Graph.Legend.Transparent = false;
      	Graph.Legend.CheckBoxesStyle = 0;
          Graph.Legend.CheckBoxes  = true;
      	Series1.Title=FieldY1.Caption;
      	Series2.Title=FieldY2.Caption;
      	Series3.Title=FieldY3.Caption;
      	Series4.Title=FieldY4.Caption;
      	Series5.Title=FieldY5.Caption;
      	Series6.Title=FieldY6.Caption;	
      	Graph.Legend.Visible = true;
      	Graph.Legend.FontSeriesColor = true;

      PavelB, а на графике реальные показатели реальной компании "ООО "Строй-фарм" из г. Щелково? :wink:

      Нет Юрий, показатели тестовые конечно!

      Павел, мне не понятно какой вид должна иметь легенда. Уточните, пожалуйста.

      Наталия вот приблизительно такого, в частности я выделил оранжевым цветом, маркеры X,Y,Z

      Павел, чтобы легенда выводилась с маркерами, закомментируйте либо удалите строки в функции function DrawGraphByDataset сервиса scr_GraphUtils, как отображено ниже:

      	} else 
      	if ((GraphType == gt_HorizontalLine) ||
      		(GraphType == gt_HorizontalArea) || 
      		(GraphType == gt_FastLine) ||
      		(GraphType == gt_Line) ||
      		(GraphType == gt_Area)) {
      		/*Series.ColorEachPoint = true;	
      		Series1.ColorEachPoint = true;
      		Series2.ColorEachPoint = true;
      		Seriesn.ColorEachPoint = true;*/		
      		Graph.Legend.Visible = true;
      	} 

      Спасибо большое!!!!

      Войдите или зарегистрируйтесь, чтобы комментировать