juweee
Goto Top

Excel VBA: Horizontal Labels mit automatischer Breite

Hallo,

da mir das Thema mit den Überschriften in der Listbox so garnicht gefällt, möchte ich für jeden Spaltenüberschrift ein Label dynamisch über die Listbox setzen. idelalerweise ist das jeweilige label so breit wie die Spalte darunter bzw. die Spalte so breit wie das Label, was schon mal recht gut funktioniert.
Irgendwie steh ich aber gerade voll auf der Leitung wie ich zum einen die Labels nebeneinander bekomme und warum das blöde Teil das Objekt newLabel nicht kennt, während Listbox kein Thema ist.

Option Explicit

Private Sub UserForm_Initialize()
    
    Dim oWks As Worksheet, i As Integer
    
    With Me.ComboBox6
        For Each oWks In ThisWorkbook.Sheets
           .AddItem oWks.Name
        Next
       .ListIndex = 0
       .SetFocus
       .SelStart = 0
       .SelLength = Len(.Text)
    End With
    
End Sub

Private Sub ComboBox6_Change()

    Dim objDic As Object, newLabel As Object, i As Integer, selSheet As String, lngZ As Long, lCol As Long, lRow As Long
        
    With Me.ComboBox6
        Sheets(.Value).Activate
        selSheet = ComboBox6.Value
        lRow = Cells(Rows.Count, 1).End(xlUp).Row
        lCol = Cells(1, 256).End(xlToLeft).Column
    End With

    Set objDic = CreateObject("Scripting.Dictionary")  
 
    For i = 1 To 5
        For lngZ = 2 To Cells(Rows.Count, 1).End(xlUp).Row
            objDic(Cells(lngZ, i).Value) = 0
        Next
     
        With Me.Controls("ComboBox" & i)  
            .List = objDic.Keys
            .ListIndex = 0
            .SetFocus
            .SelStart = 0
            .SelLength = Len(.Text)
        End With
        
        objDic.RemoveAll
    Next
              
    For i = 1 To 10
        Set newLabel = UserForm.Controls.Add("Forms.Label.1", "" & i, True)  
        With newLabel
            .Caption = Worksheets(selSheet).Cells(1, i + 1)
            .Left = 138
            .Top = 18
            AutofitWidths
        End With
    Next
        
    With Me.Controls("Listbox")  
        .ColumnCount = lCol
        .ColumnHeads = False
        .RowSource = Sheets(selSheet).Range(Cells(2, 1), Cells(lRow, lCol)).Address
        AutofitWidths
    End With
      
End Sub

Private Sub AutofitWidths()
    
Dim Row As Long, Col As Long
Dim ColWidth As String, MaxWidth As Double

Label.Visible = False
Label.WordWrap = False
Label.AutoSize = True

For Row = 0 To ListBox.ColumnCount - 1
    MaxWidth = 0
    For Col = 0 To ListBox.ListCount - 1
        Label.Caption = ListBox.Column(Row, Col) & ",,,"  
        If MaxWidth < Label.Width Then
            MaxWidth = Label.Width
        End If
    Next Col
    ColWidth = ColWidth & CLng(MaxWidth + 1) & ";"  
Next Row
ListBox.ColumnWidths = ColWidth
newLabel.Width = ColWidth

    
End Sub

Über einen Tipp würde ich mich sehr freuen, auch über einen Ansatz wie ich die Ausgabe in der Listbox mit der Auswahl in den Comboboxen filtern kann.

LG
Juwee

Content-Key: 272438

Url: https://administrator.de/contentid/272438

Printed on: April 23, 2024 at 13:04 o'clock

Mitglied: 114757
114757 May 20, 2015 at 12:30:37 (UTC)
Goto Top
Moin.

1.) Du setzt den Parameter .Left immer auf den selben Wert, also sind die Labels alle übereinander positioniert.

2.) ist die Variable newlabel in der Prozedur AutoFitWidths nicht sichtbar, weil sie ja in der anderen Prozedur deklariert wurde. Entweder du deklarierst sie außerhalb der Prozeduren als Public Variable oder du übergibst das Objekt als Parameter an die Sub AutoFitWidths.

Gruß jodel32
Member: Juweee
Juweee May 20, 2015 at 12:56:18 (UTC)
Goto Top
OK, zumindest hab ich mit dem Tipp der globalen Variable schon mal fest stellen dürfen, daß das so nicht funktioniert, da in AutoFit ja die Werte für die Spalten zusammengesetzt werden und mit ; getrennt ...
Wie wäre im besten Fall ein anderer Ansatz?
Das mit dem nebeneinander platzieren erschließt sich mir nicht so ganz ... Hab so Sachen versucht wie .Left = 138 + (i * 50), aber leider erfolglos. Die Labels werden zwar nebeneinander dargestellt, überlappen aber um 50%

Ich würde ja ColumnHeads = True setzen, aber dann habe ich nur Spalte A, Spalte B, ... usw. drin stehen

LG Juwee
Mitglied: 114757
Solution 114757 May 20, 2015 updated at 13:35:53 (UTC)
Goto Top
Zitat von @Juweee:
Wie wäre im besten Fall ein anderer Ansatz?
Habe ich doch oben geschrieben, die Variable als Parameter an die Sub übergeben !

Sub AutoFitWidths(ByRef objLabel)
'....   
End Sub
und dann so aufrufen:
AutoFitWidths newlabel

Das mit dem nebeneinander platzieren erschließt sich mir nicht so ganz ... Hab so Sachen versucht wie .Left = 138 + (i *
50), aber leider erfolglos. Die Labels werden zwar nebeneinander dargestellt, überlappen aber um 50%

Ich würde ja ColumnHeads = True setzen, aber dann habe ich nur Spalte A, Spalte B, ... usw. drin stehen
Dafür müssen im Range von .RowSource in der ersten Zeile die Überschriften stehen.

Die Breite des Labels kannst du ja nach AutoFit wieder Abfragen, speichern und beim nächsten Label zu Left addieren, feddich.
Member: Juweee
Juweee May 20, 2015 at 13:35:48 (UTC)
Goto Top
Die Sache mit .RowSource war dann doch entscheidend und ich kann mir das Labelgedöns wohl sparen (auch wenn's bestimmt schick gewesen wäre). Von daher Danke face-smile erstmal.
Hab jetzt allerdings das Problem, das die Spaltenbreite dem Inhalt anpasst sind. wenn sie nach dem Inhalt der Spaltenüberschriften angepasst wäre, wäre das ein bedeutender Fortschritt.

LG
Juwee
Mitglied: 114757
114757 May 20, 2015 updated at 15:19:33 (UTC)
Goto Top
Zitat von @Juweee:

Die Sache mit .RowSource war dann doch entscheidend und ich kann mir das Labelgedöns wohl sparen (auch wenn's bestimmt
schick gewesen wäre). Von daher Danke face-smile erstmal.
Hab jetzt allerdings das Problem, das die Spaltenbreite dem Inhalt anpasst sind. wenn sie nach dem Inhalt der
Spaltenüberschriften angepasst wäre, wäre das ein bedeutender Fortschritt.
Du kannst die Spaltenbreiten aber auch manuell in den Eigenschaften der Listbox festlegen. Die Eigenschaft heißt: ColumnWidths

Noch ein Grund Powershell und das DataGridView-Control zu verwenden face-wink die VBA-Forms sind da doch sehr eingeschränkt.
In Powershell steht dir das ganze Arsenal an Windows-Form Controls zur Verfügung.

@colinardo hat da mal ein paar schöne Beispiele gebracht, was damit möglich ist:
Powershell - GUI für offene Netzwerk-Sessions (net session) und offene Dateihandles (net file)