select multiple figures in a series using excel visual basic - vba

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

Related

Link a word graph with a word table

i'm trying to visualize my data that i have stored in a word table. I can call the table data with ThisDocument.Tables(6).Cell(i,j).Range.Text. I tried to copy this data to the datasheet of the word graph, but this was unsuccessful.
Word table with data
The chart has to visualize the amount of currency in a timeline with time on the x-axis and the amount of money on the y-axis. I have allready inserted a chart in my word document but i need to access its datasheet.
Graph in word that i want to show
Does anyone have an example code that i can use to solve this problem?
I'm trying to build my code like this:
Dim graph As Word.Chart
Set graph = ThisDocument.InlineShapes(1).Chart
If Not Len(ThisDocument.Tables(3).Cell(2, 1).Range.Text) = 2 Then
Dim temp As String
For i = 0 To ThisDocument.Tables(3).Rows.Count - 2
graph.ChartData.Workbook.Worksheets(1).Cells(1 + i, 1).Value = Left(ThisDocument.Tables(3).Cell(2 + i, 3).Range.Text, Len(ThisDocument.Tables(3).Cell(2 + i, 3).Range.Text) - 2)
temp = Left(ThisDocument.Tables(3).Cell(2 + i, 4).Range.Text, Len(ThisDocument.Tables(3).Cell(2 + i, 4).Range.Text) - 2)
graph.ChartData.Workbook.Worksheets(1).Cells(1 + i, 2).Value = Right(temp, Len(temp) - 2)
Next i
End If
I'm trying to build my code like this:
Dim graph As Word.Chart
Set graph = ThisDocument.InlineShapes(1).Chart
If Not Len(ThisDocument.Tables(3).Cell(2, 1).Range.Text) = 2 Then
Dim temp As String
For i = 0 To ThisDocument.Tables(3).Rows.Count - 2
graph.ChartData.Workbook.Worksheets(1).Cells(1 + i, 1).Value = Left(ThisDocument.Tables(3).Cell(2 + i, 3).Range.Text, Len(ThisDocument.Tables(3).Cell(2 + i, 3).Range.Text) - 2)
temp = Left(ThisDocument.Tables(3).Cell(2 + i, 4).Range.Text, Len(ThisDocument.Tables(3).Cell(2 + i, 4).Range.Text) - 2)
graph.ChartData.Workbook.Worksheets(1).Cells(1 + i, 2).Value = Right(temp, Len(temp) - 2)
Next i
End If

VBA Array getting -1.#IND value if the macro isn't paused

This code takes in a chart and the last data point, then sorts the data points .top for all the series and adds 12.5 (size of the data labels) to make sure they are not overlapping.
The problem is if I donot have the wait call to pause the macro, the lines
dLabels(i, 1) = .SeriesCollection(i).Points(lastpoint).DataLabel.Top
dLabels(i, 2) = i
Will give me a value of -1.#IND, but if I Step through it or "pause" the macro everything is fine.
oSh is a Shape and lastpoint is a Long.
Is the macro just working too fast to get a value from the label?
Sub MoveLabels(oSH, lastpoint)
Dim ch As Chart
Dim i As Long
Dim dLabels() As Double
*Call Wait(3)* ' just pauses the macro for less than a second
If oSH.Name = "SCG_US" Then
With oSH.Chart
' the -2 will only allow it to move the labels that are not static (the last two in the series)
ReDim dLabels(1 To .SeriesCollection.Count - 2, 2)
For i = 1 To .SeriesCollection.Count - 2
**dLabels(i, 1) = .SeriesCollection(i).Points(lastpoint).DataLabel.Top**
dLabels(i, 2) = i
'dLabels(i, 3) = .Chart.SeriesCollection(i).Values(lastpoint)dLabels(2, 1)
Next
Call BubbleSort(dLabels) 'simple sort of array
' This section sets top values for all data labelsto be at least 12.5 units apart
For j = 2 To .SeriesCollection.Count - 2
**If dLabels(j - 1, 1) + 12.5 > dLabels(j, 1) Then**
dLabels(j, 1) = dLabels(j, 1) + (12.5 - (dLabels(j, 1) - dLabels(j - 1, 1)))
End If
Next j
Sub Wait(waitTime)
Start = Timer
While Timer < Start + waitTime
DoEvents
Wend
End Sub
Here is the call statements that I changed the order they were in:
If .SeriesCollection.Count > 1 Then Call MoveLabels(oSH, 1) 'moves first label
If .SeriesCollection.Count > 1 And lastpoint <> 999 Then Call MoveLabels(oSH, lastpoint) ' moves last label

Dynamic labelling of shapes

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

Excel VBA: "Too many different cell formats" - Is there a way to remove or clear these formats in a Macro?

So, I made a fun and simple macro that randomly selects R, G, and B values until it uses every possible combination (skipping repeats), and setting the color values of a 10x10 square with each new color.
The only problem is that I have run into the limit for the number of cell formats. Microsoft says that the limit should be around 64000, but I found it to be exactly 65429 on a blank workbook in Excel 2013.
I've included a clear format code, but it seems to have no effect:
Cells(X, Y).ClearFormats
Microsoft lists some resolutions, but 3 out of the 4 of them are essentially "Don't make too many formats", and the 4th format is to use a third party application.
Is there really nothing that can be done in VBA?
A1:J10 will print a new color
K1 will print the percentage to completion
L1 will print the number of colors used
M1 will print the number of times a color combination is repeated
Dim CA(255, 255, 255) As Integer
Dim CC As Long
Dim RC As Long
Dim R As Integer
Dim G As Integer
Dim B As Integer
Dim X As Integer
Dim Y As Integer
CC = 0
RC = 0
X = 1
Y = 1
Do While ColorCount < 16777216
R = ((Rnd * 256) - 0.5)
G = ((Rnd * 256) - 0.5)
B = ((Rnd * 256) - 0.5)
If CA(R, G, B) <> 1 Then
CA(R, G, B) = 1
'Step down to the next row
'If at the 10th row, jump back to the first and move to the next column
If X < 10 Then
X = X + 1
Else
X = 1
If Y < 10 Then
Y = Y + 1
Else
Y = 1
End If
End If
Cells(X, Y).ClearFormats 'doesn't do what I hope :(
Cells(X, Y).Interior.Color = RGB(R, G, B)
CC = CC + 1
Cells(1, 11).Value = (CC / 16777216) * 100
Cells(1, 12).Value = CC
Else
RC = RC + 1
Cells(1, 13).Value = RC
End If
Loop
There are several ways to resolve this issue, but the cleanest and easiest method is to remove all extra styles (I have seen workbooks with 9000+ styles )
With the following simple VBA code you can remove all non-builtin styles and in the vast majority of cases this fixes the error.
Sub removeStyles()
Dim li as long
On Error Resume Next
With ActiveWorkbook
For li = .Styles.Count To 1 Step -1
If Not .Styles(li).BuiltIn Then
.Styles(li).Delete
End If
Next
End With
End Sub

My MInverse function will not work in VBA

EDIT: I fixed it, the ReDim and all starts at 0 and not 1 so I had a cell that was empty which wasn't supposed to be there!
It now works, thanks for the help!
I'm trying to take a matrix and invert it, but for some reason I get this error:
Unable to get the MInverse property of the WorksheetFunction class.
My (relevant) code is as following:
Dim covar() As Variant
ReDim covar(UBound(assetNames), UBound(assetNames))
Dim corr() As Double
ReDim corr(UBound(assetNames), UBound(assetNames))
Dim covarTmp As Double
For i = 0 To UBound(assetNames) - 1
For j = 0 To UBound(assetNames) - 1
covarTmp = 0
For t = 1 To wantedT
covarTmp = covarTmp + (Log((prices(histAmount + 1 - t, i + 1)) / (prices(histAmount - t, i + 1))) - mu(i) * dt) * (Log((prices(histAmount + 1 - t, j + 1)) / (prices(histAmount - t, j + 1))) - mu(j) * dt)
Next t
covar(i, j) = covarTmp * (1 / ((wantedT - 1) * dt))
corr(i, j) = covar(i, j) / (sigma(i) * sigma(j))
Next j
Next i
Dim covarInv() As Variant
ReDim covarInv(UBound(assetNames), UBound(assetNames))
'ReDim covar(1 To UBound(assetNames), 1 To UBound(assetNames))
covarInv = Application.WorksheetFunction.MInverse(covar)
This last row is where the error occurs.
I've tried many things, having covar and covarInv dim as double, variant etc. Different ReDims on covar and covarInv.
You don't say what version of Excel you are using, but with Excel 2010 there seems to be a Minverse maximum limit of 200 * 200 (for Excel 2003 its probably around 80 * 80): How many asset names do you have?