Колонка таблицы значений в массив, Excel и XML: рабочие приёмы для 1С 8.3
Содержание
Чтобы выгрузить колонку ТЗ (таблицы значений) в 1С, вызовите метод ТаблицаЗначений.ВыгрузитьКолонку("ИмяКолонки"): он вернёт Массив со значениями этой колонки во всех строках, в том же порядке. Код выполняется на сервере, в толстом клиенте или во внешнем соединении — на тонком клиенте таблицы значений нет.
Способов на самом деле несколько, и выбирают их по цели. Нужен список ссылок для отбора в запросе — хватит ВыгрузитьКолонку. Нужны только уникальные значения — сначала Свернуть. Нужно отдать колонку бухгалтеру или во внешнюю систему — выводят в табличный документ и сохраняют как XLSX или сериализуют в XML/JSON. Ниже каждый вариант с кодом.
Что проверить в таблице до выгрузки колонки
Перед выгрузкой ответьте себе на три вопроса. От них зависит, какой код писать.
- 📍 Где выполняется код. Таблица значений живёт на сервере. В управляемой форме на клиенте её нет: строка
Новый ТаблицаЗначенийтам даст ошибкуТип не определен (ТаблицаЗначений). Выгрузку делайте в процедуре с директивой&НаСервереили в серверном общем модуле. - 🏷️ Как точно называется колонка. Имя колонки — это идентификатор, а не заголовок. В запросе это псевдоним поля после
КАК. Список имён можно вывести отладчиком или кодом черезТЗ.Колонки. - 🧩 Какие типы лежат в колонке. Если колонка пришла из запроса с левым соединением, в ней бывают
Null. Если таблицу собирали вручную без описания типов — там может быть что угодно, вплоть доНеопределено.
Быстро посмотреть структуру таблицы помогает такой фрагмент:
Для Каждого Колонка Из ТЗ.Колонки Цикл
Сообщить(Колонка.Имя + " | " + Строка(Колонка.ТипЗначения));
КонецЦикла;
Сообщить("Строк: " + Формат(ТЗ.Количество(), "ЧН=0; ЧГ=0"));
Пустое ТипЗначения у колонки значит, что тип не задан и в ней может лежать значение любого типа. Для массива это не страшно, а для передачи таблицы параметром в запрос уже важно.
Метод ВыгрузитьКолонку: синтаксис и три способа указать колонку
Метод принимает один параметр — колонку. Её можно передать тремя способами:
| Как указать колонку | Пример | Когда удобно |
|---|---|---|
| Именем (строка) | ТЗ.ВыгрузитьКолонку("Номенклатура") | В 9 случаях из 10, код читается сразу |
| Индексом (число) | ТЗ.ВыгрузитьКолонку(0) | Колонки создаются динамически, имя заранее неизвестно |
| Объектом колонки | ТЗ.ВыгрузитьКолонку(ТЗ.Колонки.Номенклатура) | Колонка уже получена из ТЗ.Колонки в цикле |
Индексы колонок начинаются с нуля. В таблице из трёх колонок последняя имеет индекс 2.
Полный пример: собрать таблицу, выгрузить колонку и обойти полученный массив.
&НаСервере
Процедура ВыгрузитьКолонкуНаСервере()
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Товар = "Бумага А4";
НоваяСтрока.Количество = 10;
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Товар = "Скрепки";
НоваяСтрока.Количество = 3;
МассивТоваров = ТЗ.ВыгрузитьКолонку("Товар");
Для Каждого Товар Из МассивТоваров Цикл
Сообщить(Товар);
КонецЦикла;
КонецПроцедуры
После выполнения МассивТоваров содержит два элемента: «Бумага А4» и «Скрепки». Связи с таблицей у массива нет. Если потом изменить строку таблицы, массив не изменится.
Обратная операция — ЗагрузитьКолонку(Массив, Колонка). Она записывает элементы массива в колонку построчно: первый элемент в первую строку, второй во вторую. Удобно, когда значения пересчитали отдельно и хотите вернуть их в таблицу.
Тот же метод есть у табличной части объекта (ДокументОбъект.Товары.ВыгрузитьКолонку("Номенклатура")) и у коллекции строк дерева значений (Дерево.Строки.ВыгрузитьКолонку(...)). У дерева выгружается только текущий уровень, вложенные строки в массив не попадут.
Уникальные значения, сортировка и группировка перед выгрузкой
ВыгрузитьКолонку отдаёт значения из всех строк, включая повторы. В документе на 200 строк с 15 разными товарами вы получите массив из 200 элементов. Для отбора в запросе это лишняя нагрузка, а для отчёта — путаница.
Чтобы получить уникальные значения, сверните копию таблицы по нужной колонке:
КопияТЗ = ТЗ.Скопировать(, "Номенклатура");
КопияТЗ.Свернуть("Номенклатура");
КопияТЗ.Сортировать("Номенклатура");
УникальныеТовары = КопияТЗ.ВыгрузитьКолонку("Номенклатура");
Что здесь происходит:
Скопировать(, "Номенклатура")создаёт новую таблицу только с одной колонкой. Исходная таблица остаётся нетронутой.Свернуть("Номенклатура")оставляет по одной строке на каждое значение.Сортироватьупорядочивает строки. Ссылки сортируются по представлению, числа и даты — по значению.ВыгрузитьКолонкуотдаёт уже чистый массив.
Не сворачивайте исходную таблицу, если она нужна дальше: Свернуть меняет её на месте, и остальные колонки пропадут.
Если нужны не только значения, но и суммы по ним, передайте второй параметр: КопияТЗ.Свернуть("Номенклатура", "Количество, Сумма"). Колонки ресурсов при этом нужно оставить в копии: ТЗ.Скопировать(, "Номенклатура, Количество, Сумма").
Нужна выборка по условию — например, только строки с количеством больше нуля? Передайте в Скопировать массив строк, найденных через НайтиСтроки по структуре отбора, или отберите значения в цикле. НайтиСтроки ищет только по точному совпадению, поэтому условие «больше нуля» проще проверить в цикле.
В типовых конфигурациях на БСП есть функция ОбщегоНазначенияКлиентСервер.СвернутьМассив(Массив). Она убирает повторы из уже готового массива и работает и на клиенте.
Колонка из результата запроса и из табличной части формы
Чаще всего колонку берут не из ручной таблицы, а из результата запроса. У самого РезультатЗапроса метода ВыгрузитьКолонку нет, поэтому результат сначала выгружают в таблицу:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| РеализацияТоваров.Контрагент КАК Контрагент
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваров
|ГДЕ
| РеализацияТоваров.Дата МЕЖДУ &Начало И &Конец
| И РеализацияТоваров.Проведен";
Запрос.УстановитьПараметр("Начало", НачалоМесяца(ТекущаяДатаСеанса()));
Запрос.УстановитьПараметр("Конец", КонецМесяца(ТекущаяДатаСеанса()));
Контрагенты = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Контрагент");
Здесь РАЗЛИЧНЫЕ уже убрал повторы на стороне СУБД, и сворачивать ничего не нужно. Это быстрее, чем выгружать все строки и сворачивать таблицу в памяти.
Готовый массив удобно передать в следующий запрос параметром:
Запрос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С, и путь должен быть доступен учётной записи, под которой работает служба сервера.
Ошибки при выгрузке колонки и как их исправить
Ещё одна неочевидная ловушка — большой массив в параметре запроса. Список из десятков тысяч ссылок в условии В (&Список) работает медленно. В таком случае передайте в запрос саму таблицу значений и поместите её во временную таблицу: ВЫБРАТЬ Т.Ссылка ПОМЕСТИТЬ ВТ_Список ИЗ &ТЗ КАК Т. Колонки таблицы при этом должны иметь заданный тип, иначе запрос не выполнится.
Частые вопросы
Сохраняется ли порядок строк при выгрузке колонки?
Можно ли выгрузить сразу две колонки?
ТЗ.Скопировать(, "Колонка1, Колонка2") — получите таблицу только с нужными колонками.Меняется ли массив, если изменить таблицу после выгрузки?
Что вернёт метод для пустой таблицы?
Количество() равно нулю. Ошибки не будет, но перед обращением к Массив[0] проверяйте количество.Есть ли ВыгрузитьКолонку у списка значений?
ВыгрузитьЗначения(), он возвращает массив значений списка без представлений.