Как запомнить и восстановить позицию в отчете 1С при следующем открытии?

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

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

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

Общий подход к решению задачи

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

  1. При взаимодействии пользователя с отчетом (например, при активизации ячейки), мы будем фиксировать данные текущей строки, которые позволят нам однозначно ее идентифицировать (в нашем случае это `Номенклатура` и `Характеристика`).
  2. При закрытии формы отчета, мы сохраним эти зафиксированные данные в постоянном хранилище, доступном пользователю (например, в настройках пользователя или в реквизитах формы с автоматическим сохранением).
  3. При следующем открытии формы отчета, после его формирования, мы загрузим сохраненные данные.
  4. Используя эти данные, мы найдем соответствующую область в только что сформированном табличном документе.
  5. Наконец, мы установим найденную область как текущую, что приведет к прокрутке отчета до нужной строки и ее визуальной активации.

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

Шаг 1: Захват текущей позиции в отчете

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

Определяем событие: В свойствах табличного поля, которое отображает наш табличный документ, найдем событие `ПриАктивизацииЯчейки`. Мы создадим обработчик для этого события. Этот обработчик будет срабатывать каждый раз, когда пользователь кликает на ячейку в табличном документе или перемещается по нему.

Получаем данные из ячейки: Внутри обработчика события мы можем получить доступ к текущей области табличного документа. У табличного документа есть свойство ТекущиеДанные, которое может быть полезно, но для более универсального подхода, особенно если `Расшифровка` занята, мы можем получать текстовое представление данных непосредственно из ячеек текущей строки. Сохранять мы будем именно текстовые значения, так как поиск в табличном документе удобнее производить по тексту.

Предположим, что `Номенклатура` находится в первой колонке, а `Характеристика` — во второй. Мы будем сохранять их строковые представления.


&НаКлиенте
Процедура ТабличноеПолеОтчетаПриАктивизацииЯчейки(Элемент, Область)
    // Реквизиты формы для временного хранения текущей номенклатуры и характеристики
    // Эти реквизиты будут использоваться для сохранения при закрытии формы
    // и для поиска при открытии.
    // Например: ТекущаяНоменклатураТекст (Строка), ТекущаяХарактеристикаТекст (Строка)

    // Проверяем, что Область не пустая и содержит хотя бы одну строку
    Если Область.КоличествоСтрок() > 0 Тогда
        // Получаем текст из ячеек текущей строки
        // Предполагаем, что Номенклатура в первой колонке, Характеристика во второй
        Попытка
            ТекущаяНоменклатураТекст = Область.Ячейки(Область.Верх, 1).Текст;
            ТекущаяХарактеристикаТекст = Область.Ячейки(Область.Верх, 2).Текст;
        Исключение
            // Возможно, ячейки не существуют или не имеют текста
            ТекущаяНоменклатураТекст = "";
            ТекущаяХарактеристикаТекст = "";
        КонецПопытки;
    Иначе
        ТекущаяНоменклатураТекст = "";
        ТекущаяХарактеристикаТекст = "";
    КонецЕсли;
КонецПроцедуры

Здесь `ТекущаяНоменклатураТекст` и `ТекущаяХарактеристикаТекст` — это реквизиты формы, которые мы добавим для временного хранения этих значений. Они будут перезаписываться при каждом перемещении пользователя.

Шаг 2: Сохранение данных о позиции

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

  1. Использование реквизитов формы с автоматическим сохранением:

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

    • `ЗапомненнаяНоменклатураТекст` (Тип: Строка)
    • `ЗапомненнаяХарактеристикаТекст` (Тип: Строка)

    Для этих реквизитов в их свойствах необходимо установить флаг `СохранятьЗначение` в `Истина`. Это автоматически обеспечит сохранение их значений между сеансами работы пользователя для данной формы.

    В событии `ПриЗакрытии` формы отчета мы просто присвоим значения наших временных реквизитов, обновляемых при `ПриАктивизацииЯчейки`, к этим "постоянным" реквизитам формы:

    
    &НаКлиенте
    Процедура ПриЗакрытии()
        // Присваиваем временные значения постоянным реквизитам формы
        // Эти реквизиты имеют флаг "СохранятьЗначение = Истина"
        ЗапомненнаяНоменклатураТекст   = ТекущаяНоменклатураТекст;
        ЗапомненнаяХарактеристикаТекст = ТекущаяХарактеристикаТекст;
    КонецПроцедуры
    

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

  2. Использование `ХранилищаНастроекПользователя` или `ХранилищаОбщихНастроек`:

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

    В событии `ПриЗакрытии` формы мы сформируем структуру или массив с данными и сохраним его:

    
    &НаКлиенте
    Процедура ПриЗакрытии()
        // Создаем структуру для хранения данных
        ПередаваемыеДанные = Новый Структура;
        ПередаваемыеДанные.Вставить("Номенклатура", ТекущаяНоменклатураТекст);
        ПередаваемыеДанные.Вставить("Характеристика", ТекущаяХарактеристикаТекст);
    
        // Сохраняем данные в хранилище настроек пользователя
        // Ключ может быть произвольным, например, именем формы отчета
        КлючНастроек = "ПозицияОтчета_" + Метаданные.Имя;
        ХранилищеНастроекПользователя.Сохранить(ПередаваемыеДанные, КлючНастроек);
    КонецПроцедуры
    

    При этом, `ХранилищеНастроекПользователя` сохраняет настройки для конкретного пользователя, а `ХранилищеОбщихНастроек` — общие для всех пользователей. В нашем случае, поскольку это индивидуальная "закладка", лучше использовать `ХранилищеНастроекПользователя`.

Шаг 3: Восстановление позиции при открытии отчета

Самый ответственный этап — это восстановление позиции. Он должен произойти после того, как отчет будет полностью сформирован и его табличный документ будет заполнен данными. Обычно это происходит в обработчике события `ПриСозданииНаСервере` или после выполнения основной команды формирования отчета, когда табличное поле уже заполнено.

  1. Загрузка сохраненных данных:

    В зависимости от выбранного способа хранения, мы загрузим данные. Если мы использовали реквизиты формы с `СохранятьЗначение`, то они будут автоматически заполнены. Если мы использовали `ХранилищеНастроекПользователя`, то нам потребуется явно загрузить их:

    
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        // ... Ваш код формирования отчета ...
        
        // Загрузка сохраненных данных из хранилища настроек пользователя
        КлючНастроек = "ПозицияОтчета_" + Метаданные.Имя;
        СохраненныеДанные = ХранилищеНастроекПользователя.Загрузить(КлючНастроек);
    
        Если СохраненныеДанные <> Неопределено Тогда
            ЗапомненнаяНоменклатураТекст   = СохраненныеДанные.Номенклатура;
            ЗапомненнаяХарактеристикаТекст = СохраненныеДанные.Характеристика;
        Иначе
            ЗапомненнаяНоменклатураТекст   = "";
            ЗапомненнаяХарактеристикаТекст = "";
        КонецЕсли;
        
        // ... Ваш код формирования отчета, который генерирует ТабличныйДокумент ...
        // После формирования отчета вызываем процедуру позиционирования
        ПозиционироватьОтчет(); 
    КонецПроцедуры
    

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

  2. Поиск текста в сформированном табличном документе:

    После того как отчет сформирован, а сохраненные данные загружены, нам нужно найти соответствующую область в `ТабличномДокументе`. Для этого мы используем метод `НайтиТекст` объекта `ТабличныйДокумент`. Он возвращает объект `ОбластьЯчеекТабличногоДокумента`, если текст найден.

    Наша логика поиска будет следующей:

    • Сначала попытаемся найти точное совпадение по `Номенклатуре` и `Характеристике`.
    • Если точное совпадение не найдено, но есть сохраненная `Номенклатура`, попытаемся найти первое вхождение только этой `Номенклатуры`.
    • Если ничего не найдено, не предпринимаем никаких действий.
    
    &НаКлиенте
    Процедура ПозиционироватьОтчет()
        // Проверяем, есть ли что искать
        Если ЗначениеЗаполнено(ЗапомненнаяНоменклатураТекст) Тогда
            // Ссылка на табличный документ, который отображается в табличном поле
            Перем ТабличныйДокументОтчета;
            ТабличныйДокументОтчета = Элементы.ТабличноеПолеОтчета.ПолучитьТабличныйДокумент();
    
            Если ТабличныйДокументОтчета = Неопределено Тогда
                Возврат;
            КонецЕсли;
    
            ОбластьПоиска = Неопределено;
    
            // 1. Попытка найти по Номенклатуре и Характеристике
            Если ЗначениеЗаполнено(ЗапомненнаяХарактеристикаТекст) Тогда
                НайденнаяОбластьНоменклатура = ТабличныйДокументОтчета.НайтиТекст(ЗапомненнаяНоменклатураТекст);
                Если НайденнаяОбластьНоменклатура <> Неопределено Тогда
                    // Чтобы найти Характеристику в той же строке,
                    // нам нужно пройтись по строкам, начиная с найденной Номенклатуры.
                    // Это упрощенный пример, в реальном отчете может потребоваться
                    // более сложная логика поиска по строкам или колонкам.
                    Для КаждаяСтрока Из НайденнаяОбластьНоменклатура.Высота Цикл
                        СтрокаТабличногоДокумента = НайденнаяОбластьНоменклатура.Верх + КаждаяСтрока - 1;
                        ОбластьСтроки = ТабличныйДокументОтчета.Область(СтрокаТабличногоДокумента, 1, СтрокаТабличногоДокумента, ТабличныйДокументОтчета.Ширина); // Вся строка
                        
                        НайденнаяОбластьХарактеристикаВСтроке = ОбластьСтроки.НайтиТекст(ЗапомненнаяХарактеристикаТекст);
                        
                        Если НайденнаяОбластьХарактеристикаВСтроке <> Неопределено Тогда
                            // Если Номенклатура и Характеристика найдены в одной строке,
                            // считаем это нашим совпадением.
                            ОбластьПоиска = ОбластьСтроки; // Можно выбрать область самой номенклатуры или всю строку
                            Прервать;
                        КонецЕсли;
                    КонецЦикла;
                КонецЕсли;
            КонецЕсли;
            
            // 2. Если Номенклатура и Характеристика не найдены вместе, ищем только Номенклатуру
            Если ОбластьПоиска = Неопределено Тогда
                ОбластьПоиска = ТабличныйДокументОтчета.НайтиТекст(ЗапомненнаяНоменклатураТекст);
            КонецЕсли;
    
            // 3. Позиционируем отчет, если что-то найдено
            Если ОбластьПоиска <> Неопределено Тогда
                Элементы.ТабличноеПолеОтчета.ТекущаяОбласть = ОбластьПоиска;
                // Можно также выделить найденную область
                // Элементы.ТабличноеПолеОтчета.ВыделеннаяОбласть = ОбластьПоиска;
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    

    Важно: В приведенном примере поиска `Характеристики` в строке, найденной по `Номенклатуре`, предполагается, что `Характеристика` находится в той же логической строке данных отчета. Структура отчетов может быть разной, и, возможно, потребуется более сложная логика для сопоставления. Если в `Расшифровке` мы храним ссылки на объекты, поиск был бы надежнее, но мы работаем с текстовым поиском.

  3. Позиционирование на найденной строке:

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

    Строка `Элементы.ТабличноеПолеОтчета.ТекущаяОбласть = ОбластьПоиска;` выполняет всю необходимую работу по позиционированию.

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

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

← На главную