Работа с ActiveDocument в клиент-серверном варианте

Программирование - Практика программирования

Наверняка, многие, хотя бы раз в своей практике сталкивались (или еще столкнуться) с этим удивительным типом объекта метаданных Макет. В данной статье, я постараюсь дать основные тезисы и методы работы с ActiveDocument, дабы Вы не наступали на эти банальные грабли и не колупали себе мозг, почему оно не работает :)

Введение. Предметная область

Макет – это один из самых универсальных объектов 1С Предприятия 8. Использование макетов широко применяется как в оформлении различных документов (отчеты, печатные формы и т.д.), так и в решении нестандартных задач (например хранение файлов внутри конфигурации).

Для чего нужен  и применяется такой прекрасный тип макета как ActiveDocument? Самый банальный пример – это шаблон договора, сделанный юристом на скорую руку в MS Word.  Тип макета ActiveDocument позволяет загрузить этот шаблон MS Word в конфигурации и осуществлять редактирование напрямую из конфигуратора.

Т.е. вот вы сделали шаблон договора, загрузили в конфигурацию, проработали с этим шаблоном 1 год, и потом вдруг выяснилось, что нужно изменить кусок текста этого договора. Без проблем – открываем конфигуратор, 2 щелчка на нужном макете и можем править word-вский файлик прямо в конфигураторе. Закрываем, обновляем конфигурацию – дело сделано!

Принцип работы.

К сожалению (или к счастью) работа с макетом ActiveDocument возможна только программная. Т.е. чтобы при нажатии кнопки пользователю открылся наш word-вский файлик, нужно написать код! (ВАУ)

Сама схема кода следующая:

1 – Получаем макет ActiveDocument

2 – Инициализируем COM-объект нашего ActiveDocument

3 – Работаем с этим COM-объектом (заполняем данные, редактируем, выводим на экран)

И вот тут начинается самое интересное…

Когнитивный диссонанс

	&НаСервере

	АктивныйДокумент = ПолучитьМакет("Макет");
	КомОбъект = АктивныйДокумент.Получить();	

Вот самые первые строчки, на которые натыкается в гугле юный неофит. В файловом варианте такой код сработает корректно (неважно в толстом или тонком клиенте). Т.к. и сервер и клиент у нас находятся на одной машине, и MS Word тоже установлен на этой машине.

А давайте представим, что у нас клиент-сервер, да ещё и сервер находится на другой машине. Будет оно работать в тонком клиенте? Нет. И тут возникнет когнитивный диссонанс.  WTF? O_o

Во-первых, получить макет (любой) можно только &На Сервере. Результатом нашего получения будет объект «Оболочка ActiveDocument». «Фигня!» - скажет опытный гуру конфигурирования – «вернём &НаКлиент, как и в случае с табличным документом!»

Не фигня. Оболочка ActiveDocument существует только на сервере и вернуть её на клиент не получится (а нам-то нужно запустить Word именно на клиентской машине).

Во-вторых, инициализировав COM-объект &НаСервере, вернуть его на клиент, также не получится

(и кстати, если сделать наоборот - с клиента на сервер, тоже не прокатит)

Танцы с бубном

Как быть? Ведь нужно инициализировать COM-объект на клиенте, причем из данных, получаемых только на сервере и которых на клиент передать нельзя.

Решение у этой задачи самое корявое, которое только может быть. Но давайте вспомним, зачем мы вообще используем ActiveDocument? Правильно, чтобы внести изменения в шаблон через конфигуратор «на лету».  Это и есть та единственная причина, по которой мы используем ActiveDocument. Иначе бы мы использовали тип макета «Двоичные данные».

А вот само решение точно такое же, как при использовании макета с двоичными данными! Т.е. сначала нам нужно сохранить ActiveDocument в файл, а потом, используя этот файл, инициализировать COM-объект (причем сделать это нужно на клиенте!).

Таким образом наша предыдущая схема превращается вот во что:

1 – &НаСервере Получаем макет ActiveDocument

2 – &НаСервере Сохраняем полученный макет в файл и возвращаем на клиент полное имя файла (полный путь + наименование с расширением)

3 – &НаКлиенте Инициализируем COM-объект из файла

4 -  &НаКлиенте заполняем и выводим этот COM-объект

Листинг

Небольшой листинг кода:

&НаКлиенте
Процедура ПоказатьМакет(Документ)	
	
	Макет = ОбщийМодуль.ПолучитьМакет(Документ); //серверная функция, записывает макет в файл и возвращает полное имя файла

	Попытка 
		Шаблон = ПолучитьCOMОбъект(Макет); //инициализируем COM-объект
	Исключение
		КомОбъект = 0;
		Сообщение = Новый СообщениеПользователю;
		Сообщение.Текст = ОписаниеОшибки();
		Сообщение.Сообщить(); 
		
		Возврат;
	КонецПопытки;  

	Если Шаблон = Неопределено Тогда
		Возврат;
	КонецЕсли;

	//здесь делаем всякие штуки типа заполнения и прочего

	Шаблон.Fields.UpDate();
	Шаблон.Activate();
	Шаблон.Application.Visible = 1; //указываем, что надо показать юзеру наш COM-объект
	Шаблон.Save(); //записываем изменения

	Шаблон = 0;

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

//Получает макет ActiveDocument и записывает его в файл
&НаСервере
Функция ПолучитьМакет(Документ) Экспорт
	
	Каталог = ПараметрыСеанса.ТекущийПользователь.РабочийКаталог;
	Каталог = ?(Прав(Каталог,1) = "\", Каталог, Каталог+"\");
	Если ЗначениеЗаполнено(Каталог) Тогда
		Попытка
			ПолноеИмяФайла = Каталог+Документ.Номер+".doc";
			Макет = Документы.ДоговорыКонтрагентов.ПолучитьМакет("ActiveDocument");
			Макет.Записать(ПолноеИмяФайла);
			
			Возврат ПолноеИмяФайла;                       
		Исключение
			Сообщение = Новый СообщениеПользователю;
			Сообщение.Текст = "Не удалось записать файл "+ОписаниеОшибки();       
			Сообщение.Сообщить();
			Возврат Неопределено;           
		КонецПопытки;            
	Иначе
		Сообщение = Новый СообщениеПользователю;
		Сообщение.Текст = "Не указан каталог. Сохранение файла невозможно";
		Сообщение.Сообщить();
		Возврат Неопределено;
	КонецЕсли;    
	
КонецФункции // ()

Заключение

Естественно, пример с MS Word самый простой и банальный. Вы можете запихнуть туда и другие файлики).

Надеюсь статья кому-то сэкономит 10мин :) Удачи! ;)  

P.S. кстати, обратите внимание, какая изящная задача получилась для тестирования опытного кандидата на работу. Если вам нужен человек, для интеграции 1С с другими ПО, да еще и чтоб в Управляемых формах шарил - вы легко сможете это определить.

См. также

Комментарии
1. Андрей К. (andrei.k) 02.04.14 08:14 Сейчас в теме
Спасибо за статью, но ничего нового тут нет. Если Вы испытываете трудности с получением макета - храните вордовский шаблон файлом на диске (в общей шаре конечно) и все сведется к получению кома файла НаКлиенте. Возможно есть случаи, когда необходимо хранить шаблон вордовского файла в конфигурации, но на мой взгляд оперативно изменять текстовку шаблона (особенно если это договор и юристы никак не могут договориться о содержании шаблона :)) без влезания в конфигуратор проще и быстрее.
pvlunegov; CeHbKA; +2 Ответить 3
2. ффф ыыы (zqzq) 16 02.04.14 08:23 Сейчас в теме
P.S. кстати, обратите, какая изящная задача получилась для тестирования опытного кандидата на работу.
На собеседовании спрашивают то, что сами недано узнали (с)баш

А если по теме, с какой стати у клиента есть доступ к файловой системе сервера и наоборот (и расшаренные папки тоже неуниверсально)? Лучше через двоичные данные и ХранилищеЗначения передавать, см. работу с картинками, а на клиенте сохранять во временный файл.

А так полезная статья, узнал зачем нужен ActiveDocument :)

(1) andrei.k, согласен, пусть лучше юзеры свой шаблон правят, не программистское это дело.
klinval; FractalizeR; CeHbKA; +3 Ответить
3. Арсений Прялкин (CeHbKA) 178 02.04.14 09:19 Сейчас в теме
Друзья, я с Вами полностью согласен. Но файла в общей шаре может и не быть, а может у него имя изменили, а может шара недоступна, а может там что-то изменили без нашего ведома и заполнение параметров этого файла не получится сделать корректно.
Слишком уж тут много неявных причин.

По сути да - не очень понятно на кой черт такие танцы с бубном, ведь программная работа с ActiveDocument ничем не отличается от ДвоичныхДанных или ХранилищаЗначения. Принцип тот же.

Но все-таки, пусть будет - для галочки ;)
4. Юрий Сиголаев (YurySigolaev) 02.04.14 11:25 Сейчас в теме
Макет = ОбщийМодуль.ПолучитьМакет(Документ); //серверная функция, записывает макет в файл и возвращает полное имя файла

разъясните

если серверная функция записывает макет в файл, то где этот файл будет лежать?
если на сервере, то как к нему получает доступ клиент в этом коде?
Шаблон = ПолучитьCOMОбъект(Макет); //инициализируем COM-объект


если на клиенте, то как серверная функция получит доступ к файловой системе клиента?
и как она передаст на клиента этот самый файл?

в общем, нужно привести листинг этой серверной функции, а также параметры модуля "ОбщийМодуль"
5. Арсений Прялкин (CeHbKA) 178 02.04.14 11:43 Сейчас в теме
(4) YurySigolaev, у нас настроена общая шара, которая доступна для клиента и для сервера, по той простой причине, что все юзеры находятся в домене и не могут самостоятельно сохранять файл на локальную машину, с которой работают в данный момент (т.к. каждый раз они могут садиться за разные компьютеры)

В остальных случаях уже написали как это делать :)
6. Юленька (s_uu) 17 21.05.14 00:52 Сейчас в теме
А можно для тупых полный листинг привести?))
7. misha pripa (Dighty) 04.06.14 15:48 Сейчас в теме
Повторюсь
А можно для тупых полный листинг привести?))
8. Арсений Прялкин (CeHbKA) 178 04.06.14 15:51 Сейчас в теме
(6) s_uu, (7) Dighty,
какой именно листинг нужно привести?
В статье ведь есть листинг
9. misha pripa (Dighty) 04.06.14 16:15 Сейчас в теме
Листинг &НаСервере если можно.
10. misha pripa (Dighty) 04.06.14 16:19 Сейчас в теме
Или помогите я разобраться не могу. Мне надо документ activedocument на тонкий клиент вывести, сижу 3 день мозг ломаю. Пожалуйста помогите.
11. Арсений Прялкин (CeHbKA) 178 04.06.14 17:06 Сейчас в теме
(10) Dighty, через двоичные данные. Читайте 2-й пост
12. Валерий К (klinval) 208 16.09.15 17:59 Сейчас в теме
Каким методом вы записывали файл Word на сервере? У меня на файловой метод SaveAs(ПУТЬ) работает, а на сервере нет. Путь доступен соответственно и там и тут, только на сервере почему то метод SaveAs не обнаружен... Метод Save работает только для ранее сохраненных, а у меня файл вновь созданный.
/////Уточнение от 17.09.15
Метод SaveAs он не пишет, что не обнаружен, а пишет "Произошла исключительная ситуация (Microsoft Word): Ошибка команды"
13. Арсений Прялкин (CeHbKA) 178 18.09.15 11:36 Сейчас в теме
(12) klinval, a word на сервере установлен?
14. Валерий К (klinval) 208 18.09.15 12:00 Сейчас в теме
(13) CeHbKA, да, установлен. Спотыкается именно на SaveAs. Макет получается(ПолучитьМакет),
 MSWord = Макет.Получить(); Документ = MSWord.Application.Documents(1); Документ.Activate();
проходят успешно. Заполнение тоже проходит, а на Документ.SaveAs(ИмяВрем); спотыкается.
Ощущение, что что-то не так с word-ом именно под пользователем под которым работает служба 1С, хотя я под ним заходил и офис нормально запускается!
Чтобы не дебажить весь код, например можно попробовать написать (см. обработка во вложении):
&НаКлиенте
Процедура СоздатьТестWord(Команда)
	СоздатьТестWordНаСервере();
КонецПроцедуры

&НаСервере
Процедура СоздатьТестWordНаСервере()
	Word = Новый COMОбъект("Word.Application");
	Word.Visible=1;
	Документ = Word.Documents.Add();
	ИмяВрем = ПолучитьИмяВременногоФайла(".docx");
	Документ.SaveAs(ИмяВрем);
	Сообщить(ИмяВрем);
КонецПроцедуры
...Показать Скрыть

На файловой базе работает, на SQL не работает (спотыкается на SaveAs). Можете попробовать у себя? Если эта простенькая обработка у вас заработает, значит у нас что-то не так с word-ом на сервере под этим Windows-пользователем.

Я кстати задачу решил через двоичные данные, но всё равно интересно почему не работает SaveAs на сервере!
Прикрепленные файлы:
СоздатьТестWord.epf
15. Арсений Прялкин (CeHbKA) 178 18.09.15 12:51 Сейчас в теме
(14) klinval, проверьте права доступа для пользователя, word и 1С на стороне сервера
Скорей всего проблема в этом. Можете попробовать залогиниться на сервак под юзером, под которым запускается 1С сервер и проверить, даёт ли там сохранить файл интерактивно
16. Валерий К (klinval) 208 18.09.15 13:04 Сейчас в теме
(15) CeHbKA, я уже ранее проводил такую проверку: залогинился под пользователем и сохранил word интерактивно. Клиентской 1С на сервере до этого вообще не стояло, я поставил. Запустился, а там ошибка(см. приложение). Возможно в этом и косяк.
У вас то обработка (во вложении к 14 сообщению) работает на SQL базе?
Прикрепленные файлы:
17. Арсений Прялкин (CeHbKA) 178 18.09.15 16:15 Сейчас в теме
(16) klinval, конкретно в данный момент, нет возможности проверить вашу обработку

Добавьте 1С в исключения в свойствах обозревателя IE
18. Валерий К (klinval) 208 25.09.15 09:23 Сейчас в теме
(17) CeHbKA, отключил усиленную безопасность IE, поставил на самый "небезопасный" уровень, ошибка, указанная в 16 сообщении ушла, но метод SaveAS всё равно не работает.
Так всё таки под кодом:
 Макет = ОбщийМодуль.ПолучитьМакет(Документ); //серверная функция, записывает макет в файл и возвращает полное имя файла

Каким методом ты записываешь? Save, SaveAS?
19. Арсений Прялкин (CeHbKA) 178 25.09.15 09:42 Сейчас в теме
(18) klinval, посмотрите на дату публикации. Доступа к той обработке у меня давно нет, а в памяти я такое держать не могу :)

Что значит
метод SaveAS всё равно не работает.

?

Ошибка выпадает? Файл не сохраняет?
20. Валерий К (klinval) 208 25.09.15 11:27 Сейчас в теме
(19) CeHbKA,
Ошибка выпадает? Файл не сохраняет?

Да. Да:)
По-любому косяк где-то на уровне прав Windows-пользователя (т.е. связано с администрированием серверов, а не с 1С). Даже обработка с сообщения 14 не работает (хотя где там можно ошибиться?).
{Форма.Форма.Форма(13)}: Ошибка при вызове метода контекста (SaveAs)
Документ.SaveAs(ИмяВрем);
по причине:
Произошла исключительная ситуация (Microsoft Word): Ошибка команды

Поэтому мне проще было не разбираться, а запихнуть шаблон не в ActiveDocument, а в двоичные данные, которые я могу спокойно передать на клиент. Что я и сделал... А ошибка с SaveAs, скорее всего так и останется неразгаданной.
21. Арсений Прялкин (CeHbKA) 178 25.09.15 11:45 Сейчас в теме
(20) klinval, вам нужно запуститься непосредственно по тем пользователем, который указан для 1С на сервере и именно под ним попробовать сохранить MS Word интерактивно
22. Валерий К (klinval) 208 25.09.15 11:59 Сейчас в теме
(21) CeHbKA, уже пробовал. Сохраняет... как ни странно.
23. Арсений Прялкин (CeHbKA) 178 25.09.15 12:07 Сейчас в теме
(22) klinval, тогда нужно ловить ошибку, которую возвращает приложение

подключитесь к MS Word из 1С через COM на сервере и попытайтесь сохранить файл методом SaveAs
24. Валерий К (klinval) 208 25.09.15 13:59 Сейчас в теме
(23) CeHbKA, ну так это я и сделал! Ошибка уже давно выявлена и описание её ни о чём не говорит. Файл в 14 сообщении, ошибка от его исполнения в 20 сообщении.
{Форма.Форма.Форма(13)}: Ошибка при вызове метода контекста (SaveAs)
Документ.SaveAs(ИмяВрем);
по причине:
Произошла исключительная ситуация (Microsoft Word): Ошибка команды

Если дать заведомо рабочий путь вручную: та-же ошибка (не важно сетевой или на диск C:)
Если дать заведомо некорректный путь, то уже другая ошибки:
{Форма.Форма.Форма(16)}: Ошибка при вызове метода контекста (SaveAs)
Документ.SaveAs("Ы:\111.docx");
по причине:
Произошла исключительная ситуация (Microsoft Word): Неверно указано имя файла.
Попробуйте выполнить следующие действия:
* Убедитесь, что путь введен правильно.
* Выберите нужный файл из списка файлов и папок.

Пробовал эксперементировать с расширением файла:
	Для Инд = 0 По 100 Цикл
		Попытка
			Word = Новый COMОбъект("Word.Application");
			Word.Visible=1;
			Документ = Word.Documents.Add();
			Документ.SaveAs("C:\111.docx",Инд);
			Сообщить("ПОЛУЧИЛОСЬ:"+Инд);
		Исключение
			Сообщение = Новый СообщениеПользователю();
			Сообщение.Текст = Строка(Инд)+"!"+ОписаниеОшибки();
			Сообщение.Сообщить();
		КонецПопытки;
	КонецЦикла;	
...Показать Скрыть

файл так и не создался.
Сверил все настройки Word локальные и на сервере (запустившись от имени пользователя под которым работает служба 1С). Процесс ворда запускается точно под тем пользователем под которым запускается служба (проверил в диспетчере задач)...
25. Арсений Прялкин (CeHbKA) 178 25.09.15 14:20 Сейчас в теме
(24) klinval, вам нужна ошибка именно MS Word
{Форма.Форма.Форма(13)}: Ошибка при вызове метода контекста (SaveAs)
Документ.SaveAs(ИмяВрем);
по причине:
Произошла исключительная ситуация (Microsoft Word): Ошибка команды

Это листинг ошибки 1С. Обработайте через 1С, сообщение об ошибке MS Word и выведите её содержимое
26. Валерий К (klinval) 208 25.09.15 14:22 Сейчас в теме
(25) CeHbKA,
Обработайте через 1С, сообщение об ошибке MS Word и выведите её содержимое

Не понял, как это сделать?
27. Арсений Прялкин (CeHbKA) 178 25.09.15 14:54 Сейчас в теме
28. Валерий К (klinval) 208 25.09.15 15:34 Сейчас в теме
(27) CeHbKA, правильно я понял: ты хочешь увидеть ошибку как её видит Word, а не как её нам даёт 1С?
Если да, то опять вопрос: как из 1С это можно вывести?
29. Арсений Прялкин (CeHbKA) 178 25.09.15 15:50 Сейчас в теме
(28) klinval, читай про COM-объекты и инструментарий по MS Word
30. Валерий К (klinval) 208 25.09.15 16:00 Сейчас в теме
(29) CeHbKA, что искать/читать и где? Вы ответьте хотя бы на:
правильно я понял: ты хочешь увидеть ошибку как её видит Word, а не как её нам даёт 1С?
31. Арсений Прялкин (CeHbKA) 178 25.09.15 16:16 Сейчас в теме
(30) klinval, искать\читать:
- работа с COM объектами в 1С
- интеграция MS Word и 1С

где:
- в гугле

Вы ответьте хотя бы на:

1С вообще никакой ошибки не видит, она тупо посредник между пользователем и приложением (MS Word)
32. Валерий К (klinval) 208 25.09.15 16:35 Сейчас в теме
(31) CeHbKA, это реально можно вывести ошибку в 1С как её видит Word или ты чисто теоретически предполагаешь, что такой метод есть?
Может я тебя не правильно понял: по тексту мне показалось, что ты уверен, что такая возможность (такой метод) есть, а может ты имел ввиду, что чисто теоретически такая возможность должна быть.
33. Ivan Antonov (ivant) 11 17.03.16 08:41 Сейчас в теме
(32) Столкнулся с аналогичной проблемой - хотел узнать, удалось ли ее в итоге победить или забили?
Ошибка таже:
Ошибка при вызове метода контекста (SaveAs)
34. Валерий К (klinval) 208 17.03.16 09:39 Сейчас в теме
(33) ivant, вроде как CeHbKA утверждал, что можно считать ошибку как то по-другому и увидеть причину косяков. Я сильно "копнул" в этом направлении, но ничего не нашёл. Похоже это совет из разряда гипотетических, что мол возможно считать ошибку Word как то по другому, но я не знаю как, но точно можно... Можете как советовал CeHbKA копнуть в эту сторону, может я что-то не увидел!

Хотя если честно ошибку я как-то исправил. Но вот не помню как, но явно не по этому совету. Моя обработка в (14) сообщении теперь у меня работает на серверной базе. Возможно ошибка просто ушла после обновления платформы.

Ещё есть вариант перейти с ActiveDocument на двоичные данные, как я в начале и сделал. Можете посмотреть тут код как это делается. Если вкратце:
//На клиенте получаем макет и заполняем его предварительно полученными данными
ДвоичныеДанныеМакета = ПолучитьИзВременногоХранилища(ПолучитьМакетСКлиента("ПисьмоНаОплатуWord"));
            ИмяВрем = ПолучитьИмяВременногоФайла(".docx");
            ДвоичныеДанныеМакета.Записать(ИмяВрем);
            Попытка
                Документ = ПолучитьCOMОбъект(ИмяВрем); 
                Для Каждого Параметр из СтруктураПараметров.Значение Цикл
                    //В оригинале тут другой код, но для простаты пример:
                    Selection = Документ.Content;
                    Selection.Find.Execute("["+Параметр.Ключ+"]",Ложь,Истина,Ложь,,,Истина,,Ложь,Параметр.Значение,2);
                КонецЦикла;
                Документ.Application.Visible = Истина;
                Документ.Application.WindowState = 2;
                Документ.Application.WindowState = 1;
                Документ.Activate();
            Исключение
.....

&НаСервереБезКонтекста
Функция ПолучитьМакетСКлиента(Имя)
    Возврат ПоместитьВоВременноеХранилище(Документы.ПисьмоНаОплату.ПолучитьМакет("ПисьмоНаОплатуWordДвоичныеДанные"));
КонецФункции
...Показать Скрыть
35. Арсений Прялкин (CeHbKA) 178 19.03.16 11:40 Сейчас в теме
(32) klinval, (33) ivant, (34) klinval,
вы получаете COM-объект MS Word
соответственно работаете с API данного com-объекта (т.е. Word)
функция SaveAS является функцией API Word
значит, чтобы получить ошибку Word нужно воспользоваться API этого самого Word
37. Арсений Прялкин (CeHbKA) 178 10.08.16 10:20 Сейчас в теме
39. Дмитрий Индерёв (Stepka1206) 27.03.17 18:26 Сейчас в теме
Аналогичная ошибка, не может открыть документ сохраненный в темп

	

       ДвоичныеДанные = ПолучитьДвоичныеДанныеМакета();
	
	COMОбъект = Новый COMОбъект("Word.Application");

	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("DOC");
	ДвоичныеДанные.Записать(ИмяВременногоФайла);
		
	COMОбъект.Documents.Open(ИмяВременногоФайла);
        // здесь вываливается ошибка, никаких документов он не открыл, в темпе лежит созданный документ ворда , COMОбъект.Documents.Count = 0, через ЖР проверял
        Док = COMОбъект.Application.Documents(1);
	Док.Activate();		


...Показать Скрыть
40. uke_boy (uke_boy) 04.04.17 13:22 Сейчас в теме
41. Bkmz Яковенко (Bkmz) 05.04.17 09:28 Сейчас в теме
Почему при сохранении макета типа active document в файл word кодом:
Код:

ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Макет  = ОбработкаОбъект.ПолучитьМакет("ШаблонПисьмаПросрочка");
ИмяФайла = КаталогВременныхФайлов() + "\файл.doc";
Макет.Записать(ИмяФайла);


Я получаю вместо нормального документа вот такой

42. Bkmz Яковенко (Bkmz) 05.04.17 12:33 Сейчас в теме
А почему нельзя использовать документ двоичные данные? Загрузил туда шаблон. Получили шаблон. Сохранили документ. Передали на клиент имя открыли через COM и заполняем.

&НаКлиенте
Процедура ПолучитьМакет(Команда)
	
	Попытка
		Индификатор = ПолучитьДанныеМакета();
		МакетПисьма = ПолучитьИзВременногоХранилища(Индификатор);
		ИмяФайла = "Письмо.doc";
		ИмяФайлаПолное = "С:\" + ИмяФайла;
		МакетПисьма.Записать(ИмяФайлаПолное);
	Исключение
		Сообщить(ОписаниеОшибки());
	КонецПопытки;
	
	Попытка
		Шаблон = Новый COMОбъект("Word.Application");
	Исключение
		Сообщить("Ошибка при попытке создать объект ""MS Word""!" + Символы.ПС + 
				 "Возможно приложение ""MS Word"" не установлено или установлено неправильно.", СтатусСообщения.Внимание);
			 КонецПопытки;
	
	Шаблон.Documents.Open(ИмяФайлаПолное); 
	Попытка
		Шаблон.Application.Documents(1).Content.Find.Execute("{Сумма}",,,,,,,,, ЭтаФорма.Сумма, 2);				
		Шаблон.Application.Documents(1).Content.Find.Execute("{Контрагент}",,,,,,,,, ЭтаФорма.Контрагент, 2);				
		//Перемещаемся до строки в таблице
		Шаблон.Application.Selection.MoveDown(,8);		
		//Перемещаемся вниз, выделяем строку таблицы и копируем ее в буфер обмена
		Шаблон.Application.Selection.SelectRow();
		Шаблон.Application.Selection.Copy();
		Для каждого Строка Из Этаформа.ТЗ Цикл
		    //Заменяем значения
		    Шаблон.Application.Selection.Find.Execute("{НомерСчета}" ,,,,,,,,,Строка.НомерСчета, 2);
		    Шаблон.Application.Selection.Find.Execute("{ДатаПоставки}" ,,,,,,,,,Строка.ДатаПоставки, 2);
		    //Последний параметр поиска пустой
		    Шаблон.Application.Selection.Find.Execute("{КрайняяДата}" ,,,,,,,,,Строка.КрайняяДата, 2);
			Шаблон.Application.Selection.Find.Execute("{СтоимостьТоваров}" ,,,,,,,,,Строка.СтоимостьТоваров, 2);
		    //Перемещаемся вниз, вставляем из буфера обмена строку
		    Шаблон.Application.Selection.MoveDown();
		    Шаблон.Application.Selection.Paste();
		    //Перемещаемся вверх и выделяем строку для замены значений
		    Шаблон.Application.Selection.MoveUp();
		    Шаблон.Application.Selection.SelectRow();
		КонецЦикла;
		//Вырезаем лишнюю строку
		Шаблон.Application.Selection.Cut();
		Шаблон.Application.Visible = Истина;		
	Исключение
		// Если произойдет ошибка выводятся данные об ошибке и объект закрывается. 
		Сообщить("Ошибка: " + ОписаниеОшибки(), СтатусСообщения.Внимание); 
		Шаблон.Application.Quit(0);
	КонецПопытки;

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

&НаСервере
Функция ПолучитьДанныеМакета()

	АдресХранилища = Новый УникальныйИдентификатор();
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	Макет		 	= ОбработкаОбъект.ПолучитьМакет("ШаблонПисьмаПросрочка");
	Возврат ПоместитьВоВременноеХранилище(Макет, АдресХранилища);
	
КонецФункции	
...Показать Скрыть


У меня этот код на серверной базе работает
43. shumvlesu 01.06.17 10:18 Сейчас в теме
(42)
МакетПисьма = ПолучитьИзВременногоХранилища(Индификатор);


Здесь в тонком клиенте у Вас будет выскакивать ошибка. Такой способ только для толстого клиента подходит.
44. Валерий К (klinval) 208 01.06.17 12:29 Сейчас в теме
(43) Выскажусь в защиту:
Глобальный контекст (Global context)
ПолучитьИзВременногоХранилища (GetFromTempStorage)
Синтаксис:

ПолучитьИзВременногоХранилища(<Адрес>)
Параметры:

<Адрес> (обязательный)

Тип: Строка.
Адрес, указывающий на значение во временном хранилище.
Возвращаемое значение:

Тип: Произвольный.
Значение, ранее помещенное с помощью метода ПоместитьВоВременноеХранилище.
Описание:

Получает значение из временного хранилища.

Доступность:

Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение(клиент), мобильное приложение(сервер).
Вызов метода выполняет обращение к серверу.

Примечание:

Результат выполнения не кэшируется, вызов сервера осуществляется при каждом вызове метода.

В справке написано, что тонкий клиент можно использовать! Я в своей статье данный метод тоже привожу в тонком клиенте, причём этот код уже давно работает на рабочей базе (в толстом клиенте у нас никто не работает).
Оставьте свое сообщение