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

· 9 мин

Содержание

Выгрузить одну колонку из таблицы значений 1С можно одной строкой: Массив = Таблица.ВыгрузитьКолонку("ИмяКолонки");. Метод возвращает массив значений в порядке строк таблицы. Колонку можно указать по имени, по индексу или объектом из Таблица.Колонки.

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

Код работает в платформе 8.3 и в клиентском, и в серверном контексте. Исключение — запись файлов: на клиенте это путь на компьютере пользователя, на сервере — на сервере 1С.

Базовый способ: ВыгрузитьКолонку

Метод ВыгрузитьКолонку есть у таблицы значений и у дерева значений. Для таблицы он принимает один параметр — колонку.

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

Строка = Таблица.Добавить();
Строка.Номенклатура = "Болт М8";
Строка.Количество = 100;

Строка = Таблица.Добавить();
Строка.Номенклатура = "Гайка М8";
Строка.Количество = 250;

Массив = Таблица.ВыгрузитьКолонку("Номенклатура");
// Массив: "Болт М8", "Гайка М8"

Три равнозначных варианта указания колонки:

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

Индексы колонок идут с нуля: первая колонка имеет индекс 0.

💡 Массив получается независимым. Если потом изменить таблицу, массив не поменяется. И наоборот: правки в массиве таблицу не затрагивают.

Если нужна не копия, а обход

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

Для Каждого Строка Из Таблица Цикл
    Сообщить(Строка.Номенклатура);
КонецЦикла;

Выгрузка колонки оправдана, когда результат передают дальше: в параметр запроса, в СтрСоединить, в список значений, в другой метод, который ждёт массив.

Результат в виде списка значений

Для выбора из списка на форме нужен СписокЗначений, а не массив. Переложить просто:

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

Уникальные значения колонки без дублей

Колонка часто содержит повторы: один контрагент в десятках строк. Выгрузка «как есть» вернёт все повторы. Дубли убирают сверткой по этой колонке.

Копия = Таблица.Скопировать();
Копия.Свернуть("Контрагент");
Уникальные = Копия.ВыгрузитьКолонку("Контрагент");

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

⚠️ Свёртка по колонке выбрасывает все остальные колонки. Если дальше нужна, например, сумма по каждому контрагенту, передайте её вторым параметром: Копия.Свернуть("Контрагент", "Сумма"). Тогда суммы сложатся по каждому уникальному значению.

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

Встречались = Новый Соответствие;
Уникальные = Новый Массив;

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

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

Типы данных: что лежит в массиве

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

Типизированная колонка защищает от сюрпризов. Тип задают при создании:

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

Теперь колонка Сумма принимает только числа, а Код — строки не длиннее 11 символов. Значение другого типа платформа приведёт к допустимому или заменит пустым, поэтому проверяйте результат на тестовых данных.

Приведение перед выгрузкой

Нужен текстовый файл — значения надо превратить в строки. Для чисел используйте форматирование, иначе в строку попадут пробелы-разделители тысяч:

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

Здесь ЧДЦ=2 — два знака после запятой, ЧРД=. — точка как разделитель дробной части, ЧГ=0 — без разделителя групп разрядов. Для ссылок пригодится Строка(Ссылка) или обращение к реквизиту: Значение.Код.

⚠️ Не склеивайте число со строкой через + без Формат или СтрШаблон: результат зависит от региональных настроек и может содержать неразрывные пробелы.

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

Выгрузка части колонки: сначала отбор

ВыгрузитьКолонку берёт все строки. Если нужны только некоторые, строки отбирают заранее. Есть два приёма.

Копия по условию

Скопировать принимает структуру отбора и список колонок:

Отбор = Новый Структура("Склад", "Основной");
Выборка = Таблица.Скопировать(Отбор);
Массив = Выборка.ВыгрузитьКолонку("Номенклатура");

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

Поиск строк и ручной сбор

НайтиСтроки возвращает массив строк, а не таблицу. Выгрузить колонку у него нельзя, поэтому значения собирают циклом:

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

Отбор в НайтиСтроки работает только на равенство. Для условий «больше», «содержит», «в диапазоне» используйте цикл с Если или переносите отбор в запрос, который наполнил таблицу.

ЗадачаЧто взять
Равенство одному-двум полямСкопировать(Отбор) или НайтиСтроки
Больше / меньше / подстрокаЦикл с Если
Отбор по десяткам тысяч строкУсловие в тексте запроса

Экспорт колонки в файл

Три рабочих варианта: текст, CSV-строка и Excel.

Текстовый файл, одно значение на строку

Текст = Новый ТекстовыйДокумент;
Для Каждого Значение Из Таблица.ВыгрузитьКолонку("Номенклатура") Цикл
    Текст.ДобавитьСтроку(Строка(Значение));
КонецЦикла;
Текст.Записать("C:\Temp\nomenklatura.txt", КодировкаТекста.UTF8);

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

Одна строка с разделителем

Для вставки в параметр или в CSV собирают всё в одну строку. Метод СтрСоединить доступен с платформы 8.3.6:

Строка = СтрСоединить(Таблица.ВыгрузитьКолонку("Код"), ";");

Он принимает массив строк. Если в массиве числа или ссылки, сначала приведите их к строке, как в разделе про типы.

Excel через табличный документ

Документ = Новый ТабличныйДокумент;
Номер = 1;
Для Каждого Значение Из Таблица.ВыгрузитьКолонку("Номенклатура") Цикл
    Документ.Область(Номер, 1).Текст = Строка(Значение);
    Номер = Номер + 1;
КонецЦикла;
Документ.Записать("C:\Temp\nomenklatura.xlsx", ТипФайлаТабличногоДокумента.XLSX);

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

💡 На больших объёмах запись ячеек по одной медленна. Для сотен тысяч значений лучше текстовый или CSV-файл: Excel откроет его без потерь.

Пустые значения и ошибки

В колонке попадаются пустые строки, Неопределено, нулевые числа, пустые ссылки. Для файла и для параметра запроса они обычно не нужны.

Выбросить пустые

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

ЗначениеЗаполнено считает незаполненными пустую строку, пустую ссылку, Неопределено, Null, число 0 и пустую дату. Если ноль для вас — нормальное значение, например остаток, проверяйте явно: Значение <> Неопределено.

Что делать с ошибками

СообщениеПричинаЧто делать
Поле объекта не обнаруженоОпечатка в имени колонки или колонки нетСверьтесь со списком Таблица.Колонки
Значение не является значением объектного типаОбращение к реквизиту у пустого значенияПроверьте ЗначениеЗаполнено до обращения
Индекс выходит за границыИндекс колонки больше Колонки.Количество() - 1Индексы с нуля
Пустой массивВ таблице нет строкПроверьте Таблица.Количество()

Чтобы код не падал на неизвестной структуре, проверяйте колонку заранее:

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

Куда ещё пригодится выгруженная колонка

Массив из ВыгрузитьКолонку — удобный вход для других операций. Три типовых случая.

Параметр запроса с условием «В»

Список ссылок из колонки передают в запрос как массив:

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

Колонка должна содержать ссылки, а не строки с наименованиями. Иначе условие не сработает. Если в массиве тысячи значений, лучше передать таблицу значений во временную таблицу запроса: условие В с очень длинным списком работает медленнее соединения.

Проверка вхождения

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

Если Таблица.Найти("Болт М8", "Номенклатура") <> Неопределено Тогда
    Сообщить("Позиция уже есть в таблице");
КонецЕсли;

Метод возвращает первую найденную строку или Неопределено. Сравнение идёт на точное равенство.

Обратная операция: загрузить колонку

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

Для Индекс = 0 По Таблица.Количество() - 1 Цикл
    Таблица[Индекс].Номенклатура = Массив[Индекс];
КонецЦикла;

Размеры массива и таблицы должны совпадать, иначе получите ошибку выхода за границы. Проверьте Массив.Количество() = Таблица.Количество() до цикла.

Обработки и отчёты: откуда берётся таблица

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

  • 📦 результат запроса: Результат.Выгрузить() возвращает таблицу значений со всеми колонками выборки;
  • 📋 табличная часть документа: Объект.Товары.Выгрузить() даёт копию табличной части, её можно менять без риска для документа;
  • 🧾 реквизит формы типа «Таблица значений»: к нему обращаются через РеквизитФормыВЗначение("ИмяРеквизита").

Во всех трёх случаях дальше работает один и тот же ВыгрузитьКолонку. Для табличной части можно вызвать его и напрямую: Объект.Товары.ВыгрузитьКолонку("Номенклатура").

Что быстрее: выгрузка, цикл или запрос

Сравнение по принципу, а не по замерам: цифры зависят от платформы, железа и данных.

СпособСкоростьКогда выбирать
ВыгрузитьКолонкуБыстро, вся работа внутри платформыНужен массив всей колонки
Цикл по строкамМедленнее, в каждой итерации выполняется ваш кодНужны условия, расчёты, приведение
СвернутьБыстро для уникальных значенийНужны уникальные и суммы
Условие в запросеБыстрее всего для больших выборокДанные берутся из базы

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

Замерить свой случай просто:

Начало = ТекущаяУниверсальнаяДатаВМиллисекундах();
Массив = Таблица.ВыгрузитьКолонку("Номенклатура");
Сообщить("Время, мс: " + (ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало));

Прогоните оба варианта на реальном объёме, на тестовой базе. В рабочей не гоняйте тяжёлые замеры в часы закрытия периода.

Перед выгрузкой колонки
Выполнено: 0 / 5

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

Как выгрузить колонку таблицы значений в массив?
Вызовите Таблица.ВыгрузитьКолонку("ИмяКолонки"). Метод вернёт массив значений в порядке строк. Колонку можно указать по имени, индексу (с нуля) или объектом колонки.
Как получить только уникальные значения колонки?
Сделайте копию таблицы, вызовите Копия.Свернуть("ИмяКолонки") и выгрузите колонку из копии. Исходная таблица останется нетронутой.
Можно ли выгрузить сразу несколько колонок?
Один вызов ВыгрузитьКолонку возвращает одну колонку. Для нескольких вызовите его для каждой или создайте копию таблицы с нужными колонками методом Скопировать(, "Колонка1, Колонка2").
Как выгрузить колонку в файл Excel?
Выведите значения в ячейки табличного документа и вызовите Записать с типом ТипФайлаТабличногоДокумента.XLSX. Для больших объёмов быстрее писать в текстовый файл.
Меняет ли выгрузка саму таблицу?
Нет. Массив независим от таблицы. Таблицу меняет только Свернуть, поэтому его применяют к копии.