В данной статье будут публиковаться примеры доработок типовых (в основном интерфейсной части). Доработки как типовых 8.1, так и 8.2. Всё выкладывать сразу не буду, постепенно дописывая свежие примеры.
1. Вставка фото пользователя в типовой справочник Пользователи для 8.2 Управляемые формы.
2. Автоматизация ввода Грузополучателя в документе Реализация товаров и услуг
3. Номер счет-фактуры совпадает с номером документа Реализация товаров и услуг
4. Запускаем произвольную обработку и загружаем произвольные данные на компьютере пользователя при запуске 1с
5. Организация складов без учета серий и характеристик
6. Добавляем картинки к кнопкам внешних печатных форм и заполнения табличных частей (добавлено 23.11.2011)
7. Выводит вес брутто в шапке табличной части Товары документа Заказ или Реализация (добавлено 14.03.2013)
Пример 1. Типовой справочник Пользователи в 8.2. Управляемая форма - вставка фото пользователя и списка контактов. Не для тонкого и web-клиента.
В типовых конфигурациях на платформе 8.2 данных справочник перевели на управляемые формы. Захотелось сразу попробовать, что можно сотворить с ним без кодинга. Тэк-с...Ага у нас в пользователе есть поле Физлицо. Оттуда можно поднятуть несколько реквизитов, обычно редко кому нужных. Что ещё? Ага!,У физлица есть фотография. А нельзя ли вывести фотографию сразу в списке пользователей и в форме элементов? Фиг... В управляемых формах картинки выводятся по-другому ): Что ещё можно вывести? Контактную информацию! Опять облом - данные хранятся в регистре сведений и через настройку управляемой формы до неё не добраться.
Придется допиливать.
Для начала откроем в Конфигураторе форму списка и добавим туда новый реквизит АдресКартинки, типа Строка. Потом добавим Динамический список КонтактнаяИнформацияТаблица с произвольным запросом.
ВЫБРАТЬ
КонтактнаяИнформация.Вид,
КонтактнаяИнформация.Представление
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
ГДЕ
КонтактнаяИнформация.Объект = &Ссылка
Ну и размещаем эти элементы на управляемой форме. Соответственно Поле(Поле картинки, Путь к данным - АдресКартинки) и Таблица (Путь к данным - КонтактнаяИнформацияТаблица). Немного поиграть с точным размещением и размерами для удовлетворения эстетических чувств.
После этого нужно выбрать в списке элементов формы сам список пользователей и в свойствах найти событие ПриАктивизацииСтроки и добавить туда процедуру
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
Если Не ЗначениеЗаполнено(Элемент.ТекущаяСтрока) Тогда
АдресКартинки="";
КонтактнаяИнформацияТаблица.Параметры.УстановитьЗначениеПараметра("Ссылка",Неопределено);
Иначе
АдресКартинки = ПолучитьКартинкуФизЛица(Элемент.ТекущаяСтрока.ФизЛицо);
КонтактнаяИнформацияТаблица.Параметры.УстановитьЗначениеПараметра("Ссылка",Элемент.ТекущаяСтрока.Ссылка);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ПолучитьКартинкуФизЛица(ФизЛицо)
Если ЗначениеЗаполнено(ФизЛицо) Тогда
Возврат(ПоместитьВоВременноеХранилище(ФизЛицо.ОсновноеИзображение.Хранилище.Получить()));
Иначе
Возврат ("");
КонецЕсли;
КонецФункции
Теперь в списке пользователей у нас при выборе пользователя отображается его контактная информация и фотография соответствующего физ.лица...
В форме элемента вывести одновременно и фотографию и контактную информацию - не нашел места пока. Поэтому оставил только фото, которое поместил справа от списка ролей таким же образом как и в списке пользователей. Только исправлений в самом коде чуть меньше. Просто в конец процедуры ПриСозданииНаСервере добавил
Если ЗначениеЗаполнено(Объект.ФизЛицо) Тогда
АдресКартинки = ПоместитьВоВременноеХранилище(Объект.ФизЛицо.ОсновноеИзображение.Хранилище.Получить());
КонецЕсли;
Пример 2. Документ Реализация товаров и услуг. Ускорение оформления шапки для филиалов/магазинов. УПП/КА/УТ. Толстый клиент.
Ситуация следующая:
1. Есть магазины расположенные в разных частях города и в разных городах, но входящие в одну сеть.
2. Документы оформляются на головную организацию, а магазин указывается в качестве грузополучателя. Соответственно и адрес.
Таким образом, оператор при вводе реализации должен указать контрагента, перейти на закладу Дополнительно и указать там грузополучателя и адрес доставки. Это минимум 4 лишних щелчка мышью. Как можно облегчить ввод?
Операторы пошли легким путем. В документе указывается не головной контрагент, а грузополучатель. Это удобное, но НЕПРАВИЛЬНОЕ решение с т.з. учета.
Для решения данной проблемы пришлось подправить конфигурацию. За основу изменения была взят реквизит Головной контрагент в справочнике Контрагенты. Собственно, данный реквизит в типовых и присутствует именно для таких случаев, хотя и влияет обычно только на некоторые данные в печатных формах.
Сначала пишем следующую процедуру, которая будет вызываться при изменение контрагента в форме документе:
Процедура mavМеняемНаГоловногоКонтрагента(Док) Экспорт
Если Док.Контрагент = Док.Контрагент.ГоловнойКонтрагент Тогда
Если Не ЗначениеЗаполнено(Док.Грузополучатель) Тогда
Возврат;
КонецЕсли;
Если Док.Грузополучатель <> Док.Грузополучатель.ГоловнойКонтрагент Тогда
Сообщить("Внимание! Очистили поля Грузополучатель и Адрес доставки!",СтатусСообщения.Информация);
Док.Грузополучатель = Неопределено;
Док.АдресДоставки = "";
Док.Комментарий = "";
КонецЕсли;
Иначе
Док.Грузополучатель = Док.Контрагент;
Док.Комментарий = Док.Контрагент.Наименование;
Док.Контрагент = Док.Контрагент.ГоловнойКонтрагент;
Док.ДоговорКонтрагента = Справочники.ДоговорыКонтрагентов.ПустаяСсылка();
КонецЕсли;
КонецПроцедуры
Как видно, процедура обрабатывает 2 варианта:
1. Когда контрагент не имеет головного. В этом случае, если грузополучатель в документе стоит, то это поле, адрес доставки и комментарий очищает.
2. Когда у контрагента проставлен головной. В этом случае контрагент переносится в грузополучателя, в комментарий записывается название контрагента (чтобы в списке документов можно было сразу видеть к какому магазину относится документ), в поле Контрагент устанавливается головной контрагент, а поле договор контрагента очищается.
Данную функцию помещаем или в сам документ, или в общий модуль(как у меня). Потом изменяем в форме документа функцию на событие ПриИзменении поля Контрагент:
Процедура КонтрагентПриИзменении(Элемент)
НашМодуль.mavМеняемНаГоловногоКонтрагента(ЭтотОбъект); //mav
ПриИзмененииКонтрагента();
КонецПроцедуры // КонтрагентПриИзменении()
Но это ещё не всё. Не заполненным осталось поле АдресДоставки. Можно дописать процедуру по установке грузополучателя. Но можно и расширить применяемость процедуры по автоматическому проставлению Адреса доставки поместив вызов в процедуру ПриИзмененииКонтрагента. Процедура будет такой:
Процедура mavУстановитьАдресДоставки(Док) Экспорт
Если ЗначениеЗаполнено(Док.Грузополучатель) Тогда
ТекКонтрагент = Док.Грузополучатель;
Иначе
ТекКонтрагент = Док.Контрагент;
КонецЕсли;
Запрос = Новый Запрос();
Запрос.Текст = "ВЫБРАТЬ
| КонтактнаяИнформация.Представление
|ИЗ
| РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
|ГДЕ
| КонтактнаяИнформация.Объект = &Контрагент
| И КонтактнаяИнформация.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес)
| И КонтактнаяИнформация.ЗначениеПоУмолчанию = ИСТИНА";
Запрос.УстановитьПараметр("Контрагент",ТекКонтрагент);
Результат = Запрос.Выполнить().Выбрать();
Если Не Результат.Следующий() Тогда
Возврат;
КонецЕсли;
Если СокрЛП(Док.АдресДоставки) = СокрЛП(Результат.Представление) Тогда
Возврат;
КонецЕсли;
Если СокрЛП(Док.АдресДоставки)="" Тогда
Док.АдресДоставки = Результат.Представление;
Иначе
Если Вопрос("Изменить адрес доставки?",РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Нет Тогда
Возврат;
Иначе
Док.АдресДоставки = Результат.Представление;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В запросе отбираем конкретный адрес по владельцу (контрагент или грузополучатель, если заполнен). Дополнительно накладывается ограничение, что это будет именно адрес. Следующее условие зависит от пожеланий пользователей. Можно указать, что отбираться будет запись регистра с конкретным видом (например, Адрес доставки или Фактический адрес). В моем случае отбор решили делать по ресурсу ЗначениеПоУмолчанию. Данный ресурс обычно отвечает за то, чтобы с форме элемента Контрагента какие-то контактные данные отмечались жирным (кроме этой визуальной функции в типовых этот ресурс никаких функций не несет). Для это в форме есть кнопка Основной над таблицами с адресами и контактной информацией.
Вызов этом процедуры нужно добавить в конец процедуры формы Реализации ПриИзмененииКонтрагента.
После применения вышеперечисленных изменений получим следующий функционал при работе с документом Реализация товаров и услуг:
1. Если у контрагента указан основной адрес, то он автоматически проставляется в поле Адрес доставки.
2. Если у магазина проставить головного контрагента, то в документе можно в качестве контрагента выбирать магазин и все поле перезаполнятся в соответствии с требованиями учета. Как это работает:
- Есть магазины "Золушка" и "Белоснежка" принадлежащие ООО "Сказки". ООО "Сказки" просит указать в грузополучателе кроме ООО "Сказки" ещё и название магазина.
- Заводим 3 соответствующих контрагента с необходимыми юридическими данными и адресами. В магазинах указываем полное название ООО "Сказки" плюс название магазина. Короткое название делаем как удобно операторам. Например, Золушка и Белоснежка.
- У Золушки и Белоснежки указываем основные адреса и головного контрагента ООО "Сказки".
- Теперь при оформлении реализации можно выбрать контрагента Золушка. При этом в поле грузополучатель попадет Золушка, в поле адрес доставки её основной адрес, а контрагентом станет ООО "Сказки"...
Пример 3. Номер счет-фактуры совпадает с номером документа реализации.
Очень, знаете ли, бухгалтерии удобно когда номера счет-фактур совпадают с номерами документов. Но тут возниает несколько проблем:
- 1с реализовала счет-фактуру отдельным документом со своей нумерацией.
- Основанием счет-фактуры может быть не только реализация, но и несколько других видов документов.
Какое решение можно предложить бухгалтерии? Привязать нумерацию счет-фактуры на основании реализации к самой реализации, а для остальных случаев вести отдельную нумерацию. Что для этого нужно?
1. Подписка на событие ПриУстановкеНовогоНомера для документа Счет-фактура выданный.
2. Процедура на данное событие:
Если ЗначениеЗаполнено(Источник.ДокументОснование) И ТипЗнч(Источник.ДокументОснование) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
СтандартнаяОбработка = Ложь;
Источник.Номер = Источник.ДокументОснование.Номер;
КонецЕсли;
3. Контролируемо нарушить авто-нумерацию счет-фактур так, чтобы она не совпадала с нумерацией реализации. Например, поставить дополнительный буквенный префикс. Таким образом, все последующие счета-фактуры основанные не на реализации будут идти с доп.префиксом и нумерация будет сохранять уникальность. При печати такие счета фактуры будут выходить с префиксом и всеми нулями перед основной цифрой. Но это не страшно.
Пример 4. Возможность запускать произвольную обработку и загружать произвольные данные на компьютере пользователя при запуске 1с.
При этом обработку и загружаемые файлы можно менять уже без изменения конфигурации.
Итак. Как всегда наша задача - получить новый функционал с минимум изменений в типовом коде. В типовых конфигурациях есть замечательный регистр сведений - "Внешние компоненты". Регистр предназначен для хранения внешних компонент, которые загружаются в рабочий каталог 1с на машине пользователя при запуске 1с (кстати, в windows 7 это возможно только, если запускать 1с под администратором, что странно). Но в этот регистр можно записывать не только dll, но и любые другие файлы.
Таким образом, мы получим на компьютере пользователя любые файлы, которые можем использовать как нам нужно.
Один из вариантов использования - добавить в конфигурацию автозагрузку.
Для начала откроем модуль обычного приложения и найдем процедуру ПриНачалеРаботыСистемы() и добавляем в конец
Попытка
ИмяФайла = КаталогПрограммы()+"Autostart.epf";
Форма = ВнешниеОбработки.ПолучитьФорму(ИмяФайла);
Если Не Форма = Неопределено Тогда
Форма.Открыть();
Иначе
ВнешняяОбработка = ВнешниеОбработки.Создать(ИмяФайла);
КонецЕсли;
Исключение
Предупреждение("Не удалось запустить обработку Autostart.");
КонецПопытки;
где Autostart - это имя запускаемой обработки. Вот код такой обработки для примера, который с помощью внешней компоненты Miracle меняет задний фон и иконку в 1с:
Процедура ВизуальнаяИдентификацияБазы()
Попытка
ЗагрузитьВнешнююКомпоненту("MiracleV8.dll");
L=ПолучитьCOMОбъект("","AddIn.MiracleClass");
L.SetMainIcon(КаталогПрограммы()+"main.ico");
L.SetMDIPicture(КаталогПрограммы()+"logo.jpg");
Исключение
КонецПопытки;
КонецПроцедуры;
ВизуальнаяИдентификацияБазы();
Таким образом мы получаем быстронастраиваемый механизм автозагрузки - достаточно заменить/загрузить нужные файлы в регистре.
Пример 5. Организация складов без учета характеристик или серий (без документа Корректировка серий и характеристик номенклатуры)
Решение не отличается универсальностью, но зато очень простое.
Дано:
На предприятии есть несколько складов, где не нужен/не возможен/пока не реализован учет по сериям и характеристикам, но остальным складам он нужен. Типовое решение - документ Корректировка СиХ номенклатуры. Но тогда вместо одного документа Перемещение требуется создавать/исправлять и КСиХН.
Решение:
Для начала создадим для складов 2 категории "Не учитывать характеристики" и "Не учитывать серии".
Потом добавим в конфигураторе Подписку на событие составного типа для регистров Партии товаров на складах, товары на складах и товары организаций на событие Перед записью. И добавим следующую процедуру обработчик:
Если Источник.Количество() = 0 ИЛИ Источник[0].Период < '20110501' Тогда
Возврат;
КонецЕсли;
Запрос = Новый Запрос();
Запрос.Текст = "ВЫБРАТЬ
| КатегорииОбъектов.Объект КАК Склад
|ИЗ
| РегистрСведений.КатегорииОбъектов КАК КатегорииОбъектов
|ГДЕ
| КатегорииОбъектов.Категория.Код = &Код";
Запрос.УстановитьПараметр("Код","Ю00000009"); //серии
СкладыСерии = Запрос.Выполнить().Выгрузить();
Запрос.УстановитьПараметр("Код","Ю00000008"); //характеристики
СкладыХарактеристики = Запрос.Выполнить().Выгрузить();
Если СкладыСерии.Количество() = 0 И СкладыХарактеристики.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для Каждого ЗаписьРегистра Из Источник Цикл
Если СкладыСерии.Найти(ЗаписьРегистра.Склад,"Склад")<>Неопределено Тогда
ЗаписьРегистра.СерияНоменклатуры = Справочники.СерииНоменклатуры.ПустаяСсылка();
КонецЕсли;
Если СкладыХарактеристики.Найти(ЗаписьРегистра.Склад,"Склад")<>Неопределено Тогда
ЗаписьРегистра.ХарактеристикаНоменклатуры = Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка();
КонецЕсли;
КонецЦикла;
Пример 6. Добавляем картинки к кнопкам внешних печатных форм и заполнения табличных частей
Ищем процедуру ДобавитьСтрокуВДеревоКнопок. Обычно она находится в общем модуле УниверсальныеМеханизмы. Ищем в начале процедуры строчку
СтрокаКнопки.Имя = Имя;
и перед ней вставляем такой код
Если Не ЗначениеЗаполнено(Картинка) Тогда
Попытка
Расшифровка.ДополнительныеПараметрыОбработки.Свойство("НазваниеКартинки", Картинка);
Картинка = БиблиотекаКартинок[Картинка];
Исключение
Картинка = Неопределено;
КонецПопытки;
КонецЕсли;
Кроме того, в общей форме ФормаВыбораПечатныхФорм в таблице в основной колонке в поле Данные картинки нужно написать Картинка. Это требуется только для печатных форм. Для кнопок заполнения табличных частей в типовых уже всё стоит как надо.
В результате, если в дополнительных параметрах внешней обработки указать параметр НазваниеКартинки с строкой содержащей название картинки из библиотеки картинок
то эта картинка появится при выборе печатной формы или кнопки заполнения табличной части:
Пример 7. Выводит вес брутто в шапке табличной части Товары документа Заказ или Реализация
Добавляем в модуль формы саму процедуру
Процедура mavПосчитатьВесНажатие()
Вес = 0;
Для Каждого стр из Товары Цикл
Вес = Вес + стр.ЕдиницаИзмерения.Вес * стр.Количество;
КонецЦикла;
ЭлементыФормы.Товары.Колонки.Номенклатура.ТекстШапки = "Номенклатура. Брутто: " + Строка(Вес)+ " кг";
КонецПроцедуры
и её вызов в процедуры ПередОткрытием (формы), ТоварыПриОкончанииРедактирования(табличной части) и ОбработкаПодбора