gifts2017

Таблицы значений "&НаКлиенте" в Управляемом приложении

Опубликовал Дмитрий Тарасов (tarassov) в раздел Программирование - Практика программирования

Способ обойти ограничения платформы и передать с клиента на сервер таблицу значений. Используются возможности XDTO-сериализации

Практика программирования на платформах 7.7, 8.0, 8.1 и 8.2 (обычные формы) приучила многих из нас к широкому применению объектов ТаблицаЗначений. При переводе старых разработок на управляемые форы регулярно встает вопрос изменения алгоритмов из-за невозможности использования их на стороне клиента

Могу предложить способ, как достаточно легко обойти часть ограничений

Несмотря на то,что то для объекта ТаблицаЗначений определена Доступность: "Сервер, толстый клиент, внешнее соединение, мобильное приложение(сервер). ", известно  - "может быть сериализован в/из XDTO. Тип XDTO, соответствующий данному объекту, определяется в пространстве имен {http://v8.1c.ru/8.1/data/core}. Имя типа XDTO: ValueTable"

Используем возможность сериализации. На сервере таблицу значений опишем, получим соответствующий ей XML, передадим его как строку (или файл) на клиента, там заполним данные (почти так же как заполняли их в старых приложениях, в обычных формах), вернем на сервер и "в одно касание" получим обратно таблицу значений через СериализаторXDTO

Схема работы

1. В процедуре "НаСервере" создаем пустую таблицу значений нужной нам структуры

ТаблицаЗагрузки = Новый ТаблицаЗначений;
...
ТаблицаЗагрузки.Колонки.Добавить(...);
...

2. Сериализуем ее в XDTO и полученный XML возвращаем на клиента

ОбъектТаблицы = СериализаторXDTO.ЗаписатьXDTO(ТаблицаЗагрузки);

ЗаписьXML = Новый ЗаписьXML();
ЗаписьXML.УстановитьСтроку(); // запись в строку
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектТаблицы);
ДанныеXML = ЗаписьXML.Закрыть(); // документ готов!

3. "НаКлиенте" работаем с XML - по полученному с сервера XML (шаблону) формируем новый xml :

3.1 Шапка (заголовок и описания столбцов) та же

ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);

ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку(); // запись в строку

Пока ЧтениеXML.Прочитать() Цикл 
Если ЧтениеXML.Имя = "ValueTable" И ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
Прервать;
КонецЕсли; 
Если ЧтениеXML.Имя = "row" И ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Прервать;
КонецЕсли; 

ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
КонецЦикла;

3.2 В цикле заполняем данные строк таблицы 

Для  ....  Цикл //по строкам
 
ЗаписьXML.ЗаписатьНачалоЭлемента("row");

Для  ... Цикл //по колонкам

Значение = .... ;

СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Значение, "Value", "http://www.w3.org/2001/XMLSchema-instance",НазначениеТипаXML.Явное);

КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента();

КонецЦикла;

3.3 Завершаем запись XML c данными

ЗаписьXML.ЗаписатьКонецЭлемента(); //ValueTable

ЧтениеXML.Закрыть();

СтрокаXML = ЗаписьXML.Закрыть(); // документ готов!

3.4 корректируем структуру XML (к моему большому сожалению, иначе пока не получилось )

СтрокаXML = СтрЗаменить(СтрокаXML, "xsi:Value", "Value");

Может быть, кто-нибудь подскажет, как без этого обойтись и заставить СериализаторXDTO.ЗаписатьXML сразу создавать записи вида 

<Value xsi:type="xs:string">1</Value>

в то время как сейчас 1С мне возвращает 

<xsi:Value xsi:type="xs:string">1</xsi:Value>

что потом не может быть прочитано в XDTO 

4. Полученный таким образом XML передаем на сервер и там получаем из него требуемую таблицу значений

&НаСервере
Процедура ЗагрузитьНаСервере(СтрокаXML)

    ЧтениеXML = Новый ЧтениеXML();
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
    ТаблицаЗагрузки = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
    ....
КонецПроцедуры

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Никита Грызлов (nixel) 27.09.16 01:06
Чём не устраивает массив структур?
TreeDogNight; slawanix; sulfur17; Lok`Tar; shard; CherryCold; 7OH; Dementor; Gorus; kirillkr; olbu; +11 Ответить 1
2. Максим Кузнецов (Makushimo) 27.09.16 05:56
(1) nixel,
Да ладно ))
Это ж прикольно.
только отладить такой код на клиенте трудновато будет.
3. Михаил Ветров (l1ike) 27.09.16 09:56
Может быть, кто-нибудь подскажет, как без этого обойтись и заставить СериализаторXDTO.ЗаписатьXML сразу создавать записи вида
<Value xsi:type="xs:string">1</Value>

Попробуйте сериализатору указать либо пустое пространство имен, либо пространство имен по умолчанию
4. Алексей Апанасович (Aphanas) 27.09.16 10:22
Можно сделать еще лучше. Выдернуть схему {http://v8.1c.ru/8.1/data/core} ValueTable из стандартной фабрики, десериализовать XDTO на клиенте и работать нормально как с объектом без всяких ЧтениеXML и ЗаписьXML.
swiss-garant; dour-dead; +2 Ответить
5. bulpi bulpi (bulpi) 27.09.16 11:30
А гланды рвать не пробовали ? :)
6. Татьяна Щукина (tatyana_schukina) 28.09.16 08:23
7. Николай Орлов (sulfur17) 28.09.16 08:39
два раза перечитал, но так и не понял в чем проблема. Таблицы значений между клиентом и сервером передаются через
ТЗСтрокой = ЗначениеВСтрокуВнутр(ТЗ);

и
ТЗ = ЗначениеИзСтрокиВнутр(ТЗСтрокой);

Объясните пожалуйста, зачем вся эта сериализация/десериализация, корректировки, массивы структур и т.д.?

8. Дмитрий Тарасов (tarassov) 28.09.16 08:57
(6) tatyana_schukina,
Это не ссылка! Это имя схемы
9. Дмитрий К. (Dementor) 28.09.16 09:39
(7) sulfur17, не смотря на многолетние уговоры представители 1С держат круговую оборону и отказываются переносить таблицу значений в функциональность клиентской части. Ваше "ЗначениеИзСтрокиВнутр(ТЗСтрокой);" на клиенте просто не будет работать. Из-за этого все стали использовать массив структур (а некоторые структуру массивов, когда не нужно делать обходы ДляКаждого). Автор предлагает альтернативный, хоть и не очень эффективный новых подход. Согласен, что не понятно для чего нужна сериализация, когда можно спокойно работать со строковым внутренним представлением таблицы - структура таких представлений довольно простая и не нужно морочиться с XML.
sulfur17; +1 Ответить
10. Andrey Kolesnikov (Boneman) 28.09.16 10:48
оригинальное решение. Правда в реальной жизни нафиг не нужное,
но, если сильно хочется поизвращаться и усложнить читаемость кода (а иногда это действительно нужно), то вполне можно применить.
За идею +
11. Andrey Kolesnikov (Boneman) 28.09.16 10:53
(7) sulfur17,
Объясните пожалуйста, зачем вся эта сериализация/десериализация, корректировки, массивы структур и т.д.?

СП
Глобальный контекст (Global context)
ЗначениеВСтрокуВнутр (ValueToStringInternal)
Синтаксис:

ЗначениеВСтрокуВнутр(<Значение>)
Параметры:

<Значение> (обязательный)

Тип: Произвольный.
Преобразуемое значение.
Возвращаемое значение:

Тип: Строка.
Системное представление значения в информационной базе.
Описание:

Получает системное строковое представление переданного значения.

Доступность:

Сервер, толстый клиент, внешнее соединение.

в тонком клиенте, данный метод не работает
swiss-garant; sulfur17; +2 Ответить
12. Александр Глебов (HanterVol) 28.09.16 11:27
Вопрос только есть...
А НАФИГА?
Создавать таблицу на сервере, передавать на клиента, чтобы потом снова передать на сервер?
Передавайте данные с клиента на сервер, а там уже и таблицаЗначений вам доступна и проч.
14. Дмитрий Тарасов (tarassov) 28.09.16 14:29
(12) HanterVol,

У мня это решение родилось, когда потребовалось быстро переделать чужую обработку, написанную для обычных форм в формы управляемые. "Дешевле" показалось не менять структуры, а "одним махом" передать с клиента на сервер образ таблицы значений. Главный выигрыш для себя видел в конструкции
ТаблицаЗагрузки = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);

15. Дмитрий Тарасов (tarassov) 28.09.16 14:57
16. Михаил Андрияшкин (mickey.1cx) 13.10.16 23:17
Допустим, Т - реквизит формы с типом ТаблицаЗначений.

&НаКлиенте
Процедура ПередатьТаблицу()
	
	ДанныеОбработки = ОбработатьТаблицуНаСервере(Т);
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ОбработатьТаблицуНаСервере(Знач Т)
	
	//Т - копия реквизита с данными, тип ДанныеФормаКоллекция
	//если необходимо, получаем таблицу значений
	ТЗ = Т.Выгрузить(); 
	
	//Обработка таблицы значений
	//...
	
	//можно вернуть результат обратно
	Т.Загрузить(ТЗ);
	
	Возврат Т;
	
КонецФункции
...Показать Скрыть


Пример здесь
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа