Обнулить dataset GetOpenedDatasetByUSIWithFilter

Подскажите пожалуйста, как можно обнулить датасет в следующем случае:

function функция(StDataset, ParentWindow)
var Dataset             = GetOpenedDatasetByUSIWithFilter(DatasetUSI, FilterName, ParamValue, UniqueCode, DisableFieldsArray, DoDisableEvents);

        var Stop        = Dataset('Stop');                                     
       
    if (!IsZeroValue(Stop))  {
               
                        MessageBox(Стоит галка Стоп. Запись создана не будет!');
//Здесь перед выходом пробую очистить датасет, но не получается
                        Dataset.DisableEvents();
                        Dataset.Close();
                        return;
                       
                }

        for(Dataset.GotoFirst(), Counter = 0; ( !Dataset.IsEOF ); Counter++, Dataset.GotoNext()) {
.....
Dataset.Edit();
.....


 }
Dataset.Close();
}

Если Stop > 1, то вычисляем какие-то данные и заносим в БД.
Если Stop ==1, то выходим из функции, при этом очищаем датасет.

В случае Stop > 1, все нормально, данные пишутся в БД и при повторном вызове функции дата сет отрабатывает выделенную запись.
Но, если Stop ==1, т.е. мы ничего не хотим писать в БД и просто выйти с очисткой датасета.

Потом, когда заново вызываем функцию, то она начинает отрабатывать предыдущую строку (как-будто датасет не обнулился).
Как его очистить?

Нравится

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

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

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

Алекс, а при отладке перед return какой Dataset,RecordsCount? Не очищается?

"Maxim Gritsenko" написал:

Алекс, а при отладке перед return какой Dataset,RecordsCount? Не очищается?


Не очищается. В датасете те строки, в которых при предыдущих вызовах был Stop ==1 и наша текущая строка. Если мы насильно удалим из базы эти строки (где был Stop ==1) или в этих строках сделаем Stop = 0, то из датасета они пропадают.

Что значит очистить датасет? Заполнить все колонки, кроме ID значением null? Удалить запись? Не совсем понятно... Опишите, пожалуйста, Вашу бизнес задачу.

Если у вас точно известно, что

var Dataset             = GetOpenedDatasetByUSIWithFilter(DatasetUSI, FilterName, ParamValue, UniqueCode, DisableFieldsArray, DoDisableEvents);

вернет одну строку (к примеру вы фильтруете по ID), то пишем просто:

if(!Stop) {
  //пишем данные
}

если это точно не известно то в цикле:

while(!Dataset.IsEOF) {
          var Stop = Dataset('Stop');
          if(!Stop) {
          Dataset.Edit();
          ...
          Dataset.Post();
          }
          Dataset.GotoNext();
}

пс: мне кажется, что функция GetOpenedDatasetByUSIWithFilter возвращает старый экземпляр датасета. Может поможет если напишите явно?

var Dataset = Services.GetNewItemByUSI('ds_Stop');
EnableDatasetFilters(Dataset, false);
ApplyDatasetFilter(Dataset, 'FilterName', FilterValue, true);
Dataset.Open();
....

"Олейник Дмитрий" написал:

пс: мне кажется, что функция GetOpenedDatasetByUSIWithFilter возвращает старый экземпляр датасета. Может поможет если напишите явно?

var Dataset = Services.GetNewItemByUSI('ds_Stop');

EnableDatasetFilters(Dataset, false);

ApplyDatasetFilter(Dataset, 'FilterName', FilterValue, true);

Dataset.Open();

....

С уважением,

Олейник Дмитрий

На GetOpenedDatasetByUSIWithFilter очень много завязано, поэтому поменять на GetNewItemByUSI просто не получится.
Вот последовательность действий:
Если на выделенной строке (ID=A1) в мастере Stop <> 1, то пишутся в базу некие данные в деталь. Датасет А1.
Если на выделенной строке (ID=A2) в мастере Stop <> 1, то пишутся в базу некие данные в деталь. Датасет А2.
Если на выделенной строке (ID=A3) в мастере Stop == 1, то НЕ пишем в базу данные в деталь и показываем окно-предупреждение, что Stop == 1 и ничего нельзя писать в БД. Датасет А3.
Если на выделенной строке (ID=A4) в мастере Stop <> 1, то пишутся в базу некие данные в деталь. При этом dataset обращается к ID = A3, обрабатывает, затем к A4. Т.е. A3 сохраняется в датасете. Датасет А3, А4.
Если же теперь мы в A3 сделаем Stop <> 1 и отработаем эту строку. То она исчезает из дата сета. Датасет А3.
Если на выделенной строке (ID=A5) в мастере Stop <> 1, то пишутся в базу некие данные в деталь. Датасет А5.
Есть ли какой-нибудь способ принудительной очистки данного датасета в этом случае?
Пробовал вариант:

if(!Stop) {
  //пишем данные
}

Но то же самое.

Правильно ли я понял, что выделенная строка с разными ID - это строки, которые попали в датасет после его открытия через GetOpenedDatasetByUSIWithFilter ?
Если так, то по этому датасету вы ходите в цикле и при определенных условиях что-то пишете в детали? Каким образом с 4-ой строки вы перемещаетесь на 3-ую, и снова на 4-ую?

Если же теперь мы в A3 сделаем Stop <> 1

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

В общем, все-ровно не понял как это все у вас устроено. Можете прикрепить весь свой код сюда полностью, а также объясните, пожалуйста, все таки: все эти строки обрабатываются в одном цикле, или эта функция вызывается несколько раз? Если несколько - то с какими параметрами, и меняете ли Вы uniqueCode для датасета? Сбрасываются ли фильтра?

Более подробно:
Выбираю строку в гриде. В контекстном меню - Действия - ВыполнитьДействие. Попадаем сюда:

function amiOnExecute(ActionMenuItem, Sender) {
	var OpDataset  = dlOp.Dataset;
//Уже сюда вынес проверку на Stop
	var Stop = OpDataset('Stop'); 
	    if (!IsZeroValue(Stop)) {
	    MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');
//Здесь пытаюсь очистить датасет, как-будто я не выбирал строку в гриде (но не чистит)
	    OpDataset.Close();
	    OpDataset.Open();
	    return false;
	    }
 
	var Result = hConfirmation(OpDataset, OpWorkspace.COpWindow);
}

Далее следующая функция для проверки:

function hConfirmation(OpDataset, ParentWindow) 
 
{
	var Message = FormatStr('Вы действительно хотите ...' , 
					GetSystemParameterValueEx('ToPay', true));
	if (ShowConfirmationDialog(Message) != wmrYes) {
		return;
	}
 
 
	finalEv(OpDataset, ParentWindow);	
}

И наша финальная функция, которая отрабатывает и пишет в базу:

function finalEv(OpDataset, ParentWindow) {
var DatasetUSI	= 'ds_COp';
var Dataset		= GetOpenedDatasetByUSIWithFilter(DatasetUSI,	'CanEv', true, 'finalEv', null, true);
....
//Вот в этом цикле пишутся данные в БД. 
for(Dataset.GotoFirst(), Counter = 0; ( !Dataset.IsEOF ); Counter++, Dataset.GotoNext()) {
.....
Dataset.Edit();
.....
 
 }
Dataset.Close();
 
}

Хотелось бы, если Stop ==1, то выходим из функции, при этом очищаем датасет.
Судя по всему GetOpenedDatasetByUSIWithFilter запоминает строку (OLD), когда мы отрабатывали:

function amiOnExecute(ActionMenuItem, Sender) {
        var OpDataset  = dlOp.Dataset;
//Уже сюда вынес проверку на Stop
        var Stop = OpDataset('Stop'); 
            if (!IsZeroValue(Stop)) {
            MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');
//Здесь пытаюсь очистить датасет, как-будто я не выбирал строку в гриде (но не чистит)
            OpDataset.Close();
            OpDataset.Open();
            return false;
            }
 
        var Result = hConfirmation(OpDataset, OpWorkspace.COpWindow);
}

и при выполнения Действия над другой новой (new) строкой (где Stop <>1) сначала выполняется обработка этой new строки (мы её просто выбираем в гриде), а затем тут же отрабатывается наша OLD строка.
Как очистить датасет от этой (этих) OLD строк, как будто их вообще небыло?
Это
OpDataset.Close();
OpDataset.Open();
не помогает.
Что-то такое
OpDataset.Clear();
не поддерживается?

function amiOnExecute(ActionMenuItem, Sender) {
        var OpDataset  = dlOp.Dataset;
        var Stop = OpDataset('Stop'); 
        if (!IsZeroValue(Stop)) {
            MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');            
            return false;
        }
        var Result = hConfirmation(OpDataset, OpWorkspace.COpWindow);
}

Переоткрывать датасет

OpDataset.Close();
OpDataset.Open();

не имеет смысла, т.к. при открытии вы всегда будете позиционированы на первой строке. Т.е.

function Main() {	
	var Dataset = Services.GetNewItemByUSI('ds_CommunicationType');
	Dataset.Open();
        //Dataset.RecordNumber == 1;
	Dataset.GotoNext();
        //Dataset.RecordNumber == 2;
	Dataset.Close();
	Dataset.Open();
        //Dataset.RecordNumber == 1; 
}

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

Таким образом, что мы имеем:

первую функцию-действие лучше переписать так:

function amiOnExecute(ActionMenuItem, Sender) {
        var OpDataset  = dlOp.Dataset;
        var Stop = OpDataset('Stop'); 
        if (!IsZeroValue(Stop)) {
            MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');            
            return false;
        }
        var Result = hConfirmation(OpDataset, OpWorkspace.COpWindow);
}

функция hConfirmation будет выполнена только в том случае, если в текущей выделенной строке, для которой было запущено действие, поле Stop не заполнено.

Вторая функция остается без изменений:

function hConfirmation(OpDataset, ParentWindow) 
 
{
        var Message = FormatStr('Вы действительно хотите ...' , 
                                        GetSystemParameterValueEx('ToPay', true));
        if (ShowConfirmationDialog(Message) != wmrYes) {
                return;
        }
 
 
        finalEv(OpDataset, ParentWindow);       
}

а вот с третьей непонятно. Самое интересное то, что вы ей передаете датасет реестра (OpDataset), который позиционирован на нужной строке (т.е. та в которой стоп = 0), а также ParentWidnow, но при этом нигде их не используете. Покажите как Вы его используете, потому что в текущем примере OLD строка никак не может быть обработана, если вы не выполняете никаких манипуляций , которые приводят к смене текущей активной строки, что-то вроде этого:

OpDataset.GotoNext();
OppDataset.Close();
OppDataset.Open();

пс: могу предложить не передавать никаких датасетов (т..к скорее всего вы где-то там запутались), а передать сразу нужные значения, которые вы собираетесь использовать, в функцию записи данных в БД. Что-то вроде:

function amiOnExecute(ActionMenuItem, Sender) {
        var OpDataset  = dlOp.Dataset;
        var Stop = OpDataset('Stop'); 
        if (!IsZeroValue(Stop)) {
            MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');            
            return false;
        }
        var myValue1 = OppDataset('myVaule1');
        var myValue2 = OppDataset('myVaule2');
        var myValue3 = OppDataset('myVaule3');
        var Result = hConfirmation(myValue1,myValue2, myValue3,  OpWorkspace.COpWindow);
}

"Олейник Дмитрий" написал:

а вот с третьей непонятно. Самое интересное то, что вы ей передаете датасет реестра (OpDataset), который позиционирован на нужной строке (т.е. та в которой стоп = 0), а также ParentWidnow, но при этом нигде их не используете. Покажите как Вы его используете, потому что в текущем примере OLD строка никак не может быть обработана, если вы не выполняете никаких манипуляций , которые приводят к смене текущей активной строки, что-то вроде этого:

OpDataset.GotoNext();

OppDataset.Close();

OppDataset.Open();

пс: могу предложить не передавать никаких датасетов (т..к скорее всего вы где-то там запутались), а передать сразу нужные значения, которые вы собираетесь использовать, в функцию записи данных в БД. Что-то вроде:

function amiOnExecute(ActionMenuItem, Sender) {

        var OpDataset  = dlOp.Dataset;

        var Stop = OpDataset('Stop');

        if (!IsZeroValue(Stop)) {

            MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');            

            return false;

        }

        var myValue1 = OppDataset('myVaule1');

        var myValue2 = OppDataset('myVaule2');

        var myValue3 = OppDataset('myVaule3');

        var Result = hConfirmation(myValue1,myValue2, myValue3,  OpWorkspace.COpWindow);

}

С уважением,

Олейник Дмитрий


Манипуляции выполняются в этом цикле:

//Вот в этом цикле пишутся данные в БД. 
for(Dataset.GotoFirst(), Counter = 0; ( !Dataset.IsEOF ); Counter++, Dataset.GotoNext()) {
.....
Dataset.Edit();
.....
 
 }
Dataset.Close();
 
}

Сначала выполняется текущая активная строка грида с Stop=0(null), а затем в этом цикле выполняется OLD строка (с Stop=1), которую вроде бы как мы покинули здесь:

if (!IsZeroValue(Stop)) {
            MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');
            return false;
            }

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

Можно ли очистить наш OpDataset вообще как-нибудь, что-бы там не было никаких строк old?
И если можно, то в этом месте

if (!IsZeroValue(Stop)) {
            MessageBox('Стоит галка Stop ! Ничего в базу не пишем!');
// Здесь очищаем наш дата сет от нашей строки, которая попала сюда.
            return false;
            }

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

Разобрался с вопросом. Спасибо!

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