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

13.08.20

Интеграция - Внешние источники данных

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

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

 

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

 

Получение шаблона.

В конфигурациях на основе БСП удобно хранить шаблон в справочнике ”Файлы”. Подсистема работы с присоединенными файлами позволяет назначить различные права на папки из этого справочника.

Файл можно найти по имени, или прикрепить  как дополнительный реквизит к справочникам и документам. (При создании дополнительного реквизита указать тип “Файл”).

Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ДополнительныеСведения.Значение КАК Значение
	|ИЗ
	|	РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
	|ГДЕ
	|	ДополнительныеСведения.Свойство.Наименование = &Наименование
	|	И ДополнительныеСведения.Объект = &Ссылка";
	
	Запрос.УстановитьПараметр("Ссылка", ДанныеПечати.Партнер);// Укажите ваш объект с прикрепленным дополнительным реквизитом шаблона.

	Запрос.УстановитьПараметр("Наименование", "Шаблон спецификации (Сделки с клиентами)"); //Укажите ваше название реквизита
	
	РезультатЗапроса = Запрос.Выполнить();
	
	ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
	
	Если  ВыборкаДетальныеЗаписи.Следующий() Тогда
		Файл= ВыборкаДетальныеЗаписи.Значение;
		ДанныеФайлаИДвоичныеДанные = РаботаСФайламиСлужебныйВызовСервера.ДанныеФайлаИДвоичныеДанные(Файл);
		
		ДанныеФайла = ДанныеФайлаИДвоичныеДанные.ДанныеФайла;
		ДвоичныеДанные = ДанныеФайлаИДвоичныеДанные.ДвоичныеДанные;
		ИмяВременногоФайла = КаталогВременныхФайлов()+"макет.mxl";
		ДвоичныеДанные.Записать(ИмяВременногоФайла);
		Макет =Новый ТабличныйДокумент;
		Макет.Прочитать(ИмяВременногоФайла); 
		КонецЕсли;
	КонецЕсли;


Открытие объекта  документа из временного файла.

       Word = Новый COMОбъект("Word.Application");
                Попытка
                               док = Word.Documents.Open(ИмяВременногоФайла);
                               Док.SaveAs(ИмяВременногоФайла);
                Исключение
                               СообщениеОбОшибке = НСтр("Файл шаблона, указанный в константе, не найден: "+ИмяВременногоФайла+"
                                                              |Подробности:'")
                                                   + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
                               Word.Quit();
                               ВызватьИсключение СообщениеОбОшибке;
                КонецПопытки;
                РабочийКаталогПользователя = РаботаСФайламиСлужебныйКлиент.РабочийКаталогПользователя();
               
               
                Word.Visible = 1;
                Word.Options.CheckSpellingAsYouType = 0;
                Word.Options.CheckGrammarAsYouType =  0;
                Word.Options.CheckGrammarWithSpelling =  0;
                Selection = Word.Selection;

         Работа с таблицами по  макету таблицы:

          1. Макет таблицы. Создаем файл с шаблоном WORD. В файле должна быть таблица с шапкой, пустой строкой и (опционально) подвалом, например следующего вида:

    1. Поиск нужной таблицы в документе. Так как в документе обычно много таблиц, нужную таблицу нужно найти и заполнить
    Для Каждого Таб из док.Tables цикл
    Если СтрНайти(Таб.Cell(1, 1).Range.Text,"№")>0 И СтрНайти(Таб.Cell(1, 2).Range.Text,"Наименование")>0 Тогда
    //… Заполнение таблицы
           ТЗ= ПолучитьТЧТовары(Объект.СсылкаНаОбъект);
                           Таб.Rows(Таб.Rows.Count).Select();  //Выделям строку, на место которой будем вставлять новые строки
                           //Таб.Rows(1).Select(); 
                           Строка=Таб.Rows.Count;
                           Итерация=1;
                           Для Каждого стр Из ТЗ Цикл
                                           Если Итерация>1 Тогда
                                                          Selection.InsertRowsBelow( 1); //
                                           КонецЕсли;
                                           Таб.Cell(Строка, 1).Range.Text = стр.НомерСтроки;
                                           Таб.Cell(Строка, 2).Range.Text = стр.НоменклатураНаименование+" "+ТекстовоеОписаниеБезКомплектации(стр.ТекстовоеОписание);
                                           Таб.Cell(Строка, 2).Range.Paragraphs.Alignment = 0;
                                           текКол = ?(стр.Количество = 0,1,стр.Количество );
                                           Таб.Cell(Строка, 3).Range.Text =?((стр.ЦенаВключаетНДС), Формат((стр.Сумма - стр.СуммаНДС), "ЧДЦ=2"),Формат(стр.Сумма, "ЧДЦ=2"));
                                           Таб.Cell(Строка, 3).Range.Paragraphs.Alignment = 1;   
                                           Таб.Cell(Строка, 4).Range.Text =Формат(стр.СуммаНДС, "ЧДЦ=2");
                                           Таб.Cell(Строка, 4).Range.Paragraphs.Alignment = 1;   
                                           Таб.Cell(Строка, 5).Range.Text = ?((стр.ЦенаВключаетНДС), Формат((стр.Сумма ), "ЧДЦ=2"),Формат((стр.Сумма+ стр.СуммаНДС), "ЧДЦ=2"));
                                           Таб.Cell(Строка, 5).Range.Paragraphs.Alignment = 1;   
                                           Строка = Строка + 1;
                                          Итерация=Итерация+1;
                           КонецЦикла;
           КонецЦикла;
    

       Работа с таблицами 2. Вставляем невидимую таблицу по месту закладки:

  1.  

    Очень часто нужно вставить невидимую таблицу в ячейку другой таблицы, например для вывода номенклатуры и количества: 

              
    	Если Док.Bookmarks.Exists("ТаблицаПродукции") Тогда
    		Поз = Док.GoTo(-1,,, "ТаблицаПродукции");
    		Колонок = 2;
    		Таб = Док.Tables.Add(Поз, 1, Колонок);
    		//Таб.Cell(1, 1).Range.Text = "Наименование";
    		//Таб.Cell(1, 2).Range.Text = "Кол-во";
    		//Таб.Cell(1, 3).Range.Text = "Ед.";
    		Таб.Range.Paragraphs.Alignment = 1;
    		Таб.Columns(1).Width=270;
    		Таб.Columns(2).Width=80;
    		Строка = 1;
    		Для Каждого стр Из ДанныеПоБП.НоменклатураБрак Цикл
    			Таб.Rows.Add();
    			Таб.Cell(Строка, 1).Range.Text = стр.Наименование;
    			Таб.Cell(Строка, 2).Range.Text =""+ стр.КоличествоБрака+"";
    			Таб.Cell(Строка, 2).Range.Paragraphs.Alignment = 0;
    			Строка = Строка + 1;
    		КонецЦикла;
    	КонецЕсли;

     

  2.  Работа с таблицами 3. Объединяем одинаковые значения в столбцах:

  3.  

    Пример для вывода такой таблицы: 

  4.  

     Стоимость:

     

    Материал, плотность

    Печать

    Лак

    Тираж, в тыс. шт.

    Количество печатных листов

    Стоимость одной тыс. шт., с НДС в руб.

    Нева 3201

    СМУК

    ВД глянц. выб.

    200

    1

    4407,97

    Нева 320

    ВД глянц. выб. 1

     

     

     

     

     

     

    СМУК2

    ВД глянц. выб.

     

     

     

  5. //...
    				ОбъединениеСтрокВКолонке(Таб, ТЗ,3,"Лак");
    				ОбъединениеСтрокВКолонке(Таб, ТЗ,2,"Печать");
    				ОбъединениеСтрокВКолонке(Таб, ТЗ,1,"МатериалПлотность");
    //...
    &НаКлиенте
    Процедура ОбъединениеСтрокВКолонке(Знач Таб, Знач ТЗ,НомерКолонки,ИмяКолонки)
    	
    	Перем Y, НачалоВертикальногоБлока, п1, СодержимоеЯчейки, СодержимоеЯчейкиПредыдущей, Х;
    	
    		СодержимоеЯчейкиПредыдущей="";
    		КоличествоСтрок=ТЗ.Количество();
    		НачалоВертикальногоБлока=КоличествоСтрок;
    		НачалоВертикальногоБлокаПредыдущее=КоличествоСтрок;
    
    		КоличествоИзменений=0;
    		Для Y =1 по КоличествоСтрок Цикл
    			YR= КоличествоСтрок-Y+1;
    			СодержимоеЯчейки=ТЗ[YR-1][ИмяКолонки];
    			ИзменениеСодержимого=Ложь;
    			Если СодержимоеЯчейки<> СодержимоеЯчейкиПредыдущей Тогда
    				КоличествоИзменений=КоличествоИзменений+1;
    				ИзменениеСодержимого=Истина;
    				СодержимоеЯчейкиПредыдущей=СодержимоеЯчейки;
    				НачалоВертикальногоБлокаПредыдущее=НачалоВертикальногоБлока;
    				НачалоВертикальногоБлока=YR;
    			КонецЕсли;
    			
    			Если ИзменениеСодержимого И НачалоВертикальногоБлокаПредыдущее-НачалоВертикальногоБлока>1  Тогда
    				п1=Таб.cell(НачалоВертикальногоБлокаПредыдущее+2, НомерКолонки);
    				Попытка // эта конструкция выдает исключительную ситуацию, но при этом
    					// результат все-равно работает))
    					// объединяем ячейки в конце таблицы
    					Таб.cell(НачалоВертикальногоБлока+3, НомерКолонки).Merge(п1);
    				Исключение
    				КонецПопытки;
    				Таб.cell(НачалоВертикальногоБлока+3, НомерКолонки).Range.Text=ТЗ[YR][ИмяКолонки];
    			ИначеЕсли YR=1 И  НачалоВертикальногоБлока-YR>=1 Тогда
    				п1=Таб.cell(YR+2, НомерКолонки);
    				Попытка // эта конструкция выдает исключительную ситуацию, но при этом
    					// результат все-равно работает))
    					// объединяем ячейки в конце таблицы
    					Таб.cell(НачалоВертикальногоБлока+2, НомерКолонки).Merge(п1);
    				Исключение
    				КонецПопытки;
    				п1.Range.Text=ТЗ[YR][ИмяКолонки];
    			КонецЕсли
    	   КонецЦикла;
    
    КонецПроцедуры
    

     

  6. Вставляем фрагмент из другого документа WORD:
  7. Обеспечиваем в нужном месте шаблона закладку.Процедура для вставки фрагмента:
    1. Процедура ВставитьПодшаблонИзСправочникаФайл(ИмяЗакладки,Word)
             Selection = Word.Selection;
             Для Каждого Закладка из Word.ActiveDocument.Bookmarks Цикл
                             Если Найти(Закладка.Name,ИмяЗакладки) Тогда
                                             Файл = НайтиФайлПодшаблонаНаСервере();
                                             Если ЗначениеЗаполнено(Файл) Тогда
                                                            ДанныеФайлаИДвоичныеДанные = РаботаСФайламиСлужебныйВызовСервера.ДанныеФайлаИДвоичныеДанные(Файл);
                                                            ДанныеФайла = ДанныеФайлаИДвоичныеДанные.ДанныеФайла;
                                                            ДвоичныеДанные = ДанныеФайлаИДвоичныеДанные.ДвоичныеДанные;
                                                            Попытка
                                                                            ИмяВременногоФайлаШаблона = КаталогВременныхФайлов()+"Шкафы КРУ сборка1.doc";
                                                                            ДвоичныеДанные.Записать(ИмяВременногоФайлаШаблона);
                                                            Исключение
                                                                            Попытка
                                                                                            ИмяВременногоФайлаШаблона = КаталогВременныхФайлов()+"Шкафы КРУ сборка2.doc";
                                                                                            ДвоичныеДанные.Записать(ИмяВременногоФайлаШаблона);
                                                                            Исключение
                                                                            КонецПопытки;
                                                            КонецПопытки;
                                                           
                                                           
                                                            Ворд2 = Новый COMОбъект("Word.Application");
                                                            Попытка
                                                                            док2 = Ворд2.Documents.Open(ИмяВременногоФайлаШаблона);
                                                                            НомерСтрокиТаб=3;
                                                                            Для Каждого Таб из док2.Tables цикл
                                                                            //заполняем таблицу        
                                                                            КонецЦикла;
                                                                           
                                                                            Ворд2.ActiveDocument.Select();
                                                                            Ворд2.Selection.Copy();
                                                                            Закладка.Range.Select();
                                                                            Selection.paste();
                                                                            Ворд2.ActiveDocument.Close(0);
                                                                            Ворд2.Quit();
                                                            Исключение
                                                                            ПредупреждениеСерв("Файл  не найден: "+ИмяВременногоФайлаШаблона);
                                                                            Ворд2.Quit();
                                                            КонецПопытки;
                                                            Попытка
                                                                            УдалитьФайлы(ИмяВременногоФайлаШаблона); 
                                                            Исключение
                                                                            ПредупреждениеСерв(ОписаниеОшибки());
                                                            КонецПопытки;
                                             КонецЕсли;
                             КонецЕсли;
             КонецЦикла;
      КонецПроцедуры
      Замена текста шаблона на нужный нам текст WORD:
      1. Предназначенный для замены текст шаблона ограничиваем квадратными скобками. Вместо текста пишем название маркера, по которому мы будем находить этот фрагмент.
      2.  В 1С создаем таблицу маркеров, которая будет содержать два обязательных поля “ Маркер” и “Значение”

Вызываем следующий код:

         Для Каждого стр Из Маркеры Цикл
                              Если ТипЗнч(стр.Значение) = Тип("Дата") Тогда
                                              Значение = СокрЛП(Формат(стр.Значение, "ДФ=""dd.MM.yyyy 'г.'"""));
                              Иначе
                                              Значение = СокрЛП(стр.Значение);
                              КонецЕсли;
                               док.content.find.execute("["+стр.Маркер+"]",,,,,,,,, Строка(Значение), 2);
                               док.Sections(1).Headers(1).Range.Find.Execute("["+стр.Маркер+"]",,,,,,,,, Строка(Значение), 2);
         КонецЦикла;
Вставка рисунка из макета:
  1. Создаем в конфигураторе макет-двоичные данные, в него загружаем нужный рисунок.
  2. Вызываем функцию, текст которой приведен ниже. В качестве аргумента selection удобно передавать выделение ячейки таблицы, это позволяет красиво расположить рисунок в тексте. Сама таблица может быть и невидимой. Например, следующий вызов:
 

///...

ВставитьМакет( Док,Таб.Cell(Строка, 3).Range, ИмяМакета);  

///...

&НаКлиенте

Функция ВставитьМакет( Знач Док,Знач Selection,Знач ИмяМакета)

               Перем Picture, Shape;

               Попытка

                               ИмяВременногоФайла= СохранитьМакетВоВременныйФайл(ИмяМакета);                            

                               Picture = Selection.InlineShapes.AddPicture(ИмяВременногоФайла,, Истина);

                               //Picture.LockAspectRatio = -1;      //сохрняем пропорции

                           Picture.Height= 150;

                               Picture.Width  = 150;              //устанавливаем ширину

                         // Чтобы установить обтекание текста, конвертируем рисунок в фигуру

                                  Shape = Picture.ConvertToShape();

                            Shape.WrapFormat.Type = 5;// перед текстом...

               Исключение

                               Сообщить("Не удалось подгрузить временный файл:"+ИмяВременногоФайла);

               КонецПопытки;

               Попытка

               УдалитьФайлы(ИмяВременногоФайла);

               Исключение

                               Сообщить("Не удалось удалить временный файл:"+ИмяВременногоФайла+"

                               |"+ОписаниеОшибки());

               КонецПопытки;

               // Зададим размер

               Возврат Selection;

КонецФункции

P.S.: Надеюсь, вам понравится эта и другие мои статьи и разработки на //infostart.ru/profile/48714/.

См. также

Перенос данных из Парус 8 в ЗГУ 3

Зарплата Внешние источники данных Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 8 учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

84000 руб.

19.08.2020    22447    19    1    

22

Перенос данных из Парус 10 в ЗГУ ред.3

Внешние источники данных Кадровый учет Файловый обмен (TXT, XML, DBF), FTP Обмен между базами 1C Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 10 учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

60000 руб.

05.10.2022    9208    9    8    

10

Перенос данных из Парус 7.хх в ЗГУ ред.3

Внешние источники данных Зарплата Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате, фактических удержаниях, НДФЛ, вычетах, страховых взносах из базы Парус 7.хх учреждений в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ) и начать с ней работать с любого месяца года.

24000 руб.

24.04.2017    48700    97    163    

86

Перенос начальных остатков из Парус 7.71 в БГУ

Внешние источники данных Взаиморасчеты Учет ОС и НМА Логистика, склад и ТМЦ Бюджетный учет Платформа 1С v8.3 Бухгалтерский учет 1С:Бухгалтерия 2.0 1С:Бухгалтерия государственного учреждения Государственные, бюджетные структуры Россия Бюджетный учет Платные (руб)

Перенос словарей и начальных остатков из ПП Парус-Бухгалтерия Бюджет 7.71 в 1Сv8 БГУ2. Заполнение словарей и документов по вводу начальных остатков. Не требуется установка ПП Парус7. Возможна дозагрузка. Позволит автоматически и наиболее полно ввести данные в программу для начала работы. 

15600 руб.

08.12.2011    81563    128    123    

147

Перенос данных из Парус 10 (Торнадо) в ЗГУ ред.3 через Excel

Внешние источники данных Загрузка и выгрузка в Excel Зарплата Бюджетный учет Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Обработка позволяет перенести кадровую информацию и данные по заработной плате из Парус 10(Торнадо) учреждений через файлы Excel в конфигурацию 1С:Зарплата и кадры государственного учреждения ред. 3 (ЗГУ). В принципе, обработка может быть использована для загрузки из файлов Excel, полученных из любых информационных систем.

24000 руб.

16.11.2018    30001    20    31    

21

Загрузка спецификаций в УНФ из системы Базис-мебельщик

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

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

7200 руб.

24.06.2021    19127    52    50    

29
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. vladismi 168 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 375 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 375 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 25 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. 🅵🅾️🆇 522 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 2 13.12.17 01:21 Сейчас в теме
(2) (3) я писал COM сервер на C# по прикручиванию https://habrahabr.ru/post/269307/ , работает быстрее некуда, работает на сервере, из минусов только, что нужно особым образом делать шаблоны и нет универсальности, поэтому и не выкладываю
5. 🅵🅾️🆇 522 13.12.17 09:30 Сейчас в теме
(4) Здорово, но все еще медленнее чем чтение из потока двоичных данных)
3. s_vidyakin 63 12.12.17 17:37 Сейчас в теме
Я сделал с полпинка на node.js - передаешь по GET или POST набор параметров "Ключ:Значение" и имя шаблона, в 1С приходит готовый docx, удобно когда на сервере нет офиса или COMОбъект не работал как у нас (наверно 64битность имеет значение)
6. RustIG 1351 13.12.17 22:37 Сейчас в теме
автор "собаку съел" на шаблонах Word и автоматизации взаимодействия 1с и Word
респект
7. wonderboy 375 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. 224 19.01.18 11:49 Сейчас в теме
Хорошая статья и бесплатная !
9. rpgshnik 3631 14.02.18 10:54 Сейчас в теме
Добрый день.
Смотрю вы работали плотно с WORD, может знаете как программно через 1С задать стиль всему документу по умолчанию 2003, вместо 2010?
10. milkers 2859 14.02.18 11:03 Сейчас в теме
(9) Нет, не приходилось сталкиваться. Может кто-нибудь из коллег подскажет.
11. wonderboy 375 15.02.18 09:01 Сейчас в теме
(9) Дмитрий, а как бы вы это вручную сделали?
12. rpgshnik 3631 15.02.18 09:32 Сейчас в теме
(11) в ручную просто. Скриншот прилагаю.
Прикрепленные файлы:
13. wonderboy 375 15.02.18 10:49 Сейчас в теме
(12) Если знаете как сделать вручную - тогда включаете запись макроса, выполняете действие, останавливаете запись. Потом этот макрос открываете, смотрите как на VB эти действия делаются. Обычно этот код можно из 1С выполнить (с небольшими адаптациями).

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