Несколько способов форматирования и обработки данных в Word документах с помощью IS-Builder.

41 21

На одном из проектов столкнулась с ситуацией, когда построение отчета, в котором заполняются таблицы, занимало слишком много времен. Проанализировав код расчета отчета, поняла, что очень много времени тратится на заполнение таблиц с помощью функции ListMergeTableWord, таким образом, я попыталась исключить использование данной функции в расчете. Решением данной ситуации было внесение данных в таблицы Excel, а затем вставка заполненных таблиц Excel в документ отчета и дальнейшем форматированием документа с помощью IS-Builder, таким образом, удалось сократить время построения отчета в несколько раз. Это скорее не единичный случай использования объектной модели MS Office для решения задач для генерации документов, а постоянно выполняемая задача.

Например, в рамках другого проекта была поставлена одна из задач: формировать версии документов без возможности их редактирования. Для решения данной задачи был выбран вариант преобразования документов в формате doc\xls в формат pdf, хотя, возможен и другой формат, в который возможно преобразование документа в MS Office. Существует 2 способа преобразования документа: 1) с помощью службы преобразования; 2) с помощью объектной модели MS Office (с 2007 версии). Мною был выбран 2 способ так, как исключается промежуточное звено (служба преобразования), соответственно уменьшается нагрузка на сервер, увеличивается скорость преобразования и нет необходимости настраивать службу. Ниже будет приведен способ преобразования документа формата doc в формат pdf (35-й пункт).

В данной статье хотелось описать наиболее востребованные способы форматирования документа в формате doc с помощью IS-Builder.

Word = CreateObject("Word.Application") 
Doc = Word.Documents.Open(Path)

где Path - путь к документу, с которым работаете.
  1. Установка единицы измерения размера таблицы
Doc.Tables(1).PreferredWidthType = 2

Единица измерения

Константа в Word

Значение в ISBL

Сантиметры

wdPreferredWidthPoints

3

Проценты

wdPreferredWidthPercent

2

  1. Установка ширины таблицы
Doc.Tables(1).PreferredWidth = 100 // ширина таблицы в процентах
Doc.Tables(1).PreferredWidth = Word.CentimetersToPoints(17.5) // ширина таблицы в сантиметрах
  1. Автоподбор размера ячейки таблицы
Doc.Tables(1).AutoFitBehavior(2)

Режим выравнивания

Константа в Word

Значение в ISBL

Фиксированная ширина

wdAutoFitFixed

0

По содержимому

wdAutoFitContent

1

По ширине окна

wdAutoFitWindow

2

  1. Установка высоты ячеек
Doc.Tables(1).Rows.HeightRule = HeightRule   // указывает на способ изменения высоты
Doc.Tables(1).Rows.Height = RowHeigh         // RowHeight указывает на новую высоту строки в пунктах.

Значение константы HeightRule

Способ изменения высоты

Константа в Word

Значение в ISBL

Размер, указанный в параметре RowHeigh, является точным

wdRowHeightAuto

2

Размер, указанный в параметре RowHeigh, является минимальным

wdRowHeightAtLeast

1

Автоматический подбор высоты строк (параметр RowHeigh игнорируется)

wdRowHeightExactly

0

  1. Установка интервала абзаца (перед и после) в таблице
Doc.Tables(1).Range.ParagraphFormat.SpaceBefore = 6  //интервал перед
Doc.Tables(1).Range.ParagraphFormat.SpaceAfter = 6   //интервал после

Единица измерения интервала пт.
  1. Установка интервалов перед и после абзаца
Doc.Paragraphs(1).Format.SpaceBefore = 12 // интервал перед
Doc.Paragraphs(1).Format.SpaceAfter = 12  // интервал после
  1. Межстрочный интервал
Doc.Paragraphs(1).Format.LineSpacingRule = 0.5 // одинарный интервал

1 – полуторный интервал и 1.5 – двойной интервал.
  1. Установка стиля таблицы
Doc.Tables(1).Style = ИмяСтиляТаблицы
  1. Установка отступа слева 
Doc.Tables(1).Rows.LeftIndent = 0
  1. Абзацный отступ (красная строка) абзаца
Doc.Paragraphs(1).Format.FirstLineIndent = Значение в пунктах

Для перевода сантиметров в пункты можно воспользоваться функцией CentimetersToPoints, тогда абзацный отступ в 1,5 см можно задать следующим образом:

Doc.Paragraphs(1).Format.FirstLineIndent = Word.CentimetersToPoints(1.5)
  1. Установка левой и правой границ текста абзаца:
Doc.Paragraphs(1).Format.LeftIndent = 10    // отступ слева
Doc.Paragraphs(1).Format.RightIndent = 10   // отступ справа
  1. Установка значений полей ячеек по умолчанию
Doc.Tables(1).TopPadding = 0     // верхнее
Doc.Tables(1).BottomPadding = 0  // нижнее
Doc.Tables(1).LeftPadding = 0    // левое      
Doc.Tables(1).RightPadding = 0   // правое
  1. Выравнивание текста в таблице по горизонтали
Doc.Tables(1).Range.ParagraphFormat.Alignment = 3  // по ширине

Режим выравнивания

Константа в Word

Значение в ISBL

По левому краю

wdAlignParagraphLeft

0

По центру

wdAlignParagraphCenter

1

По правому краю

wdAlignParagraphRight

2

По ширине

wdAlignParagraphJustify

3

  1. Выравнивание текстового абзаца:
Doc.Paragraphs(1).Format.Alignment = 0  // выравнивание по левому краю

Значения констант выравнивания такие же как в предыдущем пункте.

  1. Выравнивание текста в ячейке по вертикали
Doc.Tables(1).Rows(НомерСтроки).Cells(НомерСтолбца).VerticalAlignment = 1

Режим выравнивания

Константа в Word

Значение в ISBL

По верхнему краю

wdCellAlignVerticalTop

0

По центру

wdCellAlignVerticalCenter

1

По нижнему краю

wdCellAlignVerticalBottom

3

  1. Установка размера шрифта таблицы
Doc.Tables(1).Range.Font.Size = 7
  1. Установка цвета текста в ячейке
Doc.Tables(1).Cell(НомерСтроки; НомерСтолбца).Range.Font.Color = 255 
  1. Выделение всего текста таблицы (жирным, курсивом, подчеркиванием)
Doc.Tables(1).Range.Font.Bold = True          // жирным
Doc.Tables(1).Range.Font.Italic = True        // курсивом
Doc.Tables(1).Range.Font.Underline  = True    // подчеркивание
  1. Установка цвета подчеркивания
Doc.Tables(1).Cell(НомерСтроки; НомерСтолбца).Range.Font.UnderlineColor = 255
  1. Установка темы шрифта таблицы
Doc.Tables(1).Range.Font.Name = "Arial"
  1. Объединение ячеек
// объединение первой и второй ячеек первой строки
Cell = Doc.Tables(1).Cell(1; 1)
Cell.Merge(Doc.Tables(1).Cell(1; 2))
  1. Вставка Excel таблицы в Word
SelectionWord = Doc.Paragraphs(Paragraph).Range
SelectionWord.PasteExcelTable(True; False; False)

 Paragraph – номер параграфа, куда будет вставлена таблица из Excel.

  1. Разрыв связь
Doc.Fields.Unlink  
  1. Удаление абзаца
Doc.Paragraphs(Paragraph).Range.Delete

 Paragraph – номер параграфа, который нужно удалить.

  1. Удаляем строку в таблице
Doc.Tables(1).Rows(НомерСтроки).Select
Doc.Tables(1).Rows(НомерСтроки).Delete
  1. Установка границ таблицы
Table = Doc.Tables(1)
Table.Borders(WdBorderType).LineStyle = 4

Расположение линии

Значение в Word

Константа в ISBL

Линия, обрамляющая диапазон сверху

wdBorderTop

-1

Линия, обрамляющая диапазон слева

wdBorderLeft

-2

Линия, обрамляющая диапазон снизу

wdBorderBottom

-3

Линия, обрамляющая диапазон справа

wdBorderRight

-4

Все горизонтальные линии внутри диапазона

wdBorderHorizontal

-5

Все вертикальные линии внутри диапазона

wdBorderVertical

-6

Линия по диагонали сверху – вниз

wdBorderDiagonalDown

-7

Линия по диагонали снизу – вверх

wdBorderDiagonalUp

-8

  1. Закрасить всю таблицу цветом
Doc.Tables(1).Shading.BackgroundPatternColor = 255 // заливка красным цветом
  1. Закрасить ячейку цветом
Cell = Doc.Tables(1).Cell(1; 1)
Cell.Shading.BackgroundPatternColor = -687800525 // заливка желтым цветом
  1. Установка ориентации страницы
Doc.Application.Selection.PageSetup.Orientation = 1 // альбомная
Doc.Application.Selection.PageSetup.Orientation = 0 // книжная
  1. Установка полей страницы
Word.Application.Selection.PageSetup.LeftMargin = Word.CentimetersToPoints(2)    // левое поле
Word.Application.Selection.PageSetup.RightMargin = Word.CentimetersToPoints(2)   // правое поле
Word.Application.Selection.PageSetup.TopMargin = Word.CentimetersToPoints(2)     // верхнее поле
Word.Application.Selection.PageSetup.BottomMargin = Word.CentimetersToPoints(2)  // нижнее поле 
  1. Добавление таблицы в документ
Doc.Tables.Add(Doc.Paragraphs(1).Range; 3; 5) // добавление таблицы из 5 столбцов и 3 строк в 1 абзац
  1. Добавление строки в таблицу
Doc.Tables(1).Rows.Add
  1. Добавление колонки в таблицу
Doc.Tables(1).Columns.Add
  1. Добавление текста в ячейку
Doc.Tables(1).Cell(1;3).Range.Text = 'Текст, который добавляется в ячейку'
  1. Сохранение документа в pdf формат
Doc.ExportAsFixedFormat(Path; 17; openAfterExport; CreateBookmarks) 

где

  • Path - полный путь и имя нового файла формата PDF;
  • 17 - значение Microsoft.Office.Interop.Word.WdExportFormat, указывающие, что сохранять документ в формате PDF;
  • openAfterExport - Значение True используется, чтобы автоматически открыть новый файл; в противном случае используется значение False.
  • CreateBookmarks - значение указывает, следует ли экспортировать закладки и тип закладки. Значение константы WdExportCreateBookmarks:
    • wdExportCreateHeadingBookmarks = 1 - Создание закладки в экспортируемом документе для всех заголовком, которые включают только заголовки внутри основного документа и текстовые поля не в пределах колонтитулов, концевых сносок, сносок или комментариев.
    • wdExportCreateNoBookmarks = 0 - Не создавать закладки в экспортируемом документе.
    • wdExportCreateWordBookmarks = 2 - Создание закладки в экспортируемом документе для каждой закладки, которая включает все закладки кроме тех, которые содержатся в верхнем и нижнем колонтитулах.

P.S.: Аналогичная статья для Excel Несколько способов форматирования и обработки данных в Excel документах с помощью IS-Builder.

41
Авторизуйтесь, чтобы оценить материал.
5
Наталия Соколова

Замеченное наблюдение к вставке текста в Word:

при вставке большого количества текста в word-овский документ с ошибками (грамматические/пунктуационные) 2010 Office ругается на большое количество ошибок и не хочет "показывать" отчет.

Чтобы этого избежать, можно программно отключать проверку орфографии:

ActiveDocument.ShowSpellingErrors = False
ActiveDocument.ShowGrammaticalErrors = False

 

Юрий Яковлев

создал простенькую таблицу.  с помощью данного материала

// Создадим объект приложения Microsoft Word
WordApp = CreateObject("Word.Application")
// Создадим новый документ
NewDoc = WordApp.Documents.Add()
// Добавим в него текст
Table = NewDoc.Tables.Add(NewDoc.Paragraphs(1).Range; 3; 5)
i =1
while i <7 // КАНТ простой линией
 Table.Borders('-'&i).LineStyle = 1
 i=i+1
endwhile

расположение  = 'C:\DirLogs\'

название=  "таблица.doc"
путь = расположение & название

WordApp.Visible = false
NewDoc.SaveAs(путь)    // куда сейвим
NewDoc.Close(false)    // закрываем док
WordApp.Quit()         // закрываем приложение

Юрий Яковлев

автору большое спасибо )) собрал отчет не громоздкий
 

Елизавета Гончарова

Пожалуйста.

В добавлении: Установить ширину столбца таблицы

Doc.Tables(1).Columns(1).PreferredWidth = Word.CentimetersToPoints(17.5)     

 

Для открытия документа в режиме чтения необходимо прописать параметры у метода Open следующим образом:

Word = CreateObject("Word.Application")  
Doc = Word.Documents.Open('Путь к документу'; True; True)
Word.Visible = true 

Третий параметр (True) указывает, что документ открывается в режиме чтения.

Для выделения определенного текста в документе можно воспользоваться, примерно, следующим кодом:

  Word = CreateObject("Word.Application")  
  Doc = Word.Documents.Open('Путь к документу'; True; True)
  myRange = Doc.Content 
  // Поиск текста для выделения
  myRange.Find.Execute("Выделяемый текст"; True)     
  isFind = myRange.Find.Found 
  while isFind
    // Выделения текста цветом
    myRange.Font.ColorIndex = 3
    myRange.Find.Execute("Выделяемый текст"; True)     
    isFind = myRange.Find.Found
  endwhile            
  Word.Visible = True 

 

 

ReadOnly мне, кстати, не подойдет, мне нужно открыть файл не "только для чтения", а в режиме чтения, переход в этот режим осуществляется в word-документе путем Вид->Режим чтения.

Видимо, я не правильно поняла задачу по режиму открытия документа.

Евгений Стоянов

Нашел небольшой недочет:
в 4 пункте:  должно быть:

Размер, указанный в параметреRowHeigh, является точным

wdRowHeightExactly

2

 

и 

Автоматический подбор высоты строк (параметр RowHeigh игнорируется)

wdRowHeightAuto 

0

 

у Вас параметры эти перепутаныwink

Елизавета Гончарова

Евгений, спасибо за замечание, данные в пункте 4 поправила.

Константин Тарасов

Хорошая статья, Елизавета спасибо.

Для быстрого нахождения материала и для обсуждения добавляю свои комментарии: 

1) Свойство таблицы "Повторять как заголовок на каждой странице"

Table.Rows.HeadingFormat = False
Table.Rows(1).HeadingFormat = True

2) Пример для удаления после разрыва страницы (до разрыва находится Закладка "СписокРассылки") страницы без содержания:

 CountTabl = WordDocument.Tables.Count           
 // Удаление двух таблиц 6-ой и 5-ой
 WordDocument.Tables.Item(CountTabl - 1).Delete
 WordDocument.Tables.Item(CountTabl - 1).Delete                       
 // Удаляем последний параграф с данными
 CountP = WordDocument.Paragraphs.Count           
 WordDocument.Paragraphs(CountP).Range.Delete
 // Удаляем строки после Закладки
 If WordDocument.Bookmarks.Exists("СписокРассылки")             
   WordDocument.Bookmarks("СписокРассылки").Range.Delete
   WordDocument.Bookmarks("СписокРассылки").Range.Delete
   WordDocument.Bookmarks("СписокРассылки").Range.Delete                           
 endif
 //WordDocument.Bookmarks("\Line").Range.Delete           
 //WordDocument.Paragraphs(CountP - 2).Range.Delete

3) Полезная статья о Закладках http://www.transcriber.ru/etudesrus/hlp_objbookmark.htm

Елизавета Гончарова

Константин, спасибо за дополнительную информацию.

Константин Алтынцев

Елизавета, большое спасибо за данную статью! Очень много интересного для себя нашел. Но вот какой вопрос: Можно ли в ячейки сделать форматирование по горизонтали?

Пробовал сделать...

Doc.Tables(1).Rows(1).Cells(1;3).HorizontalAlignment = 1

Но ругается на недопустимое число параметров sad

Елизавета Гончарова

Добрый день, Константин.

ожно ли в ячейки сделать форматирование по горизонтали?", да можно. Для выравнивания содержимого ячейки используйте аналогичный код, который описан в данной статье в пункте 13, т.е. код будет выглядеть следующим образом:

Doc.Tables(1).Cell(1;3).Range.ParagraphFormat.Alignment = 1 // выравнивание текста по центру в ячейке первой строки третьего столбца 

 

Константин Алтынцев
Doc.Tables(1).Cell(1;3).Range.ParagraphFormat.Alignment = 1 // выравнивание текста по центру в ячейке первой строки третьего столбца

Елизавета, к сожалению так он делает форматирование по горизонтали всей колонки, а не отдельно взятой ячейки sad

Елизавета Гончарова

Константин, пробовала отформатировать текст в ячейки, используя приведенный мною код выше, форматируется только текст одной ячейки, а не всей колонки.

Попробуйте вот этот код для форматирования текста в ячейке:

Doc.Tables(1).Rows(1).Cells(3).Range.ParagraphFormat.Alignment = 1 
Анатолий Придыбайло

Для получения параметров из документа Word:

Param = Doc.BuiltInDocumentProperties.Item(WdBuiltInProperty).Value

typedef enum WdBuiltInProperty
{
wdPropertyTitle = 1,
wdPropertySubject = 2,
wdPropertyAuthor = 3,
wdPropertyKeywords = 4,
wdPropertyComments = 5,
wdPropertyTemplate = 6,
wdPropertyLastAuthor = 7,
wdPropertyRevision = 8,
wdPropertyAppName = 9,
wdPropertyTimeLastPrinted = 10,
wdPropertyTimeCreated = 11,
wdPropertyTimeLastSaved = 12,
wdPropertyVBATotalEdit = 13,
wdPropertyPages = 14,
wdPropertyWords = 15,
wdPropertyCharacters = 16,
wdPropertySecurity = 17,
wdPropertyCategory = 18,
wdPropertyFormat = 19,
wdPropertyManager = 20,
wdPropertyCompany = 21,
wdPropertyBytes = 22,
wdPropertyLines = 23,
wdPropertyParas = 24,
wdPropertySlides = 25,
wdPropertyNotes = 26,
wdPropertyHiddenSlides = 27,
wdPropertyMMClips = 28,
wdPropertyHyperlinkBase = 29,
wdPropertyCharsWSpaces = 30
} WdBuiltInProperty;

Анатолий Придыбайло

небольшое замечание к предыдущему комментарию:

если вы хотите получить количество страниц в документе сразу после загрузки документа, то необходимо перед запросом количества страниц сделать паузу (sleep(1))? чтобы Word успел обновить параметр, иначе результат вернется неверным.

Пример можно посмотреть в ответе на вопрос

Максим Иванов

делаю интегрированный отчет (ртф) и нужно проставить маркеры (квадратики, кружки и пр. ерунду), подскажите, как это сделать?

Руслан Бапин
делаю интегрированный отчет (ртф) и нужно проставить маркеры (квадратики, кружки и пр. ерунду), подскажите, как это сделать?

Такие маркеры, как квадратики и кружки - это просто символы, причем они входят в "обычные" шрифты. Вопрос в том, как вставить эти символы, ведь редактор ISBL-кода этого не позволяет. Один из способов - "препарировать", т.е. изучить содержимое RTF-файла, в котором есть эти символы. Создайте в приложении WordPad документ с нужными маркерами, сохраните его в формате RTF, откройте текстовым редактором, например notepad, и изучайте, какими управляющими последовательностями закодированы нужные символы :)

Почему рекомендую WordPad, а не Word - последний вставляет в RTF-файл очень много дополнительного "мусора", это мешает поиску нужной информации. Но в WordPad-е сложнее подобрать нужный символ, поэтому для удобства можно набрать символы в Word и скопировать их в WordPad.

Например, вот простейший шаблон RTF-отчета, состоящего из одного символа "□" :

#[РТФЗагОтч("Да"; ; "К"; 1; 1; 1.5; 1; ; )]
#{\lang1049\f1\u9633?\lang1033\f2}
#[РТФКонОтч()]

Илья Чечиль

Полезная статья. Дополню кодом по вставке ссылки на документ в ячейку таблицы

Document = DocApplication.Documents.Open(ModelFilePath)
Tabl = Document.Tables(1)
Cell = Tabl.Cell(1; 7)
Document.Hyperlinks.Add(Cell.Range; Doc.Hyperlink(hltText); ; ; DocName;)

Владислав Пашковский
А может кто-нибудь подсказать причину такого поведения:
1. Есть документ с текстом после таблицы.
2. Добавляем текст командой Doc.Paragraphs(X).Range.Text = 'текст'
3. При формировании документа системой 'текст' оказывается не в абзаце, а в таблице выше, в одной из ячеек Doc.Tables(1).Range.

Такое впечатление, что для обращения к абзацам текста и то ли строкам, то ли отдельным  ячейкам таблицы (так и не понял, по какому принципу) используется одно и то же сквозное индексирование. Справка по объектной модели MS офиса об этом умалчивает.

Как корректно обращаться в таком случае к абзацам текста после таблицы?

 

Владислав Пашковский: обновлено 22.03.2022 в 17:06

Авторизуйтесь, чтобы написать комментарий