В процессе разработки в среде «1С:Предприятие 8» (особенно в обычных формах) часто возникают задачи, выходящие за рамки стандартного поведения платформы. Одной из таких задач является необходимость при выборе из справочника подставлять в поле ввода не ссылку на объект и не его наименование, а значение конкретного текстового реквизита. Параллельно с этим часто требуется автоматизировать работу с внешними файлами, например, формировать договор в MS Word, сохранять его в структурированную папку на диске и прикреплять к базе данных.
В данной статье мы разберем, как правильно реализовать программный выбор данных, настроить фильтрацию в открывающихся формах и организовать безошибочную работу с COM-объектами для сохранения документов.
Рассмотрим ситуацию: на форме справочника Контрагенты есть поле ввода, связанное с реквизитом ДоговорПокупки. Нам нужно, чтобы при нажатии на кнопку выбора открывался справочник ХранилищеДополнительнойИнформации, но после выбора строки в поле попадало не наименование справочника, а данные из его реквизита ДомДоговор.
Для решения этой задачи нам потребуется переопределить стандартную обработку выбора. Проанализируем шаги реализации:
ДоговорПокупки должен быть Строка. Если же мы хотим сохранить связь с объектом, тип должен оставаться ссылочным, но в таком случае для отображения текста потребуется дополнительное текстовое поле на форме.Разберем пример кода для этих событий:
Процедура ДоговорПокупкиНачалоВыбора(Элемент, СтандартнаяОбработка)
// Отключаем стандартный механизм открытия справочника
СтандартнаяОбработка = Ложь;
// Получаем форму выбора программно
ФормаВыбора = Справочники.ХранилищеДополнительнойИнформации.ПолучитьФормуВыбора(, Элемент);
// Открываем форму
ФормаВыбора.Открыть();
КонецПроцедуры
Процедура ДоговорПокупкиОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
// Отменяем стандартное заполнение поля ссылкой
СтандартнаяОбработка = Ложь;
// Проверяем, что значение выбрано и имеет нужный тип
Если ЗначениеЗаполнено(ВыбранноеЗначение) И ТипЗнч(ВыбранноеЗначение) = Тип("СправочникСсылка.ХранилищеДополнительнойИнформации") Тогда
// Записываем в реквизит формы значение конкретного поля выбранного объекта
ДоговорПокупки = ВыбранноеЗначение.ДомДоговор;
КонецЕсли;
КонецПроцедуры
Использование свойства СтандартнаяОбработка = Ложь критически важно, так как оно говорит платформе, что программист берет управление процессом на себя.
Часто требуется, чтобы пользователь видел не весь список справочника, а только те записи, которые относятся к текущему объекту (например, только файлы текущего контрагента). Рассмотрим, как установить отбор по наименованию в открываемой форме.
Проанализируем ситуацию: нам нужно сравнить Наименование контрагента с Наименованием в хранилище. Для этого в процедуре НачалоВыбора перед открытием формы добавим настройки отбора:
Процедура ДоговорПокупкиНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Форма2 = Справочники.ХранилищеДополнительнойИнформации.ПолучитьФормуВыбора(, Элемент);
// Настройка фильтра (отбора)
// Устанавливаем использование отбора по наименованию
Форма2.Отбор.Наименование.Использование = Истина;
// Указываем значение для фильтрации (берем из текущего объекта)
Форма2.Отбор.Наименование.Значение = Наименование;
// Вид сравнения по умолчанию "Равно"
Форма2.Открыть();
КонецПроцедуры
Важный нюанс: Фильтрация по строковому наименованию не всегда надежна. Если есть возможность, лучше использовать отбор по реквизиту Объект (владелец информации), где хранится ссылка на контрагента.
Теперь рассмотрим более сложный процесс: программное создание папки на диске, сохранение туда документа Word и последующая загрузка этого файла в базу данных 1С в объект ХранилищеЗначения.
Выясним причину частых ошибок при сохранении. Основная проблема заключается в попытке прочитать файл (создать ДвоичныеДанные), пока он еще открыт в приложении Word. Для успешной работы необходимо соблюдать строгую последовательность действий.
Разберем алгоритм по шагам:
SaveAs у COM-объекта Word.ДвоичныеДанные.ХранилищеДополнительнойИнформации.Посмотрим на пример реализации:
// 1. Подготовка пути
ДатаД = Формат(ТекущаяДата(), "ДФ=dd.MM.yyyy");
НоваяПапка = "F:\Dogovora\" + ДатаД;
// Проверяем наличие каталога и создаем его при необходимости
КаталогОбъект = Новый Файл(НоваяПапка);
Если НЕ КаталогОбъект.Существует() Тогда
СоздатьКаталог(НоваяПапка);
КонецЕсли;
// Формируем полное имя файла
ИмяФайла = НомеДог + " на " + НаименованиеПолное + ".doc";
ПолныйПуть = НоваяПапка + "\" + ИмяФайла;
// 2. Сохранение документа через Word
Попытка
Word.SaveAs(ПолныйПуть, 0); // 0 - формат документа Word 97-2003
// 3. Критически важный шаг: закрываем Word перед чтением файла!
Word.Close();
Word = Неопределено;
Исключение
Сообщить("Ошибка при сохранении Word: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// 4. Чтение файла в 1С
Попытка
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПолныйПуть);
// 5. Запись в справочник
НовыйФайл = Справочники.ХранилищеДополнительнойИнформации.СоздатьЭлемент();
НовыйФайл.Объект = Ссылка;
НовыйФайл.Наименование = "Договор " + НомеДог;
НовыйФайл.Хранилище = Новый ХранилищеЗначения(ДвоичныеДанныеФайла, Новый СжатиеДанных(9));
НовыйФайл.Записать();
Сообщить("Файл успешно сохранен и прикреплен!");
Исключение
Сообщить("Не удалось прочитать файл с диска: " + ОписаниеОшибки());
КонецПопытки;
При работе с файловой системой и внешними компонентами следует придерживаться нескольких правил, чтобы избежать «зависания» процессов и ошибок доступа:
Word = Неопределено;). Это помогает операционной системе вовремя завершить процесс WINWORD.EXE.Наименование или Номер от символов, запрещенных в Windows (/ \ : * ? " < > |). Используйте функцию СтрЗаменить() для удаления лишних знаков.ХранилищеЗначения со сжатием. Это позволит значительно сэкономить место в SQL-базе или файловом архиве.Попытка ... Исключение. Это предотвратит аварийное завершение работы пользователя при банальном отсутствии доступа к сетевому диску.Проанализировав вышеописанные подходы, мы видим, что гибкость платформы 1С позволяет реализовать практически любой сценарий взаимодействия с пользователем и внешним ПО, если правильно использовать событийную модель и методы работы с файловой системой.