Оглавление
Как правильно делать изменения в типовые конфигурации.
Помечать изменения комментариями
Добавление своих функции в общий модуль
Добавление параметров в типовую функцию
Добавление больших кусков кода
Комментарии к модулю писать в отдельной функции
Использование обычных элементов вместо предопределенных
Типовые задачи по доработкам типовых конфигураций.
Доработка общих команд типа "Движения документа" и "Структура подчиненности"
Программное добавление элементов интерфейса на обычных формах
Добавление колонок в форму списка
Добавление кнопок в панель действий
Назначение обработчиков событий
Добавление новых команд на форму "Рабочий стол"
Добавление кнопок на обычную форму
Добавление поля ввода на обычную форму
Программное добавление элементов интерфейса на управляемых формах
Добавление кнопок и действий под них
Вывести колонку с добавленным полем в табличную часть
Добавить программно колонку в табличную часть
Добавить реквизит в динамический список и отобразить его на форме в табличном поле
Добавить программно поле ввода в форму элемента
Назначение обработчиков событий
Использование дополнительных отчетов и обработок
Как правильно обновлять измененные конфигурации.
Как проверить, есть ли доработки в типовую конфигурацию..
Как при сравнении-объединении определить измененные объекты
Не показываются некоторые реквизиты формы
Постоянный рефакторинг при сопровождении
Это самое главное правило. Если изменения не отмечены комментариями, то они с вероятностью 99% будут не замечены и затерты при обновлении. Размещать комментарии надо не справа, а слева, т.к. справа они могут быть не замечены в узком окне сравнения.
Если требуется добавить свою функцию, надо ее добавлять в отдельный общий модуль, а не в типовой общий модуль. В итоге придется совершать меньше операций при обновлении.
Вместо добавления параметров в типовую функцию лучше использовать глобальные переменные, параметры сеанса, и в управляемых формах - хранилище настроек.
Вместо добавления больших кусков кода нужно добавлять вызов функции, т.к. сопоставление плохо работает с большими кусками кода, оно может ошибочно сопоставить часть большого кода.
Не стоит писать комментарии к модулю в самом модуле. Нужно создать отдельную функцию с говорящим именем, например _ОписаниеИзменений и там описать изменения.
Тогда не будет лишний раз выдаваться сообщение об изменении в основном разделе программы. При этом функцию лучше называть с подчеркивания, чтобы она была на первом месте в списке функций.
Можно использовать обычные элементы вместо предопределенных.
Для того, чтобы не было конфликтов кодов, лучше давать им префикс, например код задавать в виде "ПЭ-XXXX".
По возможности нужно использовать добавление вместо изменения исходного кода.
Вот в этом примере можно было бы вмешаться в типовой код, но понять логику было бы сложнее.
А добавление, хоть и вносит лишнее время выполнения кода, но смотрится прозрачнее для обновления.
Цена = Ценообразование.ПересчитатьЦенуПриИзмененииВалюты(Цена, ВалютаЦены, ВалютаДокумента, ЗаполнениеДокументов.КурсДокумента(ЭтотОбъект, мВалютаРегламентированногоУчета), ЗаполнениеДокументов.КратностьДокумента(ЭтотОбъект, мВалютаРегламентированногоУчета), Дата);
СтрокаТабличнойЧасти.Цена = Ценообразование.ПересчитатьЦенуПриИзмененииФлаговНалогов(Цена,
СпособЗаполненияЦен,
ТипЦен.ЦенаВключаетНДС,
УчитыватьНДС,
СуммаВключаетНДС,
УчетНДС.ПолучитьСтавкуНДС(СтрокаТабличнойЧасти.СтавкаНДС));
//РИТ Осипов 2017-07-28 +++
//Если цена не
заполнена, то цену считаем по типу цен по умолчанию (обратите внимание на
ТекТипЦен)
Если Не ЗначениеЗаполнено(ТипЦен) Тогда
ТекТипЦен = СтрокаТабличнойЧасти.Номенклатура.ОсновнойТипЦен;
СтрокаТабличнойЧасти.Цена = Ценообразование.ПересчитатьЦенуПриИзмененииФлаговНалогов(Цена,
СпособЗаполненияЦен,
ТекТипЦен.ЦенаВключаетНДС,
УчитыватьНДС,
СуммаВключаетНДС,
УчетНДС.ПолучитьСтавкуНДС(СтрокаТабличнойЧасти.СтавкаНДС));
КонецЕсли;
//РИТ Осипов 2017-07-28 +++
Если просто добавить новый отчет, то могут быть проблемы с ролями, хотя обычно проблем нет.
Поэтому нужно добавить отчет в справочник дополнительных внешних обработок.
Вызов отчета лучше привязать не к пункту меню/пиктограмме.
А добавить в какую-либо связанную с отчетом форму, например, в форму списка справочника.
Код вызова отчета будет выглядет так:
Если вы добавили свой документ, то ему хочется добавить типовые общие команды "Движения документа" и "Структура подчиненности". Но если поменять состав документов для типовой команды, появится постоянная проблема при обновлениях.
Поэтому можно добавить свои команды, скопировав обработки модуля команды (они там примитивные).
В своих командах указать свой собственный состав документов для команды.
Такой способ не будет мешать обновлению типовых конфигураций.
Нужно вставлять свои колонки после типовых кодом вроде этого:
ЭлементСписок = ЭлементыФормы.ДокументСписок;
ТекПозиция = 0;
НовКолонка = ЭлементСписок.Колонки.Вставить(ТекПозиция + 1);
НовКолонка.Имя = "КартинкаНаличие";
НовКолонка.Данные = "";
НовКолонка.ТекстШапки = "А";
НовКолонка.Ширина = 26;
ТекПозиция = ЭлементСписок.Колонки.Индекс(ЭлементСписок.Колонки.СостояниеЭД);
НовКолонка = ЭлементСписок.Колонки.Вставить(ТекПозиция + 1);
НовКолонка.Имя = "ПодписАкт";
НовКолонка.Данные = "ПодписАкт";
НовКолонка.ТекстШапки = "Подписанный акт";
НовКолонка.Ширина = 70;
НовКолонка = ЭлементСписок.Колонки.Вставить(ТекПозиция + 1);
НовКолонка.Имя = "ДатаОткрытия";
НовКолонка.Данные = "ДатаОткрытия";
НовКолонка.ТекстШапки = "Дата открытия";
НовКолонка.Ширина = 10;
НовКолонка = ЭлементСписок.Колонки.Вставить(ТекПозиция + 2);
НовКолонка.Имя = "ДатаЗакрытия";
НовКолонка.Данные = "ДатаЗакрытия";
НовКолонка.ТекстШапки = "Дата закрытия";
НовКолонка.Ширина = 10;
НовКолонка = ЭлементСписок.Колонки.Вставить(ТекПозиция + 3);
НовКолонка.Имя = "Условия";
НовКолонка.Данные = "Условия";
НовКолонка.ТекстШапки = "Комментарий";
НовКолонка.Ширина = 20;
Нужно программно добавить кнопку и обработчик события по ее нажатию.
Шаг 1. В процедуру при открытии программно добавляем кнопку на панель.
ЭлементыФормы.ДействияФормы.Кнопки.Добавить("ДействиеОтчетПоВакансиям", ТипКнопкиКоманднойПанели.Действие, "Отчет", Новый Действие("ОтчетПоВакансиям"));
Шаг2. Добавляем обработчик нажатия
Процедура ОтчетПоВакансиям(Элемент) Экспорт
Предупреждение("Отчет");
КонецПроцедуры
Все обработчики событий назначать в модуле. При обновлении можно забыть прописать их и функциональность будет нарушена.
Тем более, что обработчики прописываются просто.
Добавлять новые команды в интерфейс можно только вручную, это неудобно для обновлений.
В большинстве типовых конфигураций используется рабочий стол.
Он описывается в обработке "Рабочий стол".
Чтобы добавить на него команду, нужно внести код добавления команды в "При открытии" этой обработки.
Нужно подобрать место, где разместить кнопку, посмотреть координаты соседних верхней кнопки (координата лево) и левой кнопки (координата верх). Размеры всех кнопок одинаковы.
Вместо кнопки используется надпись, т.к. она позволяет переносить текст надписи на новую строку.
Возможно, будет проблема с наличием свободного пространства для кнопок. Тогда можно сделать вызов списка с действиями при нажатии на кнопку или открытия своей формы-меню.
Если будет желание добавить новую страницу на панель, то нужно сделать кнопку, которая будет добавлять новую панель. Важно - эта панель не использует типовой механизм закладок, сверху находятся кнопки, которые переключают закладки. Поэтому надо или добавлять свою новую кнопку (что сложно из-за привязок) или добавить кнопку на рабочий стол, которая будет переключаться на эту новую панель:
НоваяСтраница = ЭлементыФормы.ОсновнаяПанель.Страницы.Добавить();
НоваяСтраница.Заголовок = "ДОП";
НоваяСтраница.Видимость = истина;
Вот пример, который добавляет новую кнопку вызова обработки "Рассылка поздравлений с днем рождения" и обработчик команды для нее:
Процедура ПриОткрытии()
ОбработатьЭлементыУправленияПоРежиму();
УстановитьВидимостьНаписатьПисьмо();
РабочийСтол.УстановитьВидимостьЭлементовУправленияОрганизациями(ЭлементыФормы);
// Осипов
2016-02-29 +++ Добавляю кнопку
//Запоминаем текущую страницу
ПредТекСтраница = ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница;
//Меняем на
нужную страницу... В данном случае персонал
ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница = ЭлементыФормы.ОсновнаяПанель.Страницы.Персонал;
//Добавляем
кнопку, если есть роль ПолныеПрава
Если РольДоступна("ПолныеПрава") Тогда
Кнопка = ЭлементыФормы.Добавить(Тип("Надпись"), "РассылкаПоздравленийДР", Истина, ЭлементыФормы.ОсновнаяПанель);
Кнопка.Заголовок = "Рассылка
поздравлений с ДР";
Кнопка.Лево = 533;
Кнопка.Верх = 216;
Кнопка.Ширина = 150;
Кнопка.Высота = 42;
Кнопка.Гиперссылка = истина;
Кнопка.УстановитьДействие("Нажатие", Новый Действие("Нажатие_РассылкаПоздравленийДР"));
КонецЕсли;
//Возвращаем
текущую страницу
ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница = ПредТекСтраница;
//Осипов
2016-02-29 ---
КонецПроцедуры
// Осипов
2016-02-29 +++ Добавляю процедуру кнопки
Процедура Нажатие_РассылкаПоздравленийДР(Элемент) Экспорт
РассылкаПоздравлений.СформироватьПисьмо();
Предупреждение("Рассылка выполнена");
КонецПроцедуры
// Осипов
2016-02-29 ---
Выглядит так:
Нужно добавить в процедуру "При открытии" код:
Кнопка = ЭлементыФормы.Добавить(Тип("Кнопка"), "_ВводРазовыхНачислений", Истина);
Кнопка.Заголовок = "Ввод раз.начислений:";
Кнопка.Лево = 304;
Кнопка.Верх = 30;
Кнопка.Ширина = 150;
Кнопка.Высота = 19;
Кнопка.УстановитьДействие("Нажатие", Новый Действие("Нажатие_ВводРазовыхНачислений"));
И саму процедуру для реагирования на нажатие кнопки:
Процедура Нажатие_ВводРазовыхНачислений(Элемент)
КонецПроцедуры
Если просто добавить поле ввода ссылочного типа, то не будет работать кнопка выбора. Как эту проблему решить, пока не понятно, поэтому надо добавлять реквизит формы вручную.
Поле = ЭлементыФормы.Добавить(Тип("ПолеВвода"), "_ДокументРазовыхНачислений", истина);
//Поле.Заголовок
= "";
Поле.Лево = 460;
//Поле.ОграничениеТипа
= Новый
ОписаниеТипов("ДокументСсылка.РегистрацияРазовыхНачисленийРаботниковОрганизаций");
Поле.Данные = "_ДокументРазовыхНачислений";
Поле.Верх = 30;
Поле.КнопкаВыбора = истина;
Поле.Ширина = 150;
Поле.Высота = 19;
Можно добавить кнопку и команду для нее полностью программно.
В процедуру формы ПриСозданииНаСервере добавить код вида:
ИмяКоманды = "ОткрытьНастройкаПередачиТоваровДетально";
КомандаФормы = ЭтаФорма.Команды.Добавить(ИмяКоманды);
КомандаФормы.Действие = "ОткрытьНастройкаПередачиТоваровДетально";
КомандаФормы.Заголовок = "Настройка передачи товаров между организациями
(детально)";
КомандаФормы.ИзменяетСохраняемыеДанные = Ложь;
КомандаФормы.Отображение = ОтображениеКнопки.КартинкаИТекст;
НовыйЭлемент = ЭтаФорма.Элементы.Добавить("ОткрытьНастройкаПередачиТоваровДетально", Тип("КнопкаФормы"), Элементы.ГруппаРегламентированныйУчет);
НовыйЭлемент.Вид = ВидКнопкиФормы.Гиперссылка;
НовыйЭлемент.ИмяКоманды = ИмяКоманды;
В модуль формы добавить процедуру для реагирования на событие:
&НаКлиенте
Процедура ОткрытьНастройкаПередачиТоваровДетально(Команда)
ОткрытьФорму("РегистрСведений._НастройкаПередачиТоваровМеждуОрганизациямиДетальные.Форма", , ЭтаФорма);
КонецПроцедуры
ПередЭлементом = Элементы.ГруппаКомментарий;
Элемент = Элементы.Вставить("_ГруппаЗаполненияОстатками", Тип("ГруппаФормы"), ПередЭлементом.Родитель, ПередЭлементом);
Элемент.Вид = ВидГруппыФормы.ОбычнаяГруппа;
Элемент.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Горизонтальная;
После добавления поля в табличную часть его нужно вывести на форму:
Элемент = Элементы.Добавить("_СегментРасходов", Тип("ПолеФормы"), Элементы.Товары);
Элемент.Вид = ВидПоляФормы.ПолеВвода;
Элемент.ПутьКДанным = "Объект.Товары._СегментРасходов";
Описано здесь:
&НаСервере
Процедура ДобавитьКолонкуНаСервере()
нРеквизиты = Новый Массив;
нРеквизиты.Добавить(Новый РеквизитФормы("Тест3", Новый ОписаниеТипов("Строка"), "Объект.Тест", "Тест3", Истина));
ИзменитьРеквизиты(нРеквизиты);
нЭлемент = Элементы.Добавить("Тест3", Тип("ПолеФормы"), Элементы.Тест);
нЭлемент.Вид = ВидПоляФормы.ПолеВвода;
нЭлемент.ПутьКДанным = "Объект.Тест.Тест3";
КонецПроцедуры
Если в текст запроса динамического списка вносятся изменения, то необходимо также добавить поле для вывода этого реквизита. Реквизиты добавлять не требуется.
При этом тип поля можно брать непосредственно из типа того объекта, из которого он выводится запросом, в данном примере используется тип ресурсов регистра Т_Лицензии.
Элемент = Элементы.Вставить("КПП", Тип("ПолеФормы"), Элементы.Список, Элементы.Номер);
Элемент.Вид = ВидПоляФормы.ПолеВвода;
Элемент.ПутьКДанным = "Список.КПП";
Элемент.Заголовок = "КПП";
Элемент = Элементы.Вставить("Адрес", Тип("ПолеФормы"), Элементы.Список, Элементы.Номер);
Элемент.Вид = ВидПоляФормы.ПолеВвода;
Элемент.ПутьКДанным = "Список.Адрес";
Если список является динамическим списком с произвольным запросом, то нужно будет подкорректировать запрос, например так:
Затем добавить реквизит списка и элемент:
Нужно указать заголовок, если он имеется.
Также в примере используется команда вставки, а не добавления, для того, чтобы вставлять в нужную позицию:
ПередЭлементом = Элементы.Номер;
Элемент = Элементы.Вставить("_ДляАлкогольнойДекларации", Тип("ПолеФормы"), ПередЭлементом.Родитель, ПередЭлементом);
Элемент.Вид = ВидПоляФормы.ПолеФлажка;
Элемент.Заголовок = "Для А.д.";
Элемент.ПутьКДанным = " _ДляАлкогольнойДекларации";
Если нужно добавить элемент в некую группу:
ГруппаЭлемента = Элементы.Группа;
Элемент = Элементы.Добавить("_ДляАлкогольнойДекларации", Тип("ПолеФормы"), ГруппаЭлемента);
Элемент.Вид = ВидПоляФормы.ПолеФлажка;
Элемент.Заголовок = "Для А.д.";
Элемент.ПутьКДанным = " _ДляАлкогольнойДекларации";
Если поле ввода не связано с реквизитами объекта, можно добавить реквизит программно:
ДобавляемыеРеквизиты = Новый Массив;
ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы("_ПоступлениеРасходовПоГТД", Новый ОписаниеТипов("ДокументСсылка.ПоступлениеТоваровУслуг"), , , Истина));
ИзменитьРеквизиты(ДобавляемыеРеквизиты);
Элемент = Элементы.Добавить("_ПоступлениеРасходовПоГТД", Тип("ПолеФормы"), Элементы.СтраницаПоступление);
Элемент.Вид = ВидПоляФормы.ПолеНадписи;
Элемент.Гиперссылка = истина;
Элемент.Заголовок = "Поступление транспортных расходов";
Элемент.ПутьКДанным = "_ПоступлениеРасходовПоГТД";
Элемент.УстановитьДействие("Нажатие", "_ПоступлениеРасходовПоГТДГиперссылка");
Все обработчики событий назначать в модуле в процедуре ПриСозданииНаСервере. При обновлении можно забыть прописать их и функциональность будет нарушена.
Тем более, что обработчики прописываются просто.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
...
УстановитьДействие("ПередЗаписью", "_ПередЗаписьюНаКлиенте");
КонецПроцедуры
&НаКлиенте
Процедура _ПередЗаписьюНаКлиенте(Отказ, ПараметрыЗаписи)
КонецПроцедуры
Иногда требуется переместить элементы формы, вот пример:
Элементы.Переместить(Элементы.КонтактнаяИнформацияПолеEmailКонтрагенты, ЭтаФорма, Элементы.Родитель);
Элементы.КонтактнаяИнформацияПолеEmailКонтрагенты.ЦветФона = WebЦвета.БледноЗеленый;
Элементы.КонтактнаяИнформацияПолеEmailКонтрагенты.Заголовок = "E-mail";
Элементы.КонтактнаяИнформацияПолеEmailКонтрагенты.ПоложениеЗаголовка
= ПоложениеЗаголовкаЭлементаФормы.Лево;
Элементы.Переместить(Элементы.КонтактнаяИнформацияПолеТелефонКонтрагента, ЭтаФорма, Элементы.Родитель);
Элементы.КонтактнаяИнформацияПолеТелефонКонтрагента.ЦветФона = WebЦвета.БледноМиндальный;
Элементы.КонтактнаяИнформацияПолеТелефонКонтрагента.Заголовок = "Телефон";
Элементы.КонтактнаяИнформацияПолеТелефонКонтрагента.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Лево;
Иногда нужно, чтобы при выборе значения в добавленном поле ввода показывались элементы только в соответствии с отбором.
Вот пример ***:
НовыйМассив = Новый Массив();
НовыйПараметр = Новый ПараметрВыбора("Отбор.ОприходованСкладом", Истина);
НовыйМассив.Добавить(НовыйПараметр);
НовыйПараметр = Новый ПараметрВыбора("Отбор.ОприходованЗакупщиком", Ложь);
НовыйМассив.Добавить(НовыйПараметр);
НовыеПараметры = Новый ФиксированныйМассив(НовыйМассив);
Элемент.ПараметрыВыбора = НовыеПараметры;
Примерный код:
ВнешняяОбработкаСсылка = Справочники.ВнешниеОбработки.НайтиПоНаименованию("Отчет по авансам", истина);
ИмяФайла = КаталогВременныхФайлов() + ВнешняяОбработкаСсылка.УникальныйИдентификатор() + ".tmp";
ДвоичныеДанные = ВнешняяОбработкаСсылка.ХранилищеВнешнейОбработки.Получить();
ДвоичныеДанные.Записать(ИмяФайла);
Форма = ВнешниеОтчеты.ПолучитьФорму(ИмяФайла);
//Форма =
ВнешниеОбработки.ПолучитьФорму(ИмяФайла); //Для обработок
Форма.Открыть();
Нужно сравнить конфигурацию базы с конфигурацией поставщика. Если конфигурации поставщика нет, значит конфигурация полностью типовая.
Нужно зайти в пункт "Обновление" и указать новый файл конфигурации.
В окне сравнения нужно использовать фильтр по дважды измененным объектам. Будут выведены только конфликты, т.е. те объекты, которые изменены в текущей конфигурации и типовой одновременно. Их и надо обрабатывать.
К сожалению, нельзя будет сохранять промежуточный результат, т.е. нужно сделать все сравнения и только потом принять изменения.
При этом если сравнения вылетит, придется сохранять все сначала.
Поэтому если объем изменений большой, можно выписать список дважды измененных объектов (можно сделать скриншоты) и сравнивать в обычном режиме, а не через обновление. При этом лучше использовать режим "Объединять с приоритетом новой конфигурации", тогда код будет объединен в блоки MRG, по ним можно организовать поиск и разобраться в исправлениях.
При сравнении в обычном режиме имеет смысл сравнивать две конфигурации из файла - какая была до и конфигурацию от 1С. Тогда можно вносить изменения в конфигурацию и сравнение будет продолжать оставаться доступным. Потому что если сравнивать текущую конфигурацию, то при первом же изменении сравнение становится не актуальным и работа с ним блокируется.
Если у пользователя собственная настройка формы, то после обновления новые элементы не показываются. Проблема решается редактированием настройки - можно или сбросить на стандартную настройку или включить видимость реквизитов.
Если в процессе сопровождения конфигурации встречается вручную добавленный реквизит или событие, нужно постараться тут же сделать рефакторинг на его программную генерацию. Тогда при обновлении будет меньше проблем.