Господа, прошу руку помощи.

Возможно ли фильтровать mds_Dataset, если да, то каким образом?

С уважением
Егор

Нравится

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

Егор, добрый день.

Нет, но тут немного другой подход. Дело в том, что mds заполняется каждый раз на OnDatasetAfterOpen(Dataset) теми данными, которые укажите Вы. Соответственно фильтровать нужно именно эти данные. Ну к примеру, в датасете у нас фрукты (яблоки, груши), в реестре добавляем кнопку "показать только яблоки":

function btnShowApplesOnly(Control) {
     var mds = dlData.Dataset;
     mds.Attributes('IsApplesOnly') = true;
     mds.Close();
     mds.Open();
}
 
function OnDatasetAfterOpen(Dataset) {
      if(Dataset.Attributes('IsApplesOnly')) {
             Dataset.Append();
             //только яблоки
             Dataset.Post();
      } else {
             Dataset.Append();
             //все фрукты
             Dataset.Post();
      } 
}

Дмитрий, спасибо огромное! Разобрался.

Показать все комментарии

Добрый день, коллеги.
Terrasoft XRM 3.3.2.304
Собственно не срабатывает событие OnFocusedControl для окна.
Может кто знает по какой причине и как это починить?
В окне несколько контейнеров.
Событие нужно для изменения элементов окна при смене активного контейнера.
Спасибо.

Нравится

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

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

Виктор, событие вынесено в конфигурацию, но оно отрабатывает только при программном вызове.
Например:
Self.FocusedControl = edtSubject;
Для Вашей задачи вызов этого события не подойдет, попробуйте использовать события OnExit/OnEnter

Показать все комментарии

Добрый день
Подскажите на какое событие нужно прописать код , чтобы после окраски строк Grid a выходило сообщение о количестве раскрашенных строк,
пробовал onShow Prepea и тд не могу подобрать.
а если указать здесь grdDataOnGetRowDrawInfo то окно сообщения выходит по количеству строк в Dataset это не устраивает.

Нравится

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

Здравствуйте, Евгений.

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

Как-то так:

function grdDataOnGetRowDrawInfo(DataGrid, Color, TextColor, ImageName, Font) {   
      var Dataset = dlData.Dataset;
      if (DataGrid.ActiveView.Items(Column).IsVisible) { 
      	GridColumnsCount = GridColumnsCount + 1;
      }
      if (Dataset.Values('AccountTypeID') == '{3EAC7195-607B-4DAC-A832-8954E3201031}') {
          TextColor.Value = clBlue;
          RowsDrawCount  = RowsDrawCount + 1;
 
      }
 
	  Column = Column + 1;
	  MessageBox(FormatStr(RowsDrawCount * GridColumnsCount));   
}

"Безродный Андрей" написал:

Здравствуйте, Евгений.

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

Здравствуйте
Не совсем то.
Как прорисовать и подсчитать кол во записей я разобрался использую function grdDataOnGetRowDrawInfо
вопрос в том в каком месте прописать появления пользователю Окно сообщения ShowConfirmationDialog( Кол во строк") чтобы оно появлялось после открытия реестра и отрисовки строк, потому как если я это окно поставлю в функцию
function grdDataOnGetRowDrawInfo(DataGrid, Color, TextColor, ImageName, Font)
тогда оно появляется после каждой прорисованной строки.

Евгений, попробуйте на OnDatasetAfterOpen.

"Бондарь Наталия" написал:

Евгений, попробуйте на OnDatasetAfterOpen.


Пробовал окно появляется до открытия самого реестра
и потом еще появляется каждый раз при появлении окна редактирования реестра
нажатии на кнопку Изменить.

Боюсь что тогда только по действию или кнопке...

"Бондарь Наталия" написал:

Боюсь что тогда только по действию или кнопке...

а подскажите как тогда можно сообщение на Outlook отправить вместо диалогова окна?

Используйте функцию SendEmail (определена в скрипте scr_MailUtils).
В конфигурации много примеров, вот один из них:

SendEmail({Address: 'support@tscrm.com', 
		Subject: "Запрос в службу поддержки Terrasoft",
		BodyFormat: 1, Attachments: [TempFileName]});

"Бондарь Наталия" написал:

Используйте функцию SendEmail (определена в скрипте scr_MailUtils).

В конфигурации много примеров, вот один из них


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

Евгений,

развернутый пример есть в теме:
http://www.community.terrasoft.ru/blogs/7911

В качестве примера используется функция SendEmailByTemplate скрипта scr_MailUtils с параметрами AutoSend и Silent.

SendEmailByTemplate(TemplateID, {RecordID: ID, Address: AddressList,
                   AutoSend: true, Silent: true});
}

Андрей спасибо за пример, может пригодиться в будущем отправка по группам и тд,
но в данном случае мне нужно отправить письмо с списком Контрагентов, на один адрес (укажу сразу в скрипте) больше всего подходит функция

SendEmail({Address: 'Evgeniy.Evdokimov@fund.kz',
Subject: "Список контрганетов",
Body: 'Список контрагентов следующий '})

только как заставить чтобы письмо уходило автоматически
может от версии зависит
у меня 3.3.2 . 294

Евгений, установите параметр AutoSend: true (можно посмотреть в примере Андрея).

Все спасибо нашел то что нужно !

SendEmail({Address: 'Evgeniy.Evdokimov@fund.kz',
Subject: 'Список контргентов', BodyFormat: 2,
HTMLBody: 'Список просроченных договоров',
AutoSend: true, SendImmediately: true});

Показать все комментарии

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

После вызова из террасофта ReportPreviewer.Prepare(); хочется сохранить отчет как то так: ReportPreviewer.Save('C:\rez.xls','xls'); Как то это можно сделать?

         var ReportDataset = fbcFilters.DatasetLink.Dataset;
         var Report = Services.GetNewItemByUSI('fr_IncidentNotCloseOfPeriud');
         var ReportPreviewer = Services.GetNewItemByUSI('wnd_BaseFastReportPreview');
         var mainReportPreviewer = Services.GetNewItemByUSI('wnd_IncidentNotCloseOfPeriud');
         var ReportPreviewerComponent = ReportPreviewer.Attributes('ReportPreviewer');

        FilterEngine.ReportPreviewer = ReportPreviewerComponent;
        FilterEngine.Report = FilterEngine.ReportPreviewer.Report;
         FilterEngine.DateFilterWindow = wndDateFilter.Window;
         var PeriodDataset = FilterEngine.DateFilterWindow.ComponentsByName('dlData').Dataset;

         SetAttribute(ReportPreviewer, 'Report', Report);
         ApplyDatasetFilter(ReportDataset, 'BeginDate', PeriodDataset('DateFrom'), true);
         ApplyDatasetFilter(ReportDataset, 'EndDate', PeriodDataset('DateTo'), true);
         
                 
        fbcFilters.ApplyFilter();
        if (ReportDataset.State != dstInactive) {
        ReportDataset.Close();
         }
        ReportDataset.Open();
         
         Report.Attributes('BeginDate')  = PeriodDataset('DateFrom');
         Report.Attributes('EndDate')     = PeriodDataset('DateTo');
         
         FilterEngine.ReportPreviewer = ReportPreviewerComponent;
        FilterEngine.Report = FilterEngine.ReportPreviewer.Report;
        FilterEngine.DateFilterWindow = wndDateFilter.Window;
               
         ReportPreviewer.Build();
         ReportPreviewer.Prepare();

Нравится

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

Как в событие DatasetBeforePost прервать отправку данных на вставку, без сообщений об ошибках. Может ключ в DataSet можно поменять?

Нравится

2 комментария
DoPost.Value = false;

Спасибо. Завтра, протестирую. Интуитивно пробовал так: DoPost= false, не посмотрел на объект в режиме дебага.

Показать все комментарии

Подскажите, пожалуйста:
есть у меня грид в состоянии IsEditable = true
есть колонки которые можно править.
как можно сделать, чтоб в зависимости от поля в строке запрещать или разрешать редактирование?

Нравится

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

Каким образом можно получить и в зависимости от полученного значения передать другое значение в LookupDataControl?
Для примера: На карточке "Контакт" есть поле с выпадающим списком "Средства связи". В нем значения: Мобильный, Телефон, Факс, Личный и т.п.
Каким образом сделать так, чтобы при выборе значения "Личный" выдавалось предупреждение, к примеру "Личным" пользоваться запрещено"!!! и значение в LookupDataControl'е с "Личного" менялось на к примеру "Телефон".
Выбираю так

var Name = DataField.Name;
var Dataset = DataField.ParentDataFields.ParentDataset;
if (Name == 'ID') {
var Value = DataField.Value;
if (Value == '{5C0A-4C2D-8684}'/*Личный*/){
ShowWarningDialog('Личным пользоваться запрещено!!!');
// Здесь как перевести в выборе с Личного на Телефон

А вот как с "Личного" поменять на "Телефон"?

Нравится

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

Меняйте не значение поля, а значение датасета

dlData.Dataset('Communication1TypeID') = 'id нужного типа';

Используйте событие OnDatasetDataChange невизуального компонента dlData:

if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }
}

Все идентификаторы желательно выносить в scr_Consts, и затем писать так:
if(DataField.Name == myComTypeConst)

ps: желательно просто отфильтровать источник данных, чтобы в списке просто не отображались те варианты, которые выбрать нельзя. Так корректней согласитесь.

Спасибо, за варианты, все работает. Единственное, после нажатия ОК на ShowErrorDialog это диалоговое окно открывается повторно и после второго его закрытия в LookupDataControl'е изменяется значение на OldValue и можно закрыть карточку Контакта. Как можно сделать, чтобы окно ShowErrorDialog открывалось только 1 раз?
Для дальнейшего изучения Террасофта немного усложнил эту задачу:
ShowErrorDialog открывается в зависимости не только от some_id, но и от условий, данные которых находятся в Деталях.
Пример: У Контакта есть в Деталях Счета, у Счетов есть поле "Состояние оплаты".
В зависимости от:
при выборе значения "Личный" в карточке Контакта и если в поле "Состояние оплаты" Счетов этого Контакта, к примеру, есть значения "Не оплачен" запрещаем менять значение ("Личный") в нашем предыдущем примере:

if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') && /*Состояние оплаты Счетов == 'Не оплачен'*/ {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }
}

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

По поводу двойного входа в условие, при установлении старого значения, проще всего отключить события датасета:

var Dataset = DataField.ParentDataFields.ParentDataset;
if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') && /*Состояние оплаты Счетов == 'Не оплачен'*/ {
            Dataset.DisableEvents();
            DataField.Value = DataField.OldValue;
            Dataset.EnableEvents();
            ShowErrorDialog('ERROR!');
     }
}

Вариант обхода двойного открытия окна с отключением эвентов

            Dataset.DisableEvents();
            DataField.Value = DataField.OldValue;
            Dataset.EnableEvents();

не проходит. Все равно два раза вызывается диалоговое окно.

Скорее всего у Вас в скрипте условие прописано дважды или выполняется в каком-то цикле.

Прикрепите, пожалуйста, к посту весь скрипт (экспортируйте его из конфигурации).

По поводу Вашего вопроса с модификацией условия:

if (DataField.Name == 'Communication1TypeID') {   
	var bool = false;
	var ContactID = Dataset.Values('ID');
	var InvoiceDataset = Services.GetNewItemByUSI('ds_Invoice');
	ApplyDatasetFilter(InvoiceDataset, 'ContactID', ContactID, true); 
   	InvoiceDataset.Open(); 
  	if (InvoiceDataset.Values('BillStatusID')=='{89E2E62C-E2B0-47E6-A183-B774ED20CDE8}') //если по Контакту есть счет с состоянием оплаты = Ожидание оплаты
        {
            bool = true;
  	}
   	InvoiceDataset.Close(); 
	if((DataField.Value == '{FA08FC2A-9D55-40C9-9576-0017EAED3E49}')&&(bool==true)) {
              ShowErrorDialog('ERROR!');
     	}	
	return;
}

Андрей, в твоем примере проверится только первый счет, а их может быть несколько :)
Лучше всего, конечно, это создать новый сервис sq_MySelectQuery (сервис выборки данных с определенной таблицы), в котором добавить фильтр сравнения по ContactID с параметром ContactID и по StatusID с параметром StatusID, оба фильтра сразу же включить в сервисе. Из таблицы выбирать только одну колонку, к примеру ID. Затем в коде прописать что-то вроде следующего:

var ContactID = Dataset('ContactID');
var StatusID = isWaiting; //isWaiting - это константа в scr_Consts
//var isWaiting = '{id_состояния_оплаты_счета_в_ожидании}';
var mySQ = Services.GetNewItemByUSI('sq_MySelectQuery');
SetParameterValue(mySQ.Parameters, 'ContactID', ContactID, true);
SetParameterValue(mySQ.Parameters, 'StatusID', StatusID, true);
var Result = mySQ.Open();
if(Result.IsEOF) {
     ShowWarningDialog('Для тек. контакта счетов в состоянии "Ожидание оплаты" нет');
} else {
     ShowWarningDialog('Для тек. контакта есть счета в состоянии "Ожидание оплаты"! Их количество: ' + Result.RecordsCount);     
}

А вот по поводу двойного входа сюда:

if(DataField.Name == 'Communication1TypeID') {
     if(DataField.Value == 'some_id') {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }
}

немного теории: событие OnDatasetDataChange выполняется каждый раз, когда значение какого либо поля датасета изменяется. Внутри события, при изменении конкретного поля (Communication1TypeID), при определенных условиях вы опять таки его меняете (обратно), тоесть событие будет вызвано еще раз. Но, т.к. у Вас стоит доп. условие

if(DataField.Value == 'some_id')

т.е. по сути - второй раз мы не должны зайти внутрь условия:

if(DataField.Value == 'some_id') {
            DataField.Value = DataField.OldValue;
            ShowErrorDialog('ERROR!');
     }

, т.к. мы изменили это значение на другое. Но раз заходит, значит что-то пошло не так. Тут нужна отладка - поставьте перед условием отладчик (Ctrl+F5), включите в реестре Windows регистр JitDebug в 1 и перезапустите Террасофт. Для отладки нужна Visual Studio (либо MS Script Debugger, но он крайне неудобен).

Если что - пишите.

Кажется Вам поможет следующая конструкция:

1. В самом начале скрипта объявите глобальную переменную-объект. Чаще всего её называют по имени сервиса. Она может быть у Вас уже и объявлена (если это коробочный датасет):

var myObject = {};

2. Структуру события OnDatasetDataChange нужно сделать следующей:

function SelfOnDatasetDataChange(DataField) {
try {
   if(myObject.IsUpdating) {
         return;
   }
   myObject.IsUpdating = true;
   if(DataField.Name == 'Name') {
         //ваш код
   }
   //....
} finally {
   myObject.IsUpdating = false;   
}
}

Дмитрий, спасибо. Не все кейсы проверил изначально.

Так должно работать:

if (DataField.Name == 'Communication1TypeID') {   
	var bool = false;
	var ContactID = Dataset.Values('ID');
	var InvoiceDataset = Services.GetNewItemByUSI('ds_Invoice');
	ApplyDatasetFilter(InvoiceDataset, 'ContactID', ContactID, true);
	InvoiceDataset.Open(); 
   	while(!InvoiceDataset.IsEOF) {
		  if (InvoiceDataset.Values('BillStatusID')=='{89E2E62C-E2B0-47E6-A183-B774ED20CDE8}')
  		       {
  			    bool = true; 
  	               }
		  InvoiceDataset.GotoNext();
	 }
   	InvoiceDataset.Close(); 
	if((DataField.Value == '{FA08FC2A-9D55-40C9-9576-0017EAED3E49}')&&(bool==true)) {
	       ShowErrorDialog('ERROR!');
     	}	
	return;
}

Спасибо, Дмитрий, Андрей!
Вот код, который отлично работает, за исключением пресловутого двойного открытия диалогового окна:

function dlDataOnDatasetDataChange(DataField) {
   if (System.GetLocalComputerName() == 'MYCOMP') { debugger; }   
   if(ContactEdit.IsUpdating) { 
         return;
   };
   var Dataset = DataField.ParentDataFields.ParentDataset;   
       ContactEdit.IsUpdating = true;
try {  
    var Communication1TypeName = dlData.Dataset.DisplayValues('Communication1TypeID'); 
    if (DataField.Name == 'Communication1TypeID') {   
        var bool = false;
        var ContactID = Dataset.Values('ID');
        var InvoiceDataset = Services.GetNewItemByUSI('ds_Invoice');
        ApplyDatasetFilter(InvoiceDataset, 'ContactID', ContactID, true);
        InvoiceDataset.Open();
        while(!InvoiceDataset.IsEOF) {
                  if (InvoiceDataset.Values('BillStatusID')=='{89E2E62C-E2B0-47E6-A183-B774ED20CDE8}')     //Ожидание оплаты
                       {
                            bool = true; 
                       }
                  InvoiceDataset.GotoNext();
         }
        InvoiceDataset.Close();
        if((DataField.Value == '{63153BB8-52E0-468A-8DDA-1EFD4B959780}')&&(bool==true)) { //Личный
               DataField.Value = DataField.OldValue;
	       ShowErrorDialog('Внимание! В Контакте есть счета на стадии "Ожидание оплаты"!\r\n\Пользоваться ' + Communication1TypeName + ' запрещено!');
        }       
        return;
      }
    }
     finally {
       ContactEdit.IsUpdating = false;   
   }
}

На основе дебаггера удалось выяснить, что после того как выбрали "Личный" открывается ДО (Диалоговое окно) первый раз.
После закрытия окна в LookupControl'e "Личный меняется" на OldValue.
Затем OldValue опять меняется на "Личный" и ДО открывается второй раз.
После второго раза закрытия ДО "Личный" меняется на OldValue.
После этого процесс завершается и можно закрыть карточку Контакта.
Между этими двумя открытиями дебаггер заходит в scr_Contact в
function SelfOnDatasetDataChange(DataField). Но не только сюда.
Это из основного что удалось проанализировать, но механизма, чтобы открывалось только 1 раз ДО не нашел.

Alex GF,

попробуйте поставить дебаггер в самом начала скрипта (вижу, он у Вас уже установлен), а после пройтись пошагово (F11), чтобы понять, в какой момент срабатывает вызов диалогового окна.

Нужно ставить доп. условие. Посмотрите значения Value и OldValue перед каждым вызовом ДО - они у Вас должны отличаться. И затем дополните условие, что то вроде

DataField.OldValue != DataField.Value

Если не выйдет, напишите значения OldValue и Value перед каждым вызовом ДО.

Значение перед вызовом ДОкна:
Value - 'Личный'
OldValue - 'Мобильный'
После первого вызова ДОкна:
Value - 'Мобильный'
OldValue - 'Мобильный'

Затем уходит на второй круг и возвращается к нашему debbuger:
Value - 'Личный'
OldValue - 'Мобильный'
После 2-го вызова ДОкна:
Value - 'Мобильный'
OldValue - 'Мобильный'

Можно Вас попросить поставить отладчик тут:

if((DataField.Value == '{63153BB8-52E0-468A-8DDA-1EFD4B959780}')&&(bool==true)) { //Личный
debugger;
DataField.Value = DataField.OldValue;

И вот прямо в месте остановки, посмотрите DataField.Value и DataField.OldValue, и запостите сюда еще раз пожалуйста. Т.е. должно быть только две остановки, соответственно два значения.

В момент остановки
Value = 'Личный'
OldValue = 'Мобильный'

Далее, в момент открытия ДО
Value = 'Мобильный'
OldValue = 'Мобильный'

После закрытия ДО
Value = 'Личный'
OldValue = 'Мобильный'

Заходим второй раз в нашу функцию, значения теже, выходим из нашей функции делаем цикл, опять заходим в нашу функцию, значения теже.
Проходим циклом по while(!InvoiceDataset.IsEOF), далее по функции, далее открывается второй раз Диалоговое Окно.
Value = 'Мобильный'
OldValue = 'Мобильный'

P.S. Версия Террасофт 3.3.2

Что-то странное. Не смог воспроизвести. Кажется, виноват return, выделенный жирным.

InvoiceDataset.Close();
if((DataField.Value == '{63153BB8-52E0-468A-8DDA-1EFD4B959780}')&&(bool==true)) { //Личный
DataField.Value = DataField.OldValue;
ShowErrorDialog('Внимание! В Контакте есть счета на стадии "Ожидание оплаты"!\r\n\Пользоваться ' + Communication1TypeName + ' запрещено!');
}
return;
}
}
finally {
ContactEdit.IsUpdating = false;
}
}

Если нет - ставьте заглушку... После первого показа окна установите значение в свойство глобального объекта, к примеру:

if(!ContactEdit.WindowWasShowed) {
 ShowErrorDialog('Внимание! В Контакте есть счета на стадии "Ожидание оплаты"!\r\n\Пользоваться ' + Communication1TypeName + ' запрещено!'); 
}
ContactEdit.WindowWasShowed = true;

И где-то на OnPrepare Еще добавьте строку:

ContactEdit.WindowWasShowed = false;

Спасибо Дмитрий, помогла только заглушка!

Проделал тоже самое (тот же самый код, но без заглушки) на версии террасофт 3.5.1. Там двойного открытия Диалогового окна нет! Единственный неопределенный (для меня) момент там:
После закрытия Диалогового Окна в LookupDataControl значение Value не меняется на OldValue. Хотя затем при нажатии на карточке "ОК" результат в базе правильный - OldValue.
В версии 3.3.2 в LookupDataControl значения меняются как надо.

Показать все комментарии

BaseGridArea не видит dlData

function wnd_BaseGridAreaOnPrepare(Window) {
        InitializeGridArea(Window, BaseGridArea, dlData); //ВОТ ТУТ
        InitializeGridAreaHotKeyList(Window);
}

хотя

Window.ComponentsByName('dlData')

видит его.

Что-то нужно прописать для создаваемого грида?

Нравится

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

продолжение истории, там же в scr_BaseGridArea не видно Self

function btnAddOnClick(Control) {
	AddGridAreaData(Self, Self, BaseGridArea);
}

Здравствуйте, Alex!
Не совсем понятно, что Вы делаете. Проверьте, унаследовано ли Ваше окно от wnd_BaseGridArea.
Вообще, необходимо добавлять обработчик события OnPrepare для своего окна, в котором вызывать базовый и инициализировать другие параметры окна:

function wnd_AccountsGridAreaOnPrepare(Window) {
	wnd_BaseGridAreaOnPrepare(Window);
	Initialize(Window);
 
}

"Андрей Каспаревич" написал:Проверьте, унаследовано ли Ваше окно от wnd_BaseGridArea.

Андрей, а как проверить?

У окна свойство

TemplateWindowUSI = wnd_BaseGridArea

OnPrepare для окна именно так и написал:

wnd_BaseGridAreaOnPrepare(Window);

и зайдя внутрь появляется ошибка dlData, при этом и BaseGridArea "чистый" объект!

Проблема закрыта. Спасибо.
зачем-то добавил в INCLUDE scr_BaseGridArea!

Показать все комментарии

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

Подскажите в таком вопросе.
Есть функция,

function OneRecord(MyDataset ) {
...//Выполняем вычисления
...//Вставляем записи в Detail
}

которая в зависимости от вычислений делает обновления и добавляет новые записи в разные Детали.
Вызываем её на строке грида
function aOneRecordOnExecute(ActionMenuItem, Sender) {
        var MyDataset = dlData.Dataset;
        OneRecord(MyDataset );     
}

Все работает на данной выделенной строке.
А каким образом можно выделив более одной строки в гриде, заставить эту функцию отработать все выделенные строки? Пока она это делать не может.

Нравится

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

Выделить больше одной строки можно с помощью клавиш Ctrl и Shift
Ctrl - выбирает только те строки, которые вы щелкаете при нажатой клавише (так же Ctrl выполняет функцию "Перейти к", если щелкните на поле типа Lookup. Так что будьте осторожны)
Shift - выделит все строки между текущей выделенной и той, которую вы щелкните.
Функцию попробуйте переписать так:

function aOneRecordOnExecute(ActionMenuItem, Sender) {
	var SelectedIDs = grdData.SelectedIDs.CommaText.split(',');
	var MyDataset = Services.GetNEwItemByUSI(dlData.Dataset.USI);
	for(var i=0;i<SelectedIDs.length;++i) {
		MyDataset.Close();
		ApplyDatasetFilter(MyDataset, 'ID', SelectedIDs[i], true);
		MyDataset.Open();
		OneRecord(MyDataset);
	}     
}

Переделал функцию по вышеописанному способу: при отработке дебаггер пишет "grdData - Определение отсутствует". Насколько я понял не может достучаться до грида.
Функция находится в отдельном скрипте scr_OneRecord.
wnd_OneRecord, в котором находится грид лежит рядом. Как достучаться до grdData?
Пробовал так:

var wndOneRecord= Services.GetNewItemByUSI('wnd_OneRecord');
var SelectedIDs = wndOneRecord.grdData.SelectedIDs.CommaText.split(',');

Но в этом случае выдает ошибку: " 'grdData.SelectedIDs' - есть null или не является объектом".

Не понимаю, в своем варианте вы берете dlData, значит достукиваетесь до элементов окна. Проверьте, может они по другому у вас названы. Если же нет, то должен помочь этот скрипт (если все окна унаследованы от базовых):

function aOneRecordOnExecute(ActionMenuItem, Sender) {
	var MainWindow = Connector.Attributes('MainWindow');
	var WorkspaceWindow = MainWindow.ComponentsByName('wndWorkspace').Window;
	var GridWindow = WorkspaceWindow.ComponentsByName('wndGridData').Window;
	var grdData = GridWindow.ComponentsByName('grdData');
	//var dlData = GridWindow.ComponentsByName('dlData'); //если нельзя будет достучаться до dlData
        var SelectedIDs = grdData.SelectedIDs.CommaText.split(',');
        var MyDataset = Services.GetNewItemByUSI(dlData.Dataset.USI);
        for(var i=0;i<SelectedIDs.length;++i) {
                MyDataset.Close();
                ApplyDatasetFilter(MyDataset, 'ID', SelectedIDs[i], true);
                MyDataset.Open();
                OneRecord(MyDataset);
        }     
}

Выполняю действие (меняю статус) для выделенных строк грида Накладных:

	var SelectedIDs = grdData.SelectedIDs.CommaText.split(',');
 
          var Dataset = dlData.Dataset; 
        for(var i=0;i<SelectedIDs.length;++i) {
            Dataset.Close();
            ApplyDatasetFilter(Dataset, 'ID', SelectedIDs[i], true);
            Dataset.Open();
 
	var GotNoError = true;
 
	with (Dataset) {
		try {	
			DisableEvents();
			Edit();
 
			Values(FieldName) = ToValue;	//Set a new value
 
			Post();
		} catch (err) {
			GotNoError = false;
			if (State == dstEdit) {	//Rollback if still in Edit state
				Cancel();
			}
		} finally {
			EnableEvents();
		}
	}
	}

Но, статус Накладной меняется только для 1 накладной.
Подскажите что не хватает, чтобы статус Накладных поменялся для выделенных строк в гриде?

Возможно не сбрасывается старый фильтр, попробуйте:

Dataset.Close();
EnableDatasetFilters(Dataset, false);
ApplyDatasetFilter(Dataset, 'ID', SelectedIDs[i], true);

И кстати, лучше создайте новый экземляр датасета, а не тот, который сейчас привязан к гриду.

Никакие манипуляции с фильтрами не помогли.
Помогло, когда вместо

 var Dataset = dlData.Dataset; 

стал использовать

 var Dataset = Services.GetNewItemByUSI('ds_OfferingMovement')
Показать все комментарии

Добрый день коллеги!
Продолжаю создавать свой первый раздел в Terrasoft
Теперь после создания Раздела и Реестра
дошло дело до Карточки редактирования
в принцbпе карточку создал унаследовал от wnd_BaseDBEdit
добавление записи получается, а вот с редактированием не могу разобраться(((
окно появляется но компоненты без данных,
Пробовал так
scr_BaseGridArea.EditGridAreaData(Self, BaseGridArea); этот код результата не дает

с этим тоже не получается

var Attributes = new ActiveXObject('Scripting.Dictionary');
var RecordID = Attributes.Add(RecordID, 'ID');
ShowEditWindowEx('wnd_LisingEdit', Attributes);

Может быть есть простой пример кода карточки редактирования с описание основных действий
при нажатии на кнопку Изменить в Реестре (wnd_BaseGridArea)
Буду очень признателен.

Нравится

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

нашел вот такой код

{
var EditWindowUSI = 'wnd_LisingEdit';
var AccountID = dlData.Dataset.Values('ID');
var Attributes = GetNewDictionary();
Attributes.Add('RecordID', AccountID);
Attributes.Add('NotifyObject', null);
ShowEditWindowEx(EditWindowUSI, Attributes);
}

но увы, карточка данными не заполняются и поля на карточке не активные,
хотя на добавление работают нормально

Здравствуйте, Евгений.

Проверьте, пожалуйста, установлено ли у Вашего грида свойство TemplateWindowUSI = wnd_BaseGridArea?

"Безродный Андрей" написал:

Здравствуйте, Евгений.

Проверьте, пожалуйста, установлено ли у Вашего грида свойство TemplateWindowUSI = wnd_BaseGridArea?

да установлено

Евгений,

причина может быть в том, что были переопределены базовые функции (например, OnPrepare), а родительские не вызываются при этом.

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

Андрей прикладываю созданные сервисы раздела
версия 3.3.2.294

"Безродный Андрей" написал:версия 3.3.2.294

версия 3.3.2.294

Евгений,

приложите также сервисы tbl_District, sq_District, ds_Disctrict.

Без этих сервисов не удается загрузить tbl_lising_article

"Безродный Андрей" написал:

Евгений,

приложите также сервисы tbl_District, sq_District, ds_Disctrict.

Без этих сервисов не удается загрузить tbl_lising_article

прикладываю сервисы

Евгений,

причина, вероятно, в том, что у Вас в сервисе запроса нет фильтра сравнения с параметром:

[URL=http://fastpic.ru/][IMG]http://i68.fastpic.ru/big/2014/0814/b8/819214ad…]

[URL=http://fastpic.ru/][IMG]http://i65.fastpic.ru/big/2014/0814/49/754f3462…]

Спасибо Вам!
Действительно установил фильтр и карточка работает.
Видимо при создании раздела вручную не все предусмотрел.

Андрей добрый день!
у меня еще вопрос есть. Теперь по поводу работы с полями,
каким образом можно сделать чтобы при выборе значения в LookupDaatControl
допустим Наименование клиента
в другой компонент TextDataControl выводилось значение его ИИН
Во первых не нашел у LookupDaatControl события OnChange к тому же на начальном уровне не совсем
еще овладел синтаксисом Jscript
Буду очень благодарен за помощь!

Здравствуйте, Евгений!

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

http://i68.fastpic.ru/big/2014/0815/90/4a5e50285a3e1d88737e763ae33efb90.jpg

На примере ниже при выборе Контрагента в карточке Задачи в поле Заголовок задачи будет помещаться полное название выбираемого Контрагента. По аналогии Вы сможете реализовать свой функционал.

function SelfOnDatasetDataChange(DataField) {
...
if (Name == 'AccountID') { //при изменении поля AccountID в датасете задач
    var AccountID = DataField.Value; //получаем ID выбранного контрагента
    var AccountDataset = Services.GetNewItemByUSI('ds_Account'); //получаем датасет контрагентов
    ApplyDatasetFilter(AccountDataset, 'ID', AccountID, true); //фильтруем датасет по ID выбранного контрагента
    AccountDataset.Open(); //открываем датасет
    var INN = AccountDataset.Values('OfficialAccountName'); //получаем нужное значение нового контрагента
    AccountDataset.Close(); //закрываем датасет
    Dataset.Values('Title') = INN; //присваиваем полученное значение в одно из полей текущего датасета задач
    return;
}
...
}

Реализация.

У контрагента Оливия-Фарм есть полное название:

http://i65.fastpic.ru/big/2014/0815/37/4039f6e7b85da705f5278109ea3fff37.jpg

При выборе Контрагента в карточке Задачи полное название Контрагента подставляется в заголовок:

http://i65.fastpic.ru/big/2014/0815/e1/d18b615bdbba1a28275418540441fde1.jpg

"Безродный Андрей" написал:Здравствуйте, Евгений!

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

Андрей добрый день
Сделал у себя все как вы рекомендовали , по примеру,
но у меня выходит ошибка((.
Скрин ошибки прилагаю.

Евгений,

а Вы уверены, что поле Контрагент в Вашем датасете "Предметы Лизинга" называется AccountID?

Евгений, вооружитесь отладчиком. Так Вы сможете намного быстрее понять, в чем проблема.

"Безродный Андрей" написал:

Евгений,

а Вы уверены, что поле Контрагент в Вашем датасете "Предметы Лизинга" называется AccountID?

Евгений, вооружитесь отладчиком. Так Вы сможете намного быстрее понять, в чем проблема.

Да Вы правы поле называется по другому, но даже уже когда поменял тоже не работает
а картинку скинул еще до своего варианта
Но ошибка все равно не исчезает(((

if (Name == 'BorrowerId') { //при изменении поля AccountID в датасете задач
var AccountID = DataField.Value; //получаем ID выбранного контрагента
var AccountDataset = Services.GetNewItemByUSI('ds_Account'); //получаем датасет контрагентов
ApplyDatasetFilter(AccountDataset, 'ID', AccountID, true); //фильтруем датасет по ID выбранного контрагента
AccountDataset.Open(); //открываем датасет
var INN = AccountDataset.Values('Code'); //получаем нужное значение нового контрагента
AccountDataset.Close(); //закрываем датасет
dlData.Dataset.Values('BIN') = AccountID //'INN34324'; //присваиваем полученное значение в одно из полей текущего датасета задач
return;

Евгений,

смотрите детали ошибки и поставьте отладчик:
http://www.microsoft.com/ru-ru/download/details.aspx?id=40787

После установки установите значение параметра JITDebug в реестре равным 1 (параметр находится по пути:
HKEY_CURRENT_USER\Software\Microsoft\Windows Script\Settings)

При возникновении ошибки будет сразу понятно, на каком участке кода происходит свал.

Евгений, почему Вы в итоге присваиваете значению поля BIN AccountId?
Возможно, необходимо присваивать INN?

var INN = AccountDataset.Values('Code'); //получаем нужное значение нового контрагента
AccountDataset.Close(); //закрываем датасет
dlData.Dataset.Values('BIN') = AccountID //'INN34324'; //присваиваем полученное значение в одно

Также,

Вы уверены, что в датасете контрагентов у Вас присутствует поле Code?
AccountDataset.Values('Code')

"Безродный Андрей" написал:

Вы уверены, что в датасете контрагентов у Вас присутствует поле Code?

AccountDataset.Values('Code')

Андрей я тут уже пробовал присвоить хоть какое то значение этому полю)
даже просто делал строку dlData.Dataset.Values('BIN')= 'vdfsxvdf' все равно ошибка
Поле которое меня интересует точно Code

сейчас заметил что ошибка выходит именно вот когда выполняется эта строка

Dataset.Values('BIN') =INN; //присваиваем полученное значение в одно из полей текущего атасета задач

т е если ее за комментировать то ошибки нет
тип полей совпадают

Евгений,

Вы поставите отладчик?

Устанавливал Vstudiо затем установил Micrisoft Debuger с сайта скачивал отсюда,
но он не заработал, теперь в итоге нет отладчика- Vstudio тоже перестал работать

Евгений, выполните описанные мною Ваше изменения в реестре для корректной работы отладчика:
http://www.community.terrasoft.ru/forum/topic/10836#comment-49104

"Безродный Андрей" написал:

Евгений, выполните описанные мною Ваше изменения в реестре для корректной работы отладчика:

http://www.community.terrasoft.ru/forum/topic/10836#comment-49104

вот что показывает отладчик

Евгений,

в самом начале скрипта пропишите:

function SelfOnDatasetDataChange(DataField) {
if (DataField == null) {
		return;
}
var Dataset = DataField.ParentDataFields.ParentDataset;
var Name = DataField.Name;
.....

Спасибо Большое за терпение и за помощь!!
Теперь все работает!)

Показать все комментарии