Колонка таблицы значений в массив, Excel и XML: рабочие приёмы для 1С 8.3

· 9 мин

Содержание

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

Способов на самом деле несколько, и выбирают их по цели. Нужен список ссылок для отбора в запросе — хватит ВыгрузитьКолонку. Нужны только уникальные значения — сначала Свернуть. Нужно отдать колонку бухгалтеру или во внешнюю систему — выводят в табличный документ и сохраняют как XLSX или сериализуют в XML/JSON. Ниже каждый вариант с кодом.

Что проверить в таблице до выгрузки колонки

Перед выгрузкой ответьте себе на три вопроса. От них зависит, какой код писать.

  • 📍 Где выполняется код. Таблица значений живёт на сервере. В управляемой форме на клиенте её нет: строка Новый ТаблицаЗначений там даст ошибку Тип не определен (ТаблицаЗначений). Выгрузку делайте в процедуре с директивой &НаСервере или в серверном общем модуле.
  • 🏷️ Как точно называется колонка. Имя колонки — это идентификатор, а не заголовок. В запросе это псевдоним поля после КАК. Список имён можно вывести отладчиком или кодом через ТЗ.Колонки.
  • 🧩 Какие типы лежат в колонке. Если колонка пришла из запроса с левым соединением, в ней бывают Null. Если таблицу собирали вручную без описания типов — там может быть что угодно, вплоть до Неопределено.

Быстро посмотреть структуру таблицы помогает такой фрагмент:

Для Каждого Колонка Из ТЗ.Колонки Цикл
	Сообщить(Колонка.Имя + " | " + Строка(Колонка.ТипЗначения));
КонецЦикла;
Сообщить("Строк: " + Формат(ТЗ.Количество(), "ЧН=0; ЧГ=0"));

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

Метод ВыгрузитьКолонку: синтаксис и три способа указать колонку

Метод принимает один параметр — колонку. Её можно передать тремя способами:

Как указать колонкуПримерКогда удобно
Именем (строка)ТЗ.ВыгрузитьКолонку("Номенклатура")В 9 случаях из 10, код читается сразу
Индексом (число)ТЗ.ВыгрузитьКолонку(0)Колонки создаются динамически, имя заранее неизвестно
Объектом колонкиТЗ.ВыгрузитьКолонку(ТЗ.Колонки.Номенклатура)Колонка уже получена из ТЗ.Колонки в цикле

Индексы колонок начинаются с нуля. В таблице из трёх колонок последняя имеет индекс 2.

Полный пример: собрать таблицу, выгрузить колонку и обойти полученный массив.

&НаСервере
Процедура ВыгрузитьКолонкуНаСервере()

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

	НоваяСтрока = ТЗ.Добавить();
	НоваяСтрока.Товар = "Бумага А4";
	НоваяСтрока.Количество = 10;

	НоваяСтрока = ТЗ.Добавить();
	НоваяСтрока.Товар = "Скрепки";
	НоваяСтрока.Количество = 3;

	МассивТоваров = ТЗ.ВыгрузитьКолонку("Товар");

	Для Каждого Товар Из МассивТоваров Цикл
		Сообщить(Товар);
	КонецЦикла;

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

После выполнения МассивТоваров содержит два элемента: «Бумага А4» и «Скрепки». Связи с таблицей у массива нет. Если потом изменить строку таблицы, массив не изменится.

Обратная операция — ЗагрузитьКолонку(Массив, Колонка). Она записывает элементы массива в колонку построчно: первый элемент в первую строку, второй во вторую. Удобно, когда значения пересчитали отдельно и хотите вернуть их в таблицу.

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

Уникальные значения, сортировка и группировка перед выгрузкой

ВыгрузитьКолонку отдаёт значения из всех строк, включая повторы. В документе на 200 строк с 15 разными товарами вы получите массив из 200 элементов. Для отбора в запросе это лишняя нагрузка, а для отчёта — путаница.

Чтобы получить уникальные значения, сверните копию таблицы по нужной колонке:

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

Что здесь происходит:

  1. Скопировать(, "Номенклатура") создаёт новую таблицу только с одной колонкой. Исходная таблица остаётся нетронутой.
  2. Свернуть("Номенклатура") оставляет по одной строке на каждое значение.
  3. Сортировать упорядочивает строки. Ссылки сортируются по представлению, числа и даты — по значению.
  4. ВыгрузитьКолонку отдаёт уже чистый массив.

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

Если нужны не только значения, но и суммы по ним, передайте второй параметр: КопияТЗ.Свернуть("Номенклатура", "Количество, Сумма"). Колонки ресурсов при этом нужно оставить в копии: ТЗ.Скопировать(, "Номенклатура, Количество, Сумма").

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

В типовых конфигурациях на БСП есть функция ОбщегоНазначенияКлиентСервер.СвернутьМассив(Массив). Она убирает повторы из уже готового массива и работает и на клиенте.

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

Чаще всего колонку берут не из ручной таблицы, а из результата запроса. У самого РезультатЗапроса метода ВыгрузитьКолонку нет, поэтому результат сначала выгружают в таблицу:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
|	РеализацияТоваров.Контрагент КАК Контрагент
|ИЗ
|	Документ.РеализацияТоваровУслуг КАК РеализацияТоваров
|ГДЕ
|	РеализацияТоваров.Дата МЕЖДУ &Начало И &Конец
|	И РеализацияТоваров.Проведен";

Запрос.УстановитьПараметр("Начало", НачалоМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Конец", КонецМесяца(ТекущаяДатаСеанса()));

Контрагенты = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Контрагент");

Здесь РАЗЛИЧНЫЕ уже убрал повторы на стороне СУБД, и сворачивать ничего не нужно. Это быстрее, чем выгружать все строки и сворачивать таблицу в памяти.

Готовый массив удобно передать в следующий запрос параметром:

Запрос2.Текст = "... ГДЕ Взаиморасчеты.Контрагент В (&СписокКонтрагентов)";
Запрос2.УстановитьПараметр("СписокКонтрагентов", Контрагенты);

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

Табличная часть в форме документа. На клиенте Объект.Товары — это ДанныеФормыКоллекция, а не табличная часть. Метода ВыгрузитьКолонку у неё нет. Варианта два:

  • 🖥️ На сервере: Объект.Товары.Выгрузить().ВыгрузитьКолонку("Номенклатура") — сначала получаем таблицу значений, потом колонку.
  • 💻 На клиенте: обойти коллекцию циклом и добавить значения в массив через Массив.Добавить(Строка.Номенклатура).

Массив, в отличие от таблицы значений, можно вернуть с сервера на клиент. Поэтому типичная схема такая: серверная функция выгружает колонку и возвращает массив, а клиент работает уже с ним.

Как выгрузить колонку ТЗ в Excel или текстовый файл

Пользователю без доступа к коду проще всего так: если таблица выведена на форму, откройте меню Ещё → Вывести список…, оставьте отмеченной только нужную колонку и нажмите ОК. Откроется табличный документ, его можно сохранить в XLSX через меню сохранения или копировать в Excel через буфер обмена.

В коде колонку выводят в табличный документ и записывают в файл:

&НаСервере
Процедура СохранитьКолонкуВExcel(ТЗ, ИмяКолонки, ИмяФайла)

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

	ТабДок.Область("R1C1").Текст = ИмяКолонки;
	Для Индекс = 0 По Значения.ВГраница() Цикл
		НомерСтроки = Формат(Индекс + 2, "ЧГ=0");
		ТабДок.Область("R" + НомерСтроки + "C1").Текст = Строка(Значения[Индекс]);
	КонецЦикла;

	ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);

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

Первая строка — заголовок, данные идут со второй, поэтому к индексу прибавляется 2. Для массива из 50 элементов последняя заполненная ячейка — R51C1.

Формат ЧГ=0 нужен, чтобы номер строки не превратился в «1 001» с пробелом-разделителем. Без него на тысячной строке адрес ячейки сломается.

Для простого списка без оформления подойдёт текстовый файл — его откроет любой редактор и можно загрузить в Excel как CSV:

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

Файл записывается туда, где выполняется код. Если процедура серверная, файл появится на сервере 1С, а не на компьютере пользователя. Чтобы отдать файл пользователю в клиент-серверной базе, запишите его во временное хранилище и скачайте на клиенте.

Экспорт колонки в XML и JSON для внешних систем

Внешней системе обычно нужны не представления, а идентификаторы. Строка(Ссылка) даст наименование «ООО Ромашка», которое не уникально и меняется. Отдавайте код, ИНН или уникальный идентификатор ссылки.

Выгрузка колонки ссылок в JSON как массива строк-GUID:

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

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Идентификаторы);
ТекстJSON = ЗаписьJSON.Закрыть();

Глобальный метод ЗаписатьJSON понимает массивы, структуры, соответствия и примитивные типы. Ссылки на объекты он напрямую не запишет — поэтому их сначала превращаем в строки.

Для обмена между базами 1С подходит XML через сериализатор XDTO. Он сохраняет массив вместе с типами, и вторая база восстановит ссылки:

ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяФайла, "UTF-8");
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ТЗ.ВыгрузитьКолонку("Номенклатура"));
ЗаписьXML.Закрыть();
ФорматЧто передаётКому подходит
JSON-массив строкКоды, ИНН, GUIDВеб-сервисы, сайты, сторонние программы
XML через XDTOЗначения с типамиДругая база 1С с той же структурой
TXT/CSVТекст по строке на значениеРучная проверка, загрузка в Excel

Автоматизация: общая функция и внешняя обработка

Если колонку уникальных значений вы получаете в нескольких местах, вынесите код в серверный общий модуль. Тогда вызов займёт одну строку.

// Общий модуль РаботаСТаблицами (Сервер, Вызов сервера)
Функция УникальныеЗначенияКолонки(ТЗ, ИмяКолонки, БезПустых = Истина) Экспорт

	Копия = ТЗ.Скопировать(, ИмяКолонки);
	Копия.Свернуть(ИмяКолонки);

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

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

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

ЗначениеЗаполнено отсекает пустые ссылки, пустые строки, нули и Неопределено. Если ноль для вас осмысленное значение, передайте БезПустых = Ложь.

В типовой конфигурации общий модуль добавляют не в основную конфигурацию, а в расширение — так обновления пройдут без ручного объединения. Для разовых задач удобнее внешняя обработка: в ней пишется запрос, колонка выгружается одной из процедур выше, а файл сохраняется на компьютер пользователя. Внешнюю обработку открывают через Файл → Открыть, права на открытие внешних обработок должны быть у пользователя.

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

Ошибки при выгрузке колонки и как их исправить

Диагностика: выберите симптом

Ещё одна неочевидная ловушка — большой массив в параметре запроса. Список из десятков тысяч ссылок в условии В (&Список) работает медленно. В таком случае передайте в запрос саму таблицу значений и поместите её во временную таблицу: ВЫБРАТЬ Т.Ссылка ПОМЕСТИТЬ ВТ_Список ИЗ &ТЗ КАК Т. Колонки таблицы при этом должны иметь заданный тип, иначе запрос не выполнится.

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

Сохраняется ли порядок строк при выгрузке колонки?
Да. Элемент массива с индексом 0 соответствует первой строке таблицы, индекс 1 — второй и так далее.
Можно ли выгрузить сразу две колонки?
Нет, метод работает с одной колонкой. Для нескольких используйте ТЗ.Скопировать(, "Колонка1, Колонка2") — получите таблицу только с нужными колонками.
Меняется ли массив, если изменить таблицу после выгрузки?
Нет. Массив — независимая копия значений. Изменения в таблице на него не влияют, и наоборот.
Что вернёт метод для пустой таблицы?
Пустой массив: Количество() равно нулю. Ошибки не будет, но перед обращением к Массив[0] проверяйте количество.
Есть ли ВыгрузитьКолонку у списка значений?
У списка значений есть похожий метод ВыгрузитьЗначения(), он возвращает массив значений списка без представлений.