Необходимо печатать конверты по заданному макету. Задача довольно простая, когда мы заранее знаем, что необходимо печатать. Был создан интегрированный RTF-отчет. Посмотрев на него, пришли к выводу, что такой вариант будет недостаточно гибким, ведь почтовые конверты бывают разные, при условии, что наши организации закупают их не централизовано, с печатью могут возникнуть проблемы.
Был выбран путь формирование отчета из макета. Все текстовые поля замечательно проставляются с помощью макропеременных, но появляется загвоздка в формировании индекса. В RTF-отчете он формировался с помощью таблицы. Выбирая разные стили границ, мы можем рисовать цифры. Можно было бы найти какой-нибудь подходящий шрифт, но его надо было бы устанавливать на все компьютеры, с которых возможна печать конвертов.
Посмотрели на готовый результат RTF-отчета с пустым индексом, сохранили его как docx, занесли в систему и обозвали макетом. Лишнее убрали, нужное добавили и сделали генерацию документа. И вот отчет уже почти готов.
Осталось нарисовать такие цифры:
В справке по VBA можно найти значения перечисления типа границы (wdBorderType). В соответствии с этими значениями создаем список соответствий, именем которого является цифра, значением – массив границ, формирующих число.
// Верхняя часть цифры
UpperPartOfNumber = CreateList()
UpperPartOfNumber.Add(0; ArrayOf(-1; -2; -4))
UpperPartOfNumber.Add(1; ArrayOf(-4; -8))
UpperPartOfNumber.Add(2; ArrayOf(-1; -4))
UpperPartOfNumber.Add(3; ArrayOf(-1; -8))
UpperPartOfNumber.Add(4; ArrayOf(-2; -4))
UpperPartOfNumber.Add(5; ArrayOf(-1; -2))
UpperPartOfNumber.Add(6; ArrayOf(-8))
UpperPartOfNumber.Add(7; ArrayOf(-1; -8))
UpperPartOfNumber.Add(8; ArrayOf(-1; -2; -4))
UpperPartOfNumber.Add(9; ArrayOf(-1; -2; -4))
// Нижняя часть цифры
LowerPartOfNumber = CreateList()
LowerPartOfNumber.Add(0; ArrayOf(-2; -3; -4))
LowerPartOfNumber.Add(1; ArrayOf(-4))
LowerPartOfNumber.Add(2; ArrayOf(-3; -8))
LowerPartOfNumber.Add(3; ArrayOf(-1; -8))
LowerPartOfNumber.Add(4; ArrayOf(-1; -4))
LowerPartOfNumber.Add(5; ArrayOf(-1; -3; -4))
LowerPartOfNumber.Add(6; ArrayOf(-1; -2; -3; -4))
LowerPartOfNumber.Add(7; ArrayOf(-2))
LowerPartOfNumber.Add(8; ArrayOf(-1; -2; -3; -4))
LowerPartOfNumber.Add(9; ArrayOf(-1; -8))
Приступаем к заполнению.
VBDocApp = CreateObject('Word.Application')
VBDoc = VBDocApp.Documents.Open(FileName)
PositionOfIndexNumber = 1
while PositionOfIndexNumber <= Length(OrgIndex)
// Получаем цифру индекса
IndexNumber = Copy(OrgIndex; PositionOfIndexNumber; 1)
// Заполняем вернюю часть цифры
UpperPart = UpperPartOfNumber.FindItem(IndexNumber)
UpperPartTable = VBDoc.Tables(INDEX_TABLE_NUMBER).Rows(UPPER_PART_POINTER).Cells((PositionOfIndexNumber*2)-1)
// x*2-1 нужно, потому что между цифрами так же есть столбцы без отображаемых границ
CyclePointer = 0
CycleCount = ArrayHighBound(UpperPart)
// Отрисовка верхней части цифры
while CyclePointer <= CycleCount
UpperPartTable.Borders.Item(UpperPart[CyclePointer]).LineStyle = INDEX_LINE_STYLE
UpperPartTable.Borders.Item(UpperPart[CyclePointer]).LineWidth = INDEX_LINE_WIDTH
CyclePointer = CyclePointer + 1
endwhile
// Заполняем нижнюю часть цифры
LowerPart = LowerPartOfNumber.FindItem(IndexNumber)
LowerPartTable = VBDoc.Tables(INDEX_TABLE_NUMBER).Rows(LOWER_PART_POINTER).Cells((PositionOfIndexNumber*2)-1)
CyclePointer = 0
CycleCount = ArrayHighBound(LowerPart)
// Отрисовка нижней части цифры
while CyclePointer <= CycleCount
LowerPartTable.Borders.Item(LowerPart[CyclePointer]).LineStyle = INDEX_LINE_STYLE
LowerPartTable.Borders.Item(LowerPart[CyclePointer]).LineWidth = INDEX_LINE_WIDTH
CyclePointer = CyclePointer + 1
endwhile
PositionOfIndexNumber = PositionOfIndexNumber + 1
endwhile
Пожалуй, более полезная и распространенная, при этом, значительно более короткая часть изысканий в объектной модели Word.Application.
Рисование в таблице, как оказалось, не единственное действие, для которого нам понадобился данный COM-объект. В RTF-отчете, с помощью тегов, можно разбивать документ на страницы. При генерации документов из макета, их придется склеивать средствами, предоставляемыми COM.
// Берем текущее содержимое документа
Content = MainDoc.Content
Content.Collapse(END_COLLAPSE_DIRECTION)
// Вставляем разделитель страницы
Content.InsertBreak(PAGE_BREAKE)
// Переходим на вновь получившуюся страницу
NewPageContent = Report.GoTo(GOTO_PAGE_ITEM; GOTO_LAST_PAGE_DIRECTION)
// Вставляем содержимое другого документа в главный
// DocPath – путь до документа в файловой системе
NewPageContent.InsertFile(DocPath)
GOTO_PAGE_ITEM – перечисление wdGoToItem. Определяет тип элемента для перехода. В нашем случае указываем, что перемещаемся по страницам.
GOTO_LAST_PAGE_DIRECTION – перечисление wdGoToDirection. Указывает направление перемещения. Для нас это последний элемент.
Эти перечисления указывают, что надо взять содержимое, находящееся на последней странице. Туда мы и вставляем новую информацию. Если бы эта страница имела бы какой-нибудь контент, он был бы заменен новой информацией. Если бы надо было добавить только подготовленную текстовую информацию, то можно было бы использовать метод InsertAfter для всего содержимого документа, но у нас во втором документе находится несколько более комплексная информация.
Более подробную информацию по данному объекту можно найти в MSDN и справке по VBA.
Супер! Уже применил спасибо ) Работает отлично!
Авторизуйтесь, чтобы написать комментарий