2016-05-06 4 views
2

У меня есть метод, где дан VBComponent, я могу получить доступ к .Designer и оттуда, в .Controls коллекции:Как я могу перебирать элементы управления в форме MS-Access?

private void DeclareControlsAsMembers(VBComponent form) 
{ 
    var designer = form.Designer; 
    if (designer == null) 
    { 
     return; 
    } 

     // using dynamic typing here, because not only MSForms could have a Controls collection (e.g. MS-Access forms are 'document' modules). 
     foreach (var control in ((dynamic)designer).Controls) 
     { 
      var declaration = new Declaration(_qualifiedName.QualifyMemberName(control.Name), ...); 
      OnNewDeclaration(declaration); 
     } 
    } 

Проблема с этим методом является то, что, когда хозяин MS-Access, form.Designer является null, поэтому метод возвращается раньше.

dynamic листинг здесь не особо полезен, кажется, что я мог бы переходить на интерфейс UserForm, и он «просто сработает» - по крайней мере, на хосте Excel.

Но поскольку формы MS-Access не имеют конструктора (???), как мне обращаться с элементами управления с использованием итерации в форме MS-Access, учитывая код C#, который является надстройкой VBE (то есть, который может только легко получить доступ к тому, что предоставляет VBIDE API)?

+0

Какая версия ms-access это? Поскольку версии, которые я знаю, используют немного другую модель, а другую в VBE – rene

+0

@rene мой код должен работать * независимо от хост-приложения VBE *, поэтому ... все из них! –

+0

Неясно, что вы подразумеваете под «недостатком» дизайнера. Будь то формы vb.net, формы FoxPro, формы Paradox или в этом случае Access, все они работают одинаково, и у всех есть разработчики форм, и у всех есть свои собственные форматы. Итак, в течение последних 30 лет я не вижу, как формы Access или формы vb.net различаются? Как было указано, всего около 4-5 строк кода VBA для итерации коллекции forms.Controls, но вы должны открыть форму для достижения этого результата. Итак, расширяйте то, что вы подразумеваете под дизайнером формы? –

ответ

2

Вы не можете перемещать элементы управления в форме доступа , если только форма не открыта. Открытие форм, даже в режиме разработки, является дорогостоящим, поскольку элементы управления необходимо визуализировать и быть Access, связанные свойства разрешены для объектов базы данных. Существует также вопрос о субформах и под-отчетах.

Но этот код VBA займет ваш vbComponent, откройте форму (если она еще не открыта в режиме разработки), а затем верните коллекцию элементов управления из коллекции свойств vbComponent. Если форма не была открыта с самого начала, она закрывается.

Этот код довольно легко реплицировать для отчетов Access.

Function GetControls() As Access.Controls 
    Dim comp As VBIDE.VBComponent 
    Dim proj As VBIDE.VBProject 
    Dim props As VBIDE.Properties 
    Dim bCloseFormWhenDone As Boolean 
    Dim formName As String 

    Set proj = Application.VBE.ActiveVBProject 
    Set comp = proj.VBComponents("Form_Form1") 
    On Error Resume Next 
    Set props = comp.Properties 
    On Error GoTo 0 

    If props Is Nothing Then 
    bCloseFormWhenDone = True 
    'The form is not open, so open it in design mode 
    formName = Mid(comp.Name, 6) 
    Application.DoCmd.OpenForm formName, acDesign 
    End If 

    'Get the controls collection 
    Set GetControls = comp.Properties("Controls").Object 

    'Close the form if it wasn't already open 
    If bCloseFormWhenDone Then 
    Application.DoCmd.Close acForm, formName 
    End If 

End Function 
+0

Это * имеет * последнее применение ... –

+0

Нет, последнее средство будет читать двоичный файл формы из таблиц MSys: -/ – ThunderFrame

+0

С другой стороны, если надстройка охватывает тот факт, что разные хосты означают разные вещи; если он построен с помощью архитектуры подключаемого модуля, у вас может быть библиотека, специфичная для хоста, для реализации различного поведения для конкретного хоста, которое будет включать в себя способ получения деклараций DeclActionType.Control, что позволило бы решить проблему. –

0

Экспорт модулей (используя недокументированные функциональные возможности прекрасные Application.SaveAsText), и анализировать содержание. CommandButton будет выглядеть следующим образом:

Begin CommandButton 
    OverlapFlags =85 
    Left =907 
    Top =793 
    Width =3118 
    Height =1304 
    ForeColor =4210752 
    Name ="Command0" 
    Caption ="Command0" 
    OnClick ="[Event Procedure]" 
    GUID = Begin 
     0x925ed6d615e7594c83313637a6d582f4 
    End 
    GridlineColor =10921638 

    LayoutCachedLeft =907 
    LayoutCachedTop =793 
    LayoutCachedWidth =4025 
    LayoutCachedHeight =2097 
    BackColor =15123357 
    BorderColor =15123357 
    HoverColor =15652797 
    PressedColor =11957550 
    HoverForeColor =4210752 
    PressedForeColor =4210752 
    WebImagePaddingLeft =2 
    WebImagePaddingTop =2 
    WebImagePaddingRight =1 
    WebImagePaddingBottom =1 
End 

Вы можете получить значение Name собственности (и любое другое имущество вам нравится) для всех элементов управления, и даже быть в состоянии сказать, если OnClick прикрепляется к процедуре обработчика события ,

+1

См. [Это] (http://stackoverflow.com/a/29369770/5757159) сообщение для получения более подробной информации о NameMap – ThunderFrame

+0

Эй, @ Mat'sMug, просто не забывайте, что существующий код «Excel» ** действителен в Access тоже. Я использовал UserForms в Access для достижения «однократной записи, подключения в любом месте». – RubberDuck

Смежные вопросы