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

25.10.13

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

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

Скачать файлы

Наименование Файл Версия Размер
КопированиеДокументаИзЕгоФормы.epf
.epf 10,45Kb
31
.epf 10,45Kb 31 Скачать

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

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

 


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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

См. также

GUID в 1С 8.3 - как с ними быть

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

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

12.02.2024    4316    atdonya    22    

41

Переоткрытие внешних обработок

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

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

30.11.2023    3883    ke.92@mail.ru    16    

60

Валидация JSON через XDTO (включая массивы)

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

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

28.08.2023    8560    YA_418728146    6    

139

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

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

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

2 стартмани

22.08.2023    2020    21    progmaster    7    

3

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 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    16012    131    sapervodichka    112    

129

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7200    quazare    8    

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

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

Что же касается самой причины появления обработки, то условия нужно ставить в процедуре ПередЗаписью с учетом режима записи -т.е. сохранять можно, проводить нельзя.
3. skvic 27 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 лет, а пригодилось! спасибо автору!
Оставьте свое сообщение