1с найти строку в данныеформыколлекция

Обновлено: 06.07.2024

Иногда требуется создать внешнюю обработку с большим количеством реквизитов (в том числе и с табличной частью), первое, что мы делаем для сохранения настроек в этом случае - устанавливаем свойство формы АвтоматическоеСохранениеДанныхВНастройках в Использовать. Затем ставим напротив всех нужных реквизитов галочки "Сохранение" и наслаждаемся результатом.

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

То, что это возможно легко понять по намёкам на форумах, однако ни одного законченного решения найти не удалось. Что ж, к этому нам не привыкать, начинаем придумывать велосипед.

Пробуем сначала сохранить значения всех реквизитов формы в файл. Поиски в интернете приводят нас к процедуре ЗначениеВФайл и функции ЗначениеВСтрокуВнутр, приём последней пользоваться как бы не рекомендуется, якобы она предназначена для обмена с 7.7. Обе конструкции языка доступны только на сервере и толстом клиенте, поэтому возникает вопрос, как бы обойти значения всех реквизитов формы &НаСервере.

выдаст вполне ожидаемую не для всех ошибку: Итератор для значения не определен.

Тоже самое ожидает нас и с переменными ЭтаФорма, ЭтотОбъект. На такую простую вещь можно потратить пару часов, однако отладчик и поисковики творят чудеса - получить значения всех реквизитов формы внешней обработки на сервере можно с помощью следующего кода:

Казалось бы, теперь всё просто, однако не совсем. Табличная часть, как и таблица значений имеют не совсем ожидаемый тип значений, их тип ДанныеФормыКоллекция. А ведь они должны быть обязательно выгружены для сохранения, иначе в файле получим только их уникальные индификаторы.

В результате этого знания получаем:

Это даже работает, но радоваться рано - этот код неправильный! Мы допустили одну из самых распространенных ошибок при написании кода на управляемых формах. Выбрав имя файла на клиенте, а потом передав его на сервер, мы забыли, что при клиент-серверном режиме работы код, выполняемый на стороне сервера, будет запущен под другим пользователем. И далеко не факт, что этот пользователь будет иметь доступ туда (например, локальный диск терминальной сессии по RDP), куда мы сохраняем файл.

Поэтому переписываем код, сохраняем файл теперь на клиенте, правда придётся воспользоваться не очень рекомендуемой функцией ЗначениеВСтрокуВнутр:

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

А напишем другой вариант, например, используя временное хранилище:

Если внимательно посмотреть код, то легко заметить, что после получения данных из временного хранилища (с типом ДвоичныеДанные) мы вынуждены записать их во временный файл. Другого нормального способа получить данные с типом Строка из временного хранилища попросту нет.

Чтобы не насиловать файловую систему временными файлами, давайте перепишем код, без использования временного хранилища, но с использованием не очень рекомендуемой функции ЗначениеИзСтрокиВнутр:


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

В прикрепленной ниже внешней обработке используется последний вариант сохранения и чтения настроек через файл из этой статьи, ну и, конечно, автосохранение штатными средствами в информационной базе.

Функция НайтиСтрокиДанныеФормыКоллекции(_Коллекция,Знач _Владелец) Экспорт
М = Новый Массив();
Для каждого Стр из _Коллекция Цикл
Если Стр.Владелец = _Владелец и Стр.Удалено=Ложь тогда
М.Добавить(Стр);
КонецЕсли;
КонецЦикла;
Возврат М;
КонецФункции

бвстрее чем (на клиенте):

Возврат Движения.НайтиСтроки(Новый Структура("Владелец,Удалено",_Владелец,Ложь));

в коллекции несколько сотен элементов.

Стоит ли переносить эту команду явно на сервер, если ДанныеФормыКоллекция представление ТЧ документа?

Стоит ли переносить эту команду явно на сервер, если ДанныеФормыКоллекция представление ТЧ документа?

Я бы исходил из такой логики: если в документах чаще всего много строк, то я бы перенес код обработки строк табличной части явно на сервер.
Если же строк, как правило, не много, тогда оставил бы на клиенте.

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

Это такой механизм оптимизации. Зачем при открытии формы тащить все 1000 строк табличной части на клиента? Не так часто пользователи просматривают всю таблицу. При необходимости данные просто дочитываются в процессе работы пользователя (в процессе прокрутки).

В данном случае своим кодом вы буквально просматриваете всю табличную часть.
Для интереса посмотрите, сколько вызовов сервера происходит при выполнении Вашего кода. Предполагаю, что при первом (после открытия формы) выполнении производится около 10-20 вызовов. При повторном выполнении - ни одного (т.к. все данные уже прочитаны, уже все есть на клиенте).

Возможно, лучше сделать один явный вызов сервера, где обработать все строки.
Теоретически )

Область применения: управляемое приложение, мобильное приложение.

1. В целях оптимизации объема данных, передаваемых между клиентом и сервером, платформа 1С:Предприятие по-особому организует передачу объектов формы типа ДанныеФормыКоллекция . Данные таких объектов передаются определенными порциями таким образом, что новые порции данных передаются с сервера на клиент только по мере обращения к этим данным на клиенте. Необходимо учитывать эту особенность при разработке форм, т.к. в противном случае, код формы может приводить к излишним неявным серверным вызовам, инициируемым платформой.

2. При работе с объектами типа ДанныеФормыКоллекция , если предполагается, что объект типа ДанныеФормыКоллекция может содержать большое количество строк (нужно ориентироваться на количество от 20 строк), необходимо придерживаться следующих рекомендаций:

  • обход строк такой коллекции необходимо производить на сервере;
  • функцию НайтиСтроки вызывать только на сервере.

Например, если решается задача по проверке в объекте строк, удовлетворяющих некоторому условию, то
неправильно:

правильно выполнять один явный вызов сервера:

Маленький IT блог с характером 1С.

Поиск по блогу

пятница, 9 октября 2015 г.

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

Вариант №1

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

&НаСервере
Функция ПолучитьТЗКакМассивСтруктур()

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

&НаКлиенте
Процедура ПолучитьДанные()

Вариант №2

Этот вариант намного сложнее, но выполнив его, считайте что к одному из пунктов экзамена на знание платформы 1С 8.2 или 8.3 "Специалист" вы подготовились. Здесь используется динамическое создание реквизитов формы. Алгоритм, примерно, такой: создается реквизит формы с типом ТаблицаЗначений, для этого реквизита создаются подчиненные реквизиты (колонки таблицы) и производиться загрузка данных таблицы значений в новый реквизит формы.

Первым делом, необходимо у формы создать реквизит ИмяТаблицыЗначений с типом ТаблицаЗначений.


Рисунок 1. Реквизит формы типа ТаблицаЗначений

А потом написать следующий код:

ДобавляемыеРеквизиты = Новый Массив;
УдаляемыеРеквизиты = Новый Массив;

МассивКолонок = Новый Массив;
ИмяТаблицыФормы = "ИмяТаблицыЗначений";

Для Каждого ТекКолонка из ТаблицаФормы.Колонки Цикл
УдаляемыеРеквизиты.Добавить(ИмяТаблицыФормы + "." + ТекКолонка.Имя);
КонецЦикла;

Для Каждого ТекКолонка из МояТаблицаЗначений.Колонки Цикл
ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ТекКолонка.Имя, ТекКолонка.ТипЗначения, ИмяТаблицыФормы));
МассивКолонок.Добавить(ТекКолонка.Имя);
КонецЦикла;

// Добавим новые, удалим старые колонки
ИзменитьРеквизиты(ДобавляемыеРеквизиты, УдаляемыеРеквизиты);
// Поместим значение в реквизит формы
ЗначениеВРеквизитФормы(МояТаблицаЗначений, ИмяТаблицыФормы);

Далее на клиенте можно смело обращаться к свежеиспеченной таблице значений ЭтаФорма.ИмяТаблицыЗначений.

личный блог


С задачей вывода каких либо данных в Таблицу Значений (ТЗ) на форме сталкиваются наверное все программисты. Если раньше до выхода Управляемого Интерфейса все решалось довольно просто, то теперь все немного изменилось.

Для обычных форм.

Стоит отметить, что предварительно нужно создать соответствующие РезультатуЗапроса колонки таблицы значений. Делается это также просто. Добавить ТаблицуЗначений следует в реквизиты Формы. Еще раз акцентирую внимание — Названия колонок и типы данных колонок ТЗ должны совпадать и на форме и в запросе. Можно вообще не создавать ТЗ на форме, а описать ее программно, примерно как то так:

Для управляемых форм все ровно тоже самое кроме того что нужно на сервере получить значение данных ТЗ на форме, записать в них результат запроса и потом снова вернуть их на форму.

Ниже пример такого преобразования.

Во всей этой истории следует обратить внимание на 2 строчки.

Первая

Вторая

Первый из типа данных ДанныеФормыКоллекция преобразует данные в тип ТаблицаЗначений. Второй соответственно конвертирует в обратном направлении.

Читайте также: