0. milkers 2330 11.12.17 16:55 Сейчас в теме

Этюды по программированию. Взаимодействие с Microsoft Word

Часто приходится заниматься созданием сложных документов Word с таблицами, вложенными фрагментами, хитрым оформлением и прочими радостями жизни. Это - попытка как-то структурировать полученный опыт, чтобы не приходилось перерывать ворох старых обработок в поисках крупиц истины. Надеюсь, эта статья будет полезна и Вам.

Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо
1. vladismi 161 12.12.17 11:27 Сейчас в теме
Запомним как упорядочение приемов.
Однако предложенное 1С использование копипаста втыкает в файл-приемник всю ту грязь, которую пользователь копирует у себя пока программа готовит вордовый документ...
"А мужики то не знают"...
:(
ger_kar; YPermitin; +2 Ответить
15. sulitckaja 22.02.18 06:30 Сейчас в теме
Может сможет подсказать кто, как в документе Word скопировать и вставить ниже уже существующую таблицу.
Делаю так:
Шаблон = Новый COMОбъект("Word.Application");
Шаблон.Documents.Open(ИмяФайлаПолное); 
Шаблон.Application.Documents(1).Content.Tables(1).Range.Copy();
Шаблон.Application.Documents(1).Content.InsertParagraphAfter();
Шаблон.Application.Documents(1).Content.Paste();


В результате таблица копируется но весь текст и предыдущая таблица исчезает.
16. wonderboy 168 22.02.18 07:41 Сейчас в теме
(15) Предполагаю что Content.Paste() делает вставку вместо всего контента. Вам наверное нужно вставить вместо последнего параграфа, который вы добавили.
Что-то вроде
КоличествоПараграфов = Шаблон.Application.Documents(1).Paragraphs.Count;
Шаблон.Application.Documents(1).Paragraphs(КоличествоПараграфов-1).Range.Paste()
sulitckaja; +1 Ответить
17. sulitckaja 22.02.18 08:01 Сейчас в теме
(16)Спасибо большое. Сейчас попробую.
18. sulitckaja 22.02.18 08:19 Сейчас в теме
(16)
КоличествоПараграфов = Шаблон.Application.Documents(1).Paragraphs.Count;
Шаблон.Application.Documents(1).Paragraphs(КоличествоПараграфов-1).Range.Paste()

(16)
Все получилось! А можно еще один вопрос? Как сделать так, чтобы таблица копировалась с нового листа?
19. wonderboy 168 22.02.18 09:06 Сейчас в теме
(18) Я вам с ходу не подскажу. Наверное что-то вроде

Шаблон.Application.Documents(1).Selection.EndKey(6);
Шаблон.Application.Documents(1).Selection.InsertBreak();

перед добавление параграфа.
sulitckaja; +1 Ответить
20. sulitckaja 22.02.18 09:24 Сейчас в теме
21. rmarkovych 05.02.19 15:58 Сейчас в теме
Спасибо автору.
Хотелось бы еще добавить (может кому пригодиться) поиск и замену колонтитулов в макете Word:
MSWord = Новый COMОбъект("Word.Application");
MSWord.ActiveDocument.Sections(1).Headers(1).Range.Find.Execute("<ТекстИскомогоКолонтитула>",,,,,,-1,,,<НужныйТекст>, 2); - верхний
MSWord.ActiveDocument.Sections(1).Footers(1).Range.Find.Execute("<ТекстИскомогоКолонтитула>",,,,,,-1,,,<НужныйТекст>, 2); - нижний
2. 🅵🅾️🆇 12.12.17 16:23 Сейчас в теме
Вся эта объектная модель взаимодействия требует установленного ворда.
Была у меня идейка извратиться и написать взаимодействие с Word'овскими макетами через ЧтениеДанных для простых задач.
Работать должно в разы быстрее и не требовать офиса.

Раньше также делал дикую вложенность как у вас:
Для Каждого Закладка из Word.ActiveDocument.Bookmarks Цикл
	Если Найти(Закладка.Name,ИмяЗакладки) Тогда
		Если ЗначениеЗаполнено(Файл) Тогда
			...
		КонецЕсли; // Если ЗначениеЗаполнено(Файл)
	КонецЕсли; // Если Найти(Закладка.Name,ИмяЗакладки)
КонецЦикла; // Для Каждого Закладка из Word.ActiveDocument.Bookmarks
Показать


Попробуйте такую запись, она легче читается:
Для Каждого Закладка из Word.ActiveDocument.Bookmarks Цикл
	Если Не Найти() Тогда Продолжить КонецЕсли;
	Если Не ЗначениеЗаполнено(Файл) Тогда Продолжить КонецЕсли;
	...
КонецЦикла; // Для Каждого Закладка из Word.ActiveDocument.Bookmarks


Можно и от цикла избавиться с помощью рекурсивных процедур или goto, но это уже извращение)))
ger_kar; vz1987; sansys; biformatus; +4 Ответить
4. cool.vlad4 45 13.12.17 01:21 Сейчас в теме
(2) (3) я писал COM сервер на C# по прикручиванию https://habrahabr.ru/post/269307/ , работает быстрее некуда, работает на сервере, из минусов только, что нужно особым образом делать шаблоны и нет универсальности, поэтому и не выкладываю
5. 🅵🅾️🆇 13.12.17 09:30 Сейчас в теме
(4) Здорово, но все еще медленнее чем чтение из потока двоичных данных)
3. s_vidyakin 12.12.17 17:37 Сейчас в теме
Я сделал с полпинка на node.js - передаешь по GET или POST набор параметров "Ключ:Значение" и имя шаблона, в 1С приходит готовый docx, удобно когда на сервере нет офиса или COMОбъект не работал как у нас (наверно 64битность имеет значение)
6. Rustig 1173 13.12.17 22:37 Сейчас в теме
автор "собаку съел" на шаблонах Word и автоматизации взаимодействия 1с и Word
респект
7. wonderboy 168 18.01.18 10:04 Сейчас в теме
Если разрешите - несколько замечаний / дополнений:

1. Вы закладку ищете в цикле. Это лучше делать так:

Если WordFile.Bookmarks.exists(ИмяЗакладки) Тогда
	ТекЗакладка = WordFile.Bookmarks.Item(ИмяЗакладки);
...


2. По замене маркеров на нужный текст
У Вас предлагается поиск и замена, но не учитывается, что таким образом можно вставить текст только до 250 символов
Если текст больше - будет исключение. Приходится его разбивать на части и вставлять кусками - так было реализовано в 1С: Документообороте раньше.
Сейчас в БСП сделано концептуально правильно. См. общий модуль УправлениеПечатьюMSWordКлиент, процедура Заменить. Через Selection.TypeText(...).

И я бы рекомендовал использовать все же закладки. В Word-документе кроме основного контента и колонтитулов есть еще и другие Story (например, текст в надписях графических объектов). В каждой Story нужно отдельно поиск выполнять.

Есть универсальное решение
https://infostart.ru/public/662990/

Отлаженное, на его внедрениях тоже много Word'овских собак съедено :)
Serg O.; milkers; +2 Ответить
8. Serg O. 170 19.01.18 11:49 Сейчас в теме
Хорошая статья и бесплатная !
9. rpgshnik 1329 14.02.18 10:54 Сейчас в теме
Добрый день.
Смотрю вы работали плотно с WORD, может знаете как программно через 1С задать стиль всему документу по умолчанию 2003, вместо 2010?
10. milkers 2330 14.02.18 11:03 Сейчас в теме
(9) Нет, не приходилось сталкиваться. Может кто-нибудь из коллег подскажет.
11. wonderboy 168 15.02.18 09:01 Сейчас в теме
(9) Дмитрий, а как бы вы это вручную сделали?
12. rpgshnik 1329 15.02.18 09:32 Сейчас в теме
(11) в ручную просто. Скриншот прилагаю.
Прикрепленные файлы:
13. wonderboy 168 15.02.18 10:49 Сейчас в теме
(12) Если знаете как сделать вручную - тогда включаете запись макроса, выполняете действие, останавливаете запись. Потом этот макрос открываете, смотрите как на VB эти действия делаются. Обычно этот код можно из 1С выполнить (с небольшими адаптациями).

Вот для вашего случая что получилось:
ActiveDocument.ApplyQuickStyleSet ("Word 2003")
14. rpgshnik 1329 15.02.18 11:53 Сейчас в теме
(13) спасибо за идею!
Но решил отказаться от типового функционала по разбору ворда. Написать свой.
Я как понял баг заключался в том, что типовой функционал копирует участок текста и вставляет в свежий открытый документ. И естественно слитают стили. Но я ведь не могу всегда быть увереным что будет точно 2003... по этому буду как автор публикации ваят свой парсер ворда.
Хотя почти во всех конфигах даже старых типа КА1.1 есть модули по работе с шаблонами ворда. Эх.
22. coollerinc 40 06.02.19 13:25 Сейчас в теме
Зачем в типовом механизме пользовательских шаблонов делают через копирование шаблона? например при копировании не копируются оформление страницы. Сейчас придется изобретать велосипед
23. bercut0077 3 19.07.19 05:47 Сейчас в теме
Спасибо! Отличная статья. Вопрос автору - как можно вставить из файла HTML в Word информацию (с конвертацией)
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Программист 1С
Владивосток
зарплата от 60 000 руб. до 90 000 руб.
Полный день

Автор новостных обзоров на тему 1С и бухучета
Санкт-Петербург
По совместительству

Программист 1С
Москва
зарплата от 120 000 руб.
Полный день

Руководитель проекта, аналитик, консультант
Санкт-Петербург
По совместительству

Программист 1С
Самара
зарплата от 100 000 руб. до 150 000 руб.
Полный день