В форме документа счет-фактура выданный аванс заполнить табличную часть Авансы на основании документа поступление безналичных денежных средств.
Условия:
1) Перед заполнением табличной части документа получить от пользователя подтверждение на это действие;
2) Обработку создания документа сделать внешней и подключаемой к форме документа счет-фактура на аванс выданный;
3) После заполнения табличной части не записывать документ, а разрешить пользователю продолжить редактирование изменной табличной части или самостоятельно записать документ.
Решение:
Пункты 1 и 2 не представляют особой сложности, но пункт 3 заставил меня задуматься и написать, по-моему мнению, топорный, но исправно действующий код.
Понятно, что от нас требуется создать внешнюю обработку вида "ЗаполнениеОбъекта" и подключить её в информационную базу.
Приведу код в модуле обработки:
Код 1C v 8.2 УП Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
МассивНазначений = Новый Массив;
МассивНазначений.Добавить("Документ.СчетФактураВыданныйАванс");
ПараметрыРегистрации.Вставить("Вид", "ЗаполнениеОбъекта");
ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
ПараметрыРегистрации.Вставить("Наименование", "Заполнить документ");
ПараметрыРегистрации.Вставить("Версия", "1.0");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина);
ПараметрыРегистрации.Вставить("Информация", "Дополнительная обработка табличной части к документу счет-фактура выданный аванс");
ТаблицаКоманд = ПолучитьТаблицуКоманд();
ДобавитьКоманду(ТаблицаКоманд,
"Заполнить документ",
"Заполнить документ",
"ВызовКлиентскогоМетода",
Истина);
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
Функция ПолучитьТаблицуКоманд()
Команды = Новый ТаблицаЗначений;
Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
Возврат Команды;
КонецФункции
Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = Представление;
НоваяКоманда.Идентификатор = Идентификатор;
НоваяКоманда.Использование = Использование;
НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
НоваяКоманда.Модификатор = Модификатор;
КонецПроцедуры
Так как нам придется работать с формами объектов мы просто вынуждены использовать метод ВызовКлиентскогоМетода для вызова команды внешней обработки.
Напомню, при использовании ВызовСерверногоМетода с формами объектов работать не получится.
Так как мы использовали ВызовКлиентскогоМетода, то обязательную процедуру, для внешней подключаемой обработки заполнения объектов, ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт, необходимо выполнять &НаКлиенте в модуле формы обработки, а значит создадим любую форму обработки, пользователь её всеравно не увидит, и поместим внутрь модуля формы следующий код:
Код 1C v 8.2 УП &НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
//Спросим у пользователя разрешение на продолжение обработки
Режим = РежимДиалогаВопрос.ДаНет;
Текст = "Текущие данные документа будут заменены новыми без возможности восстановления.
|Продолжить?";
Ответ = Вопрос(Текст, Режим, 0);
Если Ответ = КодВозвратаДиалога.Да Тогда
//Если пользователь дал разрешение на продолжение, то начнем перебирать все
//документы, у которых мы планируем заполнить табличную часть
Для каждого Элемент из ОбъектыНазначенияМассив Цикл
//Зададим ключ поиска документа, из которого вызвана данная обработка,
//чтобы получить ссылку на редактирумый документ в удобном виде для
//функции ОткрытьФорму()
КлючПоиска = Новый Структура("Ключ", Элемент);
//Но нам не надо открывать новую форму (окно) для изменяемого документа, а
//Нам надо все изменения показать в уже открытых у клиента окнах
Окна = ПолучитьОкна();
Для каждого Окно из Окна Цикл
//Окно изменяемого документа будет точно не основным, а вспомогательным, поэтому
//сразу пропускаем основное окно, а далее идем на не очень хороший способ поиска открытого окна
//изменяемого документа. Мы просто переберем все окна, а в заголовке, которых будет встречаться
//Наименование, номер и дата нужного документа - будем изменять
Если НЕ Окно.Основное
И Найти(Окно.Заголовок, Элемент) Тогда
//Передадим ключ поиска (можно сказать ссылку на объект) и данные о найденном открытом окне
//в функцию ОткрытьФорму()
//Код находится в цикле на тот случай, если открытых окон изменяемого документа больше одного
Форма = ОткрытьФорму("Документ.СчетФактураВыданныйАванс.Форма.ФормаДокумента",КлючПоиска,,,Окно);
//Далее мы получаем объект только, что повторно открытой формы и помещаем её в переменную
//В объекте содержатся все реквизиты (элементы) формы
НовыйОбъект = Форма.Объект;
//Мы помещаем объект формы в переменную,
//так как должны передать её в процедуру на сервере,
//где нельзя изменять объект формы, зато можно править переменную содержащую его
ЗаполнитьОбъект(НовыйОбъект);
//После выполнения процедуры на сервере мы получаем изменную переменную НовыйОбъект,
//которую необходимо передать в уже полученную нами форму
КопироватьДанныеФормы(НовыйОбъект, Форма.Объект);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Ниже приведу код, который у вас может быть совершенно другим и делать, какие-либо другие манипуляции с объектом формы:
Код 1C v 8.2 УП &НаСервере
Функция ЗаполнитьОбъект(НовыйОбъект)
Если ТипЗнч(НовыйОбъект.ДокументОснование) = Тип("ДокументСсылка.ПоступлениеБезналичныхДенежныхСредств") Тогда
Если НовыйОбъект.ДокументОснование.РасшифровкаПлатежа.Количество() > 0 Тогда
НовыйОбъект.Авансы.Очистить();
КонецЕсли;
Для каждого СтрокаТЧ из НовыйОбъект.ДокументОснование.РасшифровкаПлатежа Цикл
НоваяСтрока = НовыйОбъект.Авансы.Добавить();
Если ЗначениеЗаполнено(СтрокаТЧ.СчетНаОплату) Тогда
НоваяСтрока.Содержание = "Предварительная оплата" + ФормированиеПечатныхФорм.СформироватьЗаголовокДокумента(СтрокаТЧ.СчетНаОплату, НСтр("ru=' по счету на оплату'"));
КонецЕсли;
НоваяСтрока.Сумма = СтрокаТЧ.Сумма;
НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС18_118;
ТекПроцентНДС = ЦенообразованиеКлиентСервер.ПолучитьСтавкуНДСЧислом(НоваяСтрока.СтавкаНДС);
НоваяСтрока.СуммаНДС = ЦенообразованиеКлиентСервер.РассчитатьСуммуНДС(НоваяСтрока.Сумма, ТекПроцентНДС);
КонецЦикла;
КонецЕсли;
КонецФункции
Автор
ApocalypseNTC В том случае, когда в каком-то регистре сведений нужно заменить несколько видов значений какого-то конкретного ресурса на заданное значение, лучше использовать вот такую универсальную процедуру (при ее вызове достаточно подставить название регистра, название ресурса и передать старые заменяемые значения и новое, на которое они заменяются):
Код 1C v 8.х // Процедура выполняет в независимом регистре сведений "ИмяРегистраСведений" замену
// всех значений ресурса "ИмяИзменяемогоРесурса", // соответствующих массиву "МассивСтарыхЗначенийРесурса"
// на новое значение ресурса "НовоеЗначениеРесурса".
// В запрос можно передать дополнительное условие, ограничивающее выборку данных из регистра "ДопУсловие"
Процедура ЗаменаРесурсаНезависимогоРегистра(ИмяРегистраСведений, ИмяИзменяемогоРесурса, МассивСтарыхЗначенийРесурса, НовоеЗначениеРесурса, ДопУсловие = "")
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("МассивСтарыхЗначенийИзмерения", МассивСтарыхЗначенийРесурса);
Запрос.УстановитьПараметр("НовоеЗначениеИзмерения", НовоеЗначениеРесурса);
// Подготовим таблицу значений для позиционирования (установки отбора) на нужных записях регистра:
Запрос.Текст =
"ВЫБРАТЬ *
|ИЗ
| РегистрСведений." + ИмяРегистраСведений + " КАК Регистр
|ГДЕ
| Регистр." + ИмяИзменяемогоРесурса + " В (&МассивСтарыхЗначенийИзмерения)" + ДопУсловие;
Сообщить("1 Приступаем к выполнению запроса к данным регистра """ + ИмяРегистраСведений + """ - " + ТекущаяДата());
ТаблицаЗаполнения = Запрос.Выполнить().Выгрузить();
Сообщить("2 Приступаем к обработке результата запроса к регистру """ + ИмяРегистраСведений + """ - " + ТекущаяДата());
// заполнение строки progress bar
ЭлементыФормы.Индикатор2.Значение = 0; // обнуляем, чтобы при повторном запуске статусбар сбросился в 0
ЭлементыФормы.Индикатор2.МаксимальноеЗначение = ТаблицаЗаполнения.Количество(); // задаем значение для 100%
// для каждой строки таблицы значений установим отбор и перезапишем регистр
Для Каждого СтрокаЗаполнения Из ТаблицаЗаполнения Цикл
ЭлементыФормы.Индикатор2.Значение = ЭлементыФормы.Индикатор2.Значение + 1; //указываем прирост внутри цикла
// попробуем через СоздатьМенеджерЗаписи()
текЗапись = РегистрыСведений[ИмяРегистраСведений].СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(текЗапись, СтрокаЗаполнения);
// прочитаем эту запись (внимание, эта команда обязательна, иначе можно ненароком очистить весь регистр!)
текЗапись.Прочитать();
Если текЗапись.Выбран() Тогда // убедились, что спозиционироваться удалось
// сообщаем, что именно и на какое значение нужно изменить в регистре
текЗапись[ИмяИзменяемогоРесурса] = НовоеЗначениеРесурса;
// записываем изменения в регистре
текЗапись.Записать();
Иначе // спозиционироваться не удалось, можно выходить
Сообщить("Возникла проблема определения " + НовоеЗначениеРесурса + " в регистре через менеджер записи " + НовоеЗначениеРесурса);
КонецЕсли;
КонецЦикла;
Сообщить("3 Окончание исправления регистра """ + ИмяРегистраСведений + """ - " + ТекущаяДата());
КонецПроцедуры // ЗаменаИзмеренияНезависимогоРегистра()