При работе с платформой 1С:Предприятие 8.3 программистам часто приходится решать задачи по программному созданию, открытию и модификации документов. В этой статье мы подробно разберем, как правильно программно открыть существующий документ, найти его по номеру, а также как работать с данными табличных частей уже открытой формы документа. Мы рассмотрим особенности работы как с обычными, так и с управляемыми формами.
Первоочередной задачей при программной работе с существующим документом является его поиск. Часто для этого используется метод НайтиПоНомеру(). Рассмотрим типичную ситуацию, когда этот метод может вернуть пустое значение и как это исправить.
Многие разработчики сталкиваются с тем, что вызов метода Документы.ИмяДокумента.НайтиПоНомеру(Номер) возвращает неопределенное значение или пустую ссылку, даже если документ с таким номером точно существует в базе. Приведем пример такого вызова, который может работать некорректно:
ДокументСсылка = Документы.ВозвратТоваровОтПокупателя.НайтиПоНомеру(Номер);
Если ДокументСсылка = Неопределено Тогда
Возврат;
КонецЕсли;
В этой ситуации переменная ДокументСсылка может оставаться пустой.
Причина такого поведения кроется в настройках нумерации документов в конфигурации. Для многих видов документов устанавливается так называемая периодическая нумерация, например, в пределах месяца или года. Это означает, что номер документа уникален не во всей базе, а только в рамках определенного периода.
Метод НайтиПоНомеру() имеет необязательный второй параметр – Дата. Если для документа установлена периодическая нумерация, этот параметр становится фактически обязательным для корректного поиска. Дата, переданная в этом параметре, указывает системе, в каком интервале (месяце, году) искать документ. Если дата не указана, поиск может быть выполнен с пустой датой, что, скорее всего, не даст нужного результата.
Приведем пример правильного использования метода НайтиПоНомеру():
// Предположим, что "Номер" – это строковый номер документа.
// Вторым параметром указываем любую дату из периода, в котором был создан документ.
// Например, '20230101' для документов 2023 года, если нумерация годовая.
ДокументСсылка = Документы.ВозвратТоваровОтПокупателя.НайтиПоНомеру(Номер, '20230101');
Если ДокументСсылка.Пустая() Тогда
Сообщить("Документ с номером " + Номер + " не найден.");
Возврат;
КонецЕсли;
После добавления второго параметра, поиск документа должен успешно завершиться, и ДокументСсылка будет содержать ссылку на найденный документ.
Важно: Вы можете указать любую дату, которая попадает в нужный период нумерации документа. Например, если номера уникальны в пределах года, достаточно указать '20230101' для поиска документов за 2023 год.
После того как мы получили ссылку на документ, нам необходимо открыть его форму для пользователя. Способы открытия зависят от типа формы (обычные или управляемые) и от требуемого функционала.
Для обычных форм (в толстом клиенте):
Если ваша конфигурация использует обычные формы (например, в БП 2.0 или в режимах совместимости), или вы работаете в режиме толстого клиента, вы можете получить объект формы и затем открыть его. Этот способ позволяет предварительно манипулировать формой до её показа пользователю.
ФормаДокумента = ДокументСсылка.ПолучитьФорму("ФормаДокумента");
Если ФормаДокумента = Неопределено Тогда
Сообщить("Не удалось получить форму документа.");
Возврат;
КонецЕсли;
ФормаДокумента.Открыть();
Также можно использовать более сокращенную запись:
ДокументСсылка.ПолучитьФорму().Открыть();
Или, если у вас уже есть объект документа (не ссылка), например, ДокументОбъект:
ДокументОбъект.ПолучитьФорму().Открыть();
Для управляемых форм (в тонком клиенте или веб-клиенте):
В управляемом приложении (начиная с платформы 8.2, активно используется в БП 3.0, УТ 11 и т.д.) используются другие методы открытия форм. Мы рассмотрим несколько из них.
Метод ОткрытьФорму():
Этот метод является универсальным для открытия форм в управляемом приложении. Для открытия формы существующего объекта по ссылке необходимо передать структуру с параметром "Ключ", содержащим эту ссылку.
// В контексте клиентского кода (&НаКлиенте)
&НаКлиенте
Процедура ОткрытьДокументПоСсылке(ДокументСсылка)
Если ДокументСсылка.Пустая() Тогда
Сообщить("Ссылка на документ не указана.");
Возврат;
КонецЕсли;
// Формируем структуру параметров, где "Ключ" - это ссылка на объект
ПараметрыФормы = Новый Структура("Ключ", ДокументСсылка);
// Открываем форму документа, указывая полное имя формы.
// Например, "Документ.ВозвратТоваровОтПокупателя.ФормаОбъекта"
ОткрытьФорму("Документ.ВозвратТоваровОтПокупателя.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры
Это наиболее распространенный и рекомендуемый способ открытия форм объектов в управляемом приложении.
Метод ОткрытьЗначение():
Это более простой и быстрый способ открытия формы существующего объекта по его ссылке в управляемом приложении. Он сам определяет, какую форму открыть для переданного значения.
// В контексте клиентского кода (&НаКлиенте)
&НаКлиенте
Процедура ОткрытьДокументБыстро(ДокументСсылка)
Если ДокументСсылка.Пустая() Тогда
Сообщить("Ссылка на документ не указана.");
Возврат;
КонецЕсли;
ОткрытьЗначение(ДокументСсылка);
КонецПроцедуры
Этот метод часто используется, когда не требуется предварительная обработка формы или передача дополнительных параметров.
Метод ПоказатьЗначение():
Аналогичен ОткрытьЗначение(), но предназначен для использования в тех случаях, когда не требуется интерактивное взаимодействие с объектом, а нужно лишь показать его представление. Также работает на клиенте.
// В контексте клиентского кода (&НаКлиенте)
&НаКлиенте
Процедура ПоказатьДокумент(ДокументСсылка)
Если ДокументСсылка.Пустая() Тогда
Сообщить("Ссылка на документ не указана.");
Возврат;
КонецЕсли;
ПоказатьЗначение(, ДокументСсылка); // Первый параметр - для объекта расширения формы, если есть
КонецПроцедуры
Примечание: Если в управляемом приложении необходимо открыть обычную форму, убедитесь, что в параметрах конфигуратора установлен режим редактирования "Управляемое приложение и обычное приложение", а также флаг "Использовать обычные формы в управляемом приложении". При этом обычные формы открываются только в режиме толстого клиента.
После того как форма документа открыта, часто возникает необходимость найти определенные строки в её табличной части для их дальнейшей обработки или позиционирования курсора. Рассмотрим, как это сделать правильно, избегая распространенных ошибок.
Распространенной ошибкой является попытка использовать метод Найти() непосредственно для элемента формы табличной части, например так:
ФормаДокумента.ЭлементыФормы.Товары.ТекущаяСтрока = ФормаДокумента.ЭлементыФормы.Товары.Найти(1, "НомерСтроки");
Такой код вызовет ошибку "Метод объекта не обнаружен (Найти)", поскольку элемент формы табличной части (ЭлементыФормы.Товары) не имеет метода Найти() для поиска данных.
Для поиска строк необходимо обращаться непосредственно к коллекции данных, которая привязана к элементу формы табличной части. В обычных формах эта коллекция доступна через свойство Значение элемента формы. В управляемых формах – это обычно реквизит формы, который связан с табличным полем.
Приведем правильный пример для обычных форм:
// Предположим, что "ФормаДокумента" - это уже открытая форма документа,
// а "Товары" - это имя табличной части.
// Мы хотим найти строку, где значение колонки "НомерСтроки" равно 1.
НайденнаяСтрока = ФормаДокумента.ЭлементыФормы.Товары.Значение.Найти(1, "НомерСтроки");
Если НайденнаяСтрока <> Неопределено Тогда
// Если строка найдена, можем позиционировать на ней курсор
ФормаДокумента.ЭлементыФормы.Товары.ТекущаяСтрока = НайденнаяСтрока;
Сообщить("Строка найдена и установлен курсор.");
Иначе
Сообщить("Строка не найдена.");
КонецЕсли;
В этом примере мы используем метод Найти() непосредственно для объекта ТабличнаяЧастьКоллекция (или ТаблицаЗначений), который является значением элемента формы ЭлементыФормы.Товары.
Для поиска строк в коллекциях данных (табличных частях, таблицах значений) в 1С более гибким и рекомендуемым является метод НайтиСтроки(). Этот метод позволяет задавать условия отбора в виде структуры и возвращает массив всех строк, удовлетворяющих условию. Это особенно полезно, когда может быть несколько строк, подходящих под критерий.
Приведем пример использования НайтиСтроки():
// Создаем структуру с параметрами отбора.
// Ключ структуры - имя колонки, значение - искомое значение.
ПараметрыОтбора = Новый Структура("НомерСтроки", 1);
// Вызываем метод НайтиСтроки() для коллекции данных табличной части.
МассивНайденныхСтрок = ФормаДокумента.ЭлементыФормы.Товары.Значение.НайтиСтроки(ПараметрыОтбора);
Если МассивНайденныхСтрок.Количество() > 0 Тогда
// Если строки найдены, можем взять первую из них и установить её текущей
НайденнаяСтрока = МассивНайденныхСтрок[0];
ФормаДокумента.ЭлементыФормы.Товары.ТекущаяСтрока = НайденнаяСтрока;
Сообщить("Найдены строки, установлен курсор на первую.");
Иначе
Сообщить("Строки по заданным параметрам не найдены.");
КонецЕсли;
Метод НайтиСтроки() возвращает массив, поэтому мы всегда проверяем его количество элементов. Если нужно просто получить первый найденный элемент, обращаемся по индексу [0].
В управляемых формах для позиционирования на нужной строке после её нахождения используются схожие принципы, но обращение к элементам формы происходит через коллекцию Элементы, а не ЭлементыФормы. Также, вместо прямого присваивания найденной строки свойству ТекущаяСтрока, иногда требуется работать с идентификаторами строк.
Рассмотрим пример:
// Предположим, что Товары - это реквизит формы типа ТаблицаЗначений или ТабличнаяЧасть.
// А Элементы.ТабличноеПолеТовары - это элемент формы, связанный с этим реквизитом.
ПараметрыОтбора = Новый Структура("Номенклатура", СсылкаНаНужнуюНоменклатуру);
МассивНайденныхСтрок = Товары.НайтиСтроки(ПараметрыОтбора);
Если МассивНайденныхСтрок.Количество() > 0 Тогда
// Получаем первый найденный объект строки
НайденнаяСтрокаДанных = МассивНайденныхСтрок[0];
// Получаем идентификатор этой строки
ИдентификаторСтроки = НайденнаяСтрокаДанных.ПолучитьИдентификатор();
// Устанавливаем текущую строку элемента формы по её идентификатору
Элементы.ТабличноеПолеТовары.ТекущаяСтрока = ИдентификаторСтроки;
Сообщить("Курсор установлен на найденную строку.");
Иначе
Сообщить("Строка с такой номенклатурой не найдена.");
КонецЕсли;
Здесь мы сначала получаем сам объект строки данных из коллекции, затем его идентификатор методом ПолучитьИдентификатор(), и только потом присваиваем этот идентификатор свойству ТекущаяСтрока элемента формы табличного поля.
Мы подробно разобрали основные аспекты программного открытия документов в 1С:Предприятии 8.3. Мы выяснили, что для успешного поиска документа по номеру с периодической нумерацией необходимо использовать второй параметр "Дата" в методе НайтиПоНомеру(). Также мы рассмотрели различные способы открытия форм как для обычных, так и для управляемых приложений.
Особое внимание уделили работе с табличными частями: мы проанализировали, как правильно искать строки в коллекции данных табличной части с использованием методов Найти() и более предпочтительного НайтиСтроки(), а также как позиционировать курсор на найденной строке. Помните, что регулярное обращение к синтакс-помощнику (СП) платформы 1С поможет вам избежать многих распространенных ошибок и глубже понять функционал доступных методов и объектов.