Колонка таблицы значений в массив: как получить и сохранить в файл
Содержание
Выгрузить одну колонку из таблицы значений 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 Цикл
Таблица[Индекс].Номенклатура = Массив[Индекс];
КонецЦикла;
Размеры массива и таблицы должны совпадать, иначе получите ошибку выхода за границы. Проверьте Массив.Количество() = Таблица.Количество() до цикла.
Обработки и отчёты: откуда берётся таблица
Таблица значений, из которой выгружают колонку, чаще всего приходит из одного из трёх мест:
- 📦 результат запроса:
Результат.Выгрузить()возвращает таблицу значений со всеми колонками выборки; - 📋 табличная часть документа:
Объект.Товары.Выгрузить()даёт копию табличной части, её можно менять без риска для документа; - 🧾 реквизит формы типа «Таблица значений»: к нему обращаются через
РеквизитФормыВЗначение("ИмяРеквизита").
Во всех трёх случаях дальше работает один и тот же ВыгрузитьКолонку. Для табличной части можно вызвать его и напрямую: Объект.Товары.ВыгрузитьКолонку("Номенклатура").
Что быстрее: выгрузка, цикл или запрос
Сравнение по принципу, а не по замерам: цифры зависят от платформы, железа и данных.
| Способ | Скорость | Когда выбирать |
|---|---|---|
ВыгрузитьКолонку | Быстро, вся работа внутри платформы | Нужен массив всей колонки |
| Цикл по строкам | Медленнее, в каждой итерации выполняется ваш код | Нужны условия, расчёты, приведение |
Свернуть | Быстро для уникальных значений | Нужны уникальные и суммы |
| Условие в запросе | Быстрее всего для больших выборок | Данные берутся из базы |
Практическое правило. Если можно получить нужную колонку прямо в запросе, не стоит выгружать в таблицу всё, а потом вырезать колонку. Запрос вернёт только нужное, и памяти понадобится меньше.
Замерить свой случай просто:
Начало = ТекущаяУниверсальнаяДатаВМиллисекундах();
Массив = Таблица.ВыгрузитьКолонку("Номенклатура");
Сообщить("Время, мс: " + (ТекущаяУниверсальнаяДатаВМиллисекундах() - Начало));
Прогоните оба варианта на реальном объёме, на тестовой базе. В рабочей не гоняйте тяжёлые замеры в часы закрытия периода.
Частые вопросы
Как выгрузить колонку таблицы значений в массив?
Таблица.ВыгрузитьКолонку("ИмяКолонки"). Метод вернёт массив значений в порядке строк. Колонку можно указать по имени, индексу (с нуля) или объектом колонки.Как получить только уникальные значения колонки?
Копия.Свернуть("ИмяКолонки") и выгрузите колонку из копии. Исходная таблица останется нетронутой.Можно ли выгрузить сразу несколько колонок?
ВыгрузитьКолонку возвращает одну колонку. Для нескольких вызовите его для каждой или создайте копию таблицы с нужными колонками методом Скопировать(, "Колонка1, Колонка2").Как выгрузить колонку в файл Excel?
Записать с типом ТипФайлаТабличногоДокумента.XLSX. Для больших объёмов быстрее писать в текстовый файл.Меняет ли выгрузка саму таблицу?
Свернуть, поэтому его применяют к копии.