Решение задач 1С:Предприятие 8 на примерах

Массив в таблицу значений 1С и обратно: структуры, табличные части и Excel

АлгоритмыОпубликовано

Данные в 1С постоянно перекладываются из одной коллекции в другую: массив превращают в таблицу значений, таблицу — в массив структур для передачи на клиент, табличную часть выгружают для свёртки, а Excel читают в табличный документ. В статье — рабочий код для каждого направления, функции БСП, которые делают то же одной строкой, и ошибки, на которых чаще всего спотыкаются.

Задача: переложить данные из одной коллекции в другую

В 1С данные постоянно меняют «упаковку»: результат запроса выгружают в таблицу значений, таблицу значений превращают в массив структур, чтобы передать на клиент, табличную часть документа выгружают для свёртки, а файл Excel читают в табличный документ и уже из него собирают таблицу. Универсального метода «преобразовать что угодно во что угодно» в платформе нет, но для каждого направления есть короткий и проверенный приём. Основы работы с самой таблицей значений — создание, поиск, сортировка — разобраны в статье про таблицу значений, здесь речь только о преобразованиях.

Из чегоВо чтоЧем проще всего
Массив значенийКолонка таблицы значенийЗагрузитьКолонку()
Колонка таблицы значенийМассивВыгрузитьКолонку()
Массив структурТаблица значенийЦикл + ЗаполнитьЗначенияСвойств()
Таблица значенийМассив структурЦикл или ОбщегоНазначения.ТаблицаЗначенийВМассив() (БСП)
Строка таблицы значенийСтруктураОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру() (БСП)
Табличная частьТаблица значенийВыгрузить()
Табличный документ, ExcelТаблица значенийПрочитать() + обход ячеек

Массив в таблицу значений

Если массив содержит простые значения (ссылки, строки, числа), его удобно положить в одну колонку. Метод ЗагрузитьКолонку заполняет колонку значениями массива по порядку и сам добавляет недостающие строки.

Товары = Новый Массив;
Товары.Добавить(Справочники.Номенклатура.НайтиПоКоду("00001"));
Товары.Добавить(Справочники.Номенклатура.НайтиПоКоду("00002"));

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));

Таблица.ЗагрузитьКолонку(Товары, "Номенклатура");
// В таблице две строки, колонка "Количество" заполнена нулями

Обратная операция — Таблица.ВыгрузитьКолонку("Номенклатура") — возвращает массив значений колонки в порядке строк. Её часто используют, чтобы передать список ссылок параметром в запрос с условием В (&Список).

В конфигурациях на БСП для того же есть ОбщегоНазначенияКлиентСервер.ДополнитьТаблицуИзМассива(Таблица, Массив, ИмяПоля): она не перезаписывает существующие строки, а добавляет новые, по одной на каждый элемент массива. Это удобно, когда таблица уже частично заполнена.

Массив структур в таблицу значений

Массив структур получается после разбора JSON, из ответа веб-сервиса или когда данные пришли с клиента. Чтобы превратить его в таблицу, нужно один раз создать колонки — по ключам первой структуры — и затем перенести каждую структуру в новую строку. Перенос по совпадающим именам делает ЗаполнитьЗначенияСвойств, поэтому код не зависит от количества полей.

Функция МассивСтруктурВТаблицуЗначений(МассивСтруктур) Экспорт

    Таблица = Новый ТаблицаЗначений;
    Если МассивСтруктур.Количество() = 0 Тогда
        Возврат Таблица;
    КонецЕсли;

    Для Каждого КлючИЗначение Из МассивСтруктур[0] Цикл
        Таблица.Колонки.Добавить(КлючИЗначение.Ключ);
    КонецЦикла;

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

    Возврат Таблица;

КонецФункции

Колонки здесь создаются без типа. Для обработки в памяти этого достаточно, но если таблицу потом передают в запрос, нетипизированная колонка вызовет ошибку «Тип не может быть выбран в запросе». В таком случае задавайте тип явно: либо передайте в функцию заранее созданную таблицу-шаблон, либо добавляйте колонки с Новый ОписаниеТипов(...). Если структуры в массиве разные, соберите полный набор ключей по всем элементам, иначе поля, которых нет в первой структуре, потеряются.

Таблица значений в массив структур

Таблица значений не передаётся с сервера на клиент, а массив структур с примитивными значениями и ссылками — передаётся. Отсюда самая частая причина преобразования: подготовить данные на сервере и вернуть их в клиентский обработчик.

&НаСервереБезКонтекста
Функция ДанныеДляКлиента(Документ)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    Товары.Номенклатура КАК Номенклатура,
    |    Товары.Количество КАК Количество
    |ИЗ
    |    Документ.РеализацияТоваровУслуг.Товары КАК Товары
    |ГДЕ
    |    Товары.Ссылка = &Ссылка";
    Запрос.УстановитьПараметр("Ссылка", Документ);
    Таблица = Запрос.Выполнить().Выгрузить();

    Результат = Новый Массив;
    ИменаКолонок = "";
    Для Каждого Колонка Из Таблица.Колонки Цикл
        ИменаКолонок = ИменаКолонок + ?(ИменаКолонок = "", "", ",") + Колонка.Имя;
    КонецЦикла;

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

    Возврат Результат;

КонецФункции

Имена документа и табличной части в примере условные — подставьте свои. В БСП тот же результат даёт одна строка: ОбщегоНазначения.ТаблицаЗначенийВМассив(Таблица). Функция серверная и, как указано в её описании в документации БСП, подходит для передачи на клиент, только если в таблице нет значений, которые клиент принять не может (например, объектов или вложенных таблиц значений).

Таблицу значений в структуру

Под запросом «таблица значений в структуру» обычно понимают одно из трёх действий, и решаются они по-разному.

Одна строка — в структуру

Нужна, когда строку таблицы надо передать в другую процедуру или на клиент. В БСП есть готовая ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(СтрокаТаблицы). Без БСП — тот же приём, что выше: структура с именами колонок и ЗаполнитьЗначенияСвойств.

Вся таблица — в структуру колонок

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

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

Таблица — в соответствие по ключу

Если по таблице многократно ищут строку по одному полю, быстрее один раз построить соответствие «ключ → строка», чем каждый раз вызывать Найти. Ключ должен быть уникальным: при повторе последняя строка перезапишет предыдущую.

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

НайденнаяСтрока = ПоНоменклатуре.Получить(Товар); // Неопределено, если нет

Выгрузить табличную часть в таблицу значений

У табличной части объекта есть метод Выгрузить(): он возвращает таблицу значений с теми же колонками и типами, включая НомерСтроки. Вторым параметром можно перечислить только нужные колонки — таблица получится легче.

ДокументОбъект = Документ.ПолучитьОбъект();
Товары = ДокументОбъект.Товары.Выгрузить(, "Номенклатура, Количество, Сумма");
Товары.Свернуть("Номенклатура", "Количество, Сумма");

// Вернуть обратно в табличную часть
ДокументОбъект.Товары.Загрузить(Товары);

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

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

&НаСервере
Процедура СвернутьТовары()

    ДокументОбъект = РеквизитФормыВЗначение("Объект");
    Таблица = ДокументОбъект.Товары.Выгрузить();
    Таблица.Свернуть("Номенклатура", "Количество, Сумма");
    ДокументОбъект.Товары.Загрузить(Таблица);
    ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");

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

Табличный документ в таблицу значений

Табличный документ — это сетка ячеек без типов и колонок, поэтому преобразование всегда сводится к обходу ячеек. Размер заполненной части дают свойства ВысотаТаблицы и ШиринаТаблицы, а текст ячейки — Область(Строка, Колонка).Текст. Функция ниже берёт заголовки из первой строки, а колонкам таблицы даёт имена К1, К2 и так далее: заголовки из файлов часто содержат пробелы и знаки, недопустимые в имени колонки, поэтому исходный текст сохраняется в заголовке колонки.

Функция ТабличныйДокументВТаблицуЗначений(ТабДок, ПерваяСтрокаЗаголовок = Истина) Экспорт

    Таблица = Новый ТаблицаЗначений;
    ВсегоСтрок = ТабДок.ВысотаТаблицы;
    ВсегоКолонок = ТабДок.ШиринаТаблицы;

    Для НомерКолонки = 1 По ВсегоКолонок Цикл
        Заголовок = ?(ПерваяСтрокаЗаголовок,
            СокрЛП(ТабДок.Область(1, НомерКолонки).Текст), "");
        Таблица.Колонки.Добавить("К" + Формат(НомерКолонки, "ЧГ=0"),
            Новый ОписаниеТипов("Строка"), Заголовок);
    КонецЦикла;

    ПерваяСтрокаДанных = ?(ПерваяСтрокаЗаголовок, 2, 1);
    Для НомерСтроки = ПерваяСтрокаДанных По ВсегоСтрок Цикл
        НоваяСтрока = Таблица.Добавить();
        ЕстьДанные = Ложь;
        Для НомерКолонки = 1 По ВсегоКолонок Цикл
            Текст = СокрЛП(ТабДок.Область(НомерСтроки, НомерКолонки).Текст);
            НоваяСтрока[НомерКолонки - 1] = Текст;
            ЕстьДанные = ЕстьДанные Или Не ПустаяСтрока(Текст);
        КонецЦикла;
        Если Не ЕстьДанные Тогда
            Таблица.Удалить(НоваяСтрока); // пропускаем пустые строки
        КонецЕсли;
    КонецЦикла;

    Возврат Таблица;

КонецФункции

Все значения здесь строковые. Числа и даты преобразуйте при переносе в документ или справочник: Число(Текст) и Дата(...) вызывают исключение на некорректных данных, поэтому оборачивайте их в Попытка и собирайте ошибки по строкам, чтобы показать пользователю номер проблемной строки файла.

Excel в таблицу значений

Начиная с версии 8.3.6 табличный документ умеет читать файлы XLS, XLSX и ODS без установленного Excel — это зафиксировано в описании изменений версии 8.3.6. Тогда же у метода Прочитать() появился параметр способа чтения значений (системное перечисление СпособЧтенияЗначенийТабличногоДокумента). Значит, загрузка Excel в таблицу значений — это два шага: прочитать файл в табличный документ и обойти его функцией из предыдущего раздела.

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

&НаСервере
Процедура ЗагрузитьИзExcelНаСервере(АдресФайла, Расширение)

    ИмяФайла = ПолучитьИмяВременногоФайла(Расширение);
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайла);
    ДвоичныеДанные.Записать(ИмяФайла);

    ТабДок = Новый ТабличныйДокумент;
    Попытка
        ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
    Исключение
        УдалитьФайлы(ИмяФайла);
        ВызватьИсключение "Не удалось прочитать файл: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
    КонецПопытки;
    УдалитьФайлы(ИмяФайла);

    Таблица = ТабличныйДокументВТаблицуЗначений(ТабДок, Истина);
    // Дальше: проверка, приведение типов, перенос в табличную часть
    Сообщить("Прочитано строк: " + Таблица.Количество());

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

Расширение временного файла должно совпадать с исходным ("xlsx", "xls"), иначе платформа может не определить формат. Читается первый лист книги; если данные на другом листе, попросите пользователя сохранить нужный лист отдельно или вынести его первым. Объединённые ячейки, формулы и скрытые строки тоже лучше обсудить с пользователем заранее: надёжнее всего грузить «плоскую» таблицу с одной строкой заголовков.

В типовых конфигурациях для загрузки в табличные части и справочники есть подсистема БСП «Загрузка данных из файла» со своим помощником сопоставления колонок. Если задача стандартная, сначала проверьте, не решает ли её эта подсистема — общий обзор возможностей библиотеки есть в статье про БСП.

Помощники БСП для коллекций

ФункцияЧто делает
ОбщегоНазначения.ТаблицаЗначенийВМассив(Таблица)Таблица значений → массив структур
ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(Строка)Строка таблицы → структура
ОбщегоНазначенияКлиентСервер.ДополнитьТаблицуИзМассива(Таблица, Массив, ИмяПоля)Добавляет по строке на каждый элемент массива
ОбщегоНазначенияКлиентСервер.ДополнитьТаблицу(Источник, Приемник)Дописывает строки одной таблицы в другую
ОбщегоНазначения.ВыгрузитьКолонку(Коллекция, ИмяКолонки, ТолькоУникальные)Колонка любой обходимой коллекции → массив, при необходимости без повторов

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

Типичные ошибки

  • «Тип не может быть выбран в запросе» — в запрос передана таблица с нетипизированными колонками. Добавляйте колонки с ОписаниеТипов.
  • Попытка вернуть таблицу значений на клиент из серверной функции. Преобразуйте её в массив структур или поместите во временное хранилище.
  • Потерянные поля при переносе массива структур: колонки созданы по первому элементу, а у других элементов есть дополнительные ключи.
  • Очищенные реквизиты табличной части после Загрузить() таблицы, в которую выгружали не все колонки.
  • Недопустимое имя колонки при создании колонок из заголовков Excel: пробелы, точки и цифры в начале имени приводят к ошибке.
  • Числа в виде текста из табличного документа: неразрывные пробелы и запятые в качестве разделителя мешают Число(). Очищайте строку перед преобразованием.

Актуальность для новых версий

Методы ЗагрузитьКолонку, ВыгрузитьКолонку, Выгрузить и Загрузить работают одинаково во всех версиях 8.3. Чтение файлов XLS, XLSX и ODS в табличный документ без установленного Excel доступно начиная с версии 8.3.6. Набор функций БСП и общие модули, в которых они находятся, зависят от версии библиотеки, поэтому сверяйтесь с комментариями к функциям в своей конфигурации.

Частые вопросы

Как быстро загрузить массив в колонку таблицы значений?

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

Как преобразовать массив структур в таблицу значений?

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

Можно ли передать таблицу значений на клиент?

Нет, таблица значений на клиенте недоступна. Преобразуйте её в массив структур, например функцией ОбщегоНазначения.ТаблицаЗначенийВМассив из БСП, или используйте реквизит формы типа ТаблицаЗначений.

Как выгрузить табличную часть документа в таблицу значений?

Вызовите у табличной части объекта метод Выгрузить(). Вторым параметром можно перечислить нужные колонки. Обратно данные загружаются методом Загрузить(), который полностью заменяет содержимое табличной части.

Нужен ли установленный Excel, чтобы прочитать файл xlsx в 1С?

Нет. Начиная с версии 8.3.6 табличный документ читает XLS, XLSX и ODS методом Прочитать() без Excel. После чтения обойдите ячейки и перенесите данные в таблицу значений.

Почему при передаче таблицы в запрос возникает ошибка «Тип не может быть выбран в запросе»?

У колонок таблицы не задан тип значения. Создавайте колонки с описанием типов, например Новый ОписаниеТипов("СправочникСсылка.Номенклатура"), тогда запрос сможет выбрать данные из таблицы.

Работа с датой в 1С программно: текущая дата, начало месяца, формат и разность

Алгоритмы

Все основные приёмы работы с датой в коде 1С: создание и преобразование, текущая дата, границы периодов, сдвиг и разность дат, форматирование, пустая дата и часовые пояса.

Обновление конфигурации 1С: типовой, платформы и сервера

Алгоритмы

Как обновить типовую конфигурацию 1С с доработками и без, что делать с поддержкой, как обновить базу данных, платформу и сервер 1С без потери данных.

Отладка в 1С: точки останова и отладка на сервере

Алгоритмы

Практическое руководство по отладчику 1С: точки останова, шаги, табло, остановка по ошибке, замер производительности и настройка отладки серверного кода и фоновых заданий.

Штрихкод в 1С: контрольная цифра EAN-13, генерация, поиск и печать

Алгоритмы

Практический разбор штрихкодов в 1С: расчёт контрольной цифры EAN-13 и EAN-8, внутренние уникальные коды, поиск товара по штрихкоду, вывод картинки в печатную форму и работа со сканером.