Как создать внешнюю обработку в 1С для массового изменения статуса и проведения документов поступления?

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

При создании внешних обработок в 1С мы часто сталкиваемся с задачами, требующими группового изменения данных. Давайте вместе разберем, как создать такую обработку, которая позволит отобрать документы по заданному периоду, изменить в них определенный реквизит (например, статус) и затем провести их.

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

  1. Предоставлять пользователю возможность выбора периода.
  2. Отображать все документы поступления, попавшие в этот период, в удобной табличной форме.
  3. Позволять пользователю выбирать конкретные документы для обработки с помощью флажков.
  4. Изменять в выбранных документах реквизит "Статус" на значение "ПРИНЯТ".
  5. Проводить измененные документы.

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

Шаг 1: Создание внешней обработки и её формы

Прежде всего, нам необходимо создать основу для нашей работы – новый файл внешней обработки. Мы будем работать в режиме Конфигуратора 1С.

  1. Откройте Конфигуратор 1С.
  2. Перейдите в меню Файл -> Новый.
  3. В появившемся окне выберите Внешняя обработка и нажмите ОК.
  4. Сохраните созданный файл на диске с расширением .epf (например, МассовоеИзменениеПоступлений.epf).

После создания файла обработки, мы увидим окно свойств обработки. Нам нужно создать форму, с которой будет взаимодействовать пользователь. Для этого:

  1. В дереве объектов обработки найдите ветку Формы.
  2. Щелкните правой кнопкой мыши по Формы и выберите Добавить -> Форма обработки.
  3. Оставьте имя по умолчанию (например, Форма) или задайте более осмысленное (например, ОсновнаяФорма) и нажмите Готово.

Перед нами откроется редактор формы, где мы будем размещать все необходимые элементы управления.

Шаг 2: Добавление элементов на форму обработки

Теперь, когда у нас есть пустая форма, давайте добавим на неё элементы, которые позволят пользователю задавать параметры отбора и видеть список документов.

  1. Период отбора документов

    Для того чтобы пользователь мог задать период, нам понадобятся два реквизита формы типа Дата.

    • В окне Реквизиты формы (обычно находится слева), нажмите кнопку Добавить реквизит формы.
    • Создайте реквизит с именем НачалоПериода, тип Дата, состав даты Дата.
    • Создайте второй реквизит с именем КонецПериода, тип Дата, состав даты Дата.
    • Перетащите эти реквизиты из окна Реквизиты на форму. Разместите их логично, например, рядом, и добавьте надписи "с" и "по".
    • Для удобства, мы можем установить значения по умолчанию. Например, НачалоПериода можно инициализировать началом текущего месяца, а КонецПериода – концом текущего дня. Это делается в модуле формы при создании на сервере.
  2. Табличное поле для отображения документов

    Чтобы вывести отобранные документы, нам потребуется табличное поле. Оно будет связано с реквизитом формы типа ТаблицаЗначений.

    • В окне Реквизиты формы добавьте новый реквизит с именем ТаблицаДокументов, тип ТаблицаЗначений.
    • Теперь нам нужно определить колонки для этой таблицы значений, которые будут отображаться в табличном поле. Для реквизита ТаблицаДокументов в окне Реквизиты откройте список Колонки и добавьте следующие:
      • Отмечен (Тип: Булево) – это будет наша колонка с флажками.
      • Ссылка (Тип: ДокументСсылка.ПоступлениеТоваровУслуг – или соответствующий тип документа в вашей конфигурации) – для хранения ссылки на сам документ.
      • Дата (Тип: Дата)
      • Номер (Тип: Строка)
      • Статус (Тип: ПеречислениеСсылка.СтатусыДокументовПоступления – или соответствующий тип перечисления в вашей конфигурации)
    • Теперь перетащите реквизит ТаблицаДокументов из окна Реквизиты на форму. Автоматически создастся табличное поле, связанное с этим реквизитом.
    • Настройте свойства табличного поля: убедитесь, что колонка Отмечен отображается как Флажок (в свойствах колонки табличного поля -> Вид).
  3. Кнопки команд

    Нам нужны кнопки для управления обработкой:

    • Кнопка Отобрать: Для выполнения запроса и заполнения табличного поля.
    • Кнопки для групповой отметки/снятия отметок: Отметить все и Снять отметки.
    • Кнопка Изменить и Провести: Главная кнопка, которая запустит процесс изменения статуса и проведения документов.

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

Шаг 3: Логика отбора документов с помощью запроса

После того как форма готова, переходим к основной логике – отбору документов. Эту логику мы реализуем в модуле формы. Предполагаем, что у нас есть команда ОтобратьДокументы, привязанная к кнопке Отобрать.

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

Начнем с обработчика команды ОтобратьДокументы на клиенте, который вызывает серверную процедуру:


&НаКлиенте
Процедура ОтобратьДокументы(Команда)
    ОтобратьДокументыНаСервере();
КонецПроцедуры

&НаСервере
Процедура ОтобратьДокументыНаСервере()
    // Очищаем текущие данные в таблице перед новым отбором
    ТаблицаДокументов.Очистить();

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

    // Устанавливаем параметры запроса из реквизитов формы
    Запрос.УстановитьПараметр("НачДата", НачалоПериода);
    Запрос.УстановитьПараметр("КонДата", КонецПериода);

    Попытка
        РезультатЗапроса = Запрос.Выполнить();
    Исключение
        Сообщить("Ошибка выполнения запроса: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

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

    // Заполняем табличное поле на форме
    Пока Выборка.Следующий() Цикл
        НоваяСтрока = ТаблицаДокументов.Добавить();
        НоваяСтрока.Отмечен = Ложь; // По умолчанию документы не отмечены
        НоваяСтрока.Ссылка = Выборка.Ссылка;
        НоваяСтрока.Дата = Выборка.Дата;
        НоваяСтрока.Номер = Выборка.Номер;
        НоваяСтрока.Статус = Выборка.Статус;
    КонецЦикла;
КонецПроцедуры

В этом коде мы сначала объявляем клиентскую процедуру ОтобратьДокументы, которая вызывает серверную процедуру ОтобратьДокументыНаСервере. В серверной процедуре мы создаем объект Запрос, формируем текст запроса для выбора документов ПоступлениеТоваровУслуг (замените на актуальный тип документа в вашей конфигурации) в заданном диапазоне дат. Параметры &НачДата и &КонДата устанавливаются из реквизитов формы НачалоПериода и КонецПериода.

После выполнения запроса мы перебираем полученную Выборку и для каждой строки создаем новую строку в реквизите формы ТаблицаДокументов, заполняя её данными из запроса. Важно, что колонка Отмечен по умолчанию устанавливается в Ложь.

Реализуем также команды для групповой отметки/снятия отметок:


&НаКлиенте
Процедура ОтметитьВсе(Команда)
    УстановитьОтметкуДляВсех(Истина);
КонецПроцедуры

&НаКлиенте
Процедура СнятьОтметки(Команда)
    УстановитьОтметкуДляВсех(Ложь);
КонецПроцедуры

&НаКлиенте
Процедура УстановитьОтметкуДляВсех(ЗначениеОтметки)
    Для Каждого СтрокаТЗ Из ТаблицаДокументов Цикл
        СтрокаТЗ.Отмечен = ЗначениеОтметки;
    КонецЦикла;
КонецПроцедуры

Эти процедуры клиентские, так как они работают только с данными на форме (ТаблицаДокументов) и не взаимодействуют напрямую с базой данных.

Шаг 4: Изменение реквизита и проведение документов

Это центральная часть нашей обработки. Мы должны перебрать все отмеченные документы в ТаблицаДокументов, получить их объекты, изменить статус и провести.

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

Начнем с обработчика команды ИзменитьИПровести на клиенте:


&НаКлиенте
Процедура ИзменитьИПровести(Команда)
    Если Не ИзменитьИПровестиНаСервере() Тогда
        Сообщить("Операция завершена с ошибками. Подробности в журнале регистрации.");
    Иначе
        Сообщить("Операция успешно завершена.");
        // После проведения, возможно, имеет смысл обновить данные на форме
        ОтобратьДокументыНаСервере();
    КонецЕсли;
КонецПроцедуры

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

Для реестра изменений нам понадобится еще один реквизит формы типа ТаблицаЗначений, назовем его, например, РеестрРезультатов, с колонками: Документ (тип Строка), Результат (тип Строка), ОписаниеОшибки (тип Строка). Можем также добавить его на форму в виде табличного поля.


&НаСервере
Функция ИзменитьИПровестиНаСервере()
    // Очищаем реестр результатов перед началом новой операции
    РеестрРезультатов.Очистить();

    Если ТаблицаДокументов.Количество() = 0 Тогда
        Сообщить("Нет документов для обработки.", СтатусСообщения.Важное);
        Возврат Истина;
    КонецЕсли;

    // Проверяем, есть ли отмеченные документы
    ЕстьОтмеченные = Ложь;
    Для Каждого СтрокаТЗ Из ТаблицаДокументов Цикл
        Если СтрокаТЗ.Отмечен Тогда
            ЕстьОтмеченные = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;

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

    // Начинаем транзакцию
    НачатьТранзакцию();
    ВсеУспешно = Истина;

    Для Каждого СтрокаТЗ Из ТаблицаДокументов Цикл
        Если Не СтрокаТЗ.Отмечен Тогда
            Продолжить; // Пропускаем неотмеченные
        КонецЕсли;

        НоваяСтрокаРеестра = РеестрРезультатов.Добавить();
        НоваяСтрокаРеестра.Документ = СтрокаТЗ.Ссылка; // Или СтрокаТЗ.Ссылка.Представление()

        Попытка
            // Получаем объект документа по ссылке
            ДокОбъект = СтрокаТЗ.Ссылка.ПолучитьОбъект();

            Если ДокОбъект = Неопределено Тогда
                НоваяСтрокаРеестра.Результат = "Ошибка";
                НоваяСтрокаРеестра.ОписаниеОшибки = "Объект документа не найден (возможно, удален).";
                ВсеУспешно = Ложь;
                Продолжить;
            КонецЕсли;

            // Изменяем реквизит "Статус"
            // Важно: замените "Статус" и "Перечисления.СтатусыДокументовПоступления.Принят"
            // на актуальные реквизиты и значения в вашей конфигурации.
            // Например, для документа "ПоступлениеТоваровУслуг" статус может быть "Состояние"
            // и перечисление "Перечисления.СостоянияДокументовПоступления"
            ДокОбъект.Статус = Перечисления.СтатусыДокументовПоступления.Принят;

            // Проводим документ
            ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

            НоваяСтрокаРеестра.Результат = "Успешно";
            НоваяСтрокаРеестра.ОписаниеОшибки = "Документ изменен и проведен.";

        Исключение
            НоваяСтрокаРеестра.Результат = "Ошибка";
            НоваяСтрокаРеестра.ОписаниеОшибки = ОписаниеОшибки();
            ВсеУспешно = Ложь;
            // Можно логировать ошибки в журнал регистрации 1С
            ЗаписатьВЖурналРегистрации("Массовое изменение документов",
                                        УровеньЖурналаРегистрации.Ошибка,
                                        Метаданные.Документы.ПоступлениеТоваровУслуг,
                                        СтрокаТЗ.Ссылка,
                                        "Ошибка при изменении/проведении документа: " + ОписаниеОшибки());
        КонецПопытки;
    КонецЦикла;

    // Завершаем транзакцию
    Если ВсеУспешно Тогда
        ЗафиксироватьТранзакцию();
        Сообщить("Все отмеченные документы успешно изменены и проведены.", СтатусСообщения.Информация);
    Иначе
        ОтменитьТранзакцию();
        Сообщить("Обнаружены ошибки. Транзакция отменена. Ни один документ не был изменен/проведен.", СтатусСообщения.Важное);
    КонецЕсли;

    Возврат ВсеУспешно;
КонецФункции

Давайте подробнее проанализируем этот код:

  1. Транзакции: Мы используем НачатьТранзакцию(), ЗафиксироватьТранзакцию() и ОтменитьТранзакцию(). Это критически важно для групповых операций. Если хотя бы один документ не сможет быть изменен или проведен, вся операция будет отменена, и база данных вернется в исходное состояние до начала транзакции. Это предотвращает частичное изменение данных и поддерживает их целостность.
  2. Перебор документов: Мы перебираем строки в нашей ТаблицаДокументов. Используем условие Если Не СтрокаТЗ.Отмечен Тогда Продолжить;, чтобы обрабатывать только те документы, которые пользователь выбрал флажком.
  3. Получение объекта документа: Для изменения реквизитов и проведения нам нужен не просто ссылка, а сам объект документа. Мы получаем его методом СтрокаТЗ.Ссылка.ПолучитьОбъект(). Всегда проверяйте, что ДокОбъект не равен Неопределено, так как документ мог быть удален другим пользователем.
  4. Изменение реквизита: Мы присваиваем новое значение реквизиту Статус. Обратите внимание, что значения перечислений обычно хранятся в объекте Перечисления (например, Перечисления.СтатусыДокументовПоступления.Принят). Убедитесь, что вы используете правильное имя перечисления и его значения, соответствующие вашей конфигурации.
  5. Проведение документа: Для проведения документа мы используем метод ДокОбъект.Записать(РежимЗаписиДокумента.Проведение). РежимЗаписиДокумента.Проведение указывает системе, что документ должен быть проведен. Если нам нужно было бы только записать документ без проведения, мы бы использовали РежимЗаписиДокумента.Запись.
  6. Обработка ошибок и реестр результатов: Каждый документ обрабатывается в блоке Попытка...Исключение. Это позволяет нам перехватывать ошибки, возникающие при работе с конкретным документом (например, проблемы с блокировками, некорректные данные, нехватка остатков при оперативном проведении и т.п.), и не прерывать весь процесс. Информация об успешности или ошибке записывается в РеестрРезультатов, который отображается на форме и дает пользователю обратную связь. Ошибки также рекомендуется записывать в Журнал регистрации 1С для последующего анализа.
  7. Клиент-серверное взаимодействие: Важно помнить, что операции с базой данных (запросы, запись, проведение) всегда выполняются на сервере. Поэтому мы используем директиву &НаСервере для процедур и функций, которые обращаются к данным. Процедуры, работающие только с элементами формы (как УстановитьОтметкуДляВсех), могут быть клиентскими (&НаКлиенте).

Шаг 5: Размещение и запуск обработки

После того как вы завершили разработку и отладку обработки в Конфигураторе, её можно использовать в режиме 1С:Предприятие.

  1. Запуск из файла: Самый простой способ – это сохранить файл .epf и открыть его в режиме 1С:Предприятие через меню Файл -> Открыть....
  2. Добавление в список дополнительных обработок: Для более удобного и постоянного использования обработку можно добавить в список дополнительных отчетов и обработок типовой конфигурации. Как правило, это делается через раздел Администрирование -> Печатные формы, отчеты и обработки -> Дополнительные отчеты и обработки. Там вы сможете указать путь к вашему файлу .epf и настроить доступ к ней для пользователей.

Дополнительные рекомендации

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

← На главную