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

18.11.13

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

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

Скачать файл

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

Наименование По подписке [?] Купить один файл
ОбработкаСПримеромИШаблоном
.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 Управляемые формы Запросы Система компоновки данных Платные (руб)

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

12000 руб.

02.09.2020    169318    937    403    

905

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

Инструмент представляет собой обработку для проведения свёртки или обрезки баз данных. Работает на ЛЮБЫХ конфигурациях (УТ, БП, ERP и т.д.). Поддерживаются серверные и файловые базы, управляемые и обычные формы. Может выполнять свертку сразу нескольких баз данных и выполнять их автоматически без непосредственного участия пользователя. Решение в Реестре отечественного ПО

8400 руб.

20.08.2024    12623    99    42    

101

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

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

9360 руб.

17.05.2024    26544    90    48    

134

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

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

22200 руб.

06.10.2023    16834    41    15    

75

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

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

15000 руб.

10.11.2023    11400    40    27    

66

SALE! %

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

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

4800 3840 руб.

14.01.2013    190557    1150    0    

918

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

Разработка Конструктор автоматизированных рабочих мест "Конструктор АРМ" реализована в виде расширения и является универсальным инструментом для создания АРМ любой сложности в пользовательском режиме.

3600 руб.

27.12.2024    791    2    0    

4

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

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

5000 руб.

07.02.2018    103935    244    100    

306
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
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 251 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 780 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 19 30.03.17 12:51 Сейчас в теме
13. wbazil 140 03.04.17 09:43 Сейчас в теме
нет с Эксель из примера не сработает, но подобный подход можно применить и там, т.к. файл Эекселя 2007+ это такой же контейнер с xml файлами, как и файл Ворд, хотя там на каждый лист свой xml файл.
15. artms 289 05.08.19 09:52 Сейчас в теме
Давно написал парсер (увы не все предусмотрено, но легко создать рабочий шаблон, в WORD):
https://infostart.ru/public/675307/
Увы строки замены могут разбиты тегами, определяющий шрифт, иногда пробел. Это частично решено этим парсером.
16. wbazil 140 05.08.19 10:12 Сейчас в теме
(15) в (9) (10) уже обсуждали данную проблему
17. artms 289 05.08.19 11:53 Сейчас в теме
(16) Эта проблема решена этим парсером https://infostart.ru/public/675307/ . Поэтому этот не совсем то что обсуждали.
19. WWWolfy 134 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();

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