Как получить имена всех планов счетов и регистров бухгалтерии в 1С?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

Способ 1. Получение имен планов счетов через коллекцию метаданных

Для обращения к дереву метаданных конфигурации в платформе 1С предусмотрен глобальный контекст Метаданные. Попытка обратиться к типу ОбъектМетаданныхКонфигурация напрямую в программном коде вызовет ошибку Переменная не определена, так как это тип описания объекта в синтакс-помощнике, а не экземпляр объекта.

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


Для Каждого ПланСчетов Из Метаданные.ПланыСчетов Цикл
    Сообщить("Имя: " + ПланСчетов.Имя + " | Синоним: " + ПланСчетов.Синоним);
КонецЦикла;

Проанализируем альтернативный вариант — обход по числовому индексу коллекции. Здесь разработчики часто допускают ошибку в границах цикла:


// Ошибочный вариант: коллекции в 1С индексируются с нуля!
// Для Номер = 1 По Метаданные.ПланыСчетов.Количество() Цикл ...

// Корректный индексный обход:
ВсегоПланов = Метаданные.ПланыСчетов.Количество();
Для Индекс = 0 По ВсегоПланов - 1 Цикл
    ПланСчетов = Метаданные.ПланыСчетов.Получить(Индекс);
    Сообщить("Имя плана счетов: " + ПланСчетов.Имя);
КонецЦикла;

Если начать цикл с единицы и дойти до значения метода Количество(), программа пропустит нулевой (первый по списку) элемент и на последней итерации завершится аварийно с ошибкой «Индекс находится за границами диапазона».

Способ 2. Сопоставление плана счетов и регистра бухгалтерии

Разберем фундаментальную ошибку при динамическом формировании текста запроса. В запросе вида:


|ИЗ
|    РегистрБухгалтерии." + ИмяОбъекта + ".ОборотыДтКт(...)

в секции ИЗ указывается строго имя Регистра бухгалтерии, а не Плана счетов. Имя плана счетов и имя регистра бухгалтерии могут совпадать лишь по соглашению разработчиков, но в конфигурациях (включая типовые решения «1С:Бухгалтерия» или «1С:ERP») они нередко различаются или один план счетов используется сразу несколькими регистрами.

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


ИмяВыбПланаСчетов = "Хозрасчетный";
ИмяНужногоРегистра = "";

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

Если ЗначениеЗаполнено(ИмяНужногоРегистра) Тогда
    Сообщить("Найден связанный регистр бухгалтерии: " + ИмяНужногоРегистра);
Иначе
    ВызватьИсключение "Для выбранного плана счетов не найден регистр бухгалтерии!";
КонецЕсли;

Ограничения виртуальной таблицы «ОборотыДтКт» и проверка прав

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

  1. Поддержка корреспонденции счетов: виртуальная таблица ОборотыДтКт существует только у тех регистров, у которых свойство Корреспонденция установлено в значение Истина. Если корреспонденция отключена, обращение к таблице вызовет синтаксическую ошибку запроса.
  2. Проверка прав доступа: перед чтением таблицы в сеансе пользователя необходимо проверять права с помощью метода ПравоДоступа, иначе запрос завершится ошибкой нарушения прав.
  3. Имя против Синонима: для пользовательского интерфейса (выпадающие списки, формы) выводим Синоним, но для сборки программного кода и запросов всегда используем свойство Имя.

Посмотрим на пример проверки возможности работы с таблицей корреспонденций:


МетаданныеРегистра = Метаданные.РегистрыБухгалтерии[ИмяНужногоРегистра];

// Проверяем права на чтение регистра
Если Не ПравоДоступа("Чтение", МетаданныеРегистра) Тогда
    ВызватьИсключение "У текущего пользователя нет прав на чтение регистра " + МетаданныеРегистра.Синоним;
КонецЕсли;

// Проверяем наличие свойства Корреспонденция
Если Не МетаданныеРегистра.Корреспонденция Тогда
    ВызватьИсключение "Регистр " + МетаданныеРегистра.Имя + " не поддерживает учет корреспонденции (таблица ОборотыДтКт недоступна)!";
КонецЕсли;

Динамическое построение запроса: как подставить имя таблицы

Язык запросов 1С не поддерживает передачу имен таблиц через параметры вида &ИмяТаблицы. Параметры запроса применимы только для значений условий в секциях ГДЕ, фильтрах виртуальных таблиц или полях выборки. Имя таблицы должно присутствовать непосредственно в теле строки запроса.

Вместо сложной и трудночитаемой конкатенации строк (знаков +) или функции СтрЗаменить рекомендуется использовать системную функцию СтрШаблон. Разберем итоговый пример:


ШаблонЗапроса = 
"ВЫБРАТЬ
|    Типовой.СчетДт КАК СчетДт,
|    Типовой.СчетКт КАК СчетКт,
|    Типовой.СуммаОборот КАК СуммаОборот
|ИЗ
|    РегистрБухгалтерии.%1.ОборотыДтКт(&ДатаНачала, &ДатаОкончания, , , , , , ) КАК Типовой";

ТекстЗапроса = СтрШаблон(ШаблонЗапроса, ИмяНужногоРегистра);

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

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

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

← На главную