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

25.10.13

Разработка - Универсальные функции

Публикация предназначена для тех, кому интересны неочевидные возможности программной работы с формами

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
КопированиеДокументаИзЕгоФормы.epf
.epf 10,45Kb
31
31 Скачать (1 SM) Купить за 1 850 руб.

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

Запросы к БД были бесполезны - документ не записан. Внешних обработок заполнения к документу подключено не было и нечего было подменить, чтобы обработать табличную часть уже открытого документа. Работа велась в толстом клиенте обычном приложении, что делало невозможным применение метода ПолучитьОкна(). Документ нужно было спасать другим методом.

 


Решение оказалось простым. Каждая форма документа, в том числе обычная, связана с ее ключом - ссылкой на документ. То же справедливо для форм и других объектных типов 1С. У нового документа эта ссылка пустая. Платформа 1С имеет особенность. Если для ссылки-ключа производится попытка получения/открытия формы, которая уже была открыта, то новая форма не создается. Возвращается уже открытая форма! Дальше остается только обратиться к ее свойствам и прочитать хранимый в ней объект, создать на его основе новый и записать, по ходу дела удаляя из него информацию, мешающую записи.

То есть ключевая идея выражается всего в одной строчке кода:

Форма = ПолучитьФорму("Документ."+Ссылка.Метаданные().Имя+".ФормаОбъекта", Новый Структура("Ключ", Ссылка));

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


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

Заметьте, что использование директив компиляции &НаКлиенте и &НаСервере не запрещено в том числе и в обычной форме обработки. Если интересно посмотреть на работу кода, но лень создавать обработку, можно скачать приложенный к публикации файл :)

&НаКлиенте
Процедура КнопкаВыполнитьНажатие(Команда)

   
ЭтоУправляемаяФормаОбработки = ТипЗнч(ЭтаФорма) = Тип("УправляемаяФорма");

    Если НЕ
ЭтоУправляемаяФормаОбработки Тогда//в обычной форме основной реквизит называется ОбработкаОбъект,
       
Объект = ЭтаФорма.ОбработкаОбъект;    //для однотипности кода будем всегда работать с переменной Объект
   
КонецЕсли;

    Если
Объект.СсылкаНаДокумент = Неопределено Тогда
       
Сообщить("Необходимо выбрать тип документа или указать конкретный документ");
        Возврат;
    КонецЕсли;

    Если
ЭтоУправляемаяФормаОбработки Тогда
       
#Если ТолстыйКлиентУправляемоеПриложение ИЛИ ТонкийКлиент Тогда
           
ИмяМетаданных = ПолучитьИмяМетаданныхНаСервереУправляемойФормы(Объект.СсылкаНаДокумент);
       
#КонецЕсли
   
Иначе
       
#Если ТолстыйКлиентОбычноеПриложение Тогда
           
ИмяМетаданных = Объект.СсылкаНаДокумент.Метаданные().Имя;
       
#КонецЕсли
   
КонецЕсли;

   
Форма = ПолучитьФорму("Документ."+ИмяМетаданных+".ФормаОбъекта", Новый Структура("Ключ", Объект.СсылкаНаДокумент));

    Если НЕ
Форма.Открыта() Тогда
       
Сообщить("Вы выбрали документ, форма которого не открыта. Сначала откройте форму документа.");
        Возврат;
    КонецЕсли;

    Если
ТипЗнч(Форма) = Тип("УправляемаяФорма") Тогда
       
ОбъектКопирования = Форма.Объект; //здесь не учитываем, что в редких случаях объект может быть переименован
   
ИначеЕсли ТипЗнч(Форма) = Тип("Форма") Тогда
       
ОбъектКопирования = Форма.ДокументОбъект; //здесь не учитываем, что в редких случаях объект может быть переименован
   
КонецЕсли;

    Если
ЭтоУправляемаяФормаОбработки Тогда
       
#Если ТолстыйКлиентУправляемоеПриложение ИЛИ ТонкийКлиент Тогда
           
СсылкаНаНовыйДокумент = СкопироватьОбъектНаСервереВУправляемомПриложении(ОбъектКопирования, ИмяМетаданных);
           
ОткрытьЗначение(СсылкаНаНовыйДокумент);
       
#КонецЕсли
   
Иначе
       
#Если ТолстыйКлиентОбычноеПриложение Тогда
           
СкопироватьОбъектНаКлиентеВОбычномПриложении(ОбъектКопирования, ИмяМетаданных);
       
#КонецЕсли
   
КонецЕсли;

КонецПроцедуры

&НаСервере
Функция ПолучитьИмяМетаданныхНаСервереУправляемойФормы(Ссылка)
    Возврат
Ссылка.Метаданные().Имя;
КонецФункции


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

   
//Здесь можно провести программную модификацию документа, например удалить строки, мешающие записи

   
НовыйОбъект.Дата = ДокументОбъект.Дата;
   
НовыйОбъект.Записать();
    Возврат
НовыйОбъект.Ссылка;
КонецФункции

#Если ТолстыйКлиентОбычноеПриложение Тогда
Функция СкопироватьОбъектНаКлиентеВОбычномПриложении(Объект, ИмяМетаданных)

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

   
//Здесь можно провести программную модификацию документа, например удалить строки, мешающие записи

   
ОткрытьЗначение(НовыйОбъект); //В обычном приложении документ можно открыть не записывая в базу данных
КонецФункции
#КонецЕсли

форма обычная управляемая документ

См. также

Универсальные функции Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

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

21.05.2024    25228    dimanich70    82    

149

Универсальные функции Программист Платформа 1С v8.3 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    4511    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    25635    atdonya    25    

58

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    6086    ke.92@mail.ru    17    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    16596    YA_418728146    8    

170

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

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

2 стартмани

22.08.2023    4280    73    progmaster    10    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 1C:Бухгалтерия 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    19153    181    sapervodichka    112    

136
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. elizarovs 83 30.10.13 09:12 Сейчас в теме
Нужная вещь! Работает. Проверил на УПП+УАТ.
2. bulpi 217 30.10.13 15:17 Сейчас в теме
Замечание :
Функция СкопироватьОбъектНаКлиентеВОбычномПриложении(Объект, ИмяМетаданных)
Если ТипЗнч(Объект) = Тип("ДанныеФормыСтруктура") Тогда

Это условие, ИМХО, никогда не реализуется. Ведь речь идет об обычном приложении.

Что же касается самой причины появления обработки, то условия нужно ставить в процедуре ПередЗаписью с учетом режима записи -т.е. сохранять можно, проводить нельзя.
3. skvic 28 31.10.13 07:13 Сейчас в теме
ПО быстрому (при обычных формах) делал сохранение в excel, правил код, а потом обработочкой с диска ИТС ЗагрузкаДанныхИзТабличногоДокумента :-) а за обработочку +1, вариант отличный.
4. пользователь 31.10.13 16:09
Сообщение было скрыто модератором.
...
5. пользователь 20.11.13 06:57
Сообщение было скрыто модератором.
...
6. unoDosTres 14.06.14 23:44 Сейчас в теме
способ то классный с ключом формы, но не понятно как вы потом документ собирались записывать с тем же самым составом строк, ведь при записи снова будет проверка документа на стороне сервера, т.е. каким образом вы поняли
спасен путем создания его копии на основе данных формы без строк мешающих записи
какие строки являлись мешающими, допустим не скопировав код исполняемые на стороне сервера во внешнюю обработку и там уже смотреть, хотя и это тоже не всегда будет очевидным, если там какая то "забавная" проверка, один хрен анализировать строки. может можно как то сериализовать данные скопированные с формы, тогда это уже как то лучше и быстрей, если конечно возможна сериализация не записанного объекта
7. a.zikeev 17.01.15 22:54 Сейчас в теме
Благодаря автору у меня появился шанс спасти документ, который не записывается из-за нехватки прав...
За название темы отдельный респект !
8. maxis33 45 20.10.23 15:35 Сейчас в теме
Спустя 10 лет, а пригодилось! спасибо автору!
Оставьте свое сообщение