I'm trying to store some reference data in a string array and then use that later on to compare with another string array. However, the code is not working since I'm getting a "subscript out of range" error (see code comment below).
Sub StoreBaseReferences()
Dim cell As Range
Dim val As Variant
Dim stringValues() As String
Dim i, rowCounter, columnCounter As Integer
rowCounter = 0
columnCounter = 0
For i = 2 To Sheets("sheet").UsedRange.rows.Count
For Each cell In Range(Cells(i, 2), Cells(i, 4))
stringValues(rowCounter, columnCounter) = cell.Value 'this is throwing the subscript ouf of range error
columnCounter = columnCounter + 1
Next cell
rowCounter = rowCounter + 1
columnCounter = 0
Next i
MsgBox (stringValues(0, 0))
End Sub
What is missing here?
Arrays in VBA need to be dimensioned with the number of elements that are expected to be used. You've defined the dimension, but not specified how many elements will be added to it. Try adding the following line just before the For loop:
ReDim stringValues(Sheets("sheet").UsedRange.Rows.Count, 3)
you are declaring a 1d array Dim stringValues() As String
but trying to use it as a 2d array stringValues(rowCounter, columnCounter)
Also, you are not declaring the size of the array and you are trying to use it. In VBA you have to make sure you tell the size of the array at the declaration time.
To delcare the count of elements that the array is capable of storing
Dim stringArray(0 to 10) or Dim stringArray(10)
and when iterating the counter starts at 0.
Using ReDim stringValues() allows you to resize the bounds at a later stage.
The topic is too broad to go over in one answer so check out the links to learn out how to dimension your array
VBA arrays
Array in Excel VBA
Related
I'm trying to get some data I input with another macro into a 2-dimensional array so I can then apply a function to that data, but no matter what I try I keep getting errors. The data includes strings and numbers. I could always just reference the cells and forget about the array, but that complicates the function. Here's my code:
(Declarations)
Dim nLiens As Byte, nCreditors As Byte
Dim SecurityV As Currency, ASecurityV As Currency
Const adjuster = 0.9
(Relevant subs)
Public Sub VariableDeclaration()
nLiens = InputBox("Enter number of liens in security")
nCreditors = InputBox("Enter number of creditors")
SecurityV = InputBox("Enter security full value")
ASecurityV = adjuster * SecurityV
Call ODebt
End Sub
Sub ODebt()
'
'(...)
'
Dim oDebt() As Variant
ReDim oDebt(1 To nCreditors + 1, 1 To nLiens + 1)
Dim rg As Range
Set rg = Range(Cells(1, 1), Cells(nCreditors + 1, nLiens + 1))
oDebt = rg.Value
MsgBox (oDebt)
'>>> ERROR: type mismatch
Call SAllocation
End Sub
I've tried other alternatives, such as setting the content cell by cell with two 'For' loops and LBound and UBound, but nothing seems to work.
You are getting your error not while filling, but at displaying the array.
It is not possible to just Msgbox an array, since Msgbox expects a String argument. You can, in the other hand, display specific positions (e.g. oDebt(1,1)).
If you want to have a look at all of its contents, either use debug mode and the Local window, or print it to some unused cells.
I would copy the values from the datasheet this way:
Dim oDebt As Variant
Dim rg As Range
Set rg = Range(Cells(1, 1), Cells(nCreditors + 1, nLiens + 1))
oDebt = rg ' get data from sheet
'... do calculations with oDebt array
rg = oDebt ' put data on sheet
In words: you dimension the array automatically by assigning the range. If you need the numeric boundaries, use
nrows = UBound(oDebt, 1)
ncols = UBound(oDebt, 2)
Here you see the meaning of the dimension as well, index 1 is rows, index 2 is columns.
I'm trying to write a simple code to look at a data input section and add that data into an existing data table. The number of rows I want to copy changes every time so I attempted to make the array capable of adjusting size to suit.
Dim size As Integer
Dim new_resources() As String
Dim i as Integer
size = worksheetfunction.CountA("E:E") - 1
**ReDim new_resources(size)**
i=1
For i to size
new_resources(i) = cells(i+1,5)
Next i
I get the following error:
Run-time error '9': Subscript out of range.
on the line marked with **.
If you're getting that error on your ReDim line, it must mean that size is less than zero, which must mean that COUNTA("E:E") is returning zero. You may want to assert that size >= 0 before attempting to ReDim your array. For example:
size = worksheetfunction.CountA("E:E") - 1
If size < 0 Then
MsgBox "Error! No rows found in column E."
Else
ReDim new_resources(size)
End If
Arrays start with 0 not 1. So Change your new_resources(i) to new_resources(i-1).
That's not how the WorksheetFunction object works. On the worksheet, that is sufficient to pass in a cell range but not in VBA.
Dim sz As Long
Dim new_resources() As String
Dim i as Integer
sz = worksheetfunction.CountA(Range("E:E")) - 1
ReDim new_resources(sz)
i=1
For i to sz
new_resources(i) = cells(i+1, 5)
Next i
'alternates
sz = worksheetfunction.CountA(Columns(5)) - 1
sz = worksheetfunction.CountA(Cells(1, 5).EntireColumn) - 1
You need to reference one or more cells on a worksheet like you do in other VBA operations. The lack of a parent worksheet worries me; maybe you should address that as well.
Im trying to add a value to a dynamic array but keep getting a run-time error with this. I've found a few different sources saying that this should be the answer, so I cant figure out what I have done wrong...
Sub addtoarray()
Dim catSheets() As String
ReDim Preserve catSheets(UBound(catSheets) + 1)
catSheets(UBound(catSheets)) = "Chemicals"
End Sub
When you create the catSheets() array, it's dimensionless. Therefore, you cannot use UBound() to determine the array's upper boundary.
You can certainly follow up a Dim () with a ReDim if you want to specify an array size, but you won't be able to query the array dimensions until after you've given it some.
So you have a few options. First, you could follow up your Dim () with an immediate ReDim to give your array an initial size:
Dim catSheets() As String
ReDim catSheets(0) As String
...
ReDim Preserve catSheets(...) As String
Or, you could just use ReDim from the start to assign an initial size and still have the ability to ReDim later:
ReDim catSheets(0) As String
...
ReDim Preserve catSheets(...) As String
Alternatively, you could use the Array() function and store it as a Variant. Done this way, you can query the UBound(). For example:
Dim catSheets As Variant
catSheets = Array()
Debug.Print UBound(catSheets) ' => -1
ReDim Preserve catSheets(UBound(catSheets) + 1)
catSheets(UBound(catSheets)) = "Chemicals" ' Works fine
What you can do is to use Variant if you want to preserve the way to use the code.
Sub addtoarray()
Dim catSheets As Variant
catSheets = Array() ' Initially Empty (0 to -1)
Redim Preserve catSheets(Ubound(catSheets) + 1) ' Now it's 0 to 0
catSheets(Ubound(catSheets)) = "Chemicals" ' index here is 0
End Sub
I have a 2D array and I am trying to add along one dimension. The 2D Array is of type variant and might have some of the elements as null ("")
Here is the code so far
'newArray is 2D Array
Function SumColumn(newArray As Variant, index As Integer) As Double
Dim tempArray() As Double
ReDim tempArray(1 To UBound(newArray))
For i = 1 To (UBound(newArray))
tempArray(i) = CDbl(newArray(i, index))
Next
SumColumn = Application.WorksheetFunction.Sum(tempArray)
End Function
I get a type mismatch error when I am running the above code. Please help me debug
You are probabaly getting a Type mismatch because CDbl(newArray(i, index)) might actually not be a number.
This works for me. Please amend the code to suit your needs.
For demonstration purpose, I am storing an Excel range into a 2D array and then converting it to a 1D temp array. Once that is done, I am simply storing the relevant Numbers in the Double Array and finally calculating the sum.
Lets say that the worksheet looks like this
Option Explicit
Sub Sample()
Dim MyAr, TempAr()
Dim dAr() As Double
Dim n As Long, i As Long
MyAr = ActiveSheet.Range("A1:A10").Value
TempAr = Application.Transpose(MyAr)
ReDim dAr(0 To 0)
n = 0
For i = LBound(TempAr) To UBound(TempAr)
If Len(Trim(TempAr(i))) <> 0 Then
If IsNumeric(Trim(TempAr(i))) Then
ReDim Preserve dAr(0 To n)
dAr(UBound(dAr)) = Trim(TempAr(i))
n = n + 1
End If
End If
Next i
Debug.Print Application.WorksheetFunction.Sum(dAr)
End Sub
And this is the output
I have been struggling for a while to try and implement a goal-seek function in VBA, but with no results, which is why I am turning to you guys.
I have a Variant of double-values, where the last element is just a temporary set value, which would have to be changed (as in goalseek) so that the sum of the entire array equals to 1. Of course this is exactly what you would do in a worksheet, but I need it in VBA, handling NO cells...
Is there a way to call the Goalseek function in VBA without having to use a worksheet (or cells), and instead just working with variables?
Thanks,
Niklas
If it's only about filling the last array item then this code might come in handy:
Sub FillLastElementWithDifferenceToOne()
Dim arr As Variant
Dim i As Integer, sum As Double
ReDim arr(1 To 10)
'Fill Array with .01 - .09
For i = LBound(arr) To UBound(arr)
arr(i) = i / 100
Next i
'Calculate sum = .45
For i = LBound(arr) To UBound(arr) - 1
sum = sum + arr(i)
Next i
'Set last item of array
arr(UBound(arr)) = 1 - sum
'Clean up
Set arr = Nothing
End Sub
Otherwise please specify what exactly you want to accomplish with VBA and where the problems are and post the code where the problems occur.