IE2017

Вариант доработки Бухгалтерии предприятия

Программирование - Практика программирования

Достаточно часто при доработке БП возникает необходимость добавления однотипных реквизитов или табличных частей в большое количество типовых документов конфигурации.  Сразу же возникает вопрос, а что с дальнейшей поддержкой? Каких временных и человеческих ресурсов будет требовать обновление конфигурации? Можно ли каким-либо образом минимизировать изменения, вносимые в типовые документы?

Предположим, что нам необходимо организовать проведение первичных документов по дополнительному регистру бухгалтерии в соответствии с таблицей распределения, задаваемой в каждом документе. При стандартном подходе нам необходимо в каждый документ добавить табличную часть и прописать обработку записи в регистр. При ближайшем рассмотрении оказывается, что нам необходимо изменить 67 документов. Как подумаешь, что при проведении обновления придется сравнивать 67 раз возможные изменения реквизитов,  форм документов и их модулей, вся бодрость духа куда-то пропадает. Как этого избежать? Нам помогут «Советы» :)

Очень хочется при открытии документа программно добавить на форму документа кнопку по нажатию которой будет открываться таблица в которую будем заносить наше распределение. Обработку записи в регистр вынесем в процедуру общего модуля (нами добавленного!), вызывать процедуру будем по подписке на событие ОбработкаПроведения.

Дабы не добавлять ТЧ в каждый документ, организуем справочник «РаспределениеОбъектов». Создаем у этого справочника ТЧ с требуемой структурой таблицы распределения, добавляем реквизит «Документ» в котором будем хранить ссылку на документ владелец. Рисуем форму элемента, которую будем вызывать для заполнения таблицы распределения. Как же нам вызвать  эту форму?

Перед открытием любого документа происходит вызов процедуры общего модуля РаботаСДиалогами.УстановитьПодменюСоветы(ЭлементыФормы.ДействияФормы, "ИмяДокумента"); добавляем в процедуру строку вызова нашей процедуры, в которой будет прописан обработчик добавления кнопки на форму документа.

Процедура УстановитьПодменюСоветы(КоманднаяПанель, ПараметрОтбора = "ВсеСоветы") Экспорт
     ...................
    
// начало изменения атт
    
ОбъектыУправленческогоУчета.ПриОткрытииФормыУпрУчет(КоманднаяПанель
);
    
// конец изменения атт
КонецПроцедуры
// УстановитьПодменюСоветы()

Таким образом, путем добавления 1 строки, мы фактически организовали подписку на событие ПриОткрытии. Этот способ не единственный по приведенным ссылкам можно посмотреть еще несколько прекрасных вариантов

http://www.infostart.ru/projects/4288

//infostart.ru/blogs/900

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

Для правильной отработки алгоритма нам необходимы две вещи:

  • распознать нажатие именно нашей кнопки;
  • иметь ссылку на документ из которого происходит вызов.

Попробуем поработать с процедурой ДействияФормыОткрытьСоветы(Кнопка), вызывающей процедуру общего модуля ОткрытьСоветы(Кнопка).  

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

Ниже приведены процедуры, в которых происходит непосредственное добавление кнопки на форму документа.

 Процедура ПриОткрытииФормыУпрУчет(КоманднаяПанель) Экспорт
     Попытка
         
ИсточникДействия = КоманднаяПанель.ИсточникДействий.ДокументОбъект
;
         
ДобавитьКнопкуВводУпрОбъектаВДокумент(КоманднаяПанель, ИсточникДействия
);
     Исключение
          Попытка
              
ИсточникДействия = КоманднаяПанель.ИсточникДействий.ДокументСписок
;
              
ДобавитьКолонкуВТЧСпискаДокументов(КоманднаяПанель, ИсточникДействия
);
          Исключение
          КонецПопытки;
     КонецПопытки;
КонецПроцедуры

 // добавляем кнопку вызова справочника распределения на командную панель
// кнопку добавляем только для документов являющихся регистраторами регистра "УправленческийБаланс"

Процедура ДобавитьКнопкуВводУпрОбъектаВДокумент(КоманднаяПанель, Документ
)
     Если Не
ПроверитьРегистраторРегистраБухгалтерии(Документ,"УправленческийБаланс"
) Тогда
          Возврат;
     КонецЕсли;
    
СписИсключаемыхДоков = ПолучитьСписокВидовДокументовИсключений
();
     Если Не
списИсключаемыхДоков.НайтиПоЗначению(Документ.Метаданные().Имя
) = Неопределено Тогда
          Возврат;
     КонецЕсли;

     
// в строку пояснения шифруем наш документ
    
СтрокаПояснения = "Ввести объект упр. учета для: " + Документ.Метаданные().Имя + " " + СокрЛП(Документ.Номер) + " от " + Документ.Дата
;

    
нДействие = новый Действие("ДействияФормыОткрытьСоветы"
);

    
новаяКнопка = КоманднаяПанель.Кнопки.Добавить("ВводУпрОбъекта",ТипКнопкиКоманднойпанели.Действие,"Объект упр.учета",нДействие
);
    
новаяКнопка.Подсказка = "Ввести объект упр. учета"
;
    
новаяКнопка.Пояснение = СтрокаПояснения
;
    
новаяКнопка.Отображение = ОтображениеКнопкиКоманднойПанели.НадписьКартинка
;

    
УстановитьКартинкуКнопкиВводУпрОбъекта(Документ,новаяКнопка
);
КонецПроцедуры

 

При нажатии на кнопку происходит вызов процедуры общего модуля РаботаСДиалогами ОткрытьСоветы

 

 Процедура ОткрытьСоветы(Кнопка) Экспорт
     Если
Кнопка.Имя = "ВводУпрОбъекта" Тогда
// изменение атт
         
ОбъектыУправленческогоУчета.ОткрытьФормуВыбораОбъектаУпрУчета(Кнопка
);
     Иначе 
// типовой код
         
Форма = Обработки.Советы.ПолучитьФорму
();
         
Форма.ПараметрОтбора = Сред(Кнопка.Имя, 7
);
         
Форма.Открыть
();
     КонецЕсли;
КонецПроцедуры
// ОткрытьСоветы()

 

В нашей процедуре открываем форму элемента справочника распределения

 Функция ПолучитьЭлементРаспределенияОбъектовУпрУчета(Документ)
    
Запрос = Новый Запрос
;
    
Запрос.Текст
=
    
"ВЫБРАТЬ
     |      РаспределениеОбъектовУправленческогоУчета.Ссылка
     |ИЗ
     |      Справочник.РаспределениеОбъектовУправленческогоУчета КАК РаспределениеОбъектовУправленческогоУчета
     |ГДЕ
     |      РаспределениеОбъектовУправленческогоУчета.Документ = &Документ"
;
    
Запрос.УстановитьПараметр("Документ",Документ.Ссылка
);

    
Результат = Запрос.Выполнить
();

     Если
Результат.Пустой
() Тогда
          
Элемент = Справочники.РаспределениеОбъектовУправленческогоУчета.ПустаяСсылка
();
     Иначе
          
Выборка = Результат.Выбрать
();
          
Выборка.Следующий
();
          
Элемент = Выборка.Ссылка
;
     КонецЕсли;
     Возврат
Элемент
;
КонецФункции

Процедура ОткрытьФормуВыбораОбъектаУпрУчета(Кнопка) Экспорт
    
// разбираем строку пояснения в которой зашифрован документ
    
СтрокаПояснения = Кнопка.Пояснение
;
    
СтрокаПояснения = Сред(СтрокаПояснения,31
);
    
СтрокаПояснения = СокрЛП(СтрЗаменить(СтрокаПояснения,"от ",""
));
    
СтрокаПояснения = СтрЗаменить(СтрокаПояснения," ",Символы.ПС
);

    
ВидДокумента     = СтрПолучитьСтроку(СтрокаПояснения,1
);
    
НомерДокумента = СтрПолучитьСтроку(СтрокаПояснения,2
);
    
ДатаДокумента   = СтрПолучитьСтроку(СтрокаПояснения,3
);

    
День   = Число(Лев(ДатаДокумента,2
));
    
Месяц = Число(Сред(ДатаДокумента,4,2
));
    
Год     = Число(Прав(ДатаДокумента,4
));
    
ДатаДокумента = Дата(Год,Месяц,День
);

    Если (
Дата(1,1,1) = ДатаДокумента) и (НомерДокумента = ""
) Тогда
      
Сообщить("Перед выбором объекта управленческого учета документ необходимо записать",СтатусСообщения.Внимание
);
       Возврат;
    КонецЕсли;

   
// ищем документ
   
Документ = Документы[ВидДокумента].НайтиПоНомеру(НомерДокумента,ДатаДокумента
);

   
//открываем форму справочника
   
Элемент = ПолучитьЭлементРаспределенияОбъектовУпрУчета(Документ
);

    Если
Элемент.Пустая
() Тогда
        
Элемент = Справочники.РаспределениеОбъектовУправленческогоУчета.СоздатьЭлемент
();
        
Элемент.Документ = Документ
;
    Иначе
        
Элемент = Элемент.ПолучитьОбъект
();
    КонецЕсли;

   
Форма = Элемент.ПолучитьФорму("ФормаЭлемента"
);
   
Форма.ОткрытьМодально
();

   
УстановитьКартинкуКнопкиВводУпрОбъекта(Документ,Кнопка
);
КонецПроцедуры

 Не забываем, что при пометке на удаление документа необходимо пометить на удаление соответствующий элемент справочника, а при снятии пометки удаления с документа снять ее и со справочника. Пишем обработчик и сажаем на подписку ПриЗаписи в которой проверяем состояние пометки удаления документа.

Изменения типовых объектов сведены к изменению 2 процедур общего модуля РаботаСДиалогами, все остальное стоит сбоку и жить никому не мешает :)

 

Добавил пример в виде мини конфы. Скачать можно отсюда

http://www.infostart.ru/profile/9211/forum/9884/ 

 

См. также

Комментарии
1. Роман Ершов (MRAK) 701 03.06.09 07:43 Сейчас в теме
Опять же, не раскрыта тема внешнего добавления элементов на существующую форму...
2. Сергей Троицкий (tsd) 147 03.06.09 07:48 Сейчас в теме
не совсем понял, что я должен раскрыть. Кроме кнопки никакие элементы на форму не добавляются
3. Роман Ершов (MRAK) 701 03.06.09 08:00 Сейчас в теме
(2) пользователю было бы удобней видеть добавленные элементы в типовой форме
4. smth 03.06.09 08:24 Сейчас в теме
...Изменения типовых объектов сведены к изменению 2 процедур общего модуля РаботаСДиалогами, все остальное стоит сбоку и жить никому не мешает :)...

А разве не нужно в модулях изменяемых документов делать подписку на события: ОбработкаПроведения, ПриЗаписи если мы их будем обрабатывать?
5. Роман Ершов (MRAK) 701 03.06.09 08:27 Сейчас в теме
(4) при чем здесь модули доков? подписки - это отдельные объекты конфы.
6. Сергей Троицкий (tsd) 147 03.06.09 08:33 Сейчас в теме
(4) подписка на событие устанавливается не в модуле объекта. В метаданных есть специальные объекты Общие-->"Подписки на события". В общем модуле Вы пишете свою процедуру, указываете ее как обработчик подписки, выбираете источники действия и указываете событие возникновение которого стартует Вашу процедуру. Процедура будет вызвана в конце события. Небольшим условием является то, что Ваша процедура должна содержать определенные параметры. Первым должен идти Источник действия, далее параметры стандартного обработчика 1С. Кроме того процедура должна быть экспортной.

7. Сергей Троицкий (tsd) 147 03.06.09 08:42 Сейчас в теме
(3) Вопрос спорный. Если реквизиты расположены на форме так, что они видны сразу после открытия, то да. Если необходимо переключать закладки, то разница небольшая. Если на первую страницу панели формы напихать большое количество реквизитов, то можно форму перегрузить.
8. Андрей Скляров (coder1cv8) 3301 03.06.09 09:39 Сейчас в теме
9. Геннадий Пиганов (Totoro) 523 03.06.09 10:01 Сейчас в теме
Теперь дошло. А что уникальный идентификатор не стал в пояснении шифровать, так по-моему проще:
GUID = СсылкаНаОбъект.ПолучитьУникальныйИдентификатор;
СсылкаНАОбъект = Документы[ВидДокумента].ПолучитьСсылку(GUID);
10. Геннадий Пиганов (Totoro) 523 03.06.09 10:04 Сейчас в теме
(9)+ перепутал
GUID = СсылкаНаОбъект.УникальныйИдентификатор()
11. Ulcer (KapasMordorov) 03.06.09 10:37 Сейчас в теме
<QUOTE>Изменения типовых объектов сведены к изменению 2 процедур общего модуля РаботаСДиалогами, все остальное стоит сбоку и жить никому не мешает :)</QUOTE>
В самом начале статьи написано про проведение по дополнительному регистру бухгалтерии.
Без регистратора может быть только регистр сведений. Т.е. в 67 документах нужно редактировать набор движений.
Сферический конь в ....?

12. Алексей Константинов (alexk-is) 6155 03.06.09 11:05 Сейчас в теме
Предлагаю раскрасить примеры кода
13. Сергей Троицкий (tsd) 147 03.06.09 11:11 Сейчас в теме
(10) да я как-то про это вообще не задумывался. Получение ссылки на док труда не вызывает и ладно, кроме того пояснение выводится в строку состояния. Наверное, все же лучше видеть некую внятную подсказку, чем непонятный набор символов :)

(11) да, конечно. В приведенном примере, ессно, добавятся изменения по движениям.
Но, статья писана про организацию ввода дополнительных реквизитов с минимальными изменениями типовых форм. Поэтому и указал, что изменения всего в 2 процедурах.
Кстати, по приведенному примеру обновление все равно получается очень легким. Мы в конец справки по нашему регистру забили требуемый состав регистраторов, при обновлении никто особо не парится, после объединения просто заново прощелкивается состав регистраторов, по времени минута уходит.
В любом случае, это гораздо быстрее чем проверять формы доков :)
14. Сергей Троицкий (tsd) 147 03.06.09 11:13 Сейчас в теме
(12) не умею :( Подскажи, плиз, куда тыкать нужно.
15. Геннадий Пиганов (Totoro) 523 03.06.09 11:30 Сейчас в теме
(13) Это я к тому, что дата, как и номер документа являются величинами не постоянными и за время работы в форме могут быть изменены :)
16. Геннадий Пиганов (Totoro) 523 03.06.09 11:32 Сейчас в теме
(11) Ничто не мешает использовать механизм от WiseSnake с учетом приведенного кода ... Тогда движения не нужно будет редактировать.
17. Алексей Константинов (alexk-is) 6155 03.06.09 11:32 Сейчас в теме
18. Ulcer (KapasMordorov) 03.06.09 11:41 Сейчас в теме
(16) Так и получается, что на каждую мелочь нужен механизм.
И тогда простота обновления отличается от заявленной.
19. Геннадий Пиганов (Totoro) 523 03.06.09 11:52 Сейчас в теме
(18) Извини, но тут уже готовое решение дано. Хочешь без движений - добавляей свой связанный регистр сведений, а при вызове созданной кнопки будешь открывать форму этого регистра, а не документа по его виду (можно сделать универсальную форму как для свойств) и по ссылке устанавливать подчиненые значения. Тогда изменений действительно минимум - добавить тип обекта в регистр, поведение его форм и прописать создание и выполнение кнопки из советов (можно еще использовать процедурку обновления заголовка формы в БП, что бы проверять запись нового документа и обновления ссылки на кнопке).
20. smth 03.06.09 12:54 Сейчас в теме
Каким-нибудь еще механизмом можно отловить событие нажатия созданной кнопки, кроме как через "советы"? Просто советы есть не во всех конфигурациях.
21. Сергей Троицкий (tsd) 147 03.06.09 13:06 Сейчас в теме
(17) блин, что-то не ладно с руками в датском королевстве. Оставлю как есть, лучшее враг хорошего :)
22. Сергей Троицкий (tsd) 147 03.06.09 13:11 Сейчас в теме
(20) по ссылкам можно посмотреть другие способы обработки событий.
В УТ, например, для установки кнопки можно использовать процедуру УстановитьКнопкуПечати(), а нажатие на кнопку отлавливать через ОбновитьФормуПодбора()
Правда последняя есть только в 46 документах, нет в документах по банку, кассе и доках ввода начальных остатков
23. smth 03.06.09 13:33 Сейчас в теме
А возможно отловить событие через свойство Кнопки - "Действие"?
Пр: Меню.Кнопки.Добавить(, , , Действие).
В справке написано: "Для обработки события может быть вызвана процедура или функция модуля формы или модуля приложения, имя которой задано в конструкторе."
Для того, что б не менять код документа - модуль формы не подходит. А вот в модуле приложения почему-то не запускается процедура :-(
24. Ulcer (KapasMordorov) 03.06.09 13:33 Сейчас в теме
Не буду утверждать, что в каждом документе.
Но в БП в форме документа есть меню "Действия" и подпункты а)"Редактировать номер", б)"Структура подчиненности документа", для которых есть процедуры в модуле формы, вызывающие процедуры общего модуля.
25. smth 03.06.09 13:41 Сейчас в теме
(24) они не передают в общий модуль имя кнопки, по которой произошло нажатие
26. Сергей Троицкий (tsd) 147 03.06.09 13:41 Сейчас в теме
(23) у меня не получилось вызвать процедуру, расположенную не в модуле формы.
27. Ulcer (KapasMordorov) 03.06.09 13:51 Сейчас в теме
(25)
Менюшку с вопросом, какое действие выполнить.
Неудобно, ну так вопрос про неудобства не идет, минимализм, понимаешь.
28. inse0f (inse0f) 03.06.09 22:22 Сейчас в теме
(1) а если раскрыта просто никто не хочет ее показывать?))
29. dvv01 (dvv01) 114 04.06.09 11:12 Сейчас в теме
ответ в http://infostart.ru/projects/4332/ - обработка табличных частей - автоматически к нужным документам добавляется меню, таб часть меняется или генерятся новые документы. Конфигурация не меняется (может только права доступа, хотя и это можно проверить в самой обработке). Примеры отобраны из Торговли, но сути не меняет
30. Ден (lion11) 139 15.06.09 13:18 Сейчас в теме
Хорошая штука!!!
Вот только не могу понять, как отловить признак модифицированности документа перед открытием доп.формы в процедуре ОткрытьФормуВыбораОбъектаУпрУчета, чтоб можно было сохранить этот док. В ней есть проверка на существование дока. Можно это как-нибудь сделать?
31. Сергей Троицкий (tsd) 147 15.06.09 19:13 Сейчас в теме
(30) для чего тебе признак модифицированности?
32. Ден (lion11) 139 16.06.09 07:52 Сейчас в теме
(31) Я хочу через таким образом добавленную кнопку вызывать форму дополнительных реквизитов, типа как в http://infostart.ru/projects/4288/ , только через Советы, так меньше изменений в типовой. А если док в основной форме изменен, то в этой форме с доп.реквизитами он уже не запишется. Вот мне надо проверить, были ли изменения в текущей открытой форме дока, и с вопросом записать, а потом редактировать свои реквизиты.
33. Сергей Троицкий (tsd) 147 16.06.09 10:29 Сейчас в теме
34. Сергей Троицкий (tsd) 147 17.06.09 13:30 Сейчас в теме
(32) у меня проблем никаких не возникло.
По ссылке можешь качнуть пример, там все работает.


35. Ден (lion11) 139 17.06.09 16:53 Сейчас в теме
(34) Спасибо, посмотрел. Но не увидел вот чего: если я открываю форму документа, что-нибудь на ней меняю, например номер, потом нажимаю кнопку Доп.реквизиты, не идет проверка на модифицированность, только на существование этого документа. В твоем случае - это все-равно, т.к. у тебя доп.реквизиты отдельно от документа, а у меня реквизиты принадлежат этому документу, и если я потом в доп форме жму записать - возникает ошибка. (весь смысл - чтоб типовую форму не менять) Но все равно идею приму на вооружение и буду использовать. Еще раз спасибо.
36. Сергей Троицкий (tsd) 147 17.06.09 20:06 Сейчас в теме
(35) я думал ты в процедуру Процедура ОткрытьФормуДопРеквизитов(Кнопка)заглянешь. Там специально вставлено
ФормаОбъекта = Объект.ПолучитьФорму();
// Сообщить("Модифицированность формы: " + ФормаОбъекта.Модифицированность);

:))
37. Ден (lion11) 139 18.06.09 08:21 Сейчас в теме
(36) Вот ведь ... :)) Смотрел в эту строчку, но просмотрел. У меня было нечто подобное, но я сначала находил объект, а потом его форму - и не работало, а тут у тебя гораздо проще. Потом почитал хелп ПолучитьФорму() для ссылки - там все написано. А так всё получилось. Огромное спасибо, что наставил на путь истинный :)
38. Ден (lion11) 139 21.09.09 16:18 Сейчас в теме
Возник вопрос:
У меня на некоторые документы не ловится список, а именно в строке ИсточникДействия = КоманднаяПанель.ИсточникДействий.ДокументСписок;
не ловится ДокументСписок. Пробовал на РКО и ав.отчеты. (Бухгалтерия предприятия 1.6.18.2). Хотя ДокументОбъект на эти доки ловится успешно.
Есть мысли, почему?
39. Сергей Троицкий (tsd) 147 21.09.09 19:55 Сейчас в теме
(38) ИсточникДействий должен иметь значение Форма, у формы списка РКО для командной панели ДействияФормы Источник действия установлен ВсеИсточники, поэтому и не ловит
40. Ден (lion11) 139 22.09.09 08:26 Сейчас в теме
(39) Понятно, спасибо. Поставил Форму и получилось!
Интересно, это так задумано или просто недочет разработчиков?
41. Сергей Троицкий (tsd) 147 22.09.09 09:31 Сейчас в теме
(40) а кто ж его знает. В типовых это свойство никакой поленой нагрузки не несет, наверное просто не заполнили
42. Артур Аюханов (artbear) 877 02.11.09 09:23 Сейчас в теме
(0) По адресу для скачивания примера лежит файл, который не загружается ни в 8.0, ни в 8.1.14.72
Какая версия 1С нужна для загрузки примера?
43. Сергей Троицкий (tsd) 147 02.11.09 09:33 Сейчас в теме
(42) 8.1. , судя по дате, тогда у меня стоял 12 релиз платформы. Похоже просто файл битый. Посмотрю дома, если пример сохранился, то выложу заново.
44. Владимир Владимир (vladimir_che) 26.07.10 16:01 Сейчас в теме
Занимательно. Ваш пост единстенный находится поиском по сайту по слову "писька".

" .НадписьКартинка "
45. Ден (lion11) 139 16.12.10 15:45 Сейчас в теме
Грустное примечание:
Сделал это все в редакции 1.6, все красиво. Начал переходить на редакцию 2.0 - а там засада: практически нигде нет в процедурах ПередОткрытием Советов :(
Придется сделать через функцию УстановитьДоступностьПоляВводаНомера
Оставьте свое сообщение