Вставка штрихкода на каждую страницу MS WORD для 1С: Документооборот

09.09.21

Задачи пользователя - Адаптация типовых решений

Пример реализации вставки штрихкода в MS WORD на каждую страницу 1С: Документооборот.

Добрый день.

Надеюсь, что данная мини-статья поможет кому-то сэкономить время, если будете решать похожую задачу. Похожих статей или готового решения не нашел.

Версия платформы: 8.3.19.1264

Версия 1С Документооборот: 2.1.28.14

1С Документооборот умеет вставлять штрихкод в MS WORD только на первую страницу. Поставили задачу, чтобы можно было вставлять штрихкод на каждую страницу. Предполагал изначально решать задачу через вставку в колонтитул MS WORD, но разбирая типовой код обнаружил, что работа с WORD идет через xml.

Если кратко, то логика в типовом решении следующая:

1. У файла меняется расширение на zip

2.  Распаковывается

3. Находится xml файл "document.xml"

4. В самое начало файла в узел "w:body" идет вставка своего куска xml из общего макета конфигурации

5. Запаковывается обратно и сохраняется

Основная сложность была в определении следующей страницы. Долго погуглив нашел следующее решение:

Есть тэг "w:lastRenderedPageBreak", который указывает на конец текущей страницы. Соответственно нам нужно делать доп вставку в следующий общий тэг

Типовой кусок кода, в котором происходит вставка:

Пока ЧтениеXML.Прочитать() Цикл
        Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
            ВставитьШтамп = Ложь; 
            Если ЧтениеXML.Имя = "w:body" Тогда
                ВставитьШтамп = Истина;
            КонецЕсли;
            ЗаписьXML.ЗаписатьНачалоЭлемента(ЧтениеXML.Имя);
            Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
                ЗаписьXML.ЗаписатьАтрибут(ЧтениеXML.Имя,ЧтениеXML.Значение); 
            КонецЦикла;
            Если ВставитьШтамп Тогда
                ЗаписьXML.ЗаписатьБезОбработки(ТекстДляВставкиШтампа);
                ВставитьШтамп = Ложь;
            КонецЕсли;
        ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
            ЗаписьXML.ЗаписатьТекст(ЧтениеXML.Значение);
        ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
            ЗаписьXML.ЗаписатьКонецЭлемента();
        КонецЕсли;
    КонецЦикла;

Изменения, которые внес:

//ГК++ изменения связанные со вставкой ШК на каждой странице
//конец текущей страницы определяется по тегу w:lastRenderedPageBreak

ВставитьШтампСледТег = Ложь;

    Пока ЧтениеXML.Прочитать() Цикл
        Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
            ВставитьШтамп = Ложь; 
            Если ЧтениеXML.Имя = "w:body" Тогда
                ВставитьШтамп = Истина;
            КонецЕсли;
            //ГК++
            Если ЧтениеXML.Имя = "w:lastRenderedPageBreak" Тогда
                 ВставитьШтампСледТег = Истина;
             КонецЕсли;
             //ГК--
            ЗаписьXML.ЗаписатьНачалоЭлемента(ЧтениеXML.Имя);
            Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
                ЗаписьXML.ЗаписатьАтрибут(ЧтениеXML.Имя,ЧтениеXML.Значение); 
            КонецЦикла;
            Если ВставитьШтамп Тогда
                ЗаписьXML.ЗаписатьБезОбработки(ТекстДляВставкиШтампа);
                ВставитьШтамп = Ложь;
            КонецЕсли;
        ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
            ЗаписьXML.ЗаписатьТекст(ЧтениеXML.Значение);
        ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда

            ЗаписьXML.ЗаписатьКонецЭлемента();
            //ГК++
            Если ЧтениеXML.Имя = "w:p" И ВставитьШтампСледТег Тогда
                 ЗаписьXML.ЗаписатьБезОбработки(ТекстДляВставкиШтампа);
                 ВставитьШтампСледТег = Ложь;
             КонецЕсли;
             //ГК--
        КонецЕсли;
    КонецЦикла;

Сейчас данный код ориентируется на вставку после тэга "w:p", это только текст. Если есть таблицы или в начале страницы таблица, нужно учитывать тэг <tr>.

Надеюсь, кому-то будет полезна данная мини-статья.

Вставка штрихкода на каждую страницу MS WORD

См. также

Адаптация типовых решений Платформа 1С v8.3 1С:Документооборот Россия Платные (руб)

Расширение конфигурации для «1С:Документооборот КОРП», редакция 3.0. позволяет: 1.использовать произвольные табличные части в качестве дополнительных реквизитов к документу; 2 использовать произвольные табличные части в шаблонах в формате docx для автоматического заполнения таблиц.

29400 руб.

29.06.2023    5684    14    5    

24

Логистика, склад и ТМЦ Адаптация типовых решений Пользователь Платформа 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 Россия Управленческий учет Платные (руб)

Чтобы не допустить путаницы с обещаниями клиентам и для четкого контроля исполнения заказов мы используем резервирование товаров. Мы доработали УНФ, чтобы она автоматически отменяла старые резервы и не мешала эффективно продавать.

7200 руб.

02.08.2023    3933    12    0    

29

Адаптация типовых решений Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Абонемент ($m)

Каждый из нас сталкивается с ситуацией, когда какой-нибудь менеджер показывает свой Excel и рассказывает, как он что-то из 1С копирует в него, снабжает пояснениями, выделяет цветом и т.д. и т.п. Заканчивается все просьбой сделать вот чтобы также было в 1С. И оказывается такой человек (почти с гарантией) либо лучшим продажником, либо каким-то важным, за все отвечающим, - на ком все держится.

2 стартмани

22.04.2024    5117    dimanich70    15    

21

БСП (Библиотека стандартных подсистем) Адаптация типовых решений Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Понадобилось в подменю "Создать на основании" добавить свою команду, которая открывает обработку. В процессе доработок появилась проблема двух подменю "Создать на основании". В статье о том, как решились проблемы.

01.03.2024    5601    dimanich70    9    

18
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. bilex 09.09.21 12:01 Сейчас в теме
А почему колонтитул не подошел?
2. markela 36 09.09.21 13:00 Сейчас в теме
(1) Колонтитул - это через COM объект, типовая реализация была через xml. не хотелось полностью переписывать этот блок. Плюс автоматизация чего-то через COM c MS WORD часто приводит к непонятным ошибкам и зависаниям.
или можно было бы делать колонтитул через xml, тогда пришлось бы создавать отдельный xml файл (footer, header), связывать его со структурой файла "[Content_Types]", что немного усложняло задачу, но в целом это все реализуемо. Мне хватило решения, которое описал выше
3. markela 36 09.09.21 13:08 Сейчас в теме
Уточнение, данный механизм(через xml) в типовом решении работает с форматом .docx, с обычным doc через COM
4. drov91 12.05.22 19:34 Сейчас в теме
Для того, чтобы вставить штрихкод на каждой странице документа с форматом .doc, можно доработать типовую функцию общего модуля ШтрихкодированиеКлиентСервер.ВставитьКартинкуВФайлDocСУказаниемПоложения

функция получилась такой

СисИнфо = Новый СистемнаяИнформация;
	Если СисИнфо.ТипПлатформы = ТипПлатформы.Windows_x86 ИЛИ СисИнфо.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда
		Попытка
			WordApp = Новый COMОбъект("Word.Application");
		Исключение
			ВызватьИсключение(НСтр("ru = 'Ошибка работы с приложением MS Word. Необходимо проверить правильность установки приложения.'"));
		КонецПопытки;
	Иначе
		ВызватьИсключение(НСтр("ru = 'Вставка штрихкода в файл MS Word возможна только в Windows. Обратитесь к администратору.'"));	
	КонецЕсли;
	
	ИмяВременногоФайлаOffice = ПолучитьИмяВременногоФайла(Расширение);
	НовыйПутьКФайлу = ПолучитьИмяВременногоФайла(Расширение);
	ДвоичныеДанныеФайла.Записать(ИмяВременногоФайлаOffice);
	
	ИмяВременногоФайлаКартинки = ПолучитьИмяВременногоФайла("JPG");
	ДвоичныеДанныеКартинки.Записать(ИмяВременногоФайлаКартинки);
	
	Док = WordApp.Documents.Add(ИмяВременногоФайлаOffice);
	
	//Истрелов А.А. штрихкод на каждой странице ++
	ШтрихкодНаКаждойСтранице = kit_УсловияВыполненияВызовСервера.НастройкаШтрихкодаПоПараметруСеанса();
	
	Если ШтрихкодНаКаждойСтранице Тогда
		КоличествоСтраниц = Док.ComputeStatistics(2);	
	Иначе
		КоличествоСтраниц = 1;
	КонецЕсли;
	
	Для НомерСтраницы = 1 По КоличествоСтраниц Цикл
	//Истрелов А.А. штрихкод на каждой странице --
		
		oGraphicObject = Док.Shapes.AddTextBox(1, 100, 100, 100, 50);
		
		//устанавливаем привязку положения к печатной области
		oGraphicObject.RelativeHorizontalPosition = 0;
		oGraphicObject.RelativeVerticalPosition = 0;  
		
		ПоложениеНаСтранице = ДанныеОПоложении.ПоложениеНаСтранице;
		Если ПоложениеНаСтранице = ПредопределенноеЗначение("Перечисление.ВариантыРасположенияШтрихкода.ПравыйНижний") Тогда
			СмещениеПоГоризонтали = "MAX";
			СмещениеПоВертикали = "MAX";
		ИначеЕсли ПоложениеНаСтранице = ПредопределенноеЗначение("Перечисление.ВариантыРасположенияШтрихкода.ПравыйВерхний") Тогда
			СмещениеПоГоризонтали = "MAX";
			СмещениеПоВертикали = "MIN";
		ИначеЕсли ПоложениеНаСтранице = ПредопределенноеЗначение("Перечисление.ВариантыРасположенияШтрихкода.ЛевыйВерхний") Тогда
			СмещениеПоГоризонтали = "MIN";
			СмещениеПоВертикали = "MIN";
		ИначеЕсли ПоложениеНаСтранице = ПредопределенноеЗначение("Перечисление.ВариантыРасположенияШтрихкода.ЛевыйНижний") Тогда
			СмещениеПоГоризонтали = "MIN";
			СмещениеПоВертикали = "MAX";
		КонецЕсли;
		
		Если СмещениеПоГоризонтали = "MAX" Тогда
			//выравнивание к правому краю
			oGraphicObject.Left = -999996;
		ИначеЕсли СмещениеПоГоризонтали = "MIN" Тогда
			//выравнивание к левому краю
			oGraphicObject.left = -999998;
		Иначе
			//если задано произвольное расположение, то переведем смещение по горизонтали из миллиметров в point'ы
			//1 point = 1/72"
			oGraphicObject.RelativeHorizontalPosition = 1;
			Если НЕ ЗначениеЗаполнено(ДанныеОПоложении.СмещениеПоГоризонтали) Тогда
				ДанныеОПоложении.СмещениеПоГоризонтали = 0;
			КонецЕсли;
			oGraphicObject.left = (ДанныеОПоложении.СмещениеПоГоризонтали / 25.4) * 72;
		КонецЕсли;
		
		Если СмещениеПоВертикали = "MAX" Тогда
			//выравнивание по нижнему краю
			oGraphicObject.Top = -999997;
		ИначеЕсли СмещениеПоВертикали = "MIN" Тогда
			//выравнивание по верхнему краю
			oGraphicObject.Top = -999999;
		Иначе
			//если задано произвольное расположение, то переведем смещение по горизонтали из миллиметров в point'ы
			oGraphicObject.RelativeVerticalPosition = 1;
			Если НЕ ЗначениеЗаполнено(ДанныеОПоложении.СмещениеПоВертикали) Тогда
				ДанныеОПоложении.СмещениеПоВертикали = 0;
			КонецЕсли;
			oGraphicObject.Top =(ДанныеОПоложении.СмещениеПоВертикали / 25.4) * 72;
		КонецЕсли;
				
		oGraphicObject.Select();
		
		
		WordApp.Selection.ShapeRange.Line.Visible = Ложь;
		WordApp.Selection.InlineShapes.AddPicture(ИмяВременногоФайлаКартинки);
		WordApp.Selection.ShapeRange.TextFrame.AutoSize = Истина;
		WordApp.Selection.ShapeRange.Fill.Visible = Ложь;
		WordApp.Selection.Font.Bold = Истина;
		
		Если ДанныеОПоложении.СмещениеПоГоризонтали = "MAX" ИЛИ ДанныеОПоложении.СмещениеПоГоризонтали = "MIN" Тогда 
			oGraphicObject.ConvertToFrame();		
		КонецЕсли;
		
		//Истрелов А.А. штрихкод на каждой странице ++
		WordApp.Selection.GoTo(1,,,).Select();
		
	КонецЦикла;
	//Истрелов А.А. штрихкод на каждой странице --
			
	Если Найти(WordApp.Build, "12.") > 0 Тогда
		Если Расширение = "docx" Тогда
			Док.SaveAs(НовыйПутьКФайлу, 12);                        
		Иначе
			Док.SaveAs(НовыйПутьКФайлу, 0);
		КонецЕсли;
	Иначе
	    Если Расширение = "docx" Тогда
			Док.SaveAs(НовыйПутьКФайлу, 109);                        
		Иначе
			Док.SaveAs(НовыйПутьКФайлу);
		КонецЕсли;
	КонецЕсли;
	Док.Saved = Истина;	
	Док.Close(); 
	WordApp.Quit();
	WordApp = Неопределено;
	
	УдалитьФайлы(ИмяВременногоФайлаOffice);
	
	Возврат НовыйПутьКФайлу;
Показать


перед строкой
oGraphicObject = Док.Shapes.AddTextBox(1, 100, 100, 100, 50);

проверяю, нужно ли вставлять штрихкод на каждую страницу
далее запускаю цикл по каждой странице документа. Количество страниц определяю при помощи метода
Док.ComputeStatistics(2)

вот как это выглядит

ШтрихкодНаКаждойСтранице = kit_УсловияВыполненияВызовСервера.НастройкаШтрихкодаПоПараметруСеанса();
	
	Если ШтрихкодНаКаждойСтранице Тогда
		КоличествоСтраниц = Док.ComputeStatistics(2);	
	Иначе
		КоличествоСтраниц = 1;
	КонецЕсли;
	
	Для НомерСтраницы = 1 По КоличествоСтраниц Цикл
Показать


цикл заканчивается перед строкой

Если Найти(WordApp.Build, "12.") > 0 Тогда

в конце цикла нужно подставить команду перехода на следующую страницу

WordApp.Selection.GoTo(1,,,).Select();
user591389_aska_rabota; markela; ApTeM_26_; +3 Ответить
5. siranush 17 20.02.24 18:18 Сейчас в теме
@markela можете прокомментировать вот это место
"Если есть таблицы или в начале страницы таблица, нужно учитывать тэг <tr>"

относительно кода вставки
//ГК++
Если ЧтениеXML.Имя = "w:p" И ВставитьШтампСледТег Тогда
   ЗаписьXML.ЗаписатьБезОбработки(ТекстДляВставкиШтампа);
   ВставитьШтампСледТег = Ложь;
КонецЕсли;
//ГК--


У меня есть документы просто с текстом и с текстом и таблицами.
С текстом выводится нормально, а вот с таблицами дублируется.
Оставьте свое сообщение