Dynamic labelling of shapes - vba

I am creating shapes within an For-loop and I want each shape having a different name. Therefore, the Shape in Set Shape = ... in each iteration should have Shape replaced by a dynamic variable.
If I place shapes via Set Shape = w.Shapes.AddShape(msoShapeRectangle, 10,10,10,10) how can I have Shape (the name of the shape) be dynamic e.g. Set Cells(1 + i, 1) = w.Shapes.AddShape(msoShapeRectangle, 10,10,10,10) ... so that each shape has a different name. I also tried Shape.Name = which does not seem to have the same effect as setting the name while creating the shape.
I assign a name for each shape which I create within the loop:
Shape.Name = Cells(GanttStartRow + i, 1) & Cells(GanttStartRow + i, 2)
I set the connector via
Set conn = w.Shapes.AddConnector(msoConnectorElbow, 1, 1, 1, 1)
conn.ConnectorFormat.BeginConnect D, 1
conn.ConnectorFormat.EndConnect WP, 1 ... but receive a "type mismatch" error.

Assuming ws is the worksheet you are working with:
Dim s As Shape, i as integer
for i = 1 to 5
Set s = ws.Shapes.AddShape(msoShapeRectangle, 50 + i * 120, 200, 100, 100)
s.Name = "MyShapeName" & i
next i
You can later access the shapes by name:
For i = 1 To 5
Set s = ws.Shapes("MyShapeName" & i)
s.Fill.BackColor.RGB = RGB(0, 255 - i * 50, i * 50)
s.BackgroundStyle = i
Next i
However, an alternative is to loop over all shapes:
For Each s In ws.Shapes
Dim i As Integer
if left(s.Name, 1, 11) = "MyShapeName" then
i = Val(Mid(s.Name, 12))
s.Top = s.Top + i * 4
end if
Next s

Related

How do I properly add items in a multilistbox?

I'm using vba to fetch equipment numbers and their corresponding information and putting them in a listbox. A user will enter in the equipment number they want and excel will fetch the info. However, when I click my 'Get Data' button the first time it works ok. When i do it the second time for another equipment number I get the message "Could not set the List property. Invalid property array index." Here's my code:
Dim value As Long
Public i As Integer
Private Sub GetDataButton_Click()
Dim num As Variant
value = EquipmentNumber.value
For Each num In Sheets("S1 Cvtg Eqt List").Range(Range("B1"), Range("B1").End(xlDown))
If num = value Then
MWOList.AddItem (num)
MWOList.List(i, 1) = (num.Offset(0, 1))
MWOList.List(i, 2) = (num.Offset(0, 2))
MWOList.List(i, 3) = (num.Offset(0, 3))
MWOList.List(i, 4) = (num.Offset(0, 4))
MWOList.List(i, 5) = (num.Offset(0, 5))
i = i + 1
End If
Next num
i = i + 1
End Sub
Try below, please note that I had changed not only "i" declaration, and value to public, but also the List column position starts from 0, so if this is 6 element table, then switch it back.
The reason you had error was in fact another "i" iteration "i=i+1" after the loop, the list rows also start from 0, therefore you added 2nd index, and tried to insert it on the third position.
Public value As Long
Public i As Integer
Private Sub GetDataButton_Click()
Dim num As Variant
value = EquipmentNumber.value
For Each num In Sheets("S1 Cvtg Eqt List").Range(Range("B1"), Range("B1").End(xlDown))
If num = value Then
i = MWOList.ListCount 'set i to available space
MWOList.AddItem
MWOList.List(i, 0) = (num.Offset(0, 1))
MWOList.List(i, 1) = (num.Offset(0, 2))
MWOList.List(i, 2) = (num.Offset(0, 3))
MWOList.List(i, 3) = (num.Offset(0, 4))
MWOList.List(i, 4) = (num.Offset(0, 5))
End If
Next num
EquipmentNumber = ""
End Sub

Min function not working properly in VBA

I'm working on a macro right now and it's producing weird results. The part that is specifically not working is a Min function.
a1RowTemp1 = a1Row
For i = 0 To diff1
intercept = Application.WorksheetFunction.intercept(a(),c())
LinReg1 = (slope * Cells(a1RowTemp1, 1)) + intercept
difference1 = Worksheets("GF9").Cells(a1RowTemp1, 2) - LinReg1
e(i) = difference1
a1RowTemp1 = a1RowTemp1 + 1
Next i
a2RowTemp2 = a2Row
For i = 0 To diff2
intercept2 = Application.WorksheetFunction.intercept(b(), d())
LinReg2 = (slope2 * Cells(a2RowTemp2, 1)) + intercept2
difference2 = Worksheets("GF9").Cells(a2RowTemp2, 2) - LinReg2
f(i) = difference2
a2RowTemp2 = a2RowTemp2 + 1
Next i
Worksheets("Chart").Cells(currentRow, 12) = Application.Max(e())
Worksheets("Chart").Cells(currentRow, 13) = Application.Min(e())
Worksheets("Chart").Cells(currentRow, 25) = Application.Max(f())
Worksheets("Chart").Cells(currentRow, 26) = Application.Min(f())
In the bottom of the code it stores the difference1 and difference2 values in arrays e() and f(). When I use the functions max/min the macro only outputs the correct values for the max functions. I suspect this has something to do with my incorrectly using the arrays.
If e is one dimensional array you should be able to write
Application.WorksheetFunction.Min(e)
Example:
Option Explicit
Public Sub TEST()
Dim e()
e = Array(3, 4, 2, 5)
MsgBox Application.WorksheetFunction.Min(e)
End Sub
If you are still getting the wrong values you need to step though with F8 and check the values being assigned to e in the loop are the expected ones.
You've omitted the declaration and dimensioning of the e and f array. This was an important factor in your problem.
When you declared your e and f as long or double arrays, they were instantiated with zero values.
Dim v() As Double, i As Long
ReDim v(5) '<~~ all zero values
For i = LBound(v) To UBound(v) - 1 '<~~fill all but the last one
v(i) = i + 10
Next i
Debug.Print Application.Min(v) 'zero as v(5) is zero
If you want to ignore array elements that you have not assigned values to, declare the arrays as a variant type.
Dim v() As Variant, i As Long
ReDim v(5) '<~~ all empty values
For i = LBound(v) To UBound(v) - 1 '<~~fill all but the last one
v(i) = i + 10
Next i
Debug.Print Application.Min(v) '10 as v(5) is empty and not considered in Min
An unassigned variant array element is considered empty and is not used in the Min calculation.
Alternately, use one of two methods to remove unused array elements.
'...
'redimension before the loop to the known ubound
redim e(diff1)
For i = 0 To diff1
intercept = Application.WorksheetFunction.intercept(a(),c())
LinReg1 = (slope * Cells(a1RowTemp1, 1)) + intercept
difference1 = Worksheets("GF9").Cells(a1RowTemp1, 2) - LinReg1
e(i) = difference1
a1RowTemp1 = a1RowTemp1 + 1
Next i
'...
'or redimension after the loop with Preserve
For i = 0 To diff2
intercept2 = Application.WorksheetFunction.intercept(b(), d())
LinReg2 = (slope2 * Cells(a2RowTemp2, 1)) + intercept2
difference2 = Worksheets("GF9").Cells(a2RowTemp2, 2) - LinReg2
f(i) = difference2
a2RowTemp2 = a2RowTemp2 + 1
Next i
'i exits with a value 1 greater than diff2
redim preserve f(i-1)
'...

AutoCAD VBA - Creating Blocks with a Hatch

I am trying to make blocks in AutoCAD that have a circle, number, and solid hatch but I can't seem to get the hatch to work? I'm not sure what I'm doing wrong - any help would be great!
' Create the block
insertionPnt(0) = Sheet1.Cells(n, 3)
insertionPnt(1) = Sheet1.Cells(n, 4)
insertionPnt(2) = 0
Set blockObj = ACAD.ActiveDocument.Blocks.Add(insertionPnt, namestr)
'Add the circle to the block
center(0) = Sheet1.Cells(n, 3)
center(1) = Sheet1.Cells(n, 4)
center(2) = 0
Set circleObj = blockObj.AddCircle(center, Rad(0) / 2)
'Add hatch to the block
hatchObj = blockObj.AddHatch(0, "Solid", True)
hatchObj.AppendOuterLoop (circleObj)
hatchObj.Evaluate
'Add text to the block
Set blocktext = blockObj.AddText(Nums(0), Coords, 0.5)
blocktext.Alignment = acAlignmentMiddleCenter
blocktext.TextAlignmentPoint = Coords
'Insert the block
insertionPnt(0) = Sheet1.Cells(n, 3)
insertionPnt(1) = Sheet1.Cells(n, 4)
Set blockRefObj = ACAD.ActiveDocument.ModelSpace.InsertBlock(insertionPnt, namestr, 1#, 1#, 1#, 0)
there are two faults
1) a Set keyword is missing in hatchObj = blockObj.AddHatch(0, "Solid", True)
2) the AppendOuterLoop method requires and array of objects for the loop parameter
so the hatch section should be like:
Dim outerLoop(0 To 0) As AcadEntity ' declare the array of objects
Set outerLoop(0) = blockObj.AddCircle(Center, 10#) ' fill it with a circle object
'Add hatch to the block
Set hatchObj = blockObj.AddHatch(0, "Solid", True) '
hatchObj.AppendOuterLoop (outerLoop) 'append the outerloop
hatchObj.Evaluate

select multiple figures in a series using excel visual basic

Using excel visual basic, I want to select multiple figures and group them, repeatedly.
My code goes like this:
circleCnt = 5
For j = 1 To circleCnt
ActiveSheet.Shapes.AddShape(msoShapeOval, 500, 30, 40, 30).Select
Selection.ShapeRange.Height = minWidth + circleWidth * (circleCnt - j + 1)
Selection.ShapeRange.Width = minWidth + circleWidth * (circleCnt - j + 1)
Selection.ShapeRange.IncrementLeft circleWidth / 2 * (j - 1) + circleWidth / 2
Selection.ShapeRange.IncrementTop circleWidth / 2 * (j - 1) + circleWidth / 2
Next j
Yep, it's drawing multiple circles and I'm trying to present my data with these codes. The problem is... my full data makes more than a hundred group of circles and it takes forever to transfer all the circles into the powerpoint
I want to make circles from a sample into a group - and how can I select multiple shape objects? I was thinking like
for n = 1 to 5
select shape #n
next n
but as you can see, this didn't work
Is there any 'cumulative' code for selection? or selecting last object and make them into a group of previously grouped objects?
-I don't want to make 'all circles' into one group - a group for a sample, with multiple samples :)
After you add the shapes, you need to iterate over all the shapes on the sheet and store the shape names in an array. Using that, you can create a ShapeRange object and Group the shapes. Here is a code sample:
Sub GroupAllShapes()
Dim arrShapeNames() As Variant 'must be Variant to work with Shapes.Range()
Dim shp As Shape
Dim sr As ShapeRange
Dim ws As Worksheet
Dim i As Integer
Set ws = ActiveSheet
ReDim arrShapeNames(ws.Shapes.Count - 1)
i = 0
For Each shp In ws.Shapes
arrShapeNames(i) = shp.Name
i = i + 1
Next
Set sr = ws.Shapes.Range(arrShapeNames)
sr.Group
Set sr = Nothing
Set ws = Nothing
End Sub
Note: I ported this from some of my C# code and have the arrShapeNames array with a zero-based index. You may need to make it 1-based for VBA.
Try to avoid selecting anything in your code. This makes your code really slow. It's not entirely clear for me what you're trying to do, but try something like this:
dim objShape as Shape
for j = 1 To circleCnt
set objShape = Shapes.AddShape(msoShapeOval, 500, 30, 40, 30)
With objShape
.ShapeRange.Height = minWidth + circleWidth * (circleCnt - j + 1)
.ShapeRange.Width = minWidth + circleWidth * (circleCnt - j + 1)
.ShapeRange.IncrementLeft circleWidth / 2 * (j - 1) + circleWidth / 2
.ShapeRange.IncrementTop circleWidth / 2 * (j - 1) + circleWidth / 2
End With
next
set objShape = Nothing

Working with Excel ranges and arrays

In VBA, I can easily pull in an sheet\range into an array, manipulate, then pass back to the sheet\range. I'm having trouble doing this in VB.Net though.
Here's my code.
Rng = .Range("a4", .Cells(.UsedRange.Rows.Count, .UsedRange.Columns.Count))
Dim SheetArray(,) As Object = DirectCast(Rng.Value(Excel.XlRangeValueDataType.xlRangeValueDefault), Object(,))
For X As Integer = 0 To SheetArray.GetUpperBound(0)
If IsNothing(SheetArray(X, 0)) Then Exit For
SheetArray(X, 6) = SheetArray(X, 3)
SheetArray(X, 7) = CDbl(SheetArray(X, 3).ToString) - CDbl(SheetArray(X, 1).ToString) - _
CDbl(SheetArray(X, 7).ToString)
For Y As Integer = 0 To 3
SheetArray(X, Y * 2 + 1) = Math.Round(CDbl(SheetArray(X, Y * 2 + 1).ToString), 3)
Next
If Math.Abs(CDbl(SheetArray(X, 7).ToString)) > 0.1 Then _
.Range(.Cells(X + 1, 1), .Cells(X + 1, 8)).Font.Color = -16776961
Next
I'm getting an error on the first If IsNothing(SheetArray(X, 0)) Then Exit For
line. It is telling me index is out of bounds of the array. Any idea why? The SheetArray object contains the data, but I just am not sure how to get to it.
In the For you have to loop from 0 to Count - 1:
For X As Integer = 0 To SheetArray.GetUpperBound(0) - 1
'...
Next
That will fix your problem.