Почему не получается добавить даты в массив в цикле и возникает ошибка «Поле объекта не обнаружено (Добавить)»?

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

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

Разбор исходной ситуации и анализ кода

Рассмотрим код, который изначально вызвал затруднение у автора:


Массив = Новый Массив; 
Дата = '20231124'; 
НачМесяца = Дата(НачалоМесяца(Дата) - 68400); 
Для Шаг = 1 по 30 Цикл 
    НачМесяца = НачМесяца + 86400; 
    Массив.Добавить(НачМесяца); 
КонецЦикла;

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

Причина №1: Неправильное размещение кода в модулях

В системе 1С программный код не может существовать «сам по себе» в текстовом файле модуля. В Модуле управляемого приложения (или обычного приложения) исполняемый код, такой как создание объектов и циклы, должен обязательно располагаться внутри событийных процедур. Если написать код просто в тексте модуля (в разделе объявлений), платформа может проигнорировать его или выдать ошибку при попытке обращения к неинициализированным переменным.

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


Процедура ПриНачалеРаботыСистемы()
    ДатМассив = Новый Массив;
    ТекущаяДата = НачалоМесяца(ТекущаяДата());
    // Логика заполнения массива
КонецПроцедуры

Причина №2: Особенности работы отладчика

Часто новички пытаются проверить работу кода, используя окно «Вычислить выражение» в конфигураторе. Когда вы вводите там команду ДатМассив.Добавить(Значение), система может вернуть ошибку. Почему это происходит?

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

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

Работа с датами: исправляем логические ошибки

В исходном примере автор использовал конструкцию НачалоМесяца(Дата) - 68400. Число 68400 — это количество секунд в 19 часах. Вероятно, автор хотел «отмотать» время назад, но в 1С сутки состоят из 86400 секунд. Кроме того, функции НачалоМесяца() и КонецМесяца() уже возвращают тип Дата, поэтому дополнительное использование функции Дата() избыточно.

Рассмотрим, как правильно организовать цикл для получения всех дней месяца. Вместо фиксированного цикла Для Шаг = 1 по 30, который будет давать ошибку в месяцах, где 28 или 31 день, лучше использовать цикл Пока.

Вариант №1: Использование цикла «Пока»

Этот способ является наиболее надежным, так как мы не зависим от количества дней в конкретном месяце.


Процедура ЗаполнитьМассивДат(ПроизвольнаяДата)
    МассивДней = Новый Массив;
    
    ДатаНачала = НачалоМесяца(ПроизвольнаяДата);
    ДатаОкончания = КонецМесяца(ПроизвольнаяДата);
    
    ВспомогательнаяДата = ДатаНачала;
    
    Пока ВспомогательнаяДата <= ДатаОкончания Цикл
        МассивДней.Добавить(ВспомогательнаяДата);
        // Прибавляем ровно одни сутки (86400 секунд)
        ВспомогательнаяДата = ВспомогательнаяДата + 86400; 
    КонецЦикла;
    
    Сообщить("В массиве элементов: " + МассивДней.Количество());
КонецПроцедуры

Вариант №2: Цикл «Для» с определением количества дней

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


Дата = ТекущаяДата();
КоличествоДней = День(КонецМесяца(Дата));
Начало = НачалоМесяца(Дата);

МассивДат = Новый Массив;

Для НомерДня = 0 По КоличествоДней - 1 Цикл
    МассивДат.Добавить(Начало + (НомерДня * 86400));
КонецЦикла;

Альтернатива: Использование запросов

Для более опытных разработчиков существует способ получения списка дат через запрос. Это полезно, когда нужно соединить календарь с данными из базы. Мы можем использовать временную таблицу с числами и функцию ДОБАВИТЬКДАТЕ.

Основные преимущества такого подхода:

Итоги

Подведем итог нашему разбору. Чтобы ваш код по работе с массивами дат «взлетел», придерживайтесь следующих правил:

  1. Соблюдайте структуру модуля: Пишите исполняемый код внутри процедур (например, ПриНачалеРаботыСистемы).
  2. Проверяйте инициализацию: Убедитесь, что переменная Массив действительно создана через Новый Массив до того, как вы начнете вызывать метод Добавить().
  3. Используйте функции платформы: НачалоМесяца(), КонецМесяца() и День() помогут избежать ошибок «360 дней в году».
  4. Будьте внимательны с отладчиком: Не пытайтесь выполнять модифицирующие команды в окне вычисления выражений, просто анализируйте текущее состояние объектов.

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

← На главную