2016-05-06 12 views
2

Ich habe ein Verfahren, bei dem ein VBComponent gegeben, ich habe die .Designer und von dort aus zugreifen kann, die .Controls Kollektion:Wie kann ich die Steuerelemente eines MS-Access-Formulars iterieren?

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); 
     } 
    } 

Das Problem bei dieser Methode ist, dass, wenn die Host-MS-Access ist, form.Designer ist null, so dass die Methode früh zurückkehrt.

Die dynamic Besetzung hier ist nicht besonders nützlich, es scheint, ich könnte Casting zu einem UserForm Schnittstelle und es würde "einfach funktionieren" - zumindest in einem Excel-Host.

Aber da MS-Access Formulare keinen Designer (???) haben, wie gehe ich über Iteration Kontrollen auf einem MS-Access-Formular, gegeben C# -Code, der ein VBE-Add-in ist nur leicht zugänglich, was auch immer die VBIDE API zur Verfügung stellt)?

+0

Welche Version von ms-access ist das? Da die Versionen, die ich kenne, ein etwas anderes Modell verwenden als das in VBE – rene

+0

@rene, muss mein Code funktionieren * unabhängig von der VBE-Host-Anwendung *, also ... alle 'em! –

+0

Es ist nicht klar, was Sie unter "Mangel" eines Designers verstehen. Sei es vb.net Formen, FoxPro Formen, Paradox Formen, oder in diesem Fall Access, sie alle arbeiten sehr ähnlich und alle haben Form Designer und alle haben ihre eigenen Formate. Also, in den letzten 30 Jahren sehe ich nicht, wie Access oder vb.net Formulare anders sind? Wie bereits erwähnt, werden nur etwa 4-5 Zeilen VBA-Code verwendet, um die forms.Controls-Auflistung zu durchlaufen, aber Sie müssen das Formular öffnen, um dieses Ergebnis zu erzielen. Erweitern Sie also, was Sie unter Formular-Designer verstehen? –

Antwort

2

Sie können die Steuerelemente für ein Access-Formular nicht iterieren, außer das Formular geöffnet ist. Das Öffnen von Formularen, selbst im Entwurfsmodus, ist teuer, da die Steuerelemente gerendert werden müssen. Da sie gebunden sind, werden die gebundenen Eigenschaften in Datenbankobjekte aufgelöst. Es gibt auch das Problem von Unterformularen und Unterberichten.

Aber dieser VBA-Code nimmt Ihre vbComponent, öffnen Sie das Formular (wenn es nicht bereits geöffnet ist, im Entwurfsmodus), und geben Sie dann die Steuerelementauflistung aus der Eigenschaftensammlung vbComponent zurück. Wenn das Formular zu Beginn nicht geöffnet war, ist es geschlossen.

Dieser Code ist relativ einfach für Access Reports zu replizieren.

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

Das * hat * ein letzter Ausweg zu sein ... –

+0

Nein, der letzte Ausweg wäre das Lesen des Formulars binäre aus den MSys-Tabellen: -/ – ThunderFrame

+0

Auf der anderen Seite, wenn das Add-In umfasst die Tatsache, dass verschiedene Hosts anders Dinge; Wenn es mit einer Plug-in-Architektur erstellt wird, können Sie eine hostspezifische Bibliothek verwenden, um verschiedene hostspezifische Verhaltensweisen zu implementieren, zu denen auch die Deklaration von "DeclarationType.Control" -Deklarationen gehört, die das Problem lösen. –

0

Export der Module (die schöne Application.SaveAsText undokumentierte-Funktionalität) und den Inhalt analysieren. Ein CommandButton würde wie folgt aussehen:

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 

Sie können den Wert der Name Eigenschaft abrufen (und andere Eigenschaft, die Sie mögen) für alle Steuerelemente, und sogar in der Lage sein zu sagen, ob OnClick zu einer Event-Handler Prozedur angebracht ist .

+1

Siehe [this] (http://Stackoverflow.com/a/29369770/5757159) Post für Details auf NameMap – ThunderFrame

+0

Hey @ Mat'sMug, nur nicht vergessen, dass die vorhandene "Excel" -Code ** ist ** gültig in Access auch. Ich habe UserForms in Access verwendet, um "Einmal schreiben, überall einstecken" zu erhalten. – RubberDuck

Verwandte Themen