Динамические колонки в ТЧ

Версия для печатиPDF-версия

Платформа:

Есть документ, в котором етсь табличная часть с тремя колонками и есть определенный ИЗМЕНЯЕМЫЙ список значений (например складов). Не могу добавить в табличную часть колонки с названием склада

&НаСервере
Процедура СоздатьСписокСкладовВСетке()
 
нРеквизиты = Новый Массив;
Для Каждого Стр Из Объект.СписокСкладов Цикл
ИдентификаторРеквизита =  СтрЗаменить(Строка(Стр.СкладМагазин.ВерсияДанных),"=","");
ИмяМагазина = Стр.СкладМагазин.Наименование;
нРеквизиты.Добавить(Новый РеквизитФормы(ИдентификаторРеквизита, Новый ОписаниеТипов("Строка"),"Объект.Товары",ИмяМагазина,Истина));
КонецЦикла;
 
ИзменитьРеквизиты(нРеквизиты);
 
Для Сч = 1 По нРеквизиты.Количество() Цикл
нЭлемент     = Элементы.Добавить(Сч, Тип("ПолеФормы"),Элементы.Товары);
нЭлемент.Вид = ВидПоляФормы.ПолеВвода;
ПутьКОбъектуДляЭлемента = СокрЛП("Объект.Товары."+Сч); 
нЭлемент.ПутьКДанным    = ПутьКОбъектуДляЭлемента;
 
КонецПроцедуры
 
Подскажите пожалуйста, как исправить

Боюсь, что к табличной части новые колонки добавить не получится. Да и зачем это?

Новые колонки добавляются, но если это один случай добавления реквизитов - уже попробовал, а вот если по списку складов - идентификатор колонки ведь программно добавляю, и вот тут получается затык( 

А нужно это для того, чтобы сделать расчетный документ со временными значениями. Хотя потом планирую сделать сохранение данных из этих временных колонок в таблицузначений и при последующем открытии  восстановление их же и значений из них

Вопрос в догонку - ВерсияДанных изменяемое значение или постоянное?

В чём затык с добавлением идентификатора колонки?

Реквизит СписокСкладов какой тип имеет?

Что значит ИмяДанных - имя реквизита или путь к данным? В принципе и то, и другое изменяемые.

Реквизит СписокСкладов - это вторая тч в документе, предварительно заполненная

ИмяДанных - это в массиве колонка.

В принципе - получилось следующее:

нРеквизиты = Новый Массив;
Для Каждого Стр Из Объект.СписокСкладов Цикл
ВрИдентификаторРеквизита =  СтрЗаменить(Строка(Стр.СкладМагазин.Наименование)," ","_");
ИдентификаторРеквизита = СтрЗаменить(ВрИдентификаторРеквизита,"""","");
ИмяМагазина = Стр.СкладМагазин.Наименование;
нРеквизиты.Добавить(Новый РеквизитФормы(ИдентификаторРеквизита, Новый ОписаниеТипов("Строка"),"Объект.Товары",ИмяМагазина,Истина));
КонецЦикла;
 
ИзменитьРеквизиты(нРеквизиты);
 
Для Сч = 1 По нРеквизиты.Количество() Цикл
нЭлемент     = Элементы.Добавить(Сч, Тип("ПолеФормы"),Элементы.Товары); //в этой строке как-то надо добраться до ИдентификаторРеквизита - он будет идентификатор колонки, вместо сч (временно поставил)
нЭлемент.Вид = ВидПоляФормы.ПолеВвода;
ПутьКОбъектуДляЭлемента = СокрЛП("Объект.Товары."+Сч); // соответсвенно и тут
нЭлемент.ПутьКДанным    = ПутьКОбъектуДляЭлемента;
КонецЦикла
 
 

Так сделайте перебор массива нРеквизиты во втором цикле:

Для Каждого Реквизит Из нРеквизиты Цикл
    нЭлемент     = Элементы.Добавить(Реквизит.Имя, Тип("ПолеФормы"), Элементы.Товары);
    нЭлемент.Вид = ВидПоляФормы.ПолеВвода;
    ПутьКОбъектуДляЭлемента = СокрЛП("Объект.Товары." + Реквизит.Имя);
    нЭлемент.ПутьКДанным    = ПутьКОбъектуДляЭлемента;
КонецЦикла

Спасибо огромное, счас попробую :)

//Я не волшебник еще, я просто учусь (с)

Только наверное не "реквизит",  а как-нибудь типа "нРеквизит". Ругается что итератор не определен иначе

С нРеквизит работает?

Да, с нРеквизит заработало. Я еще чуть переделал - сделал проверку на заполненность массива - а то если "случайно" нажать кнопку с командой ругается на неуникальность реквизитов табличной части)

По идее надо сначала удалять ранее созданные реквизиты, а потом создавать заново. Я так понимаю, список складов изменяется пользователем интерактивно?

Все верно. изменяется интерактивно. 

&НаСервере
Процедура НаСервереСоздатьСписокСкладовВСетке()
 
нРеквизиты = Новый Массив;
 
Для Каждого Стр Из Объект.СписокСкладов Цикл
          ВрИдентификаторРеквизита =  СтрЗаменить(Строка(Стр.СкладМагазин.Наименование)," ","_");
          ИдентификаторРеквизита = СтрЗаменить(ВрИдентификаторРеквизита,"""","");
          ИмяМагазина = Стр.СкладМагазин.Наименование;
          нРеквизиты.Добавить(Новый РеквизитФормы(ИдентификаторРеквизита, Новый ОписаниеТипов("Строка"),"Объект.Товары",ИмяМагазина,Истина));
КонецЦикла;
 
ИзменитьРеквизиты(нРеквизиты);
 
Для Каждого нРеквизит Из нРеквизиты Цикл
         нЭлемент     = Элементы.Добавить(нРеквизит.Имя, Тип("ПолеФормы"),Элементы.Товары);
         нЭлемент.Вид = ВидПоляФормы.ПолеВвода;
         ПутьКОбъектуДляЭлемента = СокрЛП("Объект.Товары."+нРеквизит.Имя); 
         нЭлемент.ПутьКДанным    = ПутьКОбъектуДляЭлемента;
КонецЦикла
// Видимо сюда ИзменитьРеквизиты(,нРеквизиты);
КонецПроцедуры
 
&НаКлиенте
Процедура СоздатьСписокСкладовВСетке(Команда)
Оповещение = Новый ОписаниеОповещения("ВыполнитьПослеЗакрытияВопроса", ЭтотОбъект);
 
ПоказатьВопрос(Оповещение, "Колонки со складами будут пересозданы, данные будут очищены!!!?",
              РежимДиалогаВопрос.ДаНетОтмена, 0, // таймаут в секундах
              КодВозвратаДиалога.Да,              // (необ.) кнопка по умолчанию
              "ВНИМАНИЕ!!!"                       // (необ.) заголовок
              );
НаСервереСоздатьСписокСкладовВСетке();
КонецПроцедуры
 
 
&НаКлиенте
Процедура ВыполнитьПослеЗакрытияВопроса(Результат, Параметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        Сообщить("Табличная часть распределительной сетки очищена и переформирована!");
    КонецЕсли;
КонецПроцедуры
 
Вот что получилось. Убрал проверку на заполнение массива - всеравно не срабатывает... :( Я так понимаю, что надо очищать список добавленных реквизитов путем добавления строки:
ИзменитьРеквизиты(,нРеквизиты);

Как вариант можно создать 2 реквизита формы: ДобавленныеРеквизиты и ДобавленныеЭлементы с типом значения Список значений.

В начало процедуры НаСервереСоздатьСписокСкладовВСетке() добавить такой код:

	Для Каждого ДобЭлемент Из ДобавленныеЭлементы Цикл 
		Элементы.Удалить(Элементы[ДобЭлемент.Значение]);
	КонецЦикла;
	
	Если ДобавленныеРеквизиты.Количество() Тогда
		ИзменитьРеквизиты(, ДобавленныеРеквизиты.ВыгрузитьЗначения());
		ДобавленныеРеквизиты.Очистить();
	КонецЕсли;

В цикл добавления реквизитов добавить строчку:

ДобавленныеРеквизиты.Добавить("Объект.Товары." + ИдентификаторРеквизита);

А в цикл добавления элементов:

ДобавленныеЭлементы.Добавить(нРеквизит.Имя);

Алексей, прошу прощения... 2 реквизита формы добавляются в? То есть если открыть форму документа на редактирование то я вижу 3 окна. В первом  Сверху/Слева- перечень элементов с закладками "Элементы" и "Командный интерфейс" во втором Сверху/Справа Перечень Реквизиты/Команды/Параметры и Внизу/Посередине большое окно. Соотвественно мне добавлять сверху/справа? :)а то что-то я туплю с ночи-то

Всё верно. Сверху справа на вкладке "Реквизиты". Там сейчас должен быть 1 реквизит - Объект.

Разобрался) Сверху/справа :)

Вот так выглядит

Форма документа

Оно самое.

Млин. собственно эпопея продолжилась( Хочелось бы, чтобы значения внесенные в колонки сохранялись, не очищались при сохранении и восстанавливались при открытии документа, воюю третий день но нифига не получается.

Еще, если нажать кнопку с командой создания динамических колонок повторно, в отладчике заметил, что реквизиты дублируются а в третье нажатие вылетает ошибка об неуникальности реквизитов :(

 

По поводу сохранения данных.

Можно добавить ещё одну табличную часть и хранить в ней таблицу в разобранном состоянии: для каждого склада из сводной таблицы добавлять отдельную строку в эту табличную часть. Задействовать эту табличную часть только при сохранении и чтении данных. Интерактивно работать с таблицей формы. Такой принцип реализован в типовых конфигурациях в документе Установка цен номенклатуры.

Другой способ: добавить реквизит документа с типом Хранилище значения. При сохранении данных помещать туда данные таблицы, а при чтении - получать их.

По поводу создания реквизитов формы.

Проверяли отладчиком удаление ранее созданных реквизитов перед пересозданием?

Проверял, там это так выглядит:

&НаСервере
Процедура ДобавитьДинамическиеКолонкиПоСпискуСкладовНаСервере()
 
 
//Удалим добавленные элементы динамических реквизитов, если есть
Для Каждого ДобЭлемент Из ДобавленныеЭлементы Цикл
Элементы.Удалить(Элементы[ДобЭлемент.Значение]);
КонецЦикла;
 
 
//Удалим сами динамические реквизиты, если есть
Если ДобавленныеРеквизиты.Количество() Тогда
ИзменитьРеквизиты(,ДобавленныеРеквизиты.ВыгрузитьЗначения());
ДобавленныеРеквизиты.Очистить();
КонецЕсли;
 
//Создадим новые динамические реквизиты
нРеквизиты = Новый Массив;
Для Каждого Стр Из Объект.Магазины Цикл
 
ВрИдентификаторРеквизита = СтрЗаменить(Строка(Стр.СкладМагазин.Наименование)," ","_"); //Заменим пробелы в наименовании магазина на нижнее подчеркивание
ИдентифкаторРеквизита    = СтрЗаменить(ВрИдентификаторРеквизита,"""","");              //Уберем ковычки  в наименовании магазина на нижнее подчеркивание
ИмяМагазина              = Стр.СкладМагазин.Наименование;                              //Сформируем заголовок колонки динамической таблицы
нРеквизиты.Добавить(Новый РеквизитФормы(ИдентифкаторРеквизита, Новый ОписаниеТипов("Число"),"Объект.Сетка",ИмяМагазина,Истина));//Добавить реквизит
   ДобавленныеРеквизиты.Добавить("Объект.Сетка." + ИдентифкаторРеквизита);                //Добавим сформированный реквизит в список значений для дальнейшего пользования
 
КонецЦикла;
 
ИзменитьРеквизиты(нРеквизиты);  //Добавим реквизиты
 
//Добавим элементы реквизитов
Для Каждого нРеквизит Из нРеквизиты Цикл
 
нЭлемент     = Элементы.Добавить(нРеквизит.Имя, Тип("ПолеФормы"), Элементы.Сетка); //
нЭлемент.Вид = ВидПоляФормы.ПолеВвода;                                             //Определим вид элемента
ПутьКОбъектуДляЭлемента = СокрЛП("Объект.Сетка." + нРеквизит.Имя);                 //Сформируем путь к элементу
нЭлемент.ПутьКДанным    = ПутьКОбъектуДляЭлемента;                                 //Добавим элемент
ДобавленныеЭлементы.Добавить(нРеквизит.Имя);
 
КонецЦикла;
 
КонецПроцедуры
 

После цикла удаления элементов добавьте строку:

ДобавленныеЭлементы.Очистить();

В остальном вроде всё логично.

Ага, вроде получилось. Спасибо

Алексей, понимаю, что Вас уже замучал, но не можете ли вы мне подсказать, как сделать так, чтобы данные из динамических колонок сохранялись и восстанавливались при открытии документа? 

Так я уже писал выше: либо добавить специальную табличную часть для этого (с дополнительными колонками "Склад" и "ИдентификаторСтроки"; при сохранении сводную таблицу разбивать на отдельные строки для каждого склада, при открытии - собирать сводную таблицу), либо добавить реквизит документа с типом Хранилище значения и хранить в нём данные таблицы.

Я дополнительные колонки Склад и КлючСтроки добавил, не могу справиться с их заполнением и восстановлением значений из них

В КлючСтроки помещаете номер строки сводной таблицы, в Склад - соответственно, склад либо имя реквизита (колонки). Для сопоставления колонок складам можно использовать СписокСкладов. Только проще будет при создании реквизитов (колонок) присваивать им имена не по наименованию склада, а "Склад" + порядковый номер в списке складов. Тогда колонки легко сопоставить со складами. Либо надо создавать соответствие с именами колонок и складами.

При сохранении документа для каждой строки сводной таблицы создаёте по строке на каждый склад. Заполняете КлючСтроки, Склад, Количество.

При открытии (точне ПриСозданииНаСервере) создаёте дополнительные колонки для складов. Обходите таблицу, в которой хранятся товары (или документы; не знаю, что там у вас). По номеру строки делаете отбор строк во вспомогательной ТЧ и заполняете по ним строку сводной таблицы.

Может немного сумбурно написал, но смысл должен быть понятен.

Лучше с именами складов- не дай бог передвинут склад по строке вверх или вниз и все - сетка неверна уже

Страницы