Как реализовать суммирование чисел в интервалах между 100 и 100 с исключением интервалов 200 в 1С?

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

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

В данной статье мы подробно разберем, как написать обработку, которая анализирует колонку чисел и суммирует значения в интервале между 100 и 100, при этом игнорируя данные внутри вложенного интервала 200. Мы также учтем особые правила закрытия этих интервалов.

Анализ условий задачи и алгоритмическая база

Давайте проанализируем вводные данные. У нас есть таблица с одной колонкой. Пользователь может вводить любые числа. Основные правила игры следующие:

  1. Начало и конец суммирования: Число 100 выступает в роли переключателя. Встретив первую сотку, мы начинаем копить сумму. Встретив вторую — прекращаем.
  2. Исключение (пауза): Если внутри активного интервала 100 встречается число 200, суммирование приостанавливается до тех пор, пока не встретится второе число 200.
  3. Приоритет закрытия: Если интервал 200 открыт, но вместо закрывающей двухсотки встретилось число 100, оно принудительно закрывает и интервал 200, и сам основной интервал 100.
  4. Незакрытые интервалы: Если таблица закончилась, а интервал не закрыт, данные считаются по текущему состоянию флагов.

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

Разбор типичных ошибок начального кода

Рассмотрим пример кода, с которого часто начинают новички. Попробуем проанализировать ситуацию, почему простая проверка "в лоб" не работает:


Процедура КнопкаВыполнитьНажатие(Кнопка)
    Итого = 0;
    Блок = Ложь;
    Для каждого Стр Из Таблица Цикл
        Если Стр.Число = 100 Тогда
            Блок = Истина;
            Продолжить;
        КонецЕсли;
        Если Стр.Число = 200 Тогда
            Блок = Ложь;
            Продолжить;
        КонецЕсли;        
        Если Блок Тогда
            Итого = Итого + Стр.Число;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

В чем проблема этого кода? Во-первых, здесь используется только один флаг Блок. Это не позволяет программе понять, находимся ли мы внутри "сотки" или внутри "двухсотки". Во-вторых, код не учитывает, что вторая сотка должна выключать суммирование, а не подтверждать его. Если мы встретим последовательность 100, 5, 100, программа продолжит суммировать все, что идет после второй сотни, что неверно.

Проектирование правильной логики с двумя флагами

Рассмотрим более продвинутый подход. Нам понадобятся две логические переменные (типа Булево), которые будут хранить состояние наших интервалов. Назовем их ВнутриИнтервала100 и ВнутриИнтервала200.

Выясним причину, по которой это важно: переменная ВнутриИнтервала100 отвечает за глобальное разрешение суммирования, а ВнутриИнтервала200 выступает в роли "блокировщика" внутри этого разрешения.

Реализация финального алгоритма

Давайте разберем по шагам создание правильной процедуры. Мы будем использовать цикл Для каждого для обхода строк таблицы и оператор Если...ИначеЕсли для обработки ключевых чисел.


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

Проанализируем ситуацию на примере

Рассмотрим подробнее, как этот код обработает сложную последовательность чисел: 10, 100, 5, 200, 50, 200, 8, 100, 30.

  1. Число 10: Оба флага Ложь. Суммирования нет.
  2. Число 100: ВнутриИнтервала100 становится Истина.
  3. Число 5: Первый флаг активен, второй — нет. Сумма = 5.
  4. Число 200: ВнутриИнтервала200 становится Истина. Суммирование на паузе.
  5. Число 50: Второй флаг (200) активен, число игнорируется.
  6. Число 200: ВнутриИнтервала200 снова становится Ложь. Пауза снята.
  7. Число 8: Суммирование продолжается. Сумма = 5 + 8 = 13.
  8. Число 100: ВнутриИнтервала100 становится Ложь. Суммирование прекращено.
  9. Число 30: Флаги выключены. Итоговая сумма остается 13.

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

Работа с граничными условиями

При написании реальных обработок в 1С всегда стоит учитывать "плохие" данные. Рассмотрим ситуацию с незакрытыми интервалами. По условию задачи, "незакрытый интервал 200 считается закрытым числом 100". В нашем коде это реализовано в блоке проверки Если ТекущееЗначение = 100 Тогда. Если программа видит сотку, а двухсотка еще активна, она сбрасывает оба флага. Это гарантирует корректную отработку логики даже при нарушении последовательности ввода данных пользователем.

Также стоит помнить, что если в ТаблицаЗначений есть пустые значения или NULL, программа может выдать ошибку. Для надежности можно использовать функцию Число() или проверку ТипЗнч(), чтобы убедиться, что мы работаем именно с числовыми данными перед выполнением сложения.

Заключение

Мы проанализировали классическую алгоритмическую задачу и реализовали её на языке 1С. Использование логических флагов (состояний) позволяет гибко управлять процессом обработки данных в цикле. Этот метод гораздо надежнее, чем попытки использовать сложные вложенные циклы или функции поиска в таблице, так как он проходит по данным всего один раз (сложность алгоритма O(n)), что обеспечивает максимальную производительность.

← На главную