Итак, книга, посвященная, главным образом, языку VBA, закончена. Я начал работать над второй книгой, в которой, собираюсь подробно рассказать об объектах каждого из приложений Office 2000 - Word, Excel, Access, Outlook, сопровождая описание проектами, в которых участвуют объекты этих приложений. Особое внимание хочется уделить применениям в Интернет. Пока, это еще только планы. Пишу об этом по той причине, что надеюсь получить от Вас письма с предложениями, а, возможно, и готовыми проектами, небольшими, но интересными для многих, которые Вы хотели бы поместить в книгу.
Теперь несколько слов о законченной книге. Знаю по себе, что книги редко отвечают на вопросы, требующие сиюминутного решения. Цель книг другая. При прочтении хорошей книги число интересных вопросов, которые можно задать, по крайней мере, самому себе должно только возрастать. И вся прелесть состоит в том, что на эти вопросы удается найти ответы. В поисках ответов мы часто обращаемся к друзьям, коллегам, а иногда, когда есть такая возможность, и к автору книги. Я получаю достаточно много писем с различными вопросами по поводу офисного программирования. Не всегда, но, по возможности, стараюсь на них отвечать. Как правило, ответы на поставленные вопросы требуют знания чуть большего числа деталей, в сравнении с тем, что, по понятным причинам, удалось изложить в рамках книги. В качестве примера, приведу два вопроса из одного из последних писем, которое я получил от Ивана Кряжева - читателя нашей предыдущей книги по Офисному программированию. Полагаю возможным и полезным поместить мой подробный ответ на вопросы этого письма.
Для выяснения сути проблемы обратимся к примеру, который я спроектировал специально для этой задачи.
Первым делом я спроектировал форму с двумя элементами управления, включив ее в состав тестового документа. На самом тестовом документе я разместил 4 кнопки, управляющие работой формы. Кнопки Show и Hide показывают и прячут форму. Кнопка "Add Controls to Form" программно добавляет элементы управления на период существования формы, то есть до тех пор, пока форма не будет закрыта. Наконец, кнопка "Add Design Controls" решает поставленную задачу, добавляя элементы управления, как теперь принято говорить, на постоянной основе. Вот как выглядит тестовый документ с командными кнопками:
(рис П-1) Тестовый документ с командными кнопкамиА вот как выглядит сама форма при ее открытии в ответ на щелчок кнопки Show:
(рис П-2) Спроектированная форма при ее открытии Вот на какие моменты при решении этой задачи следует обратить внимание:
Modal , значение которого можно установить в момент проектирования. Если это значение равно True, то окно формы является модальным и его нельзя покинуть до закрытия. Если значение - False, то можно покинуть форму, поработать с документом, нажимать, например, другие кнопки в документе, модифицируя, возможно, саму форму. Заметим, что в Office 97 создать не Balloon , входящие в состав объекта Assistant. Теперь сделан важный шаг в правильном направлении, - центральный объект интерфейса - UserForm получил возможность работать в немодальном окне. Главное, что для программиста это не требует никаких усилий, достаточно изменить значение одного свойства. Замечу, что в С++, по крайней мере, в версии 4 работа с немодальными окнами требовала профессиональных знаний, в частности, умения посылать сообщения операционной системе. Но вернемся к нашей задаче.Form есть коллекция Controls, у которой есть метод Add, позволяющий добавить любой из элементов управления. В нашем примере мы уже спроектировали форму с двумя элементами управления - командной кнопкой и окном редактирования. В обработчиках события Click командной кнопки самой формы и командной кнопки "Add Controls to Form", встроенной в тестовый документ, вызывается процедура AddControls, которая добавляет в форму еще пару таких же элементов управления. Заметьте, поскольку наша форма не является модальной, то нажимать командные кнопки можно как в самой форме, так и вне формы. Вот текст процедуры, добавляющей в форму элементы управления:Public Sub AddControls()
'Эта процедура добавляет командную кнопку и окно редактирования в форму
With UserForm1
'Добавляем окно редактирования
Set Mycmd = .Controls.Add("Forms.TextBox.1", "ProgramBox", True)
Mycmd.Left = .TextBox1.Left
Mycmd.Top = .TextBox1.Top + 100
Mycmd.Width = .TextBox1.Width
Mycmd.Height = .TextBox1.Height
Mycmd.Text = "New Control - " Mycmd.Name
'Добавляем командную кнопку
Set Mycmd = .Controls.Add("Forms.CommandButton.1", "ProgramButton", True)
Mycmd.Left = .CommandButton1.Left
Mycmd.Top = .CommandButton1.Top + 100
Mycmd.Width = .CommandButton1.Width
Mycmd.Height = .CommandButton1.Height
Mycmd.Caption = "ProgramButton"
End With
End Sub
Hide, то при повторном ее открытии элементы управления сохраняются.VBComponent - компоненты VB-проекта (объекта класса VBProject ). Чтобы можно было с ними работать, необходимо включить дополнительную ссылку на библиотеку VBIDE (Visual Basic Extensibility). Ну, а теперь отвечаю конкретно на первый поставленный вопрос. Можно программно добавить элементы управления так, чтобы они сохранялись в форме точно также как сохраняются элементы, созданные в период проектирования. Для этого нужно работать с объектом, представляющим форму в режиме проектирования, используя свойство Designer объекта VBComponent. Вот как это делается:Public Sub AddDesignControls()
'Эта процедура добавляет командную кнопку и окно редактирования в форму
Dim MyForm As UserForm
'Создаем форму этапа проектирования
Set MyForm = ActiveDocument.VBProject.VBComponents("UserForm1").Designer
With MyForm
'Добавляем окно редактирования
Set Mycmd = .Controls.Add("Forms.TextBox.1", "ProgramBox", True)
Mycmd.Left = .TextBox1.Left
Mycmd.Top = .TextBox1.Top + 100
Mycmd.Width = .TextBox1.Width
Mycmd.Height = .TextBox1.Height
Mycmd.Text = "New Control - " Mycmd.Name
'Добавляем командную кнопку
Set Mycmd = .Controls.Add("Forms.CommandButton.1", "ProgramButton", True)
Mycmd.Left = .CommandButton1.Left
Mycmd.Top = .CommandButton1.Top + 100
Mycmd.Width = .CommandButton1.Width
Mycmd.Height = .CommandButton1.Height
Mycmd.Caption = "DesignButton"
End With
'Удаляем командную кнопку, вызывающую эту процедуру.
'Эта кнопка может работать лишь раз, по крайней мере,
'пока в режиме проектирования не будут удалены добавленные элементы.
'Заметьте, кнопку можно только удалить, но нельзя сделать ее невидимой.
ActiveDocument.InlineShapes(4).Delete
End Sub
Обратите внимание, к нашей форме, рассматриваемой как объект класса VBComponent, мы добираемся через свойство VBProject нашего документа. Имея форму, в последний момент вызываем Designer, который и возвращает форму периода проектирования. Теперь добавление элементов управления будет постоянным. Само добавление делается, как и ранее, никаких изменений в этом процессе здесь нет.
Однако есть некоторые естественные ограничения, на которые следует обратить внимание. Процедура AddDesignControls, добавляющая элементы периода проектирования, должна вызываться при закрытой форме и только один раз. Поэтому в конце этой процедуры добавлен текст, удаляющий из тестового документа командную кнопку (объект класса InlineShape ), обработчик которой вызывал процедуру AddDesignControls.
Вот как выглядит форма, открытая после окончания работы этой процедуры:
(рис П-4) Форма с постоянно добавленными элементами
Ответ, кажется, очевидным - нужно переименовать один из компонентов, поскольку, действительно не могут существовать два компонента с одним именем. Какой же из компонентов переименовывать? Здесь тоже все достаточно ясно, - импортируемый компонент программно в момент его добавления не переименуешь, поскольку он скрыт в файле. Поэтому остается переименовать компонент в самом проекте. Остается понять, какой именно компонент вызвал коллизию и требует переименования. Часто подсказкой может служить имя файла с импортируемым компонентом, поскольку по умолчанию имя файла совпадает с именем компонента. В моем примере я переименовываю все компоненты текущего проекта. Это одно из возможных решений. Главное, демонстрируется возможность переименования компонент.
Но обо всем по порядку. Несколько слов о самом примере. В наш документ, содержащий форму со стандартным именем UserForm1, программно импортируются еще две формы. Обе они были экспортированы из другого документа, сохранены в виде файлов, и поскольку имели стандартные имена, то и файлы (по два файла на форму с уточнениями " frm " и " frx ") получили имена " UserForm1 " и " UserForm2 ". Вот процедура, осуществляющая импорт:
Public Sub ImportForm()
'Эта процедура импортирует формы, сохраненные в файле
Documents("Answer1.doc").VBProject.VBComponents.Import
("e:\O2000\cd2000\tests\UserForm1.frm")
Documents("Answer1.doc").VBProject.VBComponents.Import
("e:\O2000\cd2000\tests\UserForm2.frm")
End Sub
Очевидно, что при запуске этой процедуры возникнет конфликт имен (два компонента - две формы имеют одно и то же имя " UserForm1 ") и при выполнении первого же оператора возникнет ошибка. Если же предварительно запустить процедуру Rename, переименовывающую объекты класса VBComponent, то импорт пройдет гладко. Разумно, конечно, запускать процедуру Rename в обработчике исключительной ситуации, когда конфликт реально возник. Вот возможный вариант процедуры Rename:
Public Sub Rename()
Dim Comp As Object
For Each Comp In Documents("Answer1").VBProject.VBComponents
Debug.Print Comp.Name
Comp.Name = Comp.Name "New"
Debug.Print Comp.Name
Next Comp
End Sub
Вот результаты отладочной печати, показывающей, какие компоненты проекта будут переименованы:
ThisDocument ThisDocumentNew Sample SampleNew UserForm1 UserForm1New
После переименования импорт происходит без проблем.
На два вопроса Ивана Кряжева ответы даны.
Если Вы хотите задать свои вопросы, напоминаю мой адрес: Vladimir.Billig@tversu.ru
Итак, книга, посвященная, главным образом, языку VBA, закончена. Я начал работать над второй книгой, в которой, собираюсь подробно рассказать об объектах каждого из приложений Office 2000 - Word, Excel, Access, Outlook, сопровождая описание проектами, в которых участвуют объекты этих приложений. Особое внимание хочется уделить применениям в Интернет. Пока, это еще только планы. Пишу об этом по той причине, что надеюсь получить от Вас письма с предложениями, а, возможно, и готовыми проектами, небольшими, но интересными для многих, которые Вы хотели бы поместить в книгу.
Теперь несколько слов о законченной книге. Знаю по себе, что книги редко отвечают на вопросы, требующие сиюминутного решения. Цель книг другая. При прочтении хорошей книги число интересных вопросов, которые можно задать, по крайней мере, самому себе должно только возрастать. И вся прелесть состоит в том, что на эти вопросы удается найти ответы. В поисках ответов мы часто обращаемся к друзьям, коллегам, а иногда, когда есть такая возможность, и к автору книги. Я получаю достаточно много писем с различными вопросами по поводу офисного программирования. Не всегда, но, по возможности, стараюсь на них отвечать. Как правило, ответы на поставленные вопросы требуют знания чуть большего числа деталей, в сравнении с тем, что, по понятным причинам, удалось изложить в рамках книги. В качестве примера, приведу два вопроса из одного из последних писем, которое я получил от Ивана Кряжева - читателя нашей предыдущей книги по Офисному программированию. Полагаю возможным и полезным поместить мой подробный ответ на вопросы этого письма.
Для выяснения сути проблемы обратимся к примеру, который я спроектировал специально для этой задачи.
Первым делом я спроектировал форму с двумя элементами управления, включив ее в состав тестового документа. На самом тестовом документе я разместил 4 кнопки, управляющие работой формы. Кнопки Show и Hide показывают и прячут форму. Кнопка "Add Controls to Form" программно добавляет элементы управления на период существования формы, то есть до тех пор, пока форма не будет закрыта. Наконец, кнопка "Add Design Controls" решает поставленную задачу, добавляя элементы управления, как теперь принято говорить, на постоянной основе. Вот как выглядит тестовый документ с командными кнопками:
(рис П-1) Тестовый документ с командными кнопкамиА вот как выглядит сама форма при ее открытии в ответ на щелчок кнопки Show:
(рис П-2) Спроектированная форма при ее открытииВот на какие моменты при решении этой задачи следует обратить внимание:
Modal , значение которого можно установить в момент проектирования. Если это значение равно True, то окно формы является модальным и его нельзя покинуть до закрытия. Если значение - False, то можно покинуть форму, поработать с документом, нажимать, например, другие кнопки в документе, модифицируя, возможно, саму форму. Заметим, что в Office 97 создать не Balloon , входящие в состав объекта Assistant. Теперь сделан важный шаг в правильном направлении, - центральный объект интерфейса - UserForm получил возможность работать в немодальном окне. Главное, что для программиста это не требует никаких усилий, достаточно изменить значение одного свойства. Замечу, что в С++, по крайней мере, в версии 4 работа с немодальными окнами требовала профессиональных знаний, в частности, умения посылать сообщения операционной системе. Но вернемся к нашей задаче.Form есть коллекция Controls, у которой есть метод Add, позволяющий добавить любой из элементов управления. В нашем примере мы уже спроектировали форму с двумя элементами управления - командной кнопкой и окном редактирования. В обработчиках события Click командной кнопки самой формы и командной кнопки "Add Controls to Form", встроенной в тестовый документ, вызывается процедура AddControls, которая добавляет в форму еще пару таких же элементов управления. Заметьте, поскольку наша форма не является модальной, то нажимать командные кнопки можно как в самой форме, так и вне формы. Вот текст процедуры, добавляющей в форму элементы управления:Public Sub AddControls()
'Эта процедура добавляет командную кнопку и окно редактирования в форму
With UserForm1
'Добавляем окно редактирования
Set Mycmd = .Controls.Add("Forms.TextBox.1", "ProgramBox", True)
Mycmd.Left = .TextBox1.Left
Mycmd.Top = .TextBox1.Top + 100
Mycmd.Width = .TextBox1.Width
Mycmd.Height = .TextBox1.Height
Mycmd.Text = "New Control - " Mycmd.Name
'Добавляем командную кнопку
Set Mycmd = .Controls.Add("Forms.CommandButton.1", "ProgramButton", True)
Mycmd.Left = .CommandButton1.Left
Mycmd.Top = .CommandButton1.Top + 100
Mycmd.Width = .CommandButton1.Width
Mycmd.Height = .CommandButton1.Height
Mycmd.Caption = "ProgramButton"
End With
End Sub
Hide, то при повторном ее открытии элементы управления сохраняются.VBComponent - компоненты VB-проекта (объекта класса VBProject ). Чтобы можно было с ними работать, необходимо включить дополнительную ссылку на библиотеку VBIDE (Visual Basic Extensibility). Ну, а теперь отвечаю конкретно на первый поставленный вопрос. Можно программно добавить элементы управления так, чтобы они сохранялись в форме точно также как сохраняются элементы, созданные в период проектирования. Для этого нужно работать с объектом, представляющим форму в режиме проектирования, используя свойство Designer объекта VBComponent. Вот как это делается:Public Sub AddDesignControls()
'Эта процедура добавляет командную кнопку и окно редактирования в форму
Dim MyForm As UserForm
'Создаем форму этапа проектирования
Set MyForm = ActiveDocument.VBProject.VBComponents("UserForm1").Designer
With MyForm
'Добавляем окно редактирования
Set Mycmd = .Controls.Add("Forms.TextBox.1", "ProgramBox", True)
Mycmd.Left = .TextBox1.Left
Mycmd.Top = .TextBox1.Top + 100
Mycmd.Width = .TextBox1.Width
Mycmd.Height = .TextBox1.Height
Mycmd.Text = "New Control - " Mycmd.Name
'Добавляем командную кнопку
Set Mycmd = .Controls.Add("Forms.CommandButton.1", "ProgramButton", True)
Mycmd.Left = .CommandButton1.Left
Mycmd.Top = .CommandButton1.Top + 100
Mycmd.Width = .CommandButton1.Width
Mycmd.Height = .CommandButton1.Height
Mycmd.Caption = "DesignButton"
End With
'Удаляем командную кнопку, вызывающую эту процедуру.
'Эта кнопка может работать лишь раз, по крайней мере,
'пока в режиме проектирования не будут удалены добавленные элементы.
'Заметьте, кнопку можно только удалить, но нельзя сделать ее невидимой.
ActiveDocument.InlineShapes(4).Delete
End Sub
Обратите внимание, к нашей форме, рассматриваемой как объект класса VBComponent, мы добираемся через свойство VBProject нашего документа. Имея форму, в последний момент вызываем Designer, который и возвращает форму периода проектирования. Теперь добавление элементов управления будет постоянным. Само добавление делается, как и ранее, никаких изменений в этом процессе здесь нет.
Однако есть некоторые естественные ограничения, на которые следует обратить внимание. Процедура AddDesignControls, добавляющая элементы периода проектирования, должна вызываться при закрытой форме и только один раз. Поэтому в конце этой процедуры добавлен текст, удаляющий из тестового документа командную кнопку (объект класса InlineShape ), обработчик которой вызывал процедуру AddDesignControls.
Вот как выглядит форма, открытая после окончания работы этой процедуры:
(рис П-4) Форма с постоянно добавленными элементами
Ответ, кажется, очевидным - нужно переименовать один из компонентов, поскольку, действительно не могут существовать два компонента с одним именем. Какой же из компонентов переименовывать? Здесь тоже все достаточно ясно, - импортируемый компонент программно в момент его добавления не переименуешь, поскольку он скрыт в файле. Поэтому остается переименовать компонент в самом проекте. Остается понять, какой именно компонент вызвал коллизию и требует переименования. Часто подсказкой может служить имя файла с импортируемым компонентом, поскольку по умолчанию имя файла совпадает с именем компонента. В моем примере я переименовываю все компоненты текущего проекта. Это одно из возможных решений. Главное, демонстрируется возможность переименования компонент.
Но обо всем по порядку. Несколько слов о самом примере. В наш документ, содержащий форму со стандартным именем UserForm1, программно импортируются еще две формы. Обе они были экспортированы из другого документа, сохранены в виде файлов, и поскольку имели стандартные имена, то и файлы (по два файла на форму с уточнениями " frm " и " frx ") получили имена " UserForm1 " и " UserForm2 ". Вот процедура, осуществляющая импорт:
Public Sub ImportForm()
'Эта процедура импортирует формы, сохраненные в файле
Documents("Answer1.doc").VBProject.VBComponents.Import
("e:\O2000\cd2000\tests\UserForm1.frm")
Documents("Answer1.doc").VBProject.VBComponents.Import
("e:\O2000\cd2000\tests\UserForm2.frm")
End Sub
Очевидно, что при запуске этой процедуры возникнет конфликт имен (два компонента - две формы имеют одно и то же имя " UserForm1 ") и при выполнении первого же оператора возникнет ошибка. Если же предварительно запустить процедуру Rename, переименовывающую объекты класса VBComponent, то импорт пройдет гладко. Разумно, конечно, запускать процедуру Rename в обработчике исключительной ситуации, когда конфликт реально возник. Вот возможный вариант процедуры Rename:
Public Sub Rename()
Dim Comp As Object
For Each Comp In Documents("Answer1").VBProject.VBComponents
Debug.Print Comp.Name
Comp.Name = Comp.Name "New"
Debug.Print Comp.Name
Next Comp
End Sub
Вот результаты отладочной печати, показывающей, какие компоненты проекта будут переименованы:
ThisDocument ThisDocumentNew Sample SampleNew UserForm1 UserForm1New
После переименования импорт происходит без проблем.
На два вопроса Ивана Кряжева ответы даны.
Если Вы хотите задать свои вопросы, напоминаю мой адрес: Vladimir.Billig@tversu.ru
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.