Договора из Шаблона MS Word 2007+ без OLE

18.11.13

Разработка - Инструментарий разработчика

Обработка показывает, как можно создать шаблон в MS Word 2007+ и заполнить его данными из 1с, не используя технологию OLE

Скачать файл

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

Наименование SM По подписке [?] Купить один файл
ОбработкаСПримеромИШаблоном
.zip 564,85Kb
62
62
1 SM
Скачать Купить за 1 850 руб.

Обработка показывает как можно создать шаблон в MS Word 2007+ и заполнить его данными из 1с  не используя технологию OLE. Многие пользуются методом закладок, не считаю его удобным, поэтому хочу предложить идею которая использовалась мной давно в Delphi

Идея проста, сделать в тексте шаблона определённый текст который не будет повторяться и потом заменой заменить поля на нужные данные, поскольку файлы Word 2007+ это уже просто архивы ХМL, просто распаковываем делаем замену упаковываем обратно. На словах может немного сумбурно поэтому публикую сам код и пример в обработке.

поля могут быть отформатированы как нужно пользователю, т.е. можно использовать весь арсенал Word.

скорость работы высока,шаблон на 110 страниц который выложен в примере обрабатывается мение секунды.

 

Процедура кПолучитьДоговорНажатие(Элемент)
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
Фильтр = "Word (*.docx)|*.docx";
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";

Если ДиалогОткрытияФайла.Выбрать() Тогда
ВыбФайл = Новый Файл(ДиалогОткрытияФайла.ПолноеИмяФайла);
ПутьИмяШаблона = ВыбФайл.ПолноеИмя;
ПутьИмяФайла = ПутьИмяШаблона + "_результат.docx";
Иначе
Текст = "ru = ""Файл(ы) не выбран!""; en = ""File(s) not selected!""";
Предупреждение(НСтр(Текст));
Возврат;
КонецЕсли;

СписокПараметров = Новый Структура;
СписокПараметров.Вставить("ААФИОАА","ИВАНОВ");
СписокПараметров.Вставить("ААНОМЕРАА","№456-АВ-789");
СписокПараметров.Вставить("ААДАТААА","16.01.2012");
Сообщить(ТекущаяДата()); 
псоПолучитьДоговор(ПутьИмяШаблона,ПутьИмяФайла,СписокПараметров);
Сообщить(ТекущаяДата());
КонецПроцедуры
//получает готовый договор с файла шаблона
//ПутьИмяШаблона - путь и имя файла шаблона docx
//ПутьИмяФайла - путь и имя файла куда сохранять готовый договор
//СписокПараметров - параметры и их значения для замены в договоре тип структура (Ключ,Значение)

Процедура псоПолучитьДоговор(ПутьИИмяШаблона,ПутьИИмяФайла,СписокПараметров);
Сейчас = ТекущаяДата();
ПутьИИмя = ПолучитьИмяВременногоФайла();
Путь = "";
Имя = "";
ПозСлэш = Найти(ПутьИИмя,"\");
Пока ПозСлэш > 0 Цикл
Путь = Путь+Сред(ПутьИИмя,1,ПозСлэш);
ПутьИИмя = Сред(ПутьИИмя,ПозСлэш+1);
ПозСлэш = Найти(ПутьИИмя,"\");
КонецЦикла;
Имя = ПутьИИмя;
Имя = Сред(Имя,1,СтрДлина(Имя)-4);
ВременнаяПапка = КаталогВременныхФайлов() + "1c" + Формат(Год("20031120"),"ЧГ=0") + Месяц(Сейчас) + День(Сейчас) + Час(Сейчас) + Минута(Сейчас) + Секунда(Сейчас) + Имя;

ЧтениеZIP = Новый ЧтениеZipФайла(ПутьИИмяШаблона);
ЧтениеZIP.ИзвлечьВсе(ВременнаяПапка, РежимВосстановленияПутейФайловZIP.Восстанавливать);
ЧтениеZIP.Закрыть();

Текст = Новый ЧтениеТекста(ВременнаяПапка + "\word\document.xml", КодировкаТекста.UTF8);
РезТекст = Новый ЗаписьТекста(ВременнаяПапка + "\word\document1.xml", КодировкаТекста.UTF8);

Стр = Текст.Прочитать();
Пока Стр <> Неопределено Цикл
Для каждого Элемент Из СписокПараметров Цикл
Стр = СтрЗаменить(Стр,Элемент.Ключ,Элемент.Значение);
КонецЦикла;
РезТекст.Записать(Стр);
Стр = Текст.Прочитать();
КонецЦикла;
Текст.Закрыть();
РезТекст.Закрыть();

Попытка
УдалитьФайлы(ВременнаяПапка + "\word\document.xml");
ПереместитьФайл(ВременнаяПапка + "\word\document1.xml",ВременнаяПапка + "\word\document.xml");
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

ЗаписьZIP = Новый ЗаписьZipФайла(ПутьИИмяФайла);
ЗаписьZIP.Добавить(ВременнаяПапка + "\*.*", РежимСохраненияПутейZIP.СохранятьОтносительныеПути, РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно);
ЗаписьZIP.Записать();
Попытка
УдалитьФайлы(ВременнаяПапка);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

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

См. также

Инструментарий разработчика Роли и права Запросы СКД Программист Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    139760    767    391    

800

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

Инструмент, позволяющий абсолютно по-новому взглянуть на процесс разработки печатных форм. Благодаря конструктору можно значительно снизить затраты времени на разработку печатных форм, повысить качество и "прозрачность" разработки, а также навести порядок в многообразии корпоративных печатных форм.

18000 руб.

06.10.2023    11406    30    6    

60

Инструменты администратора БД Инструментарий разработчика Роли и права Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

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

10000 руб.

10.11.2023    7174    26    4    

50

Инструментарий разработчика Программист Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Инструмент для написания и отладки кода в режиме «1С:Предприятие». Представляет собой консоль кода с возможностью пошаговой отладки, просмотра значений переменных любых типов, использования процедур и функций, просмотра стека вызовов, вычисления произвольных выражений на встроенном языке в контексте точки останова, синтаксического контроля и остановки по ошибке. В консоли используется удобный редактор кода с подсветкой, контекстной подсказкой, возможностью вызова конструкторов запроса и форматной строки.

5400 руб.

17.05.2024    13283    29    27    

74

Инструментарий разработчика Инструменты администратора БД Системный администратор Программист Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Платные (руб)

Универсальный инструмент программиста для администрирования конфигураций. Сборник наиболее часто используемых обработок под единым интерфейсом.

3600 руб.

14.01.2013    181683    1103    0    

876

Инструментарий разработчика Программист 8.3.14 1С:Конвертация данных Россия Платные (руб)

Расширение для конфигурации “Конвертация данных 3”. Добавляет подсветку синтаксиса, детальную контекстную подсказку, глобальный поиск по коду.

15000 руб.

07.10.2021    15950    3    12    

38

Инструментарий разработчика Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

Восстановление партий или взаиморасчетов, расчет зарплаты, пакетное формирование документов или отчетов - теперь все это стало доступнее. * Есть желание повысить скорость работы медленных алгоритмов! Но... * Нет времени думать о реализации многопоточности? * о запуске и остановке потоков? * о поддержании потоков в рабочем состоянии? * о передаче данных в потоки и как получить ответ из потока? * об организации последовательности? Тогда ЭТО - то что надо!!!

5000 руб.

07.02.2018    101069    242    97    

302

Инструментарий разработчика Перенос данных 1C Программист Платформа 1С v8.3 Платные (руб)

В процессе работы в 1С часто возникает потребность получить данные из другой базы. Обычно это делается через COM-соединение, и время выполнения запроса при этом оставляет желать лучшего. В данной публикации представлено универсальное решение для 1С, позволяющее практически моментально выполнить произвольный код или запрос с параметрами в другой информационной базе через Web-сервис.

2400 руб.

24.09.2019    24461    17    15    

34
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. sytkosa 119 15.11.13 22:40 Сейчас в теме
(0) Да для фиксированного шаблона самая быстрая реализация. я бы добавил ещё код который упрощенно копи-пастом добавляет новую строку в простой таблице (Таблица без объединенных ячеек по вертикали)
6. rasswet 82 20.11.13 08:32 Сейчас в теме
(1) поддерживаю.
(0)Можете добавить? раз уж вы в этой теме.
7. Cyberhawk 135 11.02.15 11:15 Сейчас в теме
(1) или (6) - код по добавлению строк есть?
8. wbazil 140 12.02.15 11:52 Сейчас в теме
(7) я добавление строк не делал, но в общем думаю надо брать простую таблицу выгружать в ХМЛ и смотреть как добавлять новую строку, если сами сделаете поделитесь в ЛС или прямо тут
18. 1sig 248 24.12.19 00:26 Сейчас в теме
(8) спасибо вам за труды, по ходу это первая публикация на инфостарте по этой методике в своем роде. Кто искал код добавления строк в таблицу - формирование таблицы и добавление строк очень подробно описано здесь https://infostart.ru/public/259510/

в данной статье автор не парится с разбором xml документа, обрабатывая тело XML документа строкой) более изящное решение с помощью Документа DOM и XPath найдено здесь https://infostart.ru/public/590918/

и наконец результаты соединения всех этих разработок здесь https://infostart.ru/public/1171429/
2. RayCon 785 16.11.13 14:19 Сейчас в теме
Файл не найден или был удален :(
3. wbazil 140 16.11.13 18:11 Сейчас в теме
странно, в понедельник перезайлью т.к. файлы на работе
4. пользователь 17.11.13 17:37
Сообщение было скрыто модератором.
...
5. wbazil 140 18.11.13 10:54 Сейчас в теме
9. Cyberhawk 135 15.02.15 13:40 Сейчас в теме
К сожалению, пришлось отказаться от работы с Вордом без СОМ-модели, т.к. для замены текста (классическая задача по заполнению параметров печатных форм - договоров, например) через ковыряние в docx выяснилось, что текст иногда произвольным обрзом разделяется тегами w:r (параграфы, "run"); также положение курсора, начало-конец проверки орфографии и пунктуации и теги форматирования "вклиниваются" в куски текста внутри document.xml и делают замену текста делом практически нереальным.
Простой пример: пишу в Ворде текст (который должен заменяться потом программно в 1С) "[Договор.Номер]", в document.xml это превращается в
<w:t>Договор</w:t>
</w:r>
<w:r w:rsidR="00BD0530">
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:cs="Calibri"/>
<w:sz w:val="22"/>
<w:szCs w:val="22"/>
</w:rPr>
<w:t>.</w:t>
</w:r>
<w:r w:rsidR="007F59CC">
<w:rPr>
<w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:cs="Calibri"/>
<w:sz w:val="22"/>
<w:szCs w:val="22"/>
</w:rPr>
<w:t>НомерДоговора</w:t>)
Показать


Найденный способ обхода - вставлять текст-параметр в документ Ворд путем копирования цельного куска текста из внешнего редактора (из блокнота, например), для пользователя не под силу.
14. bogdan_sukonnov 57 12.10.18 19:01 Сейчас в теме
(9) мне кажется, самое гуманное решение проблемы вставки лишних тэгов внутрь наших "переменных" - макрос, обрабатывающий шаблон после того, как его подготовил пользователь, но до того, как его начали использовать в 1С. Пусть зло побеждает само себя!
10. wbazil 140 16.02.15 08:56 Сейчас в теме
тоже встречался с этой проблемой, 100% ловиться когда при написании названия параметра переключать шрифт нажимать бекспейс
от решения не отказывался т.к. шаблоны делаются намного реже чем печатаются, да и пользователю сразу видно какой параметр ошибочно написан, имхо лучше поискать ошибочно написанный параметр чем воевать с зависшими вордами в терминале

ЗЫ. поэтому параметры в примере и обрамляются через АА...АА а не через {} или <>
11. NoRazum 29 01.04.15 20:27 Сейчас в теме
сама идея великолепная.
сделал на ней выгрузку. Все отлично немного со заменой помучился, но стоит этого.
Даже колонтитулы можно менять
ПЛЮС.
12. XelOla 18 30.03.17 12:51 Сейчас в теме
13. wbazil 140 03.04.17 09:43 Сейчас в теме
нет с Эксель из примера не сработает, но подобный подход можно применить и там, т.к. файл Эекселя 2007+ это такой же контейнер с xml файлами, как и файл Ворд, хотя там на каждый лист свой xml файл.
15. artms 287 05.08.19 09:52 Сейчас в теме
Давно написал парсер (увы не все предусмотрено, но легко создать рабочий шаблон, в WORD):
https://infostart.ru/public/675307/
Увы строки замены могут разбиты тегами, определяющий шрифт, иногда пробел. Это частично решено этим парсером.
16. wbazil 140 05.08.19 10:12 Сейчас в теме
(15) в (9) (10) уже обсуждали данную проблему
17. artms 287 05.08.19 11:53 Сейчас в теме
(16) Эта проблема решена этим парсером https://infostart.ru/public/675307/ . Поэтому этот не совсем то что обсуждали.
19. WWWolfy 132 12.04.20 19:18 Сейчас в теме
Вот вам процедура, которая убирает разрывы в разобранном Word/DocX файле, стандартно это document.xml.
Я, например, использую её перед сохранением Шаблона docx в Хранилище 1С.
Шаблон на 5 страниц обрабатывает меньше секунды, имхо шустро.
А так как обрабатывать надо один раз, то и вообще отлично.

Лучше запускать её в Попытка/Исключение, на всякий случай.


// Убираем в Word / docx файле разрывы
// будет работать для параметров типа:   <Организация>
// ФайлXML  - строка, ссылка на файл document.xml
Процедура ОбработатьФайлПередСохранением( ФайлXML )
	//инициализация параметров
	ТегСтрокиТекста="w:t";
	СигнатураОткрывающая = "<";
	СигнатураЗакрывающая = ">";
	мУзлыКУдалению = Новый Массив;

	// читаем XML файл в  ПостроительDOM
	ЧтениеXML = Новый ЧтениеXML;
	ЧтениеXML.ОткрытьФайл(ФайлXML);
	ФайлDOM = Новый ПостроительDOM(); //
	DOM_XML = ФайлDOM.Прочитать( ЧтениеXML );
	ЧтениеXML.Закрыть();
	
	
	// ищем все случаи, когда скобка открыта (хоть раз) и не закрыта (ни разу)
	Resolver = New DOMNamespaceResolver(DOM_XML);
	XPathExpression = DOM_XML.CreateXPathEx * pression("//w:t[contains(text(),'"+СигнатураОткрывающая+"') and not(contains(text(),'"+СигнатураЗакрывающая+"'))]", Resolver);
	XPathResult 	= XPathExpression.Evaluate(DOM_XML);
		
	Node = XPathResult.IterateNext();
	Пока Node <> Undefined Цикл 
		стрПараметр = ""+Node.TextContent; //тут собираем строку
		мУзлыКУдалению.Очистить();   //тут собираем узлы от скобки < до скобки >, потом их удалим
		
		УзлыНиже = Node.РодительскийУзел;
		флНашлиЗакрывающуюСкобку = Ложь;
		Пока УзлыНиже.СледующийСоседний <> Неопределено И НЕ флНашлиЗакрывающуюСкобку Цикл
			УзлыНиже = УзлыНиже.СледующийСоседний;
			мУзлыКУдалению.Добавить( УзлыНиже );
			
			xml_Run_TextFragment = УзлыНиже;
			Для каждого xml_Text из xml_Run_TextFragment.ДочерниеУзлы Цикл
				Если xml_Text.ИмяУзла <>ТегСтрокиТекста Тогда Продолжить; КонецЕсли;
				
				стрПараметр = стрПараметр + xml_Text.TextContent;
				Если СтрНайти( xml_Text.TextContent, СигнатураЗакрывающая) >0 Тогда    // ищем  ">"
					флНашлиЗакрывающуюСкобку = Истина;
					Прервать;
				КонецЕсли;
			КонецЦикла; // ищем внутри Run_TextFragment
			
		КонецЦикла;  // идём к след. узлу
		
		//обрабатываем найденное
		Если флНашлиЗакрывающуюСкобку Тогда
			Node.TextContent = стрПараметр;
			//удаляем ненужные узлы, которые были от скобки до скобки
			Для Каждого текУзелУдалять Из мУзлыКУдалению Цикл 
				текУзелУдалять.РодительскийУзел.RemoveChild(текУзелУдалять);    //УдалитьДочерний
			КонецЦикла;
		КонецЕсли;
		
		// next
		Node = XPathResult.IterateNext();
	КонецЦикла;
	
	XMLWriter = New XMLWriter;
	XMLWriter.OpenFile(ФайлXML); 
	DOMWriter = New DOMWriter; 
	DOMWriter.Write(DOM_XML, XMLWriter); 
	XMLWriter.Close();

КонецПроцедуры
Показать
Оставьте свое сообщение