Перенос таблицы значений между клиентом и сервером

Опубликовал Александр Сленючев (Draconus) в раздел Программирование - Инструментарий

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

Сильно не пинайте.

Все мы сталкивались с ситуацией, когда необходимо с сервера передать данные на клиент. И далеко не всегда это примитивные типы.

Об одном из таких типов я бы сегодня и хотел поговорить.

Речь сегодня о таблицы значений.

Данный тип является мутабельным и при попытке выполнить это действия мы получим ошибку:

{Справочник.НастройкиЗаполненияОбъектов1СДокументооборота.МодульОбъекта(33)}: Ошибка при вызове метода контекста (ПолучитьПрокси)
Прокси = ИнтеграцияС1СДокументооборотВызовСервера.ПолучитьПрокси();
по причине:
Попытка передачи мутабельного значения результата метода ПолучитьПрокси ().

(текст ошибки в каждом случае свой)

 

Сегодня я выношу на Вашу критику и обозрение один из вариантов решения этой проблемы, а именно преобразование в Массив(может передаваться) из структур и обратно в таблицу.

 

Функция "ПреобразоватьТаблицуЗначенийВМассив" выполняется на сервере перед передачей данных, а "ПреобразоватьМассивВТаблицуЗначений" уже на клиенте соответственно.

 

Код этих функций:

 

// Функция преобразует ТаблицуЗначений в Массив из структур.
//
Функция ПреобразоватьТаблицуЗначенийВМассив(тзДанные) Экспорт
	
	мсДанные = Новый Массив;
		
	// Запишем в массив
	Для Каждого СтрокаТЗ Из тзДанные Цикл
		
		стСтрокаТаблицы = Новый Структура;
		Для Каждого ИмяКолонки Из тзДанные.Колонки Цикл
			стСтрокаТаблицы.Вставить(ИмяКолонки.Имя, СтрокаТЗ[ИмяКолонки.Имя]);
		КонецЦикла;
		
		мсДанные.Добавить(стСтрокаТаблицы);
		
	КонецЦикла;
	
	Возврат мсДанные;
	
КонецФункции // ПреобразоватьТаблицуЗначенийВМассив()

// Функция преобразует Массив из структур в ТаблицуЗначений.
//
Функция ПреобразоватьМассивВТаблицуЗначений(мсДанные) Экспорт
	
	тзДанные = Новый ТаблицаЗначений;
	
	Для Каждого ЭлементМассива Из мсДанные Цикл
		// Рисуем колонки для таблицы
		Если тзДанные.Колонки.Количество() = 0 Тогда
			Для Каждого ЗначениеСтруктуры Из ЭлементМассива Цикл
				тзДанные.Колонки.Добавить(ЗначениеСтруктуры.Ключ);
			КонецЦикла;
		КонецЕсли;
		
		// Добавляем данные в таблицу
		НоваяСтрока = тзДанные.Добавить();
		Для Каждого ЗначениеСтруктуры Из ЭлементМассива Цикл
			НоваяСтрока[ЗначениеСтруктуры.Ключ] = ЗначениеСтруктуры.Значение;
		КонецЦикла;
	КонецЦикла;
	
	Возврат тзДанные;
	
КонецФункции // ПреобразоватьМассивВТаблицуЗначений()

См. также

Добавить вознаграждение
Комментарии
1. Алексей 1 (AlX0id) 10.12.13 19:18 Сейчас в теме
ОбщегоНазначения.ТаблицаЗначенийВМассив(Таблица)
не? )
Silenser; roman77; altek; roofless; elga666; qwed557; tehas; elian; dim369; Draconus; freezetron; KonstB; +12 Ответить 1
2. Konstantin Konstantin (KonstB) 159 10.12.13 21:48 Сейчас в теме
1. Автор посмотри (0) - сравни. У тебя не оптимально.
2. Функция ПреобразоватьМассивВТаблицуЗначений(мсДанные) - не будет работать в тонком клиенте
3. anry mc (AnryMc) 706 10.12.13 21:53 Сейчас в теме
Функция "ПреобразоватьТаблицуЗначенийВМассив" выполняется на сервере перед передачей данных, а "ПреобразоватьМассивВТаблицуЗначений" уже на клиенте соответственно.


&НаСервереБезКонтекста

&НаКлиентеБезКонтекста

4. Александр Сленючев (Draconus) 32 11.12.13 08:58 Сейчас в теме
(1) AlX0id, опять велосипед изобретаю))
А в обратку кстати какой метод? "МассивВТаблицуЗначений" не нашел...
5. Борис (soap) 40 11.12.13 09:22 Сейчас в теме
Попробовал можно воспользоваться, но при большой таблице чертовски медленно
6. Борис Скворцов (gaglo) 11.12.13 09:57 Сейчас в теме
А почему не ЗначениеВСтрокуВнутр ?
7. Александр Сленючев (Draconus) 32 11.12.13 10:10 Сейчас в теме
(6) gaglo, никто не говорил, что данный вариант - это универсальные методы, которые должны быть у каждого и пользоваться надо только ими)
Это всего лишь один из возможных подходов к решению задач. Кстати как упоминалось в (5) далеко не самый оптимальный. Однако есть вероятность, что кто-то сочтет его полезным для себя.
8. Алексей 1 (AlX0id) 11.12.13 10:16 Сейчас в теме
(4) Draconus,
А обратно лично я не нашел ) Пришлось писать )
9. Гость 11.12.13 10:41 Сейчас в теме
если не ошибаюсь, ТаблицаЗначений прекрасно передается на сервер
вот СписокЗначений - не передается
Прикрепленные файлы:
tranay; Трактор; +2 1 Ответить 1
10. Александр Сленючев (Draconus) 32 11.12.13 10:41 Сейчас в теме
(8) AlX0id, тогда половина кода не "велосипед" :)
11. Александр Сленючев (Draconus) 32 11.12.13 10:43 Сейчас в теме
(9) barankin, таблица значений с сервера не передается, а вот список значений передаваться должен.
Хотя недавно у меня тоже не передавался, что странно, так как точно помню, что можно было... так же пришлось делать через массив.
12. Елена Пименова (Bukaska) 117 11.12.13 10:52 Сейчас в теме
(4) Draconus, Мутабельные значения - немножко другая тема..
если у вас модуль серверный и не стоит галка вызов сервера и наоборот... то конечно будет эта тема..
А так для тонкого клиента есть функционал: ДанныеФормыВЗначение и ЗначениеВДанныеФормы
Об этом даже рассказывает Андрей Габец в тестовом доступе УЦ3 , отрывок из курса Оперативных задач
13. Евгений Заручейский (zarucheisky) 11.12.13 10:56 Сейчас в теме
Передача массива структур с клиента на сервер в общем-то очевидна и давно известна.
А вот подобный код в статье публиковать не стОит.

Вложенные циклы по колонкам внутри перебора таблицы выглядят несколько неразумно.

На самом деле, если конечно подумать, и посмотреть как ТЗ отображается в XML, то и решение придет как бы само :)
14. Александр (kg_am) 73 11.12.13 12:01 Сейчас в теме
(6) gaglo,
ЗначениеИзСтрокиВнутр() на тонком клиенте не работает.
15. Петр (peterxx) 11.12.13 15:50 Сейчас в теме
Нормально работает, сам пользуюсь, правда преобразую ТЗ в структуру массивов. Массив тоже можно пинать между клиентом и сервером.
16. Никита Грызлов (nixel) 71 12.12.13 01:31 Сейчас в теме
Вот если бы кто написал функции по переводу тз в массив структур с двумя требованиями:
1) обход данного массива так же как и ТЗ (есть)
2) преобразование данного массива в ТЗ с сохранением типов колонок

А то в крайних случаях приходится проходиться по колонке, смотреть все типы и строить ОписаниеТипов для конструктора ТЗ по собранным данным... Медленно и не всегда верно. Особенно если таблица пустая. Колонки потеряли, типы потеряли. Ну это так, мысли о высоком.
17. Борис Скворцов (gaglo) 12.12.13 10:37 Сейчас в теме
(7) - не ответ, а вот (14) - ответ. Спасибо.
18. Яков Коган (Yashazz) 1940 12.12.13 12:50 Сейчас в теме
(13) Верно, хотя сериализация тоже не всякая прокатывает, особенно если в таблице разности и хитрости понапиханы. Да и городить огород иногда нерационально.
19. Евгений Заручейский (zarucheisky) 12.12.13 14:14 Сейчас в теме
(18) Понапихай всего разного и посмотри как сериализуется
Грубо говоря, сериализуется ВСЕГДА одинаково, как прописано в xsd-схеме ядра платформы.
20. Ловыгин Антон (wunderland) 183 13.12.13 13:31 Сейчас в теме
скользкая тема, если в таблице есть значения Null - в этом случае в тонком клиенте и WEB-клиенте код отрабатывает по разному.
21. Яков Коган (Yashazz) 1940 20.12.13 22:36 Сейчас в теме
(19) Некоторые вещи просто НЕ сериализуются. Иногда - противореча СП, например, "РазмерКартинки". А схему самой 1С я видел, так вот, теоретически должное иногда практически не выходит. Ну, xsd 1С - вообще отдельная история, здесь это оффтоп )))
22. Евгений (realEvgenius) 17.02.15 11:09 Сейчас в теме
А в чем соль, так сказать?

Функция ПреобразоватьМассивВТаблицуЗначений(мсДанные)

Всеравно передает ТЗ с сервера и всеравно вызывает ошибку...

Или я деревянный или чушь какая-то
23. Александр Сленючев (Draconus) 32 17.02.15 14:07 Сейчас в теме
(22) realEvgenius

Вариант 1.
1. С помощью ПреобразоватьТаблицуЗначенийВМассив() делаем массив, который гоняем между клиентом и сервером.
2. Обрабатываем его (это уже сами выбираете как)
3. Передаете на клиент обратно МАССИВ, который затем преобразуете в Таблицу значений с помощью ПреобразоватьМассивВТаблицуЗначений().

Вариант 1,5.
1. Делаем массив с помощью ПреобразоватьТаблицуЗначенийВМассив()
2. Получаем на сервере, преобразуем в Таблицу значений с помощью ПреобразоватьМассивВТаблицуЗначений()
3. Работаем с Таблицей значений

З.Ы. Мне надо было для второго варианта.
24. Евгений (realEvgenius) 17.02.15 16:17 Сейчас в теме
(23) Draconus, Вопрос Как в процедуре, которая идет после &НаКлиенте Использовать Таб значений как её туда передать? Ответ - никак. ПреобразоватьМассивВТаблицуЗначений() Это на сервере запускать? Оно возвращает Таб значений (Возврат тзДанные), которую нельзя передать в мою процедуру, которая выполняется на клиенте. Ибо система ругается.
Смысл этих обработок? Таб значений передать на клиента нельзя. Преобразовываем её в массив, передаем массив на клиента, предаем массив функции ПреобразоватьМассивВТаблицуЗначений(), которая по идее должна дать таб знач и получаем туже ошибку. Наверное, я - деревянный, что-то не понимаю
25. Александр Сленючев (Draconus) 32 17.02.15 16:42 Сейчас в теме
(24) realEvgenius

Обе функции кладутся в общий модуль, где проставлены галочки "Клиент" и " Сервер", назовем его "ОбщегоНазначенияКлиентСервер"

&НаКлиенте
Процедура ЧтотоДелаю1()
   
   //Есть уже таблица надо ее подправить на сервере
   ЧтотоДелаюНаСервере1(ОбщегоНазначенияКлиентСервер.ПреобразоватьТаблицуЗначенийВМассив(<НашаБеднаяТаблица>));

КонецПроцедуры

&НаСервере
Процедура ЧтотоДелаюНаСервере1(НашБедныйМассив)
   НашаБеднаяТаблица = ОбщегоНазначенияКлиентСервер.ПреобразоватьМассивВТаблицуЗначений(НашБедныйМассив).Скопировать();
   // Мучаем нашу бедную таблицу, что-то из нее берем, что-то добавляем
   
   // Если надо вернуть отбратно, то делаем не процедуру, а функцию и возвращаем
   // ОбщегоНазначенияКлиентСервер.ПреобразоватьТаблицуЗначенийВМассив(<НашаБеднаяПЕРЕДЕЛАННАЯТаблица>)

КонецПроцедуры
...Показать Скрыть


Я не знаю что тут еще можно добавить
realEvgenius; +1 Ответить 1
26. Евгений (realEvgenius) 17.02.15 17:04 Сейчас в теме
Аааа.... В общий модуль... А я ж в томже модуле мучаю...
попробую
27. Вадим Сайфутдинов (svad1) 10 21.04.16 13:37 Сейчас в теме
(25) Draconus, как у вас получилось?
//Есть уже таблица надо ее подправить на сервере 

Если на клиенте написать 
тзДанные = Новый ТаблицаЗначений; 


то сразу ошибка.

Как таблица значений может быть на клиенте? Нечего передавать по сути, так как сразу возникает ошибка... Я так понял таблица значений не может существовать на клиенте

Тип не определен (ТаблицаЗначений)
тзДанные = Новый <<?>>ТаблицаЗначений; (Проверка: Тонкий клиент)
28. Anton Loginchev (logos) 58 27.06.16 20:44 Сейчас в теме
Вот ведь парадокс.... Тип таблица значений на клиенте не определен, а реквизит формы типа "таблица значений" возможен и работает. Сдается мне это вопрос религиозного характера!
29. Никита Грызлов (nixel) 71 28.06.16 00:54 Сейчас в теме
(28) logos, посмотрите отладчиком, какой тип у этого реквизита. Удивитесь.