How to plot array in VBA? - arrays

I want to create a function plot_array(arr As Variant) which will create plot based on element in array.
On x axis I want to have numbers 1, 2,.., n which are indexes of array elements, and on y axis I want to have values stored in array. In other words
Example
Dim arr(9) As Variant
arr(0) = 0
arr(1) = 1
arr(2) = 5
arr(3) = 1
arr(4) = 5
arr(5) = 5
arr(6) = 1
arr(7) = 7
arr(8) = 6
plot_array(arr)
I tried to figure it about by running Macros and thinking how can I generalize this code to be working for any array, but I end up with nothing. Is there any possibility how it can be done ?

Try the next code, please. It will create a chart (xlLine type) and feed it with the array. You can change in the line .SeriesCollection.NewSeries.Values = arr1 arr1 with arr and obtain the same thing, if you put all the used number in the range "A1:A9":
Sub testPlotChartArray()
Dim sh As Worksheet, cH As Chart, arr1, arr(1 To 9)
Set sh = ActiveSheet
arr1 = sh.Range("A1:A9").Value
arr(1) = 0: arr(2) = 1: arr(3) = 5: arr(4) = 1: arr(5) = 5
arr(6) = 5: arr(7) = 1: arr(8) = 7: arr(9) = 6
On Error Resume Next
Set cH = sh.ChartObjects("PlotChart").Chart
If Err.Number = 0 Then
Err.Clear
cH.Parent.Delete
End If
On Error GoTo 0
Set cH = sh.ChartObjects.Add(left:=60, top:=10, width:=300, height:=300).Chart
With cH
.Parent.Name = "PlotChart"
.ChartType = xlLine
.SeriesCollection.NewSeries.Values = arr1 'or arr
End With
End Sub
The above code deletes the chart if it exists, but it can be configured to use the same existing chart and feed its .SeriesCollection(1).Values...

If you declare an array as arr(9) in Excel, the index is declared as a total of 10 arrays from 0 to 9, so your array is not the correct number.
Sub test()
Dim arr(8) As Variant
arr(0) = 0
arr(1) = 1
arr(2) = 5
arr(3) = 1
arr(4) = 5
arr(5) = 5
arr(6) = 1
arr(7) = 7
arr(8) = 6
plot_array (arr)
End Sub
Sub plot_array(arr As Variant)
Dim Srs As Series
Dim Cht As Chart
Dim xAxes As Axis, yAxes As Axis
Dim i As Integer, vX() As Variant
ReDim vX(LBound(arr) To UBound(arr))
For i = LBound(arr) To UBound(arr)
vX(i) = i + 1 '<~~ if index start from 0 then delete +1
Next i
Set Cht = ActiveSheet.Shapes.AddChart.Chart
With Cht
.HasTitle = True
.ChartTitle.Text = "My Graph"
.ChartType = xlXYScatterLinesNoMarkers
For Each Srs In .SeriesCollection
Srs.Delete
Next Srs
Set Srs = .SeriesCollection.NewSeries
With Srs
.Name = "item"
.Values = arr
.XValues = vX
.MarkerStyle = xlCircle
End With
Set xAxes = .Axes(xlCategory, xlPrimary)
With xAxes
.MinimumScale = 0
.MaximumScale = WorksheetFunction.Max(vX)
.MajorUnit = 1
.HasMajorGridlines = True
End With
Set yAxes = .Axes(xlValue, xlPrimary)
With yAxes
.MinimumScale = 0
.MaximumScale = WorksheetFunction.Max(arr) + 1
.MajorUnit = 1
.HasMajorGridlines = True
End With
End With
End Sub

Related

Adding 2 Arrays of dynamic length to 3rd Array

I have a problem with adding these 2 arrays together.
I have arr1 and arr2 this string elements.
arr1(0) = "000"
arr1(1) = "001"
arr1(2) = "002"
arr1(3) = "003"
arr1(4) = "004"
arr1(5) = "005"
arr2(0) = "Closed"
arr2(1) = "Open"
These arrays can be in dynamic size and values. (just added static values for demonstration)
I want to copy these items values to arr3. The output of arr3 should look like this:
arr3(0) = "000 Closed"
arr3(1) = "000 Open"
arr3(2) = "001 Closed"
arr3(3) = "001 Open"
arr3(4) = "002 Closed"
arr3(6) = "002 Open"
arr3(7) = "003 Closed"
arr3(8) = "003 Open"
arr3(9) = "004 Closed"
arr3(10) = "004 Open"
arr3(11) = "005 Closed"
arr3(12) = "005 Open"
I tried this:
Dim arr1(6)
Dim arr2(2)
Dim arr3(0)
Dim i
Dim y
arr1(0) = "This000"
arr1(1) = "This001"
arr1(2) = "This002"
arr1(3) = "This003"
arr1(4) = "This004"
arr1(5) = "This005"
arr2(0) = "Closed"
arr2(1) = "Open"
redim arr3 ((UBound(arr1)) * (Ubound(arr2)))
Console.WriteLine (Ubound (arr3))
for i = Lbound(arr1) to Ubound(arr1)
for y = Lbound(arr2) to Ubound(arr2)
arr3(i*y+y) = (arr1(i) & arr2(y))
next
next
for i = Lbound(arr3) to Ubound(arr3)
Console.WriteLine (arr3(i))
next `
but I can't get it to work properly.
Maybe you guys can help me? thanks
edit:
I now got it kinda working. But i guess there is a more elegant solution to it than this:
Function GetParameters(ByRef arr1, ByRef arr2)
Dim arr3()
Dim i,j,k,l
ReDim Preserve arr3 ((UBound(arr1)+1) * (UBound(arr2)+1)-1)
HMIRuntime.Trace (UBound (arr3)) &vbNewLine
l=0
For i=0 To UBound(arr3)
If i > 0 Then
i=i-1
End If
For j = 0 To UBound (arr2)
For k = 0 To UBound(arr2)
arr3(i) = arr1(l) & " " & arr2(k)
If i < UBound(arr3) Then
i=i+1
End If
Next
If l < (UBound(arr1)) Then
l=l+1
End If
Next
Next
GetParameters=arr3
End Function
edit2: Because resizing the array in the for loop got me into performance issues, I took a second attempt. Here is my final solution (in case somebody else is interested):
Dim arr1()
Dim arr2()
Dim arr3()
Dim i,j,k,l,m,n
Dim maxArr1
Dim maxArr2
maxArr1 = 5 'change for dynamic Arr
maxArr2 = 10
j=0
for l = 0 to maxArr1 'TestArray1
ReDim Preserve arr1(l)
arr1(l) = Cstr(l)
Next
for m = 0 to maxArr2 'TestArray2
ReDim Preserve arr2(m)
arr2(m) ="Closed_"& Cstr(m)
Next
ReDim Preserve arr3( (((Ubound(arr1)+1) * (Ubound(arr2)+1) )-1) ) 'New size for array 3
'Copy arr1 and arr2 in arr3 (according to pattern)
for i=0 to UBound(arr1)
for k=0 to Ubound(arr2)
arr3(j)=arr1(i)& " - "&arr2(k)
j=j+1
Next
Next
For n = 0 To UBound(arr3)
WScript.Echo "arr3("&n&") = "&arr3(n)
Next
Here's a quick attempt based on your code that uses Preserve to maintain the array and build elements dynamically.
Dim arr1(6)
Dim arr2(2)
Dim arr3()
Dim i
Dim y
arr1(0) = "000"
arr1(1) = "001"
arr1(2) = "002"
arr1(3) = "003"
arr1(4) = "004"
arr1(5) = "005"
arr2(0) = "Closed"
arr2(1) = "Open"
Dim item, x
For i = 0 To UBound(arr1) - 1
item = arr1(i)
For y = 0 To UBound(arr2) - 1
x = i + y + 1
ReDim Preserve arr3 (i + x)
arr3(i + x) = item & " " & arr2(y)
Next
Next
For i = 0 To UBound(arr3)
WScript.Echo arr3(i)
Next
Output:
000 Closed
000 Open
001 Closed
001 Open
002 Closed
002 Open
003 Closed
003 Open
004 Closed
004 Open
005 Closed
005 Open

Excel VBA using an array to speed up code

I am trying to create an array, store values in the array and then write the values of the array to a spreadsheet in VBA. This codes takes 1+ hour to run on my computer and I think that an array could really speed up the code.
However, I need help with creating the array, populating the array from the comboboxes and finally write the values of the array to the worksheet.
Create an n-dimensional array
Fill the n-dimensional array with the values of the ComboBoxes.
Iterate through all ComboBoxes.
Store values in the array
Write values from the array to the spreadsheet
Sub WantToUseArray()
Dim k As Integer
Dim l As Integer
Sheets("Test").ComboBox1.ListIndex = 0
For l = 0 To 25
Sheets("Test").ComboBox3.ListIndex = l
Sheets("Test").ComboBox2.ListIndex = 0
For n = 0 To 25
Sheets("Test").ComboBox4.ListIndex = n
Sheets("Points").Select
Dim LR As Long
LR = Cells(Rows.Count, 1).End(xlUp).Row + 1
Cells(LR, "A").Value = Sheets("Test").Range("G5").Value
Cells(LR, "B").Value = Sheets("Test").Range("G6").Value
Cells(LR, "C").Value = Sheets("Test").Range("O5").Value
Cells(LR, "D").Value = Sheets("Test").Range("O6").Value
Cells(LR, "E").Value = Sheets("Test").Range("X5").Value
Cells(LR, "F").Value = Sheets("Test").Range("X6").Value
Cells(LR, "G").Value = Sheets("Test").Range("G6").Value + Sheets("Test").Range("X6").Value
Cells(LR, "H").Value = Sheets("Test").Range("X6").Value + Sheets("Test").Range("G6").Value
Cells(LR, "I").Value = Sheets("Test").Range("K40").Value
Cells(LR, "J").Value = Sheets("Test").Range("K41").Value
Cells(LR, "K").Value = Sheets("Test").Range("K51").Value
Cells(LR, "L").Value = Sheets("Test").Range("K52").Value
Next
Next
End Sub
This code goes through each combobox in a given worksheet, generates an array that contains the list values for each comobox list, then prints all of the contents into that first column. myArray only has a single dimension. Its contents are other arrays. If the comoboxes have different list lengths, a jagged array is created.
To help visualize the arrays, enable the Locals Window by going to view in the menu bar and then selecting Locals Window. See pic below the code.
Option Explicit
Sub main()
Dim ws As Worksheet
Dim mainArray() As Variant
Dim ctrl As Object
Dim numComboBoxes As Long
Set ws = ActiveSheet
numComboBoxes = GetNumberOfComboBoxesInSheet(ws)
mainArray = GenerateJaggedArrayComboBoxListValues(ws, numComboBoxes)
PrintArray ws, mainArray
End Sub
Function GetNumberOfComboBoxesInSheet(ByRef ws As Worksheet) As Long
Dim ctrl As Object
For Each ctrl In ws.OLEObjects
If TypeName(ctrl.Object) = "ComboBox" Then
GetNumberOfComboBoxesInSheet = GetNumberOfComboBoxesInSheet + 1
End If
Next ctrl
End Function
Function GenerateJaggedArrayComboBoxListValues(ByRef ws As Worksheet, ByVal numComboBoxes As Long) As Variant()
Dim ctrl As Object
Dim tempPrimaryArray() As Variant
Dim tempArray() As Variant
Dim x As Long
Dim y As Long
Dim listNum As Long
ReDim tempPrimaryArray(0 To numComboBoxes - 1)
x = 0
For Each ctrl In ws.OLEObjects
If TypeName(ctrl.Object) = "ComboBox" Then
y = 0
For listNum = 0 To ctrl.Object.ListCount - 1
ReDim Preserve tempArray(0, 0 To y)
tempArray(0, y) = ctrl.Object.List(listNum, 0)
y = y + 1
Next listNum
tempPrimaryArray(x) = tempArray
Erase tempArray
x = x + 1
End If
Next ctrl
GenerateJaggedArrayComboBoxListValues = tempPrimaryArray()
End Function
Sub PrintArray(ByRef ws As Worksheet, ByRef mainArray As Variant)
Dim counter As Long
Dim x As Long
Dim y As Long
Dim tempArray() As Variant
counter = 1
For x = LBound(mainArray, 1) To UBound(mainArray, 1)
tempArray = mainArray(x)
For y = LBound(tempArray, 2) To UBound(tempArray, 2)
ws.Range("A" & counter) = tempArray(0, y)
counter = counter + 1
Next y
Next x
End Sub

How to unpack 2d array of elements into a 3d array of columns and rows, maybe called a series?

I am using Bloomberg sample code to collect data from Bloomberg through VBA (2d array?) and I have some old vba code that I believe takes a normal 3d array (maybe someone can clarify that for me). The problem is that Bloomberg output an array of elements.
See Bloomberg code below. Then below that is what I want to essentially convert the Bloomberg output into something that the next bit of code will accept.
Private Sub session_ProcessEvent(ByVal obj As Object)
On Error GoTo errHandler
Dim eventObj As blpapicomLib2.Event
Set eventObj = obj
If Application.Ready Then
If eventObj.EventType = PARTIAL_RESPONSE Or eventObj.EventType = RESPONSE Then
Dim it As blpapicomLib2.MessageIterator
Set it = eventObj.CreateMessageIterator()
Do While it.Next()
Dim msg As Message
Set msg = it.Message
Dim securityData As Element
Dim securityName As Element
Dim fieldData As Element
Set securityData = msg.GetElement("securityData")
Set securityName = securityData.GetElement("security")
Set fieldData = securityData.GetElement("fieldData")
Sheet1.Cells(currentRow, 4).Value = securityName.Value
Dim b As Integer
For b = 0 To fieldData.NumValues - 1
Dim fields As blpapicomLib2.Element
Set fields = fieldData.GetValue(b)
Dim a As Integer
Dim numFields As Integer
numFields = fields.NumElements
For a = 0 To numFields - 1
Dim field As Element
Set field = fields.GetElement(a)
Sheet1.Cells(currentRow, a + 5).Value = field.Name & " = " & field.Value
Next
currentRow = currentRow + 1
Next b
Loop
' skip a row for next security
currentRow = currentRow + 1
End If
End If
Exit Sub
errHandler:
MsgBox Err.Description
End Sub
This is the next bit of code I want the Bloomberg output to feed into.
Option Explicit
Dim Count() As Variant
Dim AdjCount() As Variant
Dim Rev() As Variant
Dim Conf() As Variant
Dim ncount() As Integer
Sub CreateSetupsBUY(series As Variant)
Dim x As Integer
Dim Y As Integer
Dim temp1 As Variant
Dim temp2 As Variant
Dim temp3 As Variant
Dim temp4 As Integer
Dim temp5 As Variant
ReDim Count(UBound(series))
ReDim AdjCount(UBound(series))
ReDim Rev(UBound(series))
ReDim Confn(UBound(series))
ReDim ncount(UBound(series))
For x = LBound(series) To UBound(series)
ReDim temp1(UBound(series(x)))
ReDim temp2(UBound(series(x)))
ReDim temp3(UBound(series(x)))
temp4 = 0
ReDim temp5(UBound(series(x)))
For Y = LBound(series(x)) + 5 To UBound(series(x))
If IsNumeric(series(x)(Y, 1)) Then
If series(x)(Y, 4) < series(x)(Y - 4, 4) Then
temp1(Y) = 1 + temp1(Y - 1)
Else
temp1(Y) = 0
End If
If series(x)(Y, 4) > series(x)(Y - 4, 4) Then
temp5(Y) = 1 + temp5(Y - 1)
Else
temp5(Y) = 0
End If
If temp1(Y) > 9 Then
temp2(Y) = 0
Else
temp2(Y) = temp1(Y)
End If
If temp1(Y) = 9 Then
temp4 = temp4 + 1
End If
If series(x)(Y - 1, 4) >= series(x)(Y - 5, 4) Then
temp3(Y) = 1
Else
temp3(Y) = 0
End If
Else
temp1(Y) = 0
temp2(Y) = 0
temp3(Y) = 0
temp4 = 0
temp5(Y) = 0
End If
Next Y
Count(x) = temp1
AdjCount(x) = temp2
Conf(x) = temp3
ncount(x) = temp4
Rev(x) = temp5
Next x
Call CreateCount(series, Count, Conf, ncount, Rev)
End Sub
When I tried connecting the two I get a type error. I assume its because of the way the Bloomberg array is created and unpacked.
Possible solution I have yet to try is to unpack the Bloomberg array and some how build a basic column row array while the Bloomberg array is unpacking.

VBA Dynamic Array without empty space

I have two arrays: in the first one are names and in the second one there are country codes like this example:
array1(0)="Peter" array2(0)="EN"
array1(1)="John" array2(1)="US"
array1(2)="Sandra" array2(2)="FR"
array1(3)="Margot" array2(3)="DE"
Now, I want to check the from an entry in a textbox1 if its a "FR" available in my arrays,if yes then save the positions in a third new array.
My code looks like this, but it is very bad and it does not work the way I want.
Dim name(0 To 9) As String
array1(0) = "Peter"
array1(1) = "John"
array1(2) = "Sandra"
array1(3) = "Margot"
Dim county(0 To 9)
county(0) = "EN"
county(1) = "US"
county(2) = "FR"
county(3) = "DE"
'Dim ArrayCounter
ArrayCounter = 0
Dim VarArray(9999)
For i = 0 To 9
If county(i) = "DE" Then
'ArrayCounter = ArrayCounter + 1
'MsgBox (array1(i))
VarArray(ArrayCounter) = i
ArrayCounter = ArrayCounter + 1
End If
Next i
MsgBox (UBound(VarArray))
Now, if I check the third array, the array has to look like this:
array3(0)=2 'position of FR in my second array
You can get rid of the empty values in your 0 To 9999 array by redimming it:
If ArrayCounter > 0 Then
ReDim Preserve varArray(0 to ArrayCounter - 1) 'Preserve is important because otherwise it will delete the values
Else
'do what you want to do if no match was found
End If
you may be after the following:
Sub main()
Dim names(0 To 9) As String
names(0) = "Peter"
names(1) = "John"
names(2) = "Sandra"
names(3) = "Margot"
Dim county(0 To 9) As String
county(0) = "EN"
county(1) = "US"
county(2) = "FR"
county(3) = "DE"
Dim ArrayCounter As Long
ArrayCounter = 0
Dim foundArray As Variant
foundArray = county '<--| "copy" the 'county' array into 'foundArray', since this latter won't be bigger than the former
Dim iFound As Long, iCounty As Long
iFound = -1
For iCounty = LBound(county) To UBound(county)
If county(iCounty) = "DE" Then
iFound = iFound + 1 '<-- update the 'foundArray' current counter
foundArray(iFound) = iCounty '<-- update the 'foundArray' current counter content
End If
Next iCounty
If iFound >= 0 Then
ReDim Preserve foundArray(0 To iFound) '<--| if any values have been found, resize 'foundArray' up to the found items counter
Else
Erase foundArray '<--| otherwise erase it
End If
End Sub

VBA count non empty elements of array

Noob question: I want to count the non empty elements of an array?
My attempt:
Dim Arr(1 To 15) As Double
'populating some of the elements of Arr
'...
Dim nonEmptyElements As Integer, i As Integer
nonEmptyElements = 0: i = 0
For i = LBound(Arr) To UBound(Arr)
If Not Arr(i) = "" Then
nonEmptyElements = nonEmptyElements + 1
End If
Next
With this program I get the error: Type mismatch on If statement.
If try to change the if condition to If Not IsEmpty(Arr(i)) Then and i get nonEmptyElements = 15 as a result.
Any suggestions on how to complete the code?
Dim Arr(0 To 15) As Double
Arr(6) = 1.2
Arr(3) = 7
Dim nonEmptyElements As Integer, i As Integer
nonEmptyElements = 0 : i = 0
For i = LBound(Arr) To UBound(Arr)
If Not Arr(i) = 0 Then
nonEmptyElements = nonEmptyElements + 1
End If
Next
A double value by default is 0.0, so check if:
Arr(i) = 0
Application.CountA(myarray)
CountA is a worksheet function for counting non-empty values.
Applies only to VBA6, does not work in VBA7.

Resources