expected array,compile error - vba

For j = 0 To 20
For i = 0 To 20
ReDim atoms(0 To 20, 0 To 20)
ReDim atomschange(0 To 20, 0 To 20)
atomschange(j, i) = 0
If i Mod 2 = 0 And j Mod 2 = 0 Then
[B2].Offset(j, i).Interior.ColorIndex = 37
atoms(j, i) = 1
Else
[B2].Offset(j, i).Interior.ColorIndex = 36
atoms(j, i) = 0
End If
Next i
Next j
End Sub
what am i doing wrong?

You are redim'ing your arrays inside a loop which reinitializes, then dropping any data inside the array. Use the PRESERVE keyword to insure you don't dump your array when redimensioning it ReDim Preserve atoms(0 To 20, 0 To 20)
Redimensioning your arrays to the exact same size makes no sense. They are already 0 To 20, 0 To 20 because you already set that. Redim them once outside of your for loops and then leave them alone.
Insure that your atoms and atomschange arrays are declared properly at the top of your code. It's complaining (probably when you redim them) that those two variables aren't arrays.
You know the size of the arrays before this code executes, so declare them and dim them properly in the declaration, then just use them (removing the superfluous and incorrect use of redim in your loop:
Sub somesumroutine()
Dim atoms(0 to 20, 0 to 20) as Integer
Dim atomschange(0 to 20, 0 to 20) as Integer
For j = 0 To 20
For i = 0 To 20
atomschange(j, i) = 0
If i Mod 2 = 0 And j Mod 2 = 0 Then
[B2].Offset(j, i).Interior.ColorIndex = 37
atoms(j, i) = 1
Else
[B2].Offset(j, i).Interior.ColorIndex = 36
atoms(j, i) = 0
End If
Next i
Next j
End Sub
Consider using UBound and LBound of your atoms array to set the loops so you don't have to use the 0 to 20 over and over again. This way you can dim your arrays once and leave the rest of your code alone:
Sub somesumroutine()
Dim atoms(0 to 20, 0 to 20) as Integer
Dim atomschange(0 to 20, 0 to 20) as Integer
For j = lBound(atoms, 1) To uBound(atoms, 1)
For i = lBound(atoms, 2) To uBound(atoms, 2)
atomschange(j, i) = 0
If i Mod 2 = 0 And j Mod 2 = 0 Then
[B2].Offset(j, i).Interior.ColorIndex = 37
atoms(j, i) = 1
Else
[B2].Offset(j, i).Interior.ColorIndex = 36
atoms(j, i) = 0
End If
Next i
Next j
End Sub

Related

VBA sort Two-digit array

I want to sort below Two-digit array by VBA code
A 1
B 2
A 1
C 3
or below:
1 A
2 B
1 A
3 C
I have tried to sort them by Dictionary, but, Dictionary is not allowed to insert duplate key.
Is there any want to sort above array by number 1,2,3
I made this some time ago, it might help.
Function ArraySorter(ByVal RecArray As Variant, Optional ByVal RefCol As Integer = 0) As Variant
Dim Menor As String
Dim NewArray() As Variant
Dim i As Double, j As Double
Dim menorIndex As Double
Dim NewArrayIndex() As Double
Dim UsedIndex() As Double
ReDim NewArrayIndex(UBound(RecArray, 2))
ReDim NewArray(UBound(RecArray), UBound(RecArray, 2))
For i = 0 To UBound(NewArrayIndex)
NewArrayIndex(i) = -1
Next i
UsedIndex = NewArrayIndex
For i = 0 To UBound(RecArray, 2)
Menor = ""
menorIndex = -1
For j = 0 To UBound(RecArray, 2)
If UsedIndex(j) = -1 Then
If Menor = "" Then
Menor = RecArray(RefCol, j)
menorIndex = j
Else
If RecArray(RefCol, j) < Menor Then
Menor = RecArray(RefCol, j)
menorIndex = j
End If
End If
End If
Next j
UsedIndex(menorIndex) = 1
NewArrayIndex(i) = menorIndex
Next i
For i = 0 To UBound(NewArrayIndex)
For j = 0 To UBound(NewArray)
NewArray(j, i) = RecArray(j, NewArrayIndex(i))
Next j
Next i
ArraySorter = NewArray
End Function
If you have something like:
Function testArraySorter()
Dim myArr() As Variant
ReDim myArr(1, 3)
myArr(0, 0) = "A"
myArr(0, 1) = "B"
myArr(0, 2) = "A"
myArr(0, 3) = "C"
myArr(1, 0) = 1
myArr(1, 1) = 2
myArr(1, 2) = 1
myArr(1, 3) = 3
myArr = ArraySorter(myArr)
For i = 0 To UBound(myArr, 2)
Debug.Print myArr(0, i), myArr(1, i)
Next i
End Function
you'll get this in your immediate verification :
A 1
A 1
B 2
C 3
If you need to sort based in two or more columns, you could add a dummy column into your array, concatenate the criteria columns into it and then set this dummy column as RefCol: myArr = ArraySorter(myArr, addedColNumberHere).
Hope this helps.

(expected expression) vba error

so basically my code goes like this:
Sub clor2()
For j = 0 To 10
For i = 0 To 10
if i mod = 0 and and j mod=0 then
[D2].Offset(j, i).Interior.ColorIndex = 37
Else
[D2].Offset(j, i).Interior.ColorIndex = 36
End If
Next i
Next j
End Sub
The mod operator is used like this 5 mod 2 = 1 and 6 mod 2 = 0.VBA equivalent to Excel's mod function.
Thus, it should be i Mod SomeNumber = 0 for the condition.
Option Explicit
Sub clor2()
Dim j As Long, i As Long
For j = 0 To 10
For i = 0 To 10
If i Mod 3 = 0 And j Mod 7 = 0 Then
[D2].Offset(j, i).Interior.ColorIndex = 37
Else
[D2].Offset(j, i).Interior.ColorIndex = 36
End If
Next i
Next j
End Sub
Option Explicit is also a good practice in VBA - thus your variables i and j should be declared. - VBA: problems with defining variables in function if Option Explicit is used

VBA - If two of three cells are true

I am trying to construct and If statement that turns a tab Red if two of three cells are colored, or Turns green if only on is colored. I was hoping that there would be an easier way to right it than three if statements like this.
Dim dateRng As String, num As Integer, j As Integer, irng As Range, frng As Range
dateRng = Sheets("Input Raw Data").Range("B" & counter + 2).Value
num = Sheets("Tool Setup").Range("C18").Value
NumPts = num * 3
For s = 1 To Sheets.Count
With Sheets(s)
For j = 1 To num
If .Name = j Then
.Range("A1:C1").Merge
.Range("A1") = dateRng
.Name = Sheets("Point Names").Range("B" & (3 * j - 1))
End If
Next j
End With
Next s
For s = 1 to Sheets.Count
With Sheets(s)
For y = 1 To NumPts
If .Name = Sheets("Reporting").Range("B" & (12 * y - 5)) Then
For k = 6 To -1
Set irng = Sheets("Reporting").Range("A" & (12 * y - k))
Set irng = Sheets("Reporting").Range(irng, irng.End(xlToRight).End(xlToRight))
irng.Copy (.Range("A2"))
Next k
.Columns("A:A").ColumnWidth = 12
.Columns("B:B").EntireColumn.AutoFit
If .Range("B7").Interior.ColorIndex > 0 Then
a = 1
End If
If .Range("B8").Interior.ColorIndex > 0 Then
a = a + 1
End If
If .Range("B9").Interior.ColorIndex > 0 Then
a = a + 1
End If
If a >= 2 Then
.Tab.ColorIndex = 3
ElseIf a <= 1 Then
.Tab.ColorIndex = 4
End If
End If
y = y + 2
Next y
End With
Next s
Something like this may help you. It still has multiple if statements. But the statements are simple and don't have to deal with how the combinations of different cells being colored.
Also, I used colorindex > 0 as the condition for having color filling.
a = 0
If .Range("B7").Interior.ColorIndex > 0 Then
a = 1
End If
If .Range("B8").Interior.ColorIndex > 0 Then
a = a + 1
End If
If .Range("B9").Interior.ColorIndex > 0 Then
a = a + 1
End If
If a = 2 Then
.Range("B10").Interior.ColorIndex = 3
ElseIf a = 1 Then
.Range("B10").Interior.ColorIndex = 43
End If

ReDiming an array in VBA

I have a serious problem with resizing a 2-dimensional array in VBA. I've done a lot of reading about this (popular) issue, but still I can't figure out what's wrong in my code.
So, I have some data in a spreadsheet. In the second row I have some descriptions of an element, while in the first row I have categories of those elements. What I want to do is create an array which has (distinct) categories in the first row and indexes of descriptions related to a particular category in the second row.
The code works correctly up until
If j = UBound(distinctList, 2) Then
Then ReDim comes in and I get a "Subscript out of range error".
That If is there to add a new category and is meant to kick in if the entry from the spreadsheet does not equal any entry from the new array.
Function distinctValues(arr)
Dim distinctList() As String
Dim j As Integer
k = 0
'ReDim distinctList(0 To 0, 0 To 1)
'Dodaj pierwszy wpis
For i = LBound(arr) To UBound(arr)
If arr(i) <> "" Then
ReDim distinctList(0 To 1, 0 To j)
distinctList(0, 0) = arr(i)
distinctList(1, 0) = i + 1
'k = k + 1
Exit For
End If
Next i
'Dodaj kolejne wpisy
For i = LBound(arr) + 1 To UBound(arr)
If arr(i) <> "" Then
For j = LBound(distinctList, 2) To UBound(distinctList, 2)
If arr(i) = distinctList(0, j) Then
distinctList(1, j) = distinctList(1, j) & ", " & i + 1
'k = k + 1
Exit For
End If
If j = UBound(distinctList, 2) Then
ReDim Preserve distinctList(0 To 1, 1 To UBound(distinctList, 2) + 1)
distinctList(0, j) = arr(i)
distinctList(1, j) = distinctList(UBound(distinctList, 2), 1) & ", " & i + 1
Exit For
End If
Next j
End If
Next i
Debug.Print distinctList(0, 0) & " => " & distinctList(1, 0)
'distinctValues = distinctList
End Function
It's because you can't change the lower bound of the second dimension, you need to keep it the same..
You declare ReDim distinctList(0 To 1, 0 To j) at the top
when you redim, you need to keep lower bound of the second dimension at 0
ReDim Preserve distinctList(0 To 1, 0 To UBound(distinctList, 2) + 1)
I think you could implement this general solution to your particular solution if you apply this code to change the nr. of dimensions before you add the/a new category.
Option Explicit
Public Sub redimarray()
'This sub redimensions an array as an array of arrays, so to acces the k'th element in the n-th dimension you need to type: my_array(n)(k)
'and you can still simply redefine the array dimensions by:
'my_array =FlexArray("lower_bound_n-th_dim,lower_bound_n-th_dim,_n+1-th_dim,upper_bound_n-th_dim,_n+1-th_dim) = e.g.: FlexArray("2,3,9,11")
'if you then want to have conventional array element conventional_array(3,4) you can copy the entire my_array into a 1 dimensional array where
' the array elements are added like a (nr-of_elements_per_dimension)-base numbering system. once they have been manipulated, you can store them back into
'nr of elements per dimension:
'dim 0 = 4, 0-3
'dim 1 = 3, 4-6
'dim 2 = 8, 1-8
'nr of elements in 1dim array = 4*3*8 = 96
'(0)(4)(1)
'(0)(4)(2)
'...
'(0)(4)(8)
'(0)(5)(1)
'so working_array(3,5,2) = (3-0)*nr_elem(dim 1)*nr_elem(dim 2)+(5-4)*nr_elem(dim 2)+(2-1)
'dim 0 = nr_elements(0), start_element(0)-end_element(0)
'dim 1 = nr_elements(1), start_element(1)-end_element(1)
'dim 2 = nr_elements(2), start_element(2)-end_element(2)
'so working_array(3,5,2) = (end_element(0)-start_element(0))*nr_elements(1)*nr_elements(2)+(end_element(1)-start_element(1))*nr_elements(2)+'so working_array(3,5,2) = (end_element(0)-start_element(0))*nr_elements(1)*nr_elements(2)+(end_element(2)-start_element(2))=index in 1 dimensional array.
Dim NewArray() As Variant
NewArray = FlexArray("1,2,3,8,2,9")
'NewArray = FlexibleArray("1,2,3,8,2,9")
MsgBox (NewArray(1)(8))
End Sub
Public Function FlexArray(strDimensions As String) As Variant
Dim arrTemp As Variant
Dim varTemp As Variant
Dim varDim As Variant
Dim intNumDim As Integer
Dim iDim As Integer
Dim iArr As Integer
varDim = Split(strDimensions, ",")
intNumDim = (UBound(varDim) + 1) / 2
' Setup redimensioned source array
ReDim arrTemp(intNumDim)
iArr = 0
For iDim = LBound(varDim) To UBound(varDim) Step 2
ReDim varTemp(varDim(iDim) To varDim(iDim + 1))
arrTemp(iArr) = varTemp
iArr = iArr + 1
Next iDim
FlexArray = arrTemp
End Function

vb.net insert record into dataset cell from a loop

For j = 0 To wcData.Tables(0).Rows.Count - 1
For i = 900 To 1700
wcData.Tables("db").Rows(j)("range") = i
Next
Next
trying to insert "i" into each column cell of "range"
any suggestion.
Thanks.
Dim rowOffset As Integer = 900;
For j = 0 To wcData.Tables(0).Rows.Count - 1
wcData.Tables("db").Rows(j).Item("range") = rowOffset + j
Next
Dim rowOffset As Integer = 900
For j = 0 To wcData.Tables(0).Rows.Count - 1
wcData.Tables("ratingout").Rows(j).Item("range") = rowOffset + j
If i >= 1700 Then
Exit For
End If
Next
this worked for now.
thanks