На одном из проектов столкнулась с ситуацией, когда построение отчета, в котором заполняются таблицы, занимало слишком много времен. Проанализировав код расчета отчета, поняла, что очень много времени тратится на заполнение таблиц с помощью функции 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 - путь к документу, с которым работаете.
Doc.Tables(1).PreferredWidthType = 2
Единица измерения |
Константа в Word |
Значение в ISBL |
Сантиметры |
wdPreferredWidthPoints |
3 |
Проценты |
wdPreferredWidthPercent |
2 |
Doc.Tables(1).PreferredWidth = 100 // ширина таблицы в процентах Doc.Tables(1).PreferredWidth = Word.CentimetersToPoints(17.5) // ширина таблицы в сантиметрах
Doc.Tables(1).AutoFitBehavior(2)
Режим выравнивания |
Константа в Word |
Значение в ISBL |
Фиксированная ширина |
wdAutoFitFixed |
0 |
По содержимому |
wdAutoFitContent |
1 |
По ширине окна |
wdAutoFitWindow |
2 |
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 |
Doc.Tables(1).Range.ParagraphFormat.SpaceBefore = 6 //интервал перед Doc.Tables(1).Range.ParagraphFormat.SpaceAfter = 6 //интервал после Единица измерения интервала пт.
Doc.Paragraphs(1).Format.SpaceBefore = 12 // интервал перед Doc.Paragraphs(1).Format.SpaceAfter = 12 // интервал после
Doc.Paragraphs(1).Format.LineSpacingRule = 0.5 // одинарный интервал 1 – полуторный интервал и 1.5 – двойной интервал.
Doc.Tables(1).Style = ИмяСтиляТаблицы
Doc.Tables(1).Rows.LeftIndent = 0
Doc.Paragraphs(1).Format.FirstLineIndent = Значение в пунктах
Для перевода сантиметров в пункты можно воспользоваться функцией CentimetersToPoints, тогда абзацный отступ в 1,5 см можно задать следующим образом:
Doc.Paragraphs(1).Format.FirstLineIndent = Word.CentimetersToPoints(1.5)
Doc.Paragraphs(1).Format.LeftIndent = 10 // отступ слева Doc.Paragraphs(1).Format.RightIndent = 10 // отступ справа
Doc.Tables(1).TopPadding = 0 // верхнее Doc.Tables(1).BottomPadding = 0 // нижнее Doc.Tables(1).LeftPadding = 0 // левое Doc.Tables(1).RightPadding = 0 // правое
Doc.Tables(1).Range.ParagraphFormat.Alignment = 3 // по ширине
Режим выравнивания |
Константа в Word |
Значение в ISBL |
По левому краю |
wdAlignParagraphLeft |
0 |
По центру |
wdAlignParagraphCenter |
1 |
По правому краю |
wdAlignParagraphRight |
2 |
По ширине |
wdAlignParagraphJustify |
3 |
Doc.Paragraphs(1).Format.Alignment = 0 // выравнивание по левому краю
Значения констант выравнивания такие же как в предыдущем пункте.
Doc.Tables(1).Rows(НомерСтроки).Cells(НомерСтолбца).VerticalAlignment = 1
Режим выравнивания |
Константа в Word |
Значение в ISBL |
По верхнему краю |
wdCellAlignVerticalTop |
0 |
По центру |
wdCellAlignVerticalCenter |
1 |
По нижнему краю |
wdCellAlignVerticalBottom |
3 |
Doc.Tables(1).Range.Font.Size = 7
Doc.Tables(1).Cell(НомерСтроки; НомерСтолбца).Range.Font.Color = 255
Doc.Tables(1).Range.Font.Bold = True // жирным Doc.Tables(1).Range.Font.Italic = True // курсивом Doc.Tables(1).Range.Font.Underline = True // подчеркивание
Doc.Tables(1).Cell(НомерСтроки; НомерСтолбца).Range.Font.UnderlineColor = 255
Doc.Tables(1).Range.Font.Name = "Arial"
// объединение первой и второй ячеек первой строки Cell = Doc.Tables(1).Cell(1; 1) Cell.Merge(Doc.Tables(1).Cell(1; 2))
SelectionWord = Doc.Paragraphs(Paragraph).Range SelectionWord.PasteExcelTable(True; False; False)
Paragraph – номер параграфа, куда будет вставлена таблица из Excel.
Doc.Fields.Unlink
Doc.Paragraphs(Paragraph).Range.Delete
Paragraph – номер параграфа, который нужно удалить.
Doc.Tables(1).Rows(НомерСтроки).Select Doc.Tables(1).Rows(НомерСтроки).Delete
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 |
Doc.Tables(1).Shading.BackgroundPatternColor = 255 // заливка красным цветом
Cell = Doc.Tables(1).Cell(1; 1) Cell.Shading.BackgroundPatternColor = -687800525 // заливка желтым цветом
Doc.Application.Selection.PageSetup.Orientation = 1 // альбомная Doc.Application.Selection.PageSetup.Orientation = 0 // книжная
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) // нижнее поле
Doc.Tables.Add(Doc.Paragraphs(1).Range; 3; 5) // добавление таблицы из 5 столбцов и 3 строк в 1 абзац
Doc.Tables(1).Rows.Add
Doc.Tables(1).Columns.Add
Doc.Tables(1).Cell(1;3).Range.Text = 'Текст, который добавляется в ячейку'
Doc.ExportAsFixedFormat(Path; 17; openAfterExport; CreateBookmarks)
где
P.S.: Аналогичная статья для Excel Несколько способов форматирования и обработки данных в Excel документах с помощью IS-Builder.
Замеченное наблюдение к вставке текста в Word:
при вставке большого количества текста в word-овский документ с ошибками (грамматические/пунктуационные) 2010 Office ругается на большое количество ошибок и не хочет "показывать" отчет.
Чтобы этого избежать, можно программно отключать проверку орфографии:
создал простенькую таблицу. с помощью данного материала
// Создадим объект приложения 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() // закрываем приложение
автору большое спасибо )) собрал отчет не громоздкий
Пожалуйста.
В добавлении: Установить ширину столбца таблицы
Для открытия документа в режиме чтения необходимо прописать параметры у метода Open следующим образом:
Третий параметр (True) указывает, что документ открывается в режиме чтения.
Для выделения определенного текста в документе можно воспользоваться, примерно, следующим кодом:
Видимо, я не правильно поняла задачу по режиму открытия документа.
Нашел небольшой недочет:
в 4 пункте: должно быть:
Размер, указанный в параметреRowHeigh, является точным
2
и
Автоматический подбор высоты строк (параметр RowHeigh игнорируется)
0
у Вас параметры эти перепутаны
Евгений, спасибо за замечание, данные в пункте 4 поправила.
Хорошая статья, Елизавета спасибо.
Для быстрого нахождения материала и для обсуждения добавляю свои комментарии:
1) Свойство таблицы "Повторять как заголовок на каждой странице"
2) Пример для удаления после разрыва страницы (до разрыва находится Закладка "СписокРассылки") страницы без содержания:
3) Полезная статья о Закладках http://www.transcriber.ru/etudesrus/hlp_objbookmark.htm
Константин, спасибо за дополнительную информацию.
Елизавета, большое спасибо за данную статью! Очень много интересного для себя нашел. Но вот какой вопрос: Можно ли в ячейки сделать форматирование по горизонтали?
Пробовал сделать...
Но ругается на недопустимое число параметров
Добрый день, Константин.
"Можно ли в ячейки сделать форматирование по горизонтали?", да можно. Для выравнивания содержимого ячейки используйте аналогичный код, который описан в данной статье в пункте 13, т.е. код будет выглядеть следующим образом:
Елизавета, к сожалению так он делает форматирование по горизонтали всей колонки, а не отдельно взятой ячейки
Константин, пробовала отформатировать текст в ячейки, используя приведенный мною код выше, форматируется только текст одной ячейки, а не всей колонки.
Попробуйте вот этот код для форматирования текста в ячейке:
Для получения параметров из документа Word:
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;)
Такое впечатление, что для обращения к абзацам текста и то ли строкам, то ли отдельным ячейкам таблицы (так и не понял, по какому принципу) используется одно и то же сквозное индексирование. Справка по объектной модели MS офиса об этом умалчивает.
Как корректно обращаться в таком случае к абзацам текста после таблицы?
Авторизуйтесь, чтобы написать комментарий