I have a code that places multiple nameboxes and labels on a userform. The code is very repetitive but i don't know how to create a for loop that changes the object im focusing on.
I've tried creating a loop with a variable that is included in the objects name like :
Me.Box(i).Top
For i = 1
Me.Box(i).Top = hauteur / 4
Me.Box(i).Left = (i * espace) + (i-1 * lbox)
Me.Label(i).Top = Me.Box(i).Top - 2 * hbox
Me.Label(i).Left = Me.Box(i).Left
Next i
(All my boxes are named box1 to box 7)
Here's what my code looks like :
Me.Box1.Top = hauteur / 4
Me.Box1.Left = espace
Me.Label1.Top = Me.Box1.Top - 2 * hbox
Me.Label1.Left = Me.Box1.Left
Me.Box2.Top = hauteur / 4
Me.Box2.Left = (2 * espace) + lbox
Me.Label2.Top = Me.Box2.Top - 2 * hbox
Me.Label2.Left = Me.Box2.Left
Me.Box3.Top = hauteur / 4
Me.Box3.Left = 3 * espace + 2 * lbox
Me.Label3.Top = Me.Box3.Top - 2 * hbox
Me.Label3.Left = Me.Box3.Left
etc...
I'm looking for the right syntaxe for the type of loop i'm doing !
You need to use the controls collection, which will accept a string index
for i = 1 to 7
with Me.controls("Box" & i)
.Top = hauteur / 4
.Left = espace
Me.controls("Label" & i).Top = .Top - 2 * hbox
Me.controls("Label" & i).Left = .Left
end with
next i
Related
I am trying to position an arc around a circle to show in which range our customers perform.
The sub builds an arc which has the same size as the one from the inner circle but I can't position it correctly.
I attached a picture below to demonstrate my problem.
firstang = shp.Chart.ChartGroups(1).FirstSliceAngle
radius = shp.Chart.PlotArea.Height / 2
Pi = 3.14159265358979
z = 1
j = 1
Debug.Print "Charttype: " & shp.Chart.ChartType
gradfaktor = (360 / Pi)
Breite = shp.Chart.PlotArea.Width + 2 * Abstand + 2 * Balkendicke
breitekreissegment = Balkendicke / Breite * 2
For z = 1 To shp.Chart.SeriesCollection(1).Points.Count
Set newshp = sld.Shapes.AddShape(msoShapeBlockArc, 10, 10, Breite, Breite)
x1 = shp.Chart.SeriesCollection(1).Points(z).PieSliceLocation(xlHorizontalCoordinate, xlOuterClockwisePoint)
y1 = shp.Chart.SeriesCollection(1).Points(z).PieSliceLocation(xlVerticalCoordinate, xlOuterClockwisePoint)
x2 = shp.Chart.SeriesCollection(1).Points(z).PieSliceLocation(xlHorizontalCoordinate, xlOuterCounterClockwisePoint)
y2 = shp.Chart.SeriesCollection(1).Points(z).PieSliceLocation(xlVerticalCoordinate, xlOuterCounterClockwisePoint)
newshp.Fill.ForeColor.RGB = farbe
newshp.Line.Transparency = 1
newshp.name = "B1_" & 1
DoEvents
'newshp.Height = shp.Height
DoEvents
newshp.Left = shp.Left + shp.Chart.PlotArea.Left * 0.5 - Balkendicke
newshp.Top = shp.Top + shp.Chart.PlotArea.Top * 0.5 - Balkendicke
newshp.Adjustments.Item(3) = breitekreissegment
l1 = ((x2 - x1) ^ 2 + (y2 - y1) ^ 2) ^ 0.5
alpha1 = (2 * ArcSin((l1 / (2 * radius)))) * 180 / Pi
newshp.Adjustments.Item(1) = alpha1
newshp.Adjustments.Item(2) = firstang
DoEvents
firstang = firstang + alpha1 + WinkelAbstand
Next z
chartcount = chartcount + 1
l1 = ((x2 - x1) ^ 2 + (y2 - y1) ^ 2) ^ 0.5
alpha1 = (2 * ArcSin((l1 / (2 * radius)))) * 180 / Pi
You can do something like this, just make to separate graphs.
Sub test()
Set myCht_01 = ActiveSheet.Shapes.AddChart
Set myCht_02 = ActiveSheet.Shapes.AddChart
With myCht_01
.Chart.ChartType = xlDoughnut
.Chart.SetSourceData Source:=Range("$F$3:$F$4")
.Chart.ChartGroups(1).DoughnutHoleSize = 85
.Chart.Legend.Delete
.Chart.ChartGroups(1).FirstSliceAngle = 180
Set serCol_01 = .Chart.SeriesCollection(1)
With serCol_01
.ApplyDataLabels
For Each lbl In .DataLabels
If lbl.Name = "Text S1P1" Then lbl.Text = "Nein"
If lbl.Name = "Text S1P2" Then lbl.Text = "Ja"
Next lbl
.DataLabels.ShowCategoryName = True
End With
End With
With myCht_02
.Chart.ChartType = xlDoughnut
.Chart.SetSourceData Source:=Range("$E$3:$E$4")
.Line.Visible = msoFalse
.Chart.Legend.Delete
.Chart.SeriesCollection(1).ApplyDataLabels
.Chart.ChartGroups(1).FirstSliceAngle = 270
End With
myCht_02.ScaleWidth 0.75, msoFalse, msoScaleFromMiddle
myCht_02.ScaleHeight 0.75, msoFalse, msoScaleFromMiddle
myCht_02.Fill.Visible = msoFalse
Set shpGroup = ActiveSheet.Shapes.Range(Array(myCht_01.Name, myCht_02.Name)).Group
Exit Sub
shpGroup.Delete
End Sub
Link to example graph
I'm building my first user interface in VBA on Microsoft Access.
I am trying to get the .Left variable to show up in the drop down selection (library?).
The only thing that pops up is LeftPadding, which I'm pretty sure that isn't what I need. Why am I not able to declare the Left position of the rectangles?
Is there another type of variable that I should be using to declare the position of rectangles?
My follow up issue, if I'm doing that correctly, is about a nested If statement. I'm trying to calculate whether a newly visible rectangle's position + its dimensions exceeds the Left position of an already visible rectangle, and if so, position it elsewhere.
Dim ctl As Control
For Each ctl In [Forms]![frmBuilder]
If Left(ctl.Name, 3) = "box" And Box1.Visible = True Then
If ctl.Visible = True Then
NextCaseNum = Int(Right(ctl.Name, (Len(ctl.Name)) - 3) + 1)
NextCasePosition = (ctl.lef + ctl.Width) + 1440 / 60
NextCaseName = "box" & NextCaseNum
Else
CurCaseLeft = ctl.Left
CurCaseWidth = ctl.Width
CurCaseHeight = ctl.Height
With ctl
.Top = UprightBottom - HInch
.Left = NextCasePosition
.Width = WInch
.Height = HInch
.Visible = True
End With
If CurCaseLeft + CurCaseWidth > Upright2.Left Then
With Beam1
.Top = (((5.5 + 6) * 60) + Box1.Top) / 1440
.Left = Upright1.Left
.Height = (5.5 * 60) / 1440
.Width = ((4 * 60) / 1440) + Upright2.Left - Upright1.Left
.Visible = True
End With
End If
I think the problem lies with CurCaseLeft and CurCaseWidth, because I don't know how to define them in the function due to the current box's ctl.Left not showing up.
Do I have to separate the nested If statement in to a different function and call that function from the current function?
Try to be more explicit:
Dim ctl As Control
Dim rct As Rectangle
For Each ctl In [Forms]![frmBuilder]
If Left(ctl.Name, 3) = "box" And Box1.Visible = True Then
If ctl.Visible = True Then
Set rct = ctl
NextCaseNum = Int(Right(rct.Name, (Len(rct.Name)) - 3) + 1)
NextCasePosition = (rct.Left + rct.Width) + 1440 / 60
I want to deal with the arrangement of the buttons. for example i have 10 buttons, i want that after 5 buttons the next 5 buttons will go to the nextline.
Here is the code that i have used:
For i = 1 To 10
Dim btn As New Button
btn.Width = 40
btn.Height = 30
btn.TextAlign = ContentAlignment.MiddleCenter
If i.ToString.Length = 1 Then
btn.Text = "B" & "0" & i
Else
btn.Text = "B" & i
End If
btn.Visible = True
btn.Tag = "Button" & i
Panel1.Controls.Add(btn)
If i <= 5 Then
btn.Location = New Point(10 * 1 + ((i - 1) * btn.Width), 10)
Else
btn.Location = New Point(10 * 1 + ((i - 1) * btn.Width), 10 * 1 + ((i - 1) * btn.Height))
End If
i get the wrong positioning of the buttons. kindly help me on this.
i always get this kind of position. ex:
* * * * *
*
*
*
*
*
What i want is this:
* * * * *
* * * * *
additional: How can i do it with backgroundworker...?
Assuming you are using winforms, instead of trying to position your buttons by hand, I would suggest you use a FlowLayoutPanel control instead of a straight up panel. Then you can just add them and let the panel manage their positions.
For i = 1 to 10
Dim btn As New Button
btn.Width = 40
btn.Height = 30
btn.TextAlign = ContentAlignment.MiddleCenter
If i.ToString.Length = 1 Then
btn.Text = "B" & "0" & i
Else
btn.Text = "B" & i
End If
btn.Visible = True
btn.Tag = "Button" & i
FlowLayoutPanel1.Controls.Add(btn)
Next
If you must have 5 per line (assuming your panel is wide enough), you can use SetFlowBreak:
For i = 1 to 10
'.....
FlowLayoutPanel1.Controls.Add(btn)
'Use this line if you must have only 5 buttons per line.
if i Mod 5 = 0 Then FlowLayoutPanel1.SetFlowBreak(btn, true)
Next
Try this:
If i <= 5 Then
btn.Location = New Point(10 * 1 + ((i - 1) * btn.Width), 10)
Else
btn.Location = New Point(10 * 1 + ((i - 6) * btn.Width), 10 + btn.Height)
End If
EDIT:
If you wanted to change the loop so that you wanted to multiple lines of buttons then look at this:
Dim noOfButtonsPerLine As Integer = 5
Dim buttonIndex As Integer = 0
Dim y As Integer = 10
For i = 1 To 15
Dim btn As New Button With {.Height = 40, .Width = 30}
If buttonIndex = noOfButtonsPerLine Then
buttonIndex = 1
y += btn.Height
Else
buttonIndex += 1
End If
btn.TextAlign = ContentAlignment.MiddleCenter
If i.ToString.Length = 1 Then
btn.Text = "B" & "0" & i
Else
btn.Text = "B" & i
End If
btn.Visible = True
btn.Tag = "Button" & i
Panel1.Controls.Add(btn)
btn.Location = New Point(10 * 1 + ((buttonIndex - 1) * btn.Width), y)
Next
Change the variable noofButtonsPerLine to what suits you. I've gone for 5 as per the question but you can change it and it should adapt.
I am currently programming a sheet which visualizes data sets in graphs. Because the user of this sheet will not need all the graphs, I would like to let them choose the ones needed through a UserForm. Since the amount of data sets is variable, the UserForm will have the same amount of checkboxes as there are datasets.
The Userform code is as follows.
Private Sub UserForm_Initialize()
Dim chkBoxA As MSForms.CheckBox
Dim chkBoxB As MSForms.CheckBox
Dim lblBox As MSForms.Label
Dim cnt As Control
Amount = Sheet4.Range("C4").Value 'Amount of datasets
For i = 1 To Amount
Set lblBox = Me.Controls.Add("Forms.label.1", "Label" & i)
lblBox.Caption = "Set" & i
lblBox.Left = 5
lblBox.Top = 8 + ((i - 1) * 40)
Set chkBoxA = Me.Controls.Add("Forms.CheckBox.1", "A" & i)
chkBoxA.Caption = "Graph a"
chkBoxA.Left = 55
chkBoxA.Top = 5 + ((i - 1) * 40)
Set chkBoxB = Me.Controls.Add("Forms.CheckBox.1", "B" & i)
chkBoxB.Caption = "Graph b"
chkBoxB.Left = 55
chkBoxB.Top = 20 + ((i - 1) * 40)
Next
CommandButton1.Left = 20
CommandButton1.Top = 40 + ((Amount - 1) * 40)
CommandButton1.TabIndex = Amount * 3 + 1
Me.Height = 220
Me.ScrollBars = fmScrollBarsVertical
Me.ScrollWidth = Me.InsideWidth * 9
For Each cnt In Me.Controls
If cnt.Top + cnt.Height > Me.ScrollHeight Then
Me.ScrollHeight = cnt.Top + cnt.Height + 5
End If
Next
End Sub
When the UserForm is filled in (graphs are chosen by clicking on the options), the user will press CommandButton1. An event should then be run to show the correct graph, but for the simplicity I am first testing if a MsgBox will show up. Unfortunately the MsgBox does not show up.
Private Sub CommandButton1_Click()
'Will fix this with a loop
If A1 = True Then
MsgBox ("TestA1")
End If
If B1 = True then
MsgBox ("TestB1")
End If
If A2 = True then
MsgBox ("TestA2")
End If
Unload Me
End Sub
I am stuck on this part. The checkboxes do show up on the UserForm and they are clickable, but the commandbutton only shuts down the sub (Unload Me). I would like to see the MsgBox show up when I select the corresponding option and click the commandbutton. Any help on getting this to work is appreciated!
You are referencing 'A1' in the sub, but that variable does not exitst at compile time, because you add them dynamically. What you need to do is loop the controls, to check the names. Best practice is to put the checkboxes in a frame, to be able to group them.
Add a frame to the userform and name it 'checkboxframe'
And then instead of:
For i = 1 To Amount
Set lblBox = Me.Controls.Add("Forms.label.1", "Label" & i)
lblBox.Caption = "Set" & i
lblBox.Left = 5
lblBox.Top = 8 + ((i - 1) * 40)
Set chkBoxA = Me.Controls.Add("Forms.CheckBox.1", "A" & i)
chkBoxA.Caption = "Graph a"
chkBoxA.Left = 55
chkBoxA.Top = 5 + ((i - 1) * 40)
Set chkBoxB = Me.Controls.Add("Forms.CheckBox.1", "B" & i)
chkBoxB.Caption = "Graph b"
chkBoxB.Left = 55
chkBoxB.Top = 20 + ((i - 1) * 40)
Next
you would need to do:
With Me.checkboxframe
For i = 1 To Amount
Set lblBox = .Controls.Add("Forms.label.1", "Label" & i)
lblBox.Caption = "Set" & i
lblBox.Left = 5
lblBox.Top = 8 + ((i - 1) * 40)
Set chkBoxA = .Controls.Add("Forms.CheckBox.1", "A" & i)
chkBoxA.Caption = "Graph a"
chkBoxA.Left = 55
chkBoxA.Top = 5 + ((i - 1) * 40)
Set chkBoxB = .Controls.Add("Forms.CheckBox.1", "B" & i)
chkBoxB.Caption = "Graph b"
chkBoxB.Left = 55
chkBoxB.Top = 20 + ((i - 1) * 40)
Next
End With
And to add the checkboxes to the frame, use something like:
For Each ctr In UserForm1.frame("checkboxframe").Controls
If TypeName(ctr) = "CheckBox" Then
If ctr.Value = True Then
'do something usefull here
msgbox ctr.name
End If
End If
Next ctr
The reason nothing appears is because there is no object "A1" manually defined as a variable.
To get the value of the box you Dynamically named "A1" you would have to refer to it as such:
If Me.Controls.Item("A1").Value = True then
Hope this helps!
NET developers.
I'm trying to put 20 labels on a form and place them line by line (I do this by the .Top method). I am sure there is a way I can program declaring and formatting by looping through more general code 20 times.
The below is what I've done for the first label.
Thanks in advance for help!
Dim Label1 As New Label
Me.Controls.Add(Label1)
For m = 1 To OutlookManager3.GlobalVariables.SelectedAppointmentsNo
With Label1
.Width = 512
.Height = 18
.Top = subject.Top + subject.Height + m * 6 + (m - 1) * 18 + (m - 1) * 6
.Left = 12
.Text = "label" & m
End With
Next
You should place this as the first line inside your loop:
Dim Label1 As New Label
And this as the last line insde your loop:
Me.Controls.Add(Label1)
Example 1
For m = 1 To OutlookManager3.GlobalVariables.SelectedAppointmentsNo
Dim Label1 As New Label
With Label1
.Width = 512
.Height = 18
.Top = subject.Top + subject.Height + m * 6 + (m - 1) * 18 + (m - 1) * 6
.Left = 12
.Text = "label" & m
End With
Me.Controls.Add(Label1)
Next
Example 2
For m = 1 To OutlookManager3.GlobalVariables.SelectedAppointmentsNo
Me.Controls.Add(New Label() With {.Width = 512, .Height = 18, .Top = (subject.Top + subject.Height + m * 6 + (m - 1) * 18 + (m - 1) * 6), .Left = 12, .Text = ("label" & m)})
Next
you can use your code by place declare statement inside loop
For m = 1 To OutlookManager3.GlobalVariables.SelectedAppointmentsNo
Dim Label1 As New Label
With Label1
.Width = 512
.Height = 18
.Top = subject.Top + subject.Height + m * 6 + (m - 1) * 18 + (m - 1) * 6
.Left = 12
.Text = "label" & m
End With
Me.Controls.Add(Label1)
Next
or use panel just like this but you have to place declare statement inside loop
or should make label array for future reference by
Dim label(yoursize) As Label
For m = 1 To OutlookManager3.GlobalVariables.SelectedAppointmentsNo
label(m) = new label
label(m).ID="future referece id"
With Label1
.Width = 512
.Height = 18
.Top = subject.Top + subject.Height + m * 6 + (m - 1) * 18 + (m - 1) * 6
.Left = 12
.Text = "label" & m
End With
by this you can use that next time
Me.Controls.Add(Label1)
Next