Почему функция не объявлена в 1С при старте системы и как правильно выгрузить таблицы базы данных?

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

Каждый начинающий разработчик или специалист из смежной сферы IT, впервые столкнувшись с платформой 1С:Предприятие, неизбежно наталкивается на жесткие архитектурные правила этой системы. Одними из самых частых «граблей» являются непонимание клиент-серверного взаимодействия и попытки прочитать данные напрямую из закрытого файла резервной копии (.dt). В этой статье мы подробно разберем, почему возникает популярная ошибка «Процедура или функция с указанным именем не определена», как устроена работа с контекстом в 1С, и покажем правильные, надежные способы выгрузки любых таблиц базы данных в текстовый формат или XML.

Разбор первой преграды: почему нельзя работать напрямую с файлом .dt

Прежде чем писать программный код, давайте проанализируем исходные данные. Очень часто руководство ставит задачу в духе: «Вот тебе файл резервной копии, выгрузи оттуда таблицы». Начинающий специалист пытается открыть этот файл сторонними утилитами или написать к нему прямой SQL-запрос. Это в корне неверный путь.

Выясним причину: файл с расширением .dt — это не база данных. Это специализированный сжатый архив (дамп), созданный платформой 1С. Внутри него данные упакованы в проприетарный формат. Ни одна внешняя утилита, включая популярную программу Tool1CD, не умеет читать данные напрямую из архива .dt.

Рассмотрим правильный алгоритм действий по шагам:

  1. Установите платформу 1С:Предприятие на компьютер.
  2. Запустите программу в режиме запуска и нажмите кнопку «Добавить».
  3. Выберите пункт «Создание новой информационной базы» -> «Создание информационной базы без конфигурации...». Укажите пустой каталог на диске. При этом в каталоге создастся пустой файл файловой базы данных — 1Cv8.1CD.
  4. Запустите созданную базу в режиме «Конфигуратор».
  5. В главном меню перейдите по пути: Администрирование -> Загрузить информационную базу... и выберите ваш файл .dt.

Только после выполнения этих шагов архив распакуется, физические таблицы развернутся в полноценную базу данных формата .1CD (или загрузятся на SQL-сервер), и мы сможем приступить к работе с ними.

Выясняем причину ошибки «Функция не объявлена» при старте системы

Попытка автора темы решить задачу «в лоб» привела к тому, что он открыл Модуль управляемого приложения, нашел предопределенный обработчик ПриНачалеРаботыСистемы и попытался вызвать оттуда свою функцию выгрузки. Давайте разберем, почему система выдала ошибку.

В платформе 1С реализовано строгое разделение контекста выполнения кода на клиент и сервер. Клиентское приложение (тонкий клиент, веб-клиент) отвечает за отображение интерфейса и взаимодействие с пользователем. На стороне клиента категорически запрещены любые прямые обращения к базе данных — это правило безопасности и производительности. Серверный контекст имеет полный доступ к СУБД, может выполнять запросы и обрабатывать тяжелые массивы данных.

Когда автор написал серверную функцию (например, с директивой &НаСервере) внутри Модуля управляемого приложения, он нарушил правила компиляции. Модуль управляемого приложения компилируется исключительно на клиенте. Размещать в нем директиву компиляции &НаСервере синтаксически запрещено. Платформа просто игнорирует эту директиву, компилятор не видит данную функцию в клиентском контексте и выдает ошибку: «Процедура или функция с указанным именем не определена».

Как решить проблему с контекстом: два правильных пути

Рассмотрим подробнее два надежных способа вызова серверного кода для решения нашей задачи.

Вариант 1. Использование общего модуля с вызовом сервера

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

  1. В дереве конфигурации найдите ветку «Общие модули» и добавьте новый модуль. Назовем его, например, УтилитыВыгрузкиСервер.
  2. В свойствах созданного модуля обязательно установите флажки «Сервер» и «Вызов сервера». Флаг «Вызов сервера» критически важен — он разрешает клиентскому коду обращаться к процедурам этого модуля.
  3. Внутри модуля напишите вашу процедуру выгрузки, добавив к ней ключевое слово Экспорт:

Процедура ВыполнитьЭкспортДанных() Экспорт
    // Здесь располагается серверный код запроса к базе данных
КонецПроцедуры

Теперь из Модуля управляемого приложения (в событии ПриНачалеРаботыСистемы) вы сможете успешно вызвать эту процедуру:


Процедура ПриНачалеРаботыСистемы()
    УтилитыВыгрузкиСервер.ВыполнитьЭкспортДанных();
КонецПроцедуры

Вариант 2. Создание внешней обработки (рекомендуемый способ)

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

Посмотрим на преимущества этого подхода:

Чтобы создать внешнюю обработку, в Конфигураторе выберите Файл -> Новый -> Внешняя обработка. На вкладке «Формы» добавьте форму обработки, разместите на ней кнопку и в модуле формы напишите код вызова серверной процедуры.

Почему в файле выгрузки появились непонятные GUID вместо названий?

Автор темы столкнулся со следующей проблемой: при прямой выгрузке данных в некоторых полях вместо привычных текстовых названий (например, наименований номенклатуры или контрагентов) выгрузились длинные буквенно-цифровые строки в фигурных скобках вида {sadqwsdf-gdsgfwerewfsd-fggh-fjhj}.

Проанализируем ситуацию. В базах данных 1С все ссылочные типы данных (справочники, документы, перечисления) физически хранятся в таблицах СУБД в виде 128-битных уникальных идентификаторов — UUID (они же GUID). Текстовое представление (например, строка «Агуша») хранится в одной таблице, а в другой таблице (например, в регистре сведений) хранится лишь ссылка на эту запись в виде GUID.

Если вы делаете прямой запрос и пытаетесь неявно сложить ссылку со строкой, платформа возвращает внутренний идентификатор ссылки. Чтобы исправить это и получить понятный текст, используйте специальную функцию языка запросов 1С: ПРЕДСТАВЛЕНИЕ(ИмяПоля). Она автоматически преобразует ссылку в текстовое наименование объекта на уровне СУБД.

Критический разбор ошибок в коде автора темы

В сообщении №27 автор привел свой вариант работающего кода. Несмотря на то что у автора программа отработала, представленный код содержит серьезные ошибки, которые в реальной базе приведут к аварийному завершению работы системы.

Проанализируем эти ошибки:

  1. Грубая синтаксическая ошибка: Строка query_result = query.Выполнить.Выгрузить; написана некорректно. В языке 1С вызовы методов объекта обязательно требуют наличия круглых скобок, даже если у них нет параметров. Правильная запись выглядит так: РезультатЗапроса = Запрос.Выполнить().Выгрузить();. Без скобок код выдаст ошибку компиляции.
  2. Ошибка несоответствия типов при сложении строк: Строка temp_row_str = temp_row_str + temp_cell; гарантированно вызовет критическую ошибку «Несоответствие типов», как только в ячейке таблицы окажется число, дата, булево значение или значение NULL (которое очень часто встречается в реальных базах при соединении таблиц). В 1С нельзя складывать строку с другими типами данных без явного преобразования. Необходимо использовать встроенную функцию Строка().
  3. Проблема записи файла на сервере: Код file_stream = Новый ЗаписьТекста("d:\query_result.txt"); жестко прописывает путь к локальному диску D:\. Если база данных работает в клиент-серверном режиме (на SQL-сервере), этот код будет выполняться на стороне сервера приложений. Программа попытается создать файл на физическом диске серверного компьютера. Если у сервера нет диска D или у системной службы 1С нет прав на запись в корень этого диска, программа завершится аварийно с ошибкой доступа.

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

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

Разберем по шагам создание процедуры на сервере:


&НаСервере
Процедура ВыполнитьВыгрузкуНаСервере(ИмяПутиКФайлу)
    
    // 1. Инициализируем запрос с получением строковых представлений полей
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ДанныеКомпании.Период КАК Период,
        |	ПРЕДСТАВЛЕНИЕ(ДанныеКомпании.Организация) КАК ОрганизацияПредеставление,
        |	ДанныеКомпании.ИНН КАК ИНН,
        |	ДанныеКомпании.КПП КАК КПП
        |ИЗ
        |	РегистрСведений.Данные_Компании КАК ДанныеКомпании";
    
    // Выполняем запрос и выгружаем результат в таблицу значений
    ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
    
    КоличествоКолонок = ТаблицаРезультата.Колонки.Количество();
    
    // 2. Безопасно открываем файл для записи. 
    // На сервере лучше использовать временные каталоги во избежание проблем с правами доступа.
    ЗаписьТекста = Новый ЗаписьТекста(ИмяПутиКФайлу, КодировкаТекста.UTF8);
    
    // 3. Обходим строки таблицы результатов
    Для Каждого СтрокаТаблицы Из ТаблицаРезультата Цикл
        СтрокаДляЗаписи = "";
        
        Для ИндексКолонки = 0 По КоличествоКолонок - 1 Цикл
            ТекущееЗначение = СтрокаТаблицы[ИндексКолонки];
            
            // Защищаем код от падения по ошибке "Несоответствие типов"
            ТекстовоеЗначение = Строка(ТекущееЗначение);
            
            СтрокаДляЗаписи = СтрокаДляЗаписи + ТекстовоеЗначение;
            
            // Добавляем разделитель колонок (табуляцию), если это не последняя колонка
            Если ИндексКолонки < КоличествоКолонок - 1 Тогда
                СтрокаДляЗаписи = СтрокаДляЗаписи + Символы.Таб;
            КонецЕсли;
        КонецЦикла;
        
        // Записываем сформированную строку в файл
        ЗаписьТекста.ЗаписатьСтроку(СтрокаДляЗаписи);
    КонецЦикла;
    
    // Обязательно закрываем поток записи файла
    ЗаписьТекста.Закрыть();
    
КонецПроцедуры

Для того чтобы данный код успешно работал в клиент-серверном режиме работы базы данных, путь к файлу должен формироваться на стороне клиента (например, через стандартный диалог выбора файла), после чего передаваться параметром на сервер. Это гарантирует, что файл запишется именно туда, куда ожидает пользователь.

Альтернативное решение: выгрузка всех таблиц с помощью Tool1CD без написания кода

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

Утилита поддерживает работу через командную строку (CLI), что позволяет автоматизировать экспорт всей базы данных в формат XML одной командой.

Посмотрим на пример использования консольной команды:

  1. Откройте командную строку Windows (cmd).
  2. Перейдите к каталогу, где находится исполняемый файл утилиты.
  3. Выполните следующую команду:

Tool1CD.exe -eax "C:\FolderForExport" "C:\My1CBaseFolder\1Cv8.1CD"

Разберем параметры этой команды:

Данный способ работает мгновенно, не требует запуска платформы 1С и написания программного кода, что делает его идеальным инструментом для системных администраторов и сторонних разработчиков при решении экстренных задач интеграции.

← На главную