0. nbeliaev 28.03.17 22:16 Сейчас в теме

Заполнение документа Word без ComОбъект

Идея написать публикацию пришла после прочтения очередного рассказа о том, как файл Word заполнялся через COM-объект в клиент-серверном варианте. При этом падал Сервер 1С.
Зачем в принципе использовать файлы Word как шаблоны? Ну, допустим, в организации используется некая внутренняя отчетность, выполнения в корпоративном стиле, и переделать ее на привычные табличные документы нет возможности.

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

Комментарии
Избранное Подписка Сортировка: Древо развёрнутое
Свернуть все
1. androgin 08.07.18 22:18 Сейчас в теме
код на англ., конечно красивый, но тут он гораздо более понятен на русском )
leonidt84; 🅵🅾️🆇; PLAstic; CyberCerber; Дмитрий74Чел; unichkin; +6 1 Ответить
2. Артано 669 09.07.18 02:21 Сейчас в теме
(1) Если используются англоязычные объект или библиотека, то зачем уподобляться изобретателям ЕстьNull и городить двуязычный код?
alest; Lok`Tar; A_Max; +3 2 Ответить
23. 1sig 154 24.12.19 00:44 Сейчас в теме
(1) здесь https://infostart.ru/public/1171429/ реализация разбора xml на основе данной публикации, только по-русски)
автору данной публикации однозначно + за изящное решение и грамотное описание.
3. nodel0 26 09.07.18 04:04 Сейчас в теме
разбор docx без применения COM хорошо реализован в документообороте, можно там подсмотреть реализацию.
Spartacus; PLAstic; user774630; nbeliaev; Bassgood; +5 Ответить
13. nbeliaev 09.07.18 17:24 Сейчас в теме
(3) (11) возможно. Может быть в рег. задании Извлечение текста что-то подобное используется. Не смотрел
4. rpgshnik 2185 09.07.18 06:37 Сейчас в теме
Нужно попробовать, а то был геморрой с сохранением стилей в шаблонах. Особенно проблем не было с подставлением в док, а в докх стиль сбрасывался(((
5. AlX0id 09.07.18 08:14 Сейчас в теме
Я для подставления параметров использовал, собственно, поля Word:
1. Добавил в шаблон пользовательское поле, в значение прописал что-то типа в8_НомерДоговора.
2. В файлике docProps\custom.xml просто заменил этот текст на значение параметра.

Этот файлик на порядок более структурирован, нежели document.xml, да и поменьше будет. С построителем DOM было бы красивее наверн, но лень же )
PLAstic; kare; +2 Ответить
6. AlX0id 09.07.18 08:15 Сейчас в теме
А вот с таблицами все значительно интереснее.. Приходится стараться не касаться их пятиметровой палкой..
7. Поручик 4406 09.07.18 08:16 Сейчас в теме
Похожий парсер работает в нашей конфигурации с 2013 года.
nbeliaev; +1 Ответить
8. qazaas 09.07.18 12:28 Сейчас в теме
For Each MapElement In FillData Do

XPathExpression = DomDocument.CreateXPathExpression("//w:t[contains(text(),'"+MapElement.Key+"')]", Resolver);
XPathResult = XPathExpression.Evaluate(DomDocument);

Node = XPathResult.IterateNext();
While Node <> Undefined Do

Node.TextContent = StrReplace(Node.TextContent, MapElement.Key, MapElement.Value);
Node = XPathResult.IterateNext();

EndDo;

EndDo;
Показать


Не понял, как вы получаете коллекцию "FillData"...
9. nbeliaev 09.07.18 13:33 Сейчас в теме
(8) Это псевдо коллекция. В обработке заполняется фейковыми данными
10. Сурикат 303 09.07.18 14:43 Сейчас в теме
а у вас не было проблем с XPath,когда в тегах документа были указаны пространства имен?
12. nbeliaev 09.07.18 17:22 Сейчас в теме
(10) была, но не в рамках этой задачи. В том файле была возможность это регулировать и я избавился от этого. По-другому так и не смог совладать. Было правда эта проблема года 1,5 назад. Может сейчас что-то и изменилось
11. morohon 09.07.18 16:43 Сейчас в теме
Насколько я помню в БСП 3.0 реализована работа с doc через XML
14. nytlenc 10.07.18 09:28 Сейчас в теме
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
	
// Делаем что нужно
	
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.DOCX);
15. user_gea 10.07.18 11:05 Сейчас в теме
Спасибо! Мне ваша публикация понравилась и в будующем пригодится
16. 🅵🅾️🆇 10.07.18 18:10 Сейчас в теме
В мемориз только потому, что не знал, что docx суть архив с xml.
Этож все в корне меняет.

Ух теперь заживем.
17. wbazil 129 11.07.18 08:48 Сейчас в теме
https://infostart.ru/public/237032/
что то похожее тоже без Com но на русском
18. nilabs 6 11.07.18 13:00 Сейчас в теме
малореально, если шаблон будут править юзеры.
MS WORD 2013
Прикрепленные файлы:
19. nilabs 6 11.07.18 13:03 Сейчас в теме
(18) что кстати в https://infostart.ru/public/237032/ в комментариях и пишут
20. Stim213 385 16.07.18 15:09 Сейчас в теме
Сохранил вордовский документ-шаблон в файл xml
ПутьКФайлу =  "C:\счета клиентов\шаблон.xml";


на сервере его читаю в текстовый док

ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.Прочитать(ПутьКФайлу,кодировкатекста.UTF8);
текст = ТекстДок.ПолучитьТекст();


подставляю значения параметров

текст = стрЗаменить(текст,"$POSTADRESS",ПочтовыйАдрес);


сохраняю файл doc
текстДок2 = Новый текстовыйДокумент;
текстДок2.УстановитьТекст(текст);
текстДок2.Записать(ИмяФайлаДоговора,кодировкатекста.UTF8);



и все это без всяких заморочек с ком-объектами и пр.
WWWolfy; bogdan_sukonnov; Skin123; Трактор; +4 Ответить
21. bogdan_sukonnov 57 12.10.18 19:11 Сейчас в теме
(20) Отличная идея! Но работает нормально только при открытии файла в ворде. Опен офис, к сожалению, такой файл открывает как xml - а значит, наружу такой файл не пошлешь... В этом смысле актуальнее все-таки разархивировать docx, и сделать то, что Вы и рекомендуете уже там и заархивировать его назад. Там, правда, строка с нашей переменной может оказаться разорвана другими тегами, если при вводе пользователь нажимал что-то кроме нужного (шифт, удалял и т.п.). Так что перед использованием такого шаблона в 1С его желательно обработать макросом, вычищающим из наших переменных все мусорные данные форматирования.
22. ISP 20.08.19 08:25 Сейчас в теме
Пытаюсь сделать печатную форму word через БСП. В ней реализован такой же механизм как и в статье. Т.е работа через XML и сборка уже самого файла из отдельных XML.

Проблема в том, что 1C не видит параметры, которые надо заполнить. В вордоском макет написал

{v8 Область.Заголовок}
Согласие на обработку персональных данных
{/v8 Область.Заголовок}

но система разбора не видет эти области (в файле document вообще нет текста V8).

Как правильно сделать вордоский макет, чтобы 1C увидела параметры для заполнения
24. tmn72.1C 110 25.02.20 11:50 Сейчас в теме
А как быть с выводом нескольких строчек (таблицы)?
25. Greek26rusa 2 10.03.20 10:07 Сейчас в теме
Добрый день. А возможно ли получить данные перед заполнением. У нас в ворде есть параметры для заполнения можно ли их как то за ранее получить? и дать им значение а не за ранее описывать их.
26. WWWolfy 98 12.04.20 19:09 Сейчас в теме
Вот вам процедура, которая убирает разрывы в разобранном 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();

КонецПроцедуры
Показать
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

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

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

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

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

Ведущий программист 1С (УТ 11)
Москва
зарплата до 200 000 руб.
Полный день