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

18.11.13

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

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

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

Наименование Файл Версия Размер
ОбработкаСПримеромИШаблоном
.zip 564,85Kb
62
.zip 564,85Kb 62 Скачать

Обработка показывает как можно создать шаблон в 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.Записать();
Попытка
УдалитьФайлы(ВременнаяПапка);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

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

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

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

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

13000 руб.

02.09.2020    119912    656    389    

701

Infostart PrintWizard

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

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

18000 руб.

06.10.2023    7007    20    6    

37

Infostart УДиФ: Управление данными и формами

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

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

10000 руб.

10.11.2023    3246    10    1    

31

SALE! 30%

PowerTools

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

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

3600 2520 руб.

14.01.2013    177341    1070    0    

846

Многопоточность. Универсальный «Менеджер потоков» 2.1

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

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

5000 руб.

07.02.2018    99203    239    97    

296

[ЕХТ] Фреймворк для Расширений 1С

Инструментарий разработчика Платформа 1С v8.3 Управляемые формы Платные (руб)

"Фреймворк для Расширений 1С" это универсальное и многофункциональное решение, упрощающее разработку и поддержку создаваемых Расширений. Поставляется в виде комплекта из нескольких Расширений с открытым исходным кодом. Работает в любых Конфигурациях в режиме Управляемого приложения с режимом совместимости 8.3.12 и выше без необходимости внесения изменений в Конфигурацию.

3000 руб.

27.08.2019    17912    6    8    

38

1С HTML Шаблоны / HTML Templates

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

Быстрая и удобная обработка для работы с шаблонами HTML. Позволяет легко и быстро формировать код HTML.

2040 руб.

27.12.2017    27945    3    10    

14

Выполнение произвольного кода или запроса с параметрами через Web-сервис (замена COM-подключений)

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

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

2400 руб.

24.09.2019    23490    15    15    

31
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
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 138 12.02.15 11:52 Сейчас в теме
(7) я добавление строк не делал, но в общем думаю надо брать простую таблицу выгружать в ХМЛ и смотреть как добавлять новую строку, если сами сделаете поделитесь в ЛС или прямо тут
18. 1sig 243 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 784 16.11.13 14:19 Сейчас в теме
Файл не найден или был удален :(
3. wbazil 138 16.11.13 18:11 Сейчас в теме
странно, в понедельник перезайлью т.к. файлы на работе
4. пользователь 17.11.13 17:37
Сообщение было скрыто модератором.
...
5. wbazil 138 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 138 16.02.15 08:56 Сейчас в теме
тоже встречался с этой проблемой, 100% ловиться когда при написании названия параметра переключать шрифт нажимать бекспейс
от решения не отказывался т.к. шаблоны делаются намного реже чем печатаются, да и пользователю сразу видно какой параметр ошибочно написан, имхо лучше поискать ошибочно написанный параметр чем воевать с зависшими вордами в терминале

ЗЫ. поэтому параметры в примере и обрамляются через АА...АА а не через {} или <>
11. NoRazum 29 01.04.15 20:27 Сейчас в теме
сама идея великолепная.
сделал на ней выгрузку. Все отлично немного со заменой помучился, но стоит этого.
Даже колонтитулы можно менять
ПЛЮС.
12. XelOla 17 30.03.17 12:51 Сейчас в теме
13. wbazil 138 03.04.17 09:43 Сейчас в теме
нет с Эксель из примера не сработает, но подобный подход можно применить и там, т.к. файл Эекселя 2007+ это такой же контейнер с xml файлами, как и файл Ворд, хотя там на каждый лист свой xml файл.
15. artms 282 05.08.19 09:52 Сейчас в теме
Давно написал парсер (увы не все предусмотрено, но легко создать рабочий шаблон, в WORD):
https://infostart.ru/public/675307/
Увы строки замены могут разбиты тегами, определяющий шрифт, иногда пробел. Это частично решено этим парсером.
16. wbazil 138 05.08.19 10:12 Сейчас в теме
(15) в (9) (10) уже обсуждали данную проблему
17. artms 282 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();

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