Версия для печати темы (https://pro1c.org.ua/index.php?s=12404ff574434bf752bbd83b1575767a&showtopic=42944)

Нажмите сюда для просмотра этой темы в обычном формате

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 _ Программирование в 1С Предприятие 7.7 _ Как программно разрешить или запретить сохранение реквизита...

Автор: Victor Skif 24.12.17, 23:08

Добрый вечер.
1С 7.70.027.
Формекс.

Наведите на мысль, плз.

Имеем форму списка справочника. Пользователь редактирует реквизит. Когда он нажимает Энтер - необходимо программно проверять введенное значение (частный случай - проверить уникальность), и в зависимости от результатов проверки, разрешить или запретить сохранение. Как это по-нормальному сделать? Что-то у меня не придумывается. Отследить нажатие энтера, и устроить проверку - можно в назначенной реквизиту процедуре. Но как в ней сказать, что это значение не годится, и запретить его сохранять?

Автор: Gazulo 25.12.17, 18:52

Victor Skif @ Вчера, 23:08 * ,
Примерно так
Сообщить("Ваше сообщение");
ВашРеквизит = "";

Автор: Victor Skif 25.12.17, 19:51

Gazulo @ Сегодня, 18:52 * ,

Красиво, но не совсем то. Потому что реквизит при этом все равно сохраняется - с новым значением, или исправленным. И выходит из редактирования. А надо - чтобы было Сообщить("Вы ввели херню"); - и остаться в режиме редактирования, мол, исправляй. А по нажатию Esc - вернуться к нередактированному.

Можно, конечно, его ре-активизировать программно (прямо нельзя, через ложное закрытие можно), и подставить заранее сохраненное старое значение... Но это некрасиво ) Похоже, нет менее геморройного способа?

Автор: Bernet 26.12.17, 11:12

Victor Skif @ Вчера, 19:51 * ,
Проверку делайте в модуле объекта в процедуре "Перед записью" - выполняете свою проверку, если проверку не прошло пишите Отказ = Истина и ниже сообщение что пользователь ввел херню. Тогда выдаст сообщение и не даст сохранить изменения

P.S. провтыкал что это должно быть на 7-ку, на 7-ке не знаю, я с ней стараюсь не стыкаться

Автор: Стрелок 26.12.17, 15:57

В ПриЗаписи делаете следующее
1. создаете объект типа текущего справочника
2. находите текущий элемент
3. сравниваете текущее значение реквизита (оно доступно в контексте формы) со значением из найденной ссылки или с допустимым значением (то что "не херня"). Не прошла проверка - СтатусВозврата(0) и Возврат. И Вы остаетесь в режиме редактирования. а по esc вернете старое значение.

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

Автор: Flexy 26.12.17, 17:47

Зачем так сложно?
В свойствах поля ввода на закладке "Дополнительно" в поле "Формула" пишите имя Вашей процедуры, в которой будут происходить проверка введенного значения. Напр. ПроверитьЗначение().
В модуле формы:

Процедура ПроверитьЗначение()
Если МойРеквизит <> НужноеЗначение Тогда
        Возврат;
КонецЕсли;
КонецПроцедуры

Автор: Стрелок 26.12.17, 18:07

Flexy @ Сегодня, 17:47 * ,

не сработает.

Автор: volodya1122 27.12.17, 10:03

Цитата(Стрелок @ 26.12.17, 18:07) *
Flexy @ Сегодня, 17:47 * ,

не сработает.


Повністю робочий варіант. В мене таким методом контролюється введення години в текстовий реквізит. І якщо формат години не відповідає 24:60 то по "ентеру" вийти з редагування цього реквізиту неможливо.

Автор: Стрелок 27.12.17, 14:20

volodya1122 @ Сегодня, 10:03 * ,

серьезно? а можно код посмотреть этого чуда smile.gif
прям глаза открыли мне smile.gif
или вы тоже путаете предопределенные процедуры (например ПриЗаписи) в которых срабатывает СтатусВозврата(0) и Возврат() и процедуры срабатывающие при ЗАВЕРШЕНИИ редактирования реквизита?
просто "возврат" означает выход из процедуры но никак не возврат в режим редактирования

и как интересно происходит запуск процедуры проверки корректности формата если процедура прописанная в свойствах реквизита формы стартует именно при нажатии ENTER (или потери фокуса реквизита формы - переход например по Tab или мышкой)

Автор: volodya1122 28.12.17, 9:38

Стрелок @ Вчера, 14:20 * ,
Все елементарно, Ватсон.
На реквізиті (на формі) вішаємо процедуру (вводГодини()) і прописуємо маску 99:99 - Все в розділі Дополнительно.
Сама процедура

Процедура вводГодини()  
//ГодОпл    
//Если СтрДлина(СокрЛП(ГодОпл))=3 тогда
// ГодОпл="0"+СокрЛП(ГодОпл);    
Если СтрДлина(СокрЛП(ГодОпл))=4 тогда
    Симв2=Сред(СокрЛП(ГодОпл),2,1);
    Если (Симв2="1") или (Симв2="2") или (Симв2="3") или (Симв2="4") или (Симв2="5") или (Симв2="6") или (Симв2="7") или (Симв2="8") или (Симв2="9") или (Симв2="0") тогда
    иначе
    ГодОпл="0"+СокрЛП(ГодОпл);
//    Возврат;
    КонецЕсли;
Иначеесли СтрДлина(СокрЛП(ГодОпл))<4 тогда
Предупреждение("Ще не заповнена година розпломбування",0);
Возврат;
КонецЕсли;      

год=Лев(СокрЛП(ГодОпл),2);
хв=Прав(СокрЛП(ГодОпл),2);  
хв2=Лев(хв,1);
хв1=Прав(хв,1);
Если (хв1="1") или (хв1="2") или (хв1="3") или (хв1="4") или (хв1="5") или (хв1="6") или (хв1="7") или (хв1="8") или (хв1="9") или (хв1="0") тогда
иначе
Предупреждение("Невірно задано хвилини");
Возврат;
КонецЕсли;     
Если (хв2="1") или (хв2="2") или (хв2="3") или (хв2="4") или (хв2="5") или (хв2="0") тогда
иначе
Предупреждение("Невірно задано хвилини");
Возврат;
КонецЕсли;  
год1=Прав(год,1);
год2=Лев(год,1);
Если (год1="1") или (год1="2") или (год1="3") или (год1="4") или (год1="5") или (год1="6") или (год1="7") или (год1="8") или (год1="9") или (год1="0") тогда
иначе
Предупреждение("Невірно задано годину");
Возврат;
КонецЕсли;
Если (год2="1") или (год2="2") или (год2="0") тогда
иначе
Предупреждение("Невірно задано годину");
Возврат;
КонецЕсли;


если Число(год)>23 тогда
Предупреждение("Невірно задано годину");
Возврат;
КонецЕсли;

если Число(хв)>59 тогда
Предупреждение("Невірно задано хвилини");
Возврат;
КонецЕсли;

ГодОпл=год+":"+хв;
ВирахЧасРемонту()

КонецПроцедуры


Хоча код зовсім не ідеальний (писав давно, а переписувати не хочеться).
Як все відбувається. Користувач набирає на формі годину (наприклад 12:75) нажимає "ентер" А йому на екран повідомлення"про невірні хвилини. і знову повертається до того самого реквізиту для виправлення години. Тобто при неправильній годині по "єнтер" користувач не зможе перейти до редагування слідуючого реквізиту.

Автор: Стрелок 29.12.17, 12:31

volodya1122 @ Вчера, 9:38 * ,

1. вводим "00:88"
2. тыкаем энтер
3. получаем предупреждение
4. тыкаем мышкой на другой реквизит или Табом и вуаля- попадаем на следующий реквизит без всяких проверок

понятна логика? процедура в "дополнительно" срабатывает ТОЛЬКО если значение реквизита изменено и ТОЛЬКО один раз. Для нового срабатывания нужно чтобы реквизит опять изменился.
вот поэтому и "не сработает". Конечно можно в вашей процедуре Холмс поставить ГодОпл="00:00" (эта комбинация не проверяется в коде никак). Но даже если поставить ошибочное значение реквизита
то мышкой или табулятором проверка спокойно игнорируется... так что.....

ЗЫ
и код не "не идеальный". он ужасный. я бы руки отрывал за такое

Автор: Flexy 29.12.17, 12:45

Цитата(Стрелок @ 29.12.17, 12:31) *
2. тыкаем энтер

Дык автор писал, что юзер тыкает энтер.
Цитата(Стрелок @ 29.12.17, 12:31) *
процедура в "дополнительно" срабатывает ТОЛЬКО если значение реквизита изменено и ТОЛЬКО один раз. Для нового срабатывания нужно чтобы реквизит опять изменился.

У меня постоянно срабатывает smile.gif Видимо, какая-то другая 7.7 у меня smile.gif

Да и кстати:
Форма.МойРеквизит.ВыполнятьФормулуТолькоПриИзменении(0);

Ни кто не отменял.

Автор: Стрелок 29.12.17, 21:56

Flexy @ Сегодня, 12:45 * ,

Цитата(Flexy @ 29.12.17, 12:45) *
Да и кстати:

Форма.МойРеквизит.ВыполнятьФормулуТолькоПриИзменении(0);

Ни кто не отменял.


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

Автор: Victor Skif 06.01.18, 2:19

Стрелок @ 29.12.17, 21:56 * ,
Спасибо за обсуждение!

Я решил вопрос в итоге следующим способом: проверку реквизита Артикул вешаю на процедуру этого реквизита ИзмАртикул(); перед этим сохраняю старое значение в переменную; если значение плохое - то возвращаю в реквизит сохраненное старое значение, и активизирую. Активизирую ректально - через ложное закрытие, других путей нет. Минус решения - плохое значение в этот момент уже записано. Если пользователь выйдет по эскейпу - оно останется. Это не критично, в целом результат удовлетворительный.

Вот код:

Перем флЛожноеЗакрытие;

// =========================
Процедура ПриЗакрытии()
    Если флЛожноеЗакрытие = 1 Тогда
        флЛожноеЗакрытие = 0;
        Активизировать("Артикул");
        СтатусВозврата(0);
        Возврат;
    КонецЕсли;
КонецПроцедуры


// =========================
Процедура АктивистАртикул()             // вот через такую жопу можно активировать отсюда объект
    флЛожноеЗакрытие = 1;
    Форма.Закрыть(0);
КонецПроцедуры


// =========================
Процедура ИзмАртикул()
    Арт = Стро(Артикул);  
    Если Арт = "" Тогда
        Возврат;
    КонецЕсли;
    СтарыйАрт = Стро(ТекущийЭлемент().Артикул);  // берем старое значение из записанного реквизита!
    Если СтарыйАрт = Арт Тогда
        Возврат; // не менялось ничего
    КонецЕсли;
    Если УникальностьАртикула(Арт) = 0 Тогда
        Предупреждение("Артикул " + Арт + " не уникален!");
        // СтатусВозврата(0);  // - не работает!
        // сохраняем старое значение
        // а теперь обратно активизируем
        Артикул = СтарыйАрт;
        АктивистАртикул();
    КонецЕсли;
КонецПроцедуры

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7
https://pro1c.org.ua