Maak Form @ Runtime MET ListView (en vul deze)

Status
Niet open voor verdere reacties.

dprod

Gebruiker
Lid geworden
2 jun 2010
Berichten
80
Beste mede-forum leden,

Ik heb voor mijn gevoel het gehele internet afgezocht naar DE oplossing, en telkens leek deze binnen handbereik maaaaaaaaar... HELAAS!

Wat ik wil is een "Form maken at Runtime", zodat ik niet 100 verschillende Forms hoef aan te maken in mijn VBProject. De UserForm wordt d.m.v. code aangepast met toegewezen variabelen.
Dit alles is geen probleem, het probleem zit 'm in de ListView die ik wil gebruiken in mijn Form.
Bij het vullen hiervan krijg ik elke keer de melding: "Fout 394 tijdens uitvoering: Property is write-only".
Als ik exact dezelfde Form maak in de VBE, dan lukt het wel om de ListView te vullen en krijg ik dus GEEN foutmelding.

Voor een beter beeld, eerst de CODE om het form met de juiste variabelen te maken:
Code:
Private Sub CallTheForm()
    MakeUserForm "Personeelsgegevens", "Medewerkers", clsIni.IBUITENMDW, "101;60;60;100"
End Sub

Tweede CODE, het maken van de UserForm:
Code:
Public Sub MakeUserForm(frmName As String, pageName As String, strSelection As String, ColumnWidth As String)
    Dim TempForm As Object
    Dim NewMultiPage As MSForms.MultiPage
    Dim NewLabel As MSForms.Label
    Dim NewListView As MSComctlLib.ListView
    Dim NewButton As MSForms.CommandButton
Application.VBE.MainWindow.Visible = False
Set TempForm = ThisWorkbook.VBProject.VBComponents.Add(3)
    With TempForm
        .Properties("Caption") = frmName
        .Properties("Width") = 369.75
        .Properties("Height") = 283.5
    End With

Set NewMultiPage = TempForm.designer.Controls.Add("Forms.MultiPage.1")
    NewMultiPage.Pages.Remove (1)
    With NewMultiPage
        .Height = 228
        .Width = 354
        .Left = 6
        .Top = 6
        .Pages(0).Caption = pageName
    End With

Set NewLabel = NewMultiPage.Pages(0).Controls.Add("Forms.Label.1")
    With NewLabel
        .Height = 2
        .Left = 12
        .Top = 11.05
        .Width = 252
        .SpecialEffect = fmSpecialEffectSunken
    End With

Set NewLabel = NewMultiPage.Pages(0).Controls.Add("Forms.Label.1")
    With NewLabel
        .Caption = "Databasegegevens"
        .Height = 12
        .Left = 270
        .Top = 6
        .Width = 72.05
    End With

Set NewLabel = NewMultiPage.Pages(0).Controls.Add("Forms.Label.1")
    With NewLabel
        .Caption = "De volgende personen zijn in opgenomen in uw personeelsbestand:"
        .Height = 12
        .Left = 8
        .Top = 24
        .Width = 330
    End With

Set NewListView = NewMultiPage.Pages(0).Controls.Add("MSComctlLib.ListViewCtrl.2")
    With NewListView
        .BorderStyle = ccFixedSingle
        .Gridlines = True
        .Height = 138
        .Left = 6
        .Sorted = True
        .Top = 36
        .Width = 336
        .FullRowSelect = True
    End With

Set NewButton = NewMultiPage.Pages(0).Controls.Add("Forms.CommandButton.1")
    With NewButton
        .Caption = "Wijzigen"
        .Height = 19
        .Left = 6
        .Top = 180
        .Width = 72
    End With

Set NewButton = NewMultiPage.Pages(0).Controls.Add("Forms.CommandButton.1")
    With NewButton
        .Caption = "Toevoegen..."
        .Height = 19
        .Left = 192
        .Top = 180
        .Width = 72
    End With

Set NewButton = NewMultiPage.Pages(0).Controls.Add("Forms.CommandButton.1")
    With NewButton
        .Caption = "Verwijderen"
        .Height = 19
        .Left = 270
        .Top = 180
        .Width = 72
    End With

Set NewButton = TempForm.designer.Controls.Add("Forms.CommandButton.1")
    With NewButton
        .Caption = "OK"
        .Default = True
        .Height = 19
        .Left = 288
        .Top = 240
        .Width = 72
    End With

    Dim strUsedPath As String
If clsIni.CLOCAL Then strUsedPath = clsIni.LOCALDIR
If clsIni.CSERVER Then strUsedPath = clsIni.CSERVERDIR
strUsedPath = strUsedPath & "\" & clsIni.CINPUTDIR & "\" & strSelection
    GetValuesFromDBFile strUsedPath, NewListView, ColumnWidth
    NewListView.View = lvwReport
    If NewListView.ListItems.Count = 0 Then
        frmPGEGEVENS.btnVERWIJDEREN.Enabled = False
        frmPGEGEVENS.btnWIJZIGEN.Enabled = False
    End If
VBA.UserForms.Add(TempForm.Name).Show
ThisWorkbook.VBProject.VBComponents.Remove TempForm
End Sub

Derde CODE, om het database-bestand te openen en uit te lezen:
Code:
Public Function GetValuesFromDBFile(FileToRead As String, _
                                    objToFill As Object, _
                                    ColumnWidth As String)
    Dim FileNum As Integer
    Dim strTmp As String
    Dim aTmp() As String
    Dim lRow As Long
Close
    FileNum = FreeFile
Open FileToRead For Input As #FileNum
While Not EOF(FileNum)
    Line Input #FileNum, strTmp
    aTmp = Split(strTmp, ";")
    WriteValuesToDBObject aTmp, lRow, objToFill, ColumnWidth
    lRow = lRow + 1
Wend
Close
End Function

Vierde CODE, om elke regel in het database-bestand te schrijven in de ListView:
Code:
Private Sub WriteValuesToDBObject(strValue() As String, _
                                rowID As Long, _
                                objToFill As Object, _
                                ColumnWidth As String)
Dim i As Integer
Dim objListItem As Object
Dim aColumnWidth() As String
aColumnWidth = Split(ColumnWidth, ";")
'eerste row in database zijn column values...
If rowID = 0 Then
    For i = 0 To UBound(strValue)
        objToFill.ColumnHeaders.Add , , strValue(i), aColumnWidth(i)
    Next i
Else
'alles daarna is input voor de ListView...
     For i = 0 To UBound(strValue)
        If i = 0 Then
            [COLOR="red"]Set objListItem = objToFill.ListItems.Add(, , strValue(i))[/COLOR] 'FOUTMELDING!
        Else
            objListItem.SubItems(i) = strValue(i)
        End If
    Next i
End If
End Sub

Iemand enig idee hoe ik mijn probleem kan oplossen?
Nogmaals... als ik in designtime het Form maak en dan de Derde & Vierde CODE gebruik werkt het wel, het zit 'm dus waarschijnlijk in code bij het maken van de ListView.
Alvast heel veel dank!

Groeten,
dProd

Tags: UserForm Runtime ListView VBA Excel MSComctlLib.ListView write-only property
 
Laatst bewerkt:
OPGELOST

Ik heb de code die de ListView moet vullen weg laten schrijven in de UserForm_Initialize procedure.
Wanneer de Form opgeroepen wordt, wordt de boel geïnitialiseerd en werkt het wel!

extra stukje CODE:
Code:
    Dim strCode As String
strCode = "Private Sub UserForm_Initialize()" & vbCrLf
strCode = strCode & "    Dim strUsedPath As String" & vbCrLf
strCode = strCode & "If clsIni.CLOCAL Then strUsedPath = clsIni.LOCALDIR" & vbCrLf
strCode = strCode & "If clsIni.CSERVER Then strUsedPath = clsIni.CSERVERDIR" & vbCrLf
strCode = strCode & "strUsedPath = strUsedPath & ""\"" & clsIni.CINPUTDIR & ""\" & strDBFile & vbCrLf
strCode = strCode & "    GetValuesFromDBFile strUsedPath, Me.ListView1" & vbCrLf
strCode = strCode & "    Me.ListView1.View = lvwReport" & vbCrLf
strCode = strCode & "    If Me.ListView1.ListItems.Count = 0 Then" & vbCrLf
strCode = strCode & "        Me.btnVerwijderen.Enabled = False" & vbCrLf
strCode = strCode & "        Me.btnWijzigen.Enabled = False" & vbCrLf
strCode = strCode & "    End If" & vbCrLf
strCode = strCode & "Application.Cursor = xlDefault" & vbCrLf
strCode = strCode & "End Sub"
With ThisWorkbook.VBProject.VBComponents(TempForm.Name).CodeModule
    .insertlines .CountOfLines + 1, strCode
End With

:thumb:

Groeten,
dProd
 
Het lijkt me helemaal niet verkeerd als je je eens grondig verdiept in wat een userform nu precies is. Een runtime userform is een teken van verlegenheid/onwetendheid van de programmeur.
Te oordelen aan de code die je geplaatst hebt is er nl. geen enkele variatie tussen de userforms. De enige variatie bestaat uit de inhoud van een listbox.
Je had niet ver hoeven zoeken (bijv. officeforums; Excel Tips en Trucs) om te zien dat je een listbox en een combobox altijd in de initialize gebeurtenis van een userform vult.
De zin van een multipage in jouw userform ontgaat me ook volledig.

Om een listbox te vullen:

Code:
Private Sub Userform_Initialize()
  open "E:\OF\voorbeeld.txt" for input as #1
    sn=split(Input(LOF(1),#1),vbcrlf)
  close $1
  
'  als het bestand maar 1 kolom heeft
  Listbox1.list=sn

' als het bestand multidimensioneel is

  for j=0 to ubound(sn)
    for jj=0 to ubound(sn,jj)
      Listbox1.List(j,jj)=sn(j,jj)
    next
  next
End Sub
 
Laatst bewerkt:
Beste snb,

Ik begrijp je redenatie, echter verwar je de Listbox/Combobox met een ListView (welke ik bedoel).
Uiteraard ben ik op de hoogte van een UserForm_Initialize procedure.
Sterker nog, mijn mainOPTIONS Form wordt volledig gevuld door de UserForm_Initialize procedure welke alles via mijn iniClass uit een config.ini bestand leest.

Ik gebruik een ListBox waarin diverse personeelsbestanden te selecteren zijn..
Bijv. Inhuur1, Inhuur2, Inhuur3, Inhuur4.
Nu is het zo dat de databasegegevens van het betreffende personeelsbestand variërende kolommen bevat (alleen Naam, pers.nr of ook leidinggevende, contract e.d.).
De ListView moet hier dus automatisch aan worden aangepast (columnHeaders/ColumnWidths).
Zoals je dus zal begrijpen is een ListView totaal niet te vergelijken met een ListBox.

Een ListView staat overigens ook niet tussen de standaard besturingselementen.
Op internet zijn helaas weinig tutorials te vinden over ListViews (de bekendste ListView in Windows is eigenlijk wel de Windows Verkenner :))
Ieder geval bedankt voor je interesse/moeite!

Groeten,
dProd
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan