Этюды по программированию. Взаимодействие с 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. В файле должна быть таблица с шапкой, пустой строкой и (опционально) подвалом, например следующего вида:

-
- Поиск нужной таблицы в документе. Так как в документе обычно много таблиц, нужную таблицу нужно найти и заполнить
Для Каждого Таб из док.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. Вставляем невидимую таблицу по месту закладки:
-
Очень часто нужно вставить невидимую таблицу в ячейку другой таблицы, например для вывода номенклатуры и количества:
Если Док.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; КонецЦикла; КонецЕсли; -
Работа с таблицами 3. Объединяем одинаковые значения в столбцах:
-
Пример для вывода такой таблицы:
-
Стоимость:
Материал, плотность
Печать
Лак
Тираж, в тыс. шт.
Количество печатных листов
Стоимость одной тыс. шт., с НДС в руб.
Нева 3201
СМУК
ВД глянц. выб.
200
1
4407,97
Нева 320
ВД глянц. выб. 1
СМУК2
ВД глянц. выб.
-
//... ОбъединениеСтрокВКолонке(Таб, ТЗ,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][ИмяКолонки]; КонецЕсли КонецЦикла; КонецПроцедуры - Вставляем фрагмент из другого документа WORD:
- Обеспечиваем в нужном месте шаблона закладку.Процедура для вставки фрагмента:
-
Процедура ВставитьПодшаблонИзСправочникаФайл(ИмяЗакладки,Word) Selection = Word.Selection; Для Каждого Закладка из Word.ActiveDocument.Bookmarks Цикл Если Найти(Закладка.Name,ИмяЗакладки) Тогда Файл = НайтиФайлПодшаблонаНаСервере(); Если ЗначениеЗаполнено(Файл) Тогда ДанныеФайлаИДвоичныеДанные = РаботаСФайламиСлужебныйВызовСервера.ДанныеФайлаИДвоичныеДанные(Файл); ДанныеФайла = ДанныеФайлаИДвоичныеДанные.ДанныеФайла; ДвоичныеДанные = ДанныеФайлаИДвоичныеДанные.ДвоичныеДанные; Попытка ИмяВременногоФайлаШаблона = КаталогВременныхФайлов()+"Шкафы КРУ сборка1.doc"; ДвоичныеДанные.Записать(ИмяВременногоФайлаШаблона); Исключение Попытка ИмяВременногоФайлаШаблона = КаталогВременныхФайлов()+"Шкафы КРУ сборка2.doc"; ДвоичныеДанные.Записать(ИмяВременногоФайлаШаблона); Исключение КонецПопытки; КонецПопытки; Ворд2 = Новый COMОбъект("Word.Application"); Попытка док2 = Ворд2.Documents.Open(ИмяВременногоФайлаШаблона); НомерСтрокиТаб=3; &nb
-
Вступайте в нашу телеграмм-группу Инфостарт