VBA를 사용하여 Excel 사용자 양식의 다중 열 목록 상자에 헤더를 추가하는 방법
워크시트 범위를 원본으로 사용하지 않고 다중 열 목록 상자에서 헤더를 설정할 수 있습니까?
다음은 목록 상자의 목록 속성에 할당된 변형 배열을 사용하는 방법입니다. 머리글은 비어 있습니다.
Sub testMultiColumnLb()
ReDim arr(1 To 3, 1 To 2)
arr(1, 1) = "1"
arr(1, 2) = "One"
arr(2, 1) = "2"
arr(2, 2) = "Two"
arr(3, 1) = "3"
arr(3, 2) = "Three"
With ufTestUserForm.lbTest
.Clear
.ColumnCount = 2
.List = arr
End With
ufTestUserForm.Show 1
End Sub
문제를 해결하기 위한 저의 접근 방식은 다음과 같습니다.
이 솔루션을 사용하려면 두 번째 ListBox 요소를 추가하고 첫 번째 요소 위에 배치해야 합니다.
다음과 같이:
그런 다음 CreateListBoxHeader 함수를 호출하여 정렬을 정확하게 하고 헤더 항목을 추가합니다.
결과:
코드:
Public Sub CreateListBoxHeader(body As MSForms.ListBox, header As MSForms.ListBox, arrHeaders)
' make column count match
header.ColumnCount = body.ColumnCount
header.ColumnWidths = body.ColumnWidths
' add header elements
header.Clear
header.AddItem
Dim i As Integer
For i = 0 To UBound(arrHeaders)
header.List(0, i) = arrHeaders(i)
Next i
' make it pretty
body.ZOrder (1)
header.ZOrder (0)
header.SpecialEffect = fmSpecialEffectFlat
header.BackColor = RGB(200, 200, 200)
header.Height = 10
' align header to body (should be done last!)
header.Width = body.Width
header.Left = body.Left
header.Top = body.Top - (header.Height - 1)
End Sub
용도:
Private Sub UserForm_Activate()
Call CreateListBoxHeader(Me.listBox_Body, Me.listBox_Header, Array("Header 1", "Header 2"))
End Sub
아니오. 목록 상자 위에 레이블을 만들어 머리글로 사용합니다.당신은 목록 상자가 바뀔 때마다 라벨을 바꾸는 것이 왕실의 고통이라고 생각할 수 있습니다.당신이 옳을 것입니다 - 그것은 고통입니다.처음 설정하는 것은 고통이지만, 변경은 말할 것도 없습니다.하지만 저는 더 좋은 방법을 찾지 못했습니다.
저는 방금 이 문제를 보고 이 해결책을 찾았습니다.RowSource가 셀 범위를 가리킬 경우 다중 열 목록 상자의 열 머리글은 RowSource 바로 위의 셀에서 가져옵니다.
여기 그림의 예를 사용하여 목록 상자 안에 기호와 이름이 제목 제목으로 나타납니다.AB1 셀에서 이름이라는 단어를 변경한 다음 VBE에서 양식을 다시 열었을 때 열 제목이 변경되었습니다.
예제는 S의 VBA 모델러용 워크북에서 제공됩니다.크리스찬 올브라이트, 그리고 나는 그가 어떻게 그의 목록 상자에 열 제목을 넣었는지 알아내려고 노력하고 있었습니다 :)
간단한 대답: 아니오.
제가 예전에 했던 일은 표제를 0행에 로드한 다음 양식을 표시할 때 ListIndex를 0으로 설정하는 것이었습니다.그런 다음 머리글이 파란색으로 강조 표시되어 머리글처럼 보입니다.ListIndex가 0으로 유지되면 양식 작업 단추가 무시되므로 이러한 값을 선택할 수 없습니다.
물론 다른 목록 항목을 선택하는 즉시 제목의 포커스가 사라지지만, 이때쯤이면 해당 항목의 작업이 완료됩니다.
이러한 방식으로 작업을 수행하면 목록 상자 위에 떠 있는 별도의 레이블로 수행하기 어렵거나 불가능한 가로 스크롤 제목을 사용할 수도 있습니다.반대로 목록 상자를 세로로 스크롤해야 하는 경우 제목이 표시되지 않습니다.
기본적으로 제가 처한 상황에서 효과가 있는 절충안입니다.
여러 열 목록 상자의 맨 위에 머리글을 표시하는 매우 쉬운 솔루션이 있습니다.기본적으로 false인 "열 제목"에 대한 속성 값을 "true"로 변경하면 됩니다.
그런 다음 데이터 범위에서 헤더를 제외한 "행 소스" 속성의 데이터 범위를 언급하고 헤더가 데이터 범위의 첫 번째 맨 위 행에 있어야 합니다. 그러면 헤더가 자동으로 선택되고 헤더가 동결됩니다.
데이터 범위가 "A1:" 데이터가 있다고 가정합니다.H100" 및 "A1:H1"의 헤더는 첫 번째 행이고 데이터 범위는 "A2:속성 "rowsource" 및 "columnheads" 속성 값에서 언급해야 하는 H100"은 참이어야 합니다.
잘 부탁드립니다.
두 개의 목록 상자(하나는 머리글용, 다른 하나는 데이터용)만 사용
헤더의 경우 - RowSource 속성을 맨 위 행으로 설정합니다.사건들!Q4:S4
데이터의 경우 - 행 소스 속성을 인시던트로 설정합니다!Q5:S10
"3-frm 특수 효과 식각"에 대한 특수 효과
CboBx가 워크시트에서 로드되지 않는 ComboBox의 헤더에 대해 다음과 같은 접근 방식을 사용하고 싶습니다(예: sql의 데이터).워크시트에서 지정하지 않는 이유는 RowSource를 작동시키는 유일한 방법은 워크시트에서 로드하는 것이라고 생각하기 때문입니다.
이것은 나에게 도움이 됩니다.
- ComboBox를 만들고 동일한 레이아웃에 하나의 행만 있는 ListBox를 만듭니다.
- 콤보 상자 바로 위에 목록 상자를 놓습니다.
- VBA에서 ListBox 행 1을 원하는 헤더로 로드합니다.
ListBoxName_Click 작업의 VBA에 다음 코드를 입력합니다.
yourComboBoxName.Activate` yourComboBoxName.DropDown`
목록 상자를 클릭하면 목록 상자의 제목이 목록 위에 있는 동안 콤보 상자가 드롭다운되고 정상적으로 작동합니다.
저는 별도의 시트를 사용하지 않고 헤더를 추가하고 모든 것을 사용자 양식에 복사할 수 있는 솔루션을 한참 찾고 있었습니다.
제 해결책은 첫 번째 행을 헤더로 사용하여 if 조건을 실행하고 아래에 추가 항목을 추가하는 것입니다.
그런 식으로:
If lborowcount = 0 Then
With lboorder
.ColumnCount = 5
.AddItem
.Column(0, lborowcount) = "Item"
.Column(1, lborowcount) = "Description"
.Column(2, lborowcount) = "Ordered"
.Column(3, lborowcount) = "Rate"
.Column(4, lborowcount) = "Amount"
End With
lborowcount = lborowcount + 1
End If
With lboorder
.ColumnCount = 5
.AddItem
.Column(0, lborowcount) = itemselected
.Column(1, lborowcount) = descriptionselected
.Column(2, lborowcount) = orderedselected
.Column(3, lborowcount) = rateselected
.Column(4, lborowcount) = amountselected
End With
lborowcount = lborowcount + 1
이 예에서 lboorder는 listbox이고 lborow count는 다음 listbox 항목을 추가할 행입니다.5열 목록 상자입니다.이상적이지는 않지만 작동하며 수평으로 스크롤해야 할 경우 "헤더"가 행 위에 유지됩니다.
제 해결책은 이렇습니다.
VBE의 속성 창을 통해 목록 상자의 행 소스를 지정하면 헤더가 팝업되지 않습니다.VBA 코드를 통해 행 소스를 정의하려고 할 때에만 헤더가 손실됩니다.
먼저 속성 창을 통해 목록 상자 행 소스를 VBE의 명명된 범위로 정의한 다음 VBA 코드에서 행 소스를 재설정할 수 있습니다.헤더는 여전히 매번 표시됩니다.
이것을 목록 개체의 고급 필터 매크로와 함께 사용하여 행 소스의 기반이 되는 다른 (필터링된) 목록 개체를 만듭니다.
이것은 나에게 효과가 있었습니다.
루나틱의 또 다른 변형은 로컬 부울 및 변경 이벤트를 사용하여 초기화 시 행을 강조 표시할 수 있지만 사용자가 선택을 변경한 후 선택을 취소하고 차단하는 것입니다.
Private Sub lbx_Change()
If Not bHighlight Then
If Me.lbx.Selected(0) Then Me.lbx.Selected(0) = False
End If
bHighlight = False
End Sub
목록 상자가 초기화되면 bHighlight 및 lbx를 설정합니다.Selected(0) = True. 헤더 행이 선택을 초기화할 수 있도록 합니다. 그 후 첫 번째 변경을 수행하면 선택이 취소되고 행이 다시 선택되지 않습니다.
목록 상자의 각 열 위(워크시트)에 레이블을 자동으로 생성하는 방법은 다음과 같습니다.
목록 상자에 가로 스크롤 막대가 없으면 작동합니다(예쁘지는 않습니다!
Sub Tester()
Dim i As Long
With Me.lbTest
.Clear
.ColumnCount = 5
'must do this next step!
.ColumnWidths = "70;60;100;60;60"
.ListStyle = fmListStylePlain
Debug.Print .ColumnWidths
For i = 0 To 10
.AddItem
.List(i, 0) = "blah" & i
.List(i, 1) = "blah"
.List(i, 2) = "blah"
.List(i, 3) = "blah"
.List(i, 4) = "blah"
Next i
End With
LabelHeaders Me.lbTest, Array("Header1", "Header2", _
"Header3", "Header4", "Header5")
End Sub
Sub LabelHeaders(lb, arrHeaders)
Const LBL_HT As Long = 15
Dim T, L, shp As Shape, cw As String, arr
Dim i As Long, w
'delete any previous headers for this listbox
For i = lb.Parent.Shapes.Count To 1 Step -1
If lb.Parent.Shapes(i).Name Like lb.Name & "_*" Then
lb.Parent.Shapes(i).Delete
End If
Next i
'get an array of column widths
cw = lb.ColumnWidths
If Len(cw) = 0 Then Exit Sub
cw = Replace(cw, " pt", "")
arr = Split(cw, ";")
'start points for labels
T = lb.Top - LBL_HT
L = lb.Left
For i = LBound(arr) To UBound(arr)
w = CLng(arr(i))
If i = UBound(arr) And (L + w) < lb.Width Then w = lb.Width - L
Set shp = ActiveSheet.Shapes.AddShape(msoShapeRectangle, _
L, T, w, LBL_HT)
With shp
.Name = lb.Name & "_" & i
'do some formatting
.Line.ForeColor.RGB = vbBlack
.Line.Weight = 1
.Fill.ForeColor.RGB = RGB(220, 220, 220)
.TextFrame2.TextRange.Characters.Text = arrHeaders(i)
.TextFrame2.TextRange.Font.Size = 9
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = vbBlack
End With
L = L + w
Next i
End Sub
한 번 해보세요.저는 이 포럼에 처음 참가하는 사람이지만 과거에 이 사이트에서 많은 도움을 받았기 때문에 저에게 도움이 되는 무언가를 제안하고 싶었습니다.이것은 본질적으로 위의 변형이지만, 저는 그것이 더 간단하다는 것을 알았습니다.
사용자 양식에 붙여넣기만 하면 됩니다.사용자 양식 코드의 섹션을 초기화합니다.사용자 양식에 목록 상자가 이미 있거나 이 코드 위에 동적으로 작성되어 있어야 합니다.또한 배열은 제목 목록입니다(아래 "Header1", "Header2" 등).사용자의 제목으로 대체합니다.그러면 이 코드는 목록 상자의 열 너비를 기준으로 상단에 제목 표시줄을 설정합니다.죄송합니다. 스크롤이 안 됩니다. 고정 라벨입니다.
더 많은 고위 코더 - 이 문제에 대해 자유롭게 의견을 제시하거나 개선하십시오.
Dim Mywidths As String
Dim Arrwidths, Arrheaders As Variant
Dim ColCounter, Labelleft As Long
Dim theLabel As Object
[Other code here that you would already have in the Userform_Initialize section]
Set theLabel = Me.Controls.Add("Forms.Label.1", "Test" & ColCounter, True)
With theLabel
.Left = ListBox1.Left
.Top = ListBox1.Top - 10
.Width = ListBox1.Width - 1
.Height = 10
.BackColor = RGB(200, 200, 200)
End With
Arrheaders = Array("Header1", "Header2", "Header3", "Header4")
Mywidths = Me.ListBox1.ColumnWidths
Mywidths = Replace(Mywidths, " pt", "")
Arrwidths = Split(Mywidths, ";")
Labelleft = ListBox1.Left + 18
For ColCounter = LBound(Arrwidths) To UBound(Arrwidths)
If Arrwidths(ColCounter) > 0 Then
Header = Header + 1
Set theLabel = Me.Controls.Add("Forms.Label.1", "Test" & ColCounter, True)
With theLabel
.Caption = Arrheaders(Header - 1)
.Left = Labelleft
.Width = Arrwidths(ColCounter)
.Height = 10
.Top = ListBox1.Top - 10
.BackColor = RGB(200, 200, 200)
.Font.Bold = True
End With
Labelleft = Labelleft + Arrwidths(ColCounter)
End If
Next
아쉽습니다.엑셀이 헤더를 잡을 수 있도록 중간 시트를 사용하여 데이터를 넣어야 합니다.하지만 저는 워크북이 숨겨져 있기를 원했습니다. 그래서 제가 행 소스를 어떻게 해야 했는지를 보여드리겠습니다.이 코드의 대부분은 단지 상황을 설정하는 것일 뿐입니다.
Sub listHeaderTest()
Dim ws As Worksheet
Dim testarr() As String
Dim numberOfRows As Long
Dim x As Long, n As Long
'example sheet
Set ws = ThisWorkbook.Sheets(1)
'example headers
For x = 1 To UserForm1.ListBox1.ColumnCount
ws.Cells(1, x) = "header" & x
Next x
'example array dimensions
numberOfRows = 15
ReDim testarr(numberOfRows, UserForm1.ListBox1.ColumnCount - 1)
'example values for the array/listbox
For n = 0 To UBound(testarr)
For x = 0 To UBound(testarr, 2)
testarr(n, x) = "test" & n & x
Next x
Next n
'put array data into the worksheet
ws.Range("A2").Resize(UBound(testarr), UBound(testarr, 2) + 1) = testarr
'provide rowsource
UserForm1.ListBox1.RowSource = "'[" & ws.Parent.Name & "]" & ws.Name & "'!" _
& ws.Range("A2").Resize(ws.UsedRange.Rows.Count - 1, ws.UsedRange.Columns.Count).Address
UserForm1.Show
End Sub
스크롤의 경우 전체 목록 상자를 왼쪽과 오른쪽으로 이동하는 시뮬레이션 스크롤 막대를 만드는 것이 좋습니다.
- 가로 스크롤 막대가 나타나지 않도록 목록 상자를 전체 너비로 설정합니다(사용 가능한 공간보다 작거나 스크롤할 필요가 없음).
- 사용 가능한 수평 공간과 일치하도록 .left 및 .width를 사용하여 하단에 스크롤 막대 컨트롤 추가(너무 넓지 않은 목록 상자)
- 확장 목록 상자의 너비와 사용 가능한 수평 공간의 너비 간의 차이로 스크롤해야 하는 거리 계산
- .Min을 0으로 설정하고 .스크롤해야 하는 최대 양
- set.Large 슬라이더 막대를 더 넓게 변경합니다(총 스팬의 절반만 사용할 수 있었습니다).
이렇게 하려면 목록 상자가 해당 보기 공간 아래를 통과하고 양식의 수평 프레임을 유지할 수 있도록 보기 공간의 왼쪽과 오른쪽을 프레임으로 가릴 수 있어야 합니다.목록 상자를 덮을 프레임을 얻는 것은 쉽게 작동하지 않는 것처럼 보이기 때문에 이것은 어려운 것으로 밝혀졌습니다.저는 그 시점에서 포기했지만 이 단계들을 후손들을 위해 공유하고 있습니다.
작동하는 것처럼 보이는 방법을 찾았지만 검색이나 범위를 변경할 때마다 동적으로 범위를 삭제하면 코드가 복잡해질수록 더 복잡해질 수 있습니다.
스프레드시트:
A B C
1 LName Fname
2 Smith Bob
set rng_Name = ws_Name.range("A1", ws_Name.range("C2").value
lstbx.Main.rowsource = rng_Name.Address
그러면 머리글이 목록 상자에 로드되고 스크롤할 수 있습니다.
가장 중요한 것은 데이터를 반복하고 있는데 범위가 비어 있는 경우 목록 상자에서 헤더를 올바르게 로드하지 않으므로 "일치"를 고려하지 않아도 된다는 것입니다.
목록 상자의 맨 위에 레이블을 추가하고 변경이 필요한 경우 프로그래밍 방식으로 변경해야 하는 것은 레이블뿐입니다.
언급URL : https://stackoverflow.com/questions/657498/how-to-add-headers-to-a-multicolumn-listbox-in-an-excel-userform-using-vba
'programing' 카테고리의 다른 글
Oracle 19의 최대 절전 모드 방언 (0) | 2023.06.23 |
---|---|
소스 트리를 밀어넣으려고 할 때 "태그가 이미 존재하기 때문에 업데이트가 거부되었습니다." (0) | 2023.06.23 |
Excel 셀 텍스트가 다음 빈 셀로 표시되지 않음 (0) | 2023.06.23 |
일치하는 값을 포함하는 해시 키를 찾는 방법 (0) | 2023.06.23 |
Mongoose 인덱스를 만들지 않음 (0) | 2023.06.23 |