Если вы занимаетесь разработкой в системе 1С:Предприятие 8, то наверняка знаете про функцию ЗаполнитьЗначенияСвойств(), с помощью которой можно очень быстро заполнить достаточно большие объекты. Причем объекты самые разные - структуры, таблицы и деревья значений, справочники, документы и др.
При параллельной разработке в предыдущей версии - 1С:Предприятии 7.7, когда приходится писать большие объемы программного кода, остро приходит понятие - какой же удобной функции не хватает.
Попробуем это исправить!
Итак, сценарий следующий - нужно заставить работать функцию ЗаполнитьЗначенияСвойств() в правилах конвертации, которые можно разработать с помощью 1С:Конвертация данных, ред. 2.1. Оговоримся - источником должна быть конфигурация на платформе 1С:Предприятие 7.7. Важно знать, что алгоритмы, которые разрабатываются с помощью конвертации, реализованы в виде функций, которые затем будут перенесены в обработку выгрузки. Исходя из этого, приступим.
Свойства, которые нужно будет заполнить, или наоборот - исключить из заполнения будут передаваться с помощью строки с разделителями. Разделитель - запятая. С помощью этого алгоритма строка будет раскладываться в список значений.
Стр = ИсходящиеДанные; Разделитель = ?(ЗначениеЗаполнено(ВходящиеДанные) = 1, ВходящиеДанные, ","); Результат = СоздатьОбъект("СписокЗначений"); Если ПустаяСтрока(ИсходящиеДанные) = 1 Тогда Возврат Результат; ИначеЕсли Найти(ИсходящиеДанные, Разделитель) = 0 Тогда Результат.ДобавитьЗначение(ИсходящиеДанные); Возврат Результат; КонецЕсли; Если Разделитель = " " Тогда Стр = СокрЛП(Стр); Пока 1=1 Цикл Поз = Найти(Стр, Разделитель); Если Поз=0 Тогда Результат.ДобавитьЗначение(СокрЛП(Стр)); Возврат Результат; КонецЕсли; Результат.ДобавитьЗначение(СокрЛП(Лев(Стр, Поз-1))); Стр = СокрЛ(Сред(Стр, Поз)); КонецЦикла; Иначе ДлинаРазделителя = СтрДлина(Разделитель); Пока 1=1 Цикл Поз = Найти(Стр, Разделитель); Если Поз=0 Тогда Результат.ДобавитьЗначение(СокрЛП(Стр)); Возврат Результат; КонецЕсли; Результат.ДобавитьЗначение(СокрЛП(Лев(Стр, Поз-1))); Стр = Сред(Стр,Поз+ДлинаРазделителя); КонецЦикла; КонецЕсли; Возврат Результат;
Рабочий алгоритм. Синтаксис - тот же, что и в 1С:Предприятии 8, позволяет заполнять справочники, документы, списки и таблицы значений.
// Выполняет заполнение приемника по данным источника. // // Параметры: // ДанныеПриемник - Произвольный, справочник, документ, список значений, индексированная таблица или таблица значений. // ДанныеИсточник - Произвольный, справочник, документ, список значений, индексированная таблица или таблица значений. // СписокСвойствСтрока - Строка, список свойств, разделенных запятыми. // ИсключаяСвойстваСтрока - Строка, список исключаемых свойств, разделенных запятыми. // // Возвращаемое значение: // Число, 1 - если заполнение выполнено успешно, 0 - не удалось выполнить заполнение. ДанныеПриемник = ИсходящиеДанные; ДанныеИсточник = ВходящиеДанные; СписокСвойствСтрока = Источник; ИсключаяСвойстваСтрока = Приемник; ТипКоллекцииПриемник = ТипЗначенияСтр(ДанныеПриемник); ТипКоллекцииИсточник = ТипЗначенияСтр(ДанныеИсточник); /////////////////////////////////////////////////////////////////////////////// // Список свойств коллекции Если ТипКоллекцииПриемник = "СписокЗначений" Тогда КоллекцияПоставщикСвойств = ДанныеИсточник; ИначеЕсли (ТипКоллекцииПриемник = "ТаблицаЗначений") ИЛИ (ТипКоллекцииПриемник = "ИндексированнаяТаблица") Тогда Если ДанныеПриемник.КоличествоСтрок() = 0 Тогда Возврат 0; КонецЕсли; КоллекцияПоставщикСвойств = ДанныеПриемник; ИначеЕсли (ТипКоллекцииПриемник = "Справочник") ИЛИ (ТипКоллекцииПриемник = "Документ") Тогда КоллекцияПоставщикСвойств = ДанныеПриемник; Иначе Возврат 0; КонецЕсли; ТипКоллекцииПоставщик = ТипЗначенияСтр(КоллекцияПоставщикСвойств); ПоляКоллекции = СоздатьОбъект("СписокЗначений"); Если (ТипКоллекцииПоставщик = "ТаблицаЗначений") ИЛИ (ТипКоллекцииПоставщик = "ИндексированнаяТаблица") Тогда Если ПустаяСтрока(СписокСвойствСтрока) = 1 Тогда ИсключаяСвойства = РазложитьСтрокуВМассивПодстрок(ИсключаяСвойстваСтрока); Для НомерКолонки = 1 По КоллекцияПоставщикСвойств.КоличествоКолонок() Цикл Если ТипКоллекцииПоставщик = "ТаблицаЗначений" Тогда Колонка = КоллекцияПоставщикСвойств.ПолучитьПараметрыКолонки(НомерКолонки); ИначеЕсли ТипКоллекцииПоставщик = "ИндексированнаяТаблица" Тогда Колонка = КоллекцияПоставщикСвойств.ИмяКолонки(НомерКолонки); КонецЕсли; Если ПустаяСтрока(ИсключаяСвойстваСтрока) = 0 Тогда Если ИсключаяСвойства.Принадлежит(Колонка) = 1 Тогда Продолжить; КонецЕсли; КонецЕсли; ПоляКоллекции.ДобавитьЗначение(Колонка); КонецЦикла; Иначе СписокСвойств = РазложитьСтрокуВМассивПодстрок(СписокСвойствСтрока); Для НомерПоля = 1 По СписокСвойств.РазмерСписка() Цикл Колонка = СписокСвойств.ПолучитьЗначение(НомерПоля); Если ЕстьКолонкаТаблицыЗначений(КоллекцияПоставщикСвойств, Колонка) = 1 Тогда ПоляКоллекции.ДобавитьЗначение(Колонка); КонецЕсли; КонецЦикла; КонецЕсли; ИначеЕсли ТипКоллекцииПоставщик = "СписокЗначений" Тогда СписокСвойств = РазложитьСтрокуВМассивПодстрок(СписокСвойствСтрока); ИсключаяСвойства = РазложитьСтрокуВМассивПодстрок(ИсключаяСвойстваСтрока); Для Ном = 1 По КоллекцияПоставщикСвойств.РазмерСписка() Цикл ИмяСвойства = ""; Значение = КоллекцияПоставщикСвойств.ПолучитьЗначение(Ном, ИмяСвойства); Если ПустаяСтрока(ИмяСвойства) = 1 Тогда Продолжить; КонецЕсли; Если ПустаяСтрока(СписокСвойствСтрока) = 1 Тогда Если ПустаяСтрока(ИсключаяСвойства) = 0 Тогда Если ИсключаяСвойства.Принадлежит(ИмяСвойства) = 1 Тогда Продолжить; КонецЕсли; КонецЕсли; ПоляКоллекции.ДобавитьЗначение(ИмяСвойства); Иначе Если СписокСвойств.Принадлежит(ИмяСвойства) = 1 Тогда ПоляКоллекции.ДобавитьЗначение(ИмяСвойства); КонецЕсли; КонецЕсли; КонецЦикла; ИначеЕсли (ТипКоллекцииПоставщик = "Справочник") ИЛИ (ТипКоллекцииПоставщик = "Документ") Тогда Если ТипКоллекцииПоставщик = "Справочник" Тогда ВидСправочника = КоллекцияПоставщикСвойств.Вид(); МетаданныеСправочника = Метаданные.Справочник(ВидСправочника); // Реквизиты Для Ном = 1 По МетаданныеСправочника.Реквизит() Цикл ПоляКоллекции.ДобавитьЗначение(МетаданныеСправочника.Реквизит(Ном).Идентификатор); КонецЦикла; Иначе ВидДокумента = КоллекцияПоставщикСвойств.Вид(); МетаданныеДокумента = Метаданные.Документ(ВидДокумента); // Общие реквизиты Для Ном = 1 По Метаданные.ОбщийРеквизитДокумента() Цикл ПоляКоллекции.ДобавитьЗначение(Метаданные.ОбщийРеквизитДокумента(Ном).Идентификатор); КонецЦикла; // Реквизиты шапки Для Ном = 1 По МетаданныеДокумента.РеквизитШапки() Цикл ПоляКоллекции.ДобавитьЗначение(МетаданныеДокумента.РеквизитШапки(Ном).Идентификатор); КонецЦикла; КонецЕсли; Если ПустаяСтрока(СписокСвойствСтрока) = 1 Тогда ИсключаяСвойства = РазложитьСтрокуВМассивПодстрок(ИсключаяСвойстваСтрока); Для Ном = 1 По ИсключаяСвойства.РазмерСписка() Цикл ИмяСвойства = ИсключаяСвойства.ПолучитьЗначение(Ном); Если ПоляКоллекции.Принадлежит(ИмяСвойства) = 1 Тогда Поз = ПоляКоллекции.НайтиЗначение(ИмяСвойства); ПоляКоллекции.УдалитьЗначение(Поз); КонецЕсли; КонецЦикла; Иначе НовыеПоляКоллекции = СоздатьОбъект("СписокЗначений"); СписокСвойств = РазложитьСтрокуВМассивПодстрок(СписокСвойствСтрока); Для НомерПоля = 1 По ПоляКоллекции.РазмерСписка() Цикл ИмяСвойства = ПоляКоллекции.ПолучитьЗначение(НомерПоля); Если СписокСвойств.Принадлежит(ИмяСвойства) = 1 Тогда НовыеПоляКоллекции.ДобавитьЗначение(ИмяСвойства); КонецЕсли; КонецЦикла; ПоляКоллекции = НовыеПоляКоллекции; КонецЕсли; КонецЕсли; /////////////////////////////////////////////////////////////////////////////// // Заполнение источника данными приемника Для НомерСвойства = 1 По ПоляКоллекции.РазмерСписка() Цикл ИмяСвойства = ПоляКоллекции.ПолучитьЗначение(НомерСвойства); ЗначениеСвойства = ""; Если ТипКоллекцииИсточник = "СписокЗначений" Тогда ЗначениеСвойства = ДанныеИсточник.Получить(ИмяСвойства); ИначеЕсли (ТипКоллекцииИсточник = "ТаблицаЗначений") ИЛИ (ТипКоллекцииИсточник = "ИндексированнаяТаблица") Тогда Если ЕстьКолонкаТаблицыЗначений(ДанныеИсточник, ИмяСвойства) = 0 Тогда Продолжить; КонецЕсли; ЗначениеСвойства = ДанныеИсточник.ПолучитьЗначение(ДанныеИсточник.НомерСтроки, ИмяСвойства); ИначеЕсли ТипКоллекцииИсточник = "Справочник" Тогда Если ЕстьРеквизит(ИмяСвойства, ДанныеИсточник.Вид()) = 1 Тогда ЗначениеСвойства = ДанныеИсточник.ПолучитьАтрибут(ИмяСвойства); КонецЕсли; ИначеЕсли ТипКоллекцииИсточник = "Документ" Тогда Если ЕстьРеквизитШапки(ИмяСвойства, ДанныеИсточник.Вид()) = 1 Тогда ЗначениеСвойства = ДанныеИсточник.ПолучитьАтрибут(ИмяСвойства); КонецЕсли; КонецЕсли; Если ТипЗначенияСтр(ЗначениеСвойства) = "Строка" Тогда ЗначениеСвойства = СокрЛП(ЗначениеСвойства); КонецЕсли; Если ТипКоллекцииПриемник = "СписокЗначений" Тогда ДанныеПриемник.Установить(ИмяСвойства, ЗначениеСвойства); ИначеЕсли (ТипКоллекцииПриемник = "ТаблицаЗначений") ИЛИ (ТипКоллекцииПриемник = "ИндексированнаяТаблица") Тогда Если ЕстьКолонкаТаблицыЗначений(ДанныеПриемник, ИмяСвойства) = 1 Тогда ДанныеПриемник.УстановитьЗначение(ДанныеПриемник.НомерСтроки, ИмяСвойства, ЗначениеСвойства); КонецЕсли; ИначеЕсли ТипКоллекцииПриемник = "Справочник" Тогда Если ЕстьРеквизит(ИмяСвойства, ДанныеПриемник.Вид()) = 1 Тогда ДанныеПриемник.УстановитьАтрибут(ИмяСвойства, ЗначениеСвойства); КонецЕсли; ИначеЕсли ТипКоллекцииПриемник = "Документ" Тогда Если ЕстьРеквизитШапки(ИмяСвойства, ДанныеПриемник.Вид()) = 1 Тогда ДанныеПриемник.УстановитьАтрибут(ИмяСвойства, ЗначениеСвойства); КонецЕсли; КонецЕсли; КонецЦикла; Возврат 1;
Вот и все. Теперь метод ЗаполнитьЗначенияСвойств() будет доступен в любых обработчиках разрабатываемых правил.
ТаблицаИсточник = СоздатьОбъект("ТаблицаЗначений"); ТаблицаИсточник.НоваяКолонка("Контрагент"); ТаблицаИсточник.НоваяКолонка("Договор"); ТаблицаИсточник.НоваяКолонка("Сумма"); ТаблицаИсточник.НоваяСтрока(); ТаблицаИсточник.Контрагент = "Иванов"; ТаблицаИсточник.Договор = "Договор №1 от 01.02.2014"; ТаблицаИсточник.Сумма = 1000; ТаблицаПриемник = СоздатьОбъект("ТаблицаЗначений"); ТаблицаПриемник.НоваяКолонка("Контрагент"); ТаблицаПриемник.НоваяКолонка("Договор"); ТаблицаПриемник.НоваяКолонка("Сумма"); ТаблицаПриемник.НоваяКолонка("Задолженность"); ТаблицаПриемник.НоваяСтрока(); ЗаполнитьЗначенияСвойств(ТаблицаПриемник, ТаблицаИсточник,, "Сумма,Договор");