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

Публикация № 240022

Программирование - Инструментарий

Мутабельные Клиент Сервер Перенос таблицы значений

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

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

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

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

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

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

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

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

 

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

 

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

 

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

 

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

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

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. AlX0id 10.12.13 19:18 Сейчас в теме
ОбщегоНазначения.ТаблицаЗначенийВМассив(Таблица)
не? )
sergio199; Gorus; kar911; Gang031; vovaikilko; Огонек; NN2P; Silenser; roman77; altek; roofless; elga666; qwed557; tehas; elian; dim369; Draconus; freezetron; KonstB; +19 Ответить
4. Draconus 54 11.12.13 08:58 Сейчас в теме
(1) AlX0id, опять велосипед изобретаю))
А в обратку кстати какой метод? "МассивВТаблицуЗначений" не нашел...
8. AlX0id 11.12.13 10:16 Сейчас в теме
(4)
А обратно лично я не нашел ) Пришлось писать )
10. Draconus 54 11.12.13 10:41 Сейчас в теме
(8) AlX0id, тогда половина кода не "велосипед" :)
12. Bukaska 127 11.12.13 10:52 Сейчас в теме
(4) Мутабельные значения - немножко другая тема..
если у вас модуль серверный и не стоит галка вызов сервера и наоборот... то конечно будет эта тема..
А так для тонкого клиента есть функционал: ДанныеФормыВЗначение и ЗначениеВДанныеФормы
Об этом даже рассказывает Андрей Габец в тестовом доступе УЦ3 , отрывок из курса Оперативных задач
31. El_Loco 297 01.09.18 13:42 Сейчас в теме
Коллеги, я сейчас решаю озвученную в теме задачу.
Пишу обработку заполнения табличной части (с вызовом клиентского метода).
Юзер указывает ссылку на документ, по которой я на сервере собираю ТЗ, а потом эту ТЗ возвращаю на клиент, чтобы заполнить ТЧ своего документа.

Понимаю, что можно тупо упаковать строки в структуры,, а их в массив, и этот массив вернуть на клиент.

но тут в (12) сказано
А так для тонкого клиента есть функционал: ДанныеФормыВЗначение и ЗначениеВДанныеФормы

это применимо в моей задаче или проще массив из структур швырнуть на клиент?
34. azhilichev 146 03.12.18 09:21 Сейчас в теме
(31) ДанныеФормыВЗначение и ЗначениеВДанныеФормы нельзя открывать от контекста формы. Бесконтекстные вызовы не отработают.
2. KonstB 173 10.12.13 21:48 Сейчас в теме
1. Автор посмотри (0) - сравни. У тебя не оптимально.
2. Функция ПреобразоватьМассивВТаблицуЗначений(мсДанные) - не будет работать в тонком клиенте
rpgshnik; +1 Ответить
3. AnryMc 721 10.12.13 21:53 Сейчас в теме
Функция "ПреобразоватьТаблицуЗначенийВМассив" выполняется на сервере перед передачей данных, а "ПреобразоватьМассивВТаблицуЗначений" уже на клиенте соответственно.


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

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

5. soap 53 11.12.13 09:22 Сейчас в теме
Попробовал можно воспользоваться, но при большой таблице чертовски медленно
6. gaglo 11.12.13 09:57 Сейчас в теме
А почему не ЗначениеВСтрокуВнутр ?
myALKleon; +1 Ответить
7. Draconus 54 11.12.13 10:10 Сейчас в теме
(6) gaglo, никто не говорил, что данный вариант - это универсальные методы, которые должны быть у каждого и пользоваться надо только ими)
Это всего лишь один из возможных подходов к решению задач. Кстати как упоминалось в (5) далеко не самый оптимальный. Однако есть вероятность, что кто-то сочтет его полезным для себя.
17. gaglo 12.12.13 10:37 Сейчас в теме
(7) - не ответ, а вот (14) - ответ. Спасибо.
14. kg_am 123 11.12.13 12:01 Сейчас в теме
(6) gaglo,
ЗначениеИзСтрокиВнутр() на тонком клиенте не работает.
lsnr; vvvalera; gaglo; +3 Ответить
9. Гость 11.12.13 10:41
если не ошибаюсь, ТаблицаЗначений прекрасно передается на сервер
вот СписокЗначений - не передается
Прикрепленные файлы:
tranay; Трактор; +2 3 Ответить
11. Draconus 54 11.12.13 10:43 Сейчас в теме
(9) barankin, таблица значений с сервера не передается, а вот список значений передаваться должен.
Хотя недавно у меня тоже не передавался, что странно, так как точно помню, что можно было... так же пришлось делать через массив.
13. zarucheisky 11.12.13 10:56 Сейчас в теме
Передача массива структур с клиента на сервер в общем-то очевидна и давно известна.
А вот подобный код в статье публиковать не стОит.

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

На самом деле, если конечно подумать, и посмотреть как ТЗ отображается в XML, то и решение придет как бы само :)
18. Yashazz 2325 12.12.13 12:50 Сейчас в теме
(13) Верно, хотя сериализация тоже не всякая прокатывает, особенно если в таблице разности и хитрости понапиханы. Да и городить огород иногда нерационально.
19. zarucheisky 12.12.13 14:14 Сейчас в теме
(18) Понапихай всего разного и посмотри как сериализуется
Грубо говоря, сериализуется ВСЕГДА одинаково, как прописано в xsd-схеме ядра платформы.
21. Yashazz 2325 20.12.13 22:36 Сейчас в теме
(19) Некоторые вещи просто НЕ сериализуются. Иногда - противореча СП, например, "РазмерКартинки". А схему самой 1С я видел, так вот, теоретически должное иногда практически не выходит. Ну, xsd 1С - вообще отдельная история, здесь это оффтоп )))
15. peterxx 20 11.12.13 15:50 Сейчас в теме
Нормально работает, сам пользуюсь, правда преобразую ТЗ в структуру массивов. Массив тоже можно пинать между клиентом и сервером.
16. nixel 641 12.12.13 01:31 Сейчас в теме
Вот если бы кто написал функции по переводу тз в массив структур с двумя требованиями:
1) обход данного массива так же как и ТЗ (есть)
2) преобразование данного массива в ТЗ с сохранением типов колонок

А то в крайних случаях приходится проходиться по колонке, смотреть все типы и строить ОписаниеТипов для конструктора ТЗ по собранным данным... Медленно и не всегда верно. Особенно если таблица пустая. Колонки потеряли, типы потеряли. Ну это так, мысли о высоком.
20. wunderland 202 13.12.13 13:31 Сейчас в теме
скользкая тема, если в таблице есть значения Null - в этом случае в тонком клиенте и WEB-клиенте код отрабатывает по разному.
22. realEvgenius 17.02.15 11:09 Сейчас в теме
А в чем соль, так сказать?

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

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

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

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

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

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

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

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

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

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

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


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

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


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

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

Тип не определен (ТаблицаЗначений)
тзДанные = Новый <<?>>ТаблицаЗначений; (Проверка: Тонкий клиент)
afrodit; bow; +2 Ответить
26. realEvgenius 17.02.15 17:04 Сейчас в теме
Аааа.... В общий модуль... А я ж в томже модуле мучаю...
попробую
28. logos 74 27.06.16 20:44 Сейчас в теме
Вот ведь парадокс.... Тип таблица значений на клиенте не определен, а реквизит формы типа "таблица значений" возможен и работает. Сдается мне это вопрос религиозного характера!
rpgshnik; +1 Ответить
29. nixel 641 28.06.16 00:54 Сейчас в теме
(28) logos, посмотрите отладчиком, какой тип у этого реквизита. Удивитесь.
30. It-developer 20 23.03.17 14:28 Сейчас в теме
Они ограничили передачи ТаблицыЗначений, потому что хз что туда можно напихать. Было бы лучше не ограничивать таблицу, а ограничивать типы передаваемых данных
32. chukawata 10 23.10.18 05:00 Сейчас в теме
33. komanch75 28.11.18 09:29 Сейчас в теме
Можно передавать массив, элементы которого - массивы выгруженных колонок таблицы.
Правда таблица значений доступна только на толстом клиенте.
&НаКлиенте
Процедура ЧтоТо(Команда)
	Мсс=ПередачаНаСервере();
	ТЗ=Новый ТаблицаЗначений;
	Для йй=0 по Мсс.Количество()-1 цикл
		ИмяКолонки=СокрЛП(Мсс[йй][0]);
		ТЗ.Колонки.Добавить(ИмяКолонки);
		Мсс[йй].Удалить(0);
		Если йй=0 тогда //на первом проходе добавим в ТЗ строки
			Для цц=1 по Мсс[йй].Количество() цикл
				ТЗ.Добавить();
			КонецЦикла;
		КонецЕсли;
		ТЗ.ЗагрузитьКолонку(Мсс[йй], ТЗ.Колонки[ИмяКолонки]);
	КонецЦикла;
КонецПроцедуры

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