Add worksheets to array by VBA - arrays

I practice on VBA for one month and I have some problem.I want to create array from data in worksheet by this loop but it doesn't work. I have 6 worksheets but it can get only one worksheet into array. I think problem in this loop is DataArray but I can't solve it.
Sub LoopByArray()
Dim ws As Worksheet
Dim LastRow As Long
Dim LastCol As Long
Dim DataArray() As Variant
Dim Sheetnum As String
Dim SheetNames()
Dim i As Long
SheetCount = ActiveWorkbook.Sheets.Count
ReDim SheetNames(1 To SheetCount)
For i = 1 To SheetCount
SheetNames(i) = ActiveWorkbook.Sheets(i).Name
Debug.Print SheetNames(i)
Sheetnum = i
Set ws = worksheets(SheetNames(i))
LastRow = ThisWorkbook.Sheets(SheetNames(i)).Range("A" & Rows.Count).End(xlUp).Row
Debug.Print LastRow
LastCol = ThisWorkbook.Sheets(SheetNames(i)).Cells(1, ThisWorkbook.Sheets(SheetNames(i)).Columns.Count).End(xlToLeft).Column
Debug.Print LastCol
ColLetter = GetColumnLetter(LastCol)
DataArray = ThisWorkbook.Sheets(SheetNames(i)).Range("A1" & ":" & ColLetter & LastRow).Value
Next i
End Sub
Function GetColumnLetter(colNum As Long) As String
Dim vArr
vArr = Split(Cells(1, colNum).Address(True, False), "$")
GetColumnLetter = vArr(0)
End Function

Here's a couple of possibilities to work with
Public Sub Shts2Arrays()
Dim ShtAR1() As Variant, ShtAR2() As Variant, ShtAR3() As Variant
Dim i As Integer, J As Integer
ShtAR1 = Sheets(1).UsedRange.Value
ShtAR2 = Sheets(2).UsedRange.Value
ShtAR3 = Sheets(3).UsedRange.Value
For i = LBound(ShtAR1) To UBound(ShtAR1)
For J = 1 To Sheets(1).UsedRange.Columns.Count
Debug.Print i, J, ShtAR1(i, J)
Next J
Next i
For i = LBound(ShtAR2) To UBound(ShtAR2)
For J = 1 To Sheets(2).UsedRange.Columns.Count
Debug.Print i, J, ShtAR2(i, J)
Next J
Next i
For i = LBound(ShtAR3) To UBound(ShtAR3)
For J = 1 To Sheets(3).UsedRange.Columns.Count
Debug.Print i, J, ShtAR3(i, J)
Next J
Next i
End Sub
In the following the arrays are transposed using Application.Transpose otherwise the same
Public Sub TransposeShts2Arrays()
Dim ShtAR1() As Variant, ShtAR2() As Variant, ShtAR3() As Variant
Dim i As Integer, J As Integer
ShtAR1 = Application.Transpose(Sheets(1).UsedRange.Value)
ShtAR2 = Application.Transpose(Sheets(2).UsedRange.Value)
ShtAR3 = Application.Transpose(Sheets(3).UsedRange.Value)
For i = LBound(ShtAR1) To UBound(ShtAR1)
For J = 1 To Sheets(1).UsedRange.Columns.Count
Debug.Print i, J, ShtAR1(i, J)
Next J
Next i
For i = LBound(ShtAR2) To UBound(ShtAR2)
For J = 1 To Sheets(2).UsedRange.Columns.Count
Debug.Print i, J, ShtAR2(i, J)
Next J
Next i
For i = LBound(ShtAR3) To UBound(ShtAR3)
For J = 1 To Sheets(3).UsedRange.Columns.Count
Debug.Print i, J, ShtAR3(i, J)
Next J
Next i
End Sub

You can make dataArray() a 1D array.
Option Explicit
Sub FillArrays()
Dim dataArray(), wb As Workbook, ws As Worksheet
Set wb = ThisWorkbook
ReDim dataArray(wb.Sheets.Count)
For Each ws In wb.Sheets
dataArray(ws.Index) = ws.UsedRange.Value
Next
Debug.Print dataArray(3)(1, 1) 'Sheets(3).Cells(1, 1)
End Sub

Related

Finding Cells in which all values of fixed array are present

I have an array with fixed values. How can I find cells in Column B that contain all the 'String' values present in array?
Here is my code
With Worksheets("Data")
Dim kwrSets As Variant
.Activate
kwrSets = .Range("B2:B" & Application.WorksheetFunction.Max(2, .Range("A100000").End(xlUp).Row)).Value
For k = LBound(kwrSets) To UBound(kwrSets)
For i = LBound(arr) To UBound(arr)
Delete entire row if all values of arr not found in kwrSets
Next i
Next k
End With
Following is the updated code based on the answer below but it is giving error "Subscript out of range" in inStr line.
Sub Extractor()
Dim ws As Worksheet, wsd As Worksheet
Dim cell As Variant
Dim tmp As Variant
Dim blnFound As Boolean
Dim j As Long, i As Long
Dim kwrSets() As Variant
Dim arr() As String
Set ws = Worksheets("Sheet1")
With ws
.Activate
For Each cell In .Range("A1:A" & .Cells(.Rows.Count, "B").End(xlUp).Row)
If (cell.Offset(0, 2) = 1) Then
tmp = tmp & cell & "|"
End If
Next cell
If Len(tmp) > 0 Then tmp = Left(tmp, Len(tmp) - 1)
arr = Split(tmp, "|")
End With
Set wsd = Worksheets("Data")
With wsd
.Activate
kwrSets = .Range("B2:B" & Application.WorksheetFunction.Max(2, .Range("A100000").End(xlUp).Row)).Value
For k = LBound(kwrSets) To UBound(kwrSets)
blnFound = True
For i = LBound(arr) To UBound(arr)
If InStr(kwrSets(j, 1), arr(i)) = 0 Then
blnFound = False
Exit For
End If
Next i
Next k
End With
End Sub
Below is some VBA code that gets all of the data in column B into an array, then loops this array checking for the existence of each of the elements in the search array. If any of the search elements are not found, then it exits that loop. If all elements are found then it highlights the cell.
Sub sFindArray()
Dim ws As Worksheet
Dim aSearch() As Variant
Dim aData() As Variant
Dim lngLoop1 As Long
Dim lngLoop2 As Long
Dim lngFirstRow As Long
Dim lngLastRow As Long
Dim lngLBound As Long
Dim lngUBound As Long
Dim blnFound As Boolean
aSearch = Array("a", "b", "c")
lngLBound = LBound(aSearch)
lngUBound = UBound(aSearch)
Set ws = Worksheets("Sheet1")
lngLastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
aData() = ws.Range("B1:B" & lngLastRow)
lngFirstRow = LBound(aData, 1)
lngLastRow = UBound(aData, 1)
For lngLoop1 = lngFirstRow To lngLastRow
blnFound = True
For lngLoop2 = lngLBound To lngUBound
If InStr(aData(lngLoop1, 1), aSearch(lngLoop2)) = 0 Then
blnFound = False
Exit For
End If
Next lngLoop2
If blnFound = True Then
ws.Cells(lngLoop1, 2).Interior.Color = vbRed
End If
Next lngLoop1
End Sub
Regards,

Excel VBA autofilter for multiple wildcard then change field value and filldown

I have search until I cannot find how to do this and it work properly. What I am trying to do is find a wildcard value that is more than one. I also would like to fill down column Z.
What is happening is that if I enter more than 1 wildcard it only finds one of them even though the column has many. If there is only 1 returned it inputs Tier 1 then on filldown it defaults back to Tier 2. What am I missing?
Thank you in advance for your help!
ActiveSheet.Range("$A$1:$AB$" & Rows.Count).End(xlUp).AutoFilter Field:=13, Criteria1:=Array( _
"*9365*", "*9575*", "*9375*"), _
Operator:=xlOr
With Worksheets("Raw Data").AutoFilter.Range
Range("Z" & .Offset(1, 0).SpecialCells(xlCellTypeVisible)(1).Row).Select
End With
ActiveCell.FormulaR1C1 = "Tier 1"
With ActiveSheet.UsedRange
.Resize(.Rows.Count - 1).Offset(1).Columns("Z"). _
SpecialCells(xlCellTypeVisible).FillDown
End With
I have tried the fix per #dwirony but my values return no data.
Sub AutoFilterWorkaround()
Dim sht As Worksheet
Dim filterarr As Variant, tofindarr As Variant
Dim lastrow As Long, i As Long, j As Long, k As Long
Set sht = ThisWorkbook.Worksheets("Raw Data")
lastrow = sht.Cells(sht.Rows.Count, "Z").End(xlUp).Row
'List the parts of the words you need to find here
tofindarr = Array("9365", "9375")
ReDim filterarr(0 To 0)
j = 0
For k = 0 To UBound(tofindarr)
For i = 2 To lastrow
If InStr(sht.Cells(i, 1).Value, tofindarr(k)) > 0 Then
filterarr(j) = sht.Cells(i, 1).Value
j = j + 1
ReDim Preserve filterarr(0 To j)
End If
Next i
Next k
'Filter on array
sht.Range("$A$1:$AB$" & lastrow).AutoFilter Field:=13,
Criteria1:=Array(filterarr), Operator:=xlFilterValues
End Sub
This is a picture of the result of the filtered list if I manually enter "95"
This code did the trick!
Sub AutoFilterWorkaround()
Dim sht As Worksheet
Dim filterarr As Variant, tofindarr As Variant
Dim lastrow As Long, i As Long, j As Long, k As Long
Set sht = ThisWorkbook.Worksheets("Raw Data")
lastrow = sht.Cells(sht.Rows.Count, "M").End(xlUp).Row
'List the parts of the words you need to find here
tofindarr = Array("9365", "9375")
ReDim filterarr(0 To 0)
j = 0
For k = 0 To UBound(tofindarr)
For i = 2 To lastrow
If InStr(sht.Cells(i, 13).Value, tofindarr(k)) > 0 Then
filterarr(j) = sht.Cells(i, 13).Value
j = j + 1
ReDim Preserve filterarr(0 To j)
End If
Next i
Next k
'Filter on array
sht.Range("$M$1:$M$" & lastrow).AutoFilter Field:=13,
Criteria1:=Array(filterarr), Operator:=xlFilterValues
End Sub

Create an array of rows VBA

New to VBA. I'm trying to create an array of rows.
Basically, I have an entire sheet and want to take all the rows that start with a certain value ("MA") in column 8.
I eventually want to manipulate that array (as if it were a range), and paste it somewhere else in the sheet. Can anyone help? Here's my code so far:
Dim top0M As Variant
ReDim top0M(1 To 1) As Variant
For i = 4 To Rows.Count
If Cells(i, 8).Value Like "MA*" Then
top0M(UBound(top0M)) = Rows(i)
ReDim Preserve top0M(1 To UBound(top0M) + 1) As Variant
End If
Next i
This code runs but I'm not sure how to debug it to know if I even have the right rows inside. Can I paste these rows as if they were a range?
This sets the range and loads the whole into an array then it loads a different array with the lines that you want:
With ActiveSheet 'This should be changed to the name of the worksheet: Worksheets("MySheet")
Dim rng As Range
Set rng = .Range(.Cells(4, 1), .Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, .Cells(4, .Columns.Count).End(xlToLeft).Column))
Dim tot As Variant
tot = rng.Value
Dim top0M As Variant
ReDim top0M(1 To Application.CountIf(.Range("H:H"), "MA*"), 1 To UBound(tot, 2)) As Variant
Dim k As Long
k = 1
Dim i As Long
For i = LBound(tot, 1) To UBound(tot, 1)
If tot(i, 8) Like "MA*" Then
Dim j As Long
For j = LBound(tot, 2) To UBound(tot, 2)
top0M(k, j) = tot(i, j)
Next j
k = k + 1
End If
Next i
End With
'to print to a sheet just assign the values:
Worksheets("sheet1").Range("A1").Resize(UBound(top0M, 1), UBound(top0M, 2)).Value = top0M
Try this code
Sub Test()
Dim x As Variant
x = ActiveSheet.Range("A4").CurrentRegion.Value
x = FilterArray(x, 8, "MA*", True)
ActiveSheet.Range("K14").Resize(UBound(x, 1), UBound(x, 2)).Value = x
End Sub
Function FilterArray(ByVal myRefArr As Variant, ByVal col As Integer, ByVal refValue As String, ByVal equal As Boolean) As Variant
Dim a As Variant
Dim i As Long
Dim j As Long
Dim n As Long
On Error Resume Next
n = 1
If refValue = "" Then
FilterArray = myRefArr
Else
ReDim a(1 To UBound(myRefArr, 1), 1 To UBound(myRefArr, 2))
For i = 1 To UBound(a, 1)
If IIf(equal, UCase(myRefArr(i, col)) Like UCase(refValue), Not (UCase(myRefArr(i, col)) Like UCase(refValue))) Then
For j = 1 To UBound(a, 2)
a(n, j) = myRefArr(i, j)
Next j
n = n + 1
End If
Next i
a = Application.Transpose(a)
ReDim Preserve a(1 To UBound(a, 1), 1 To n - 1)
a = Application.Transpose(a)
FilterArray = a
End If
On Error GoTo 0
End Function

Subtraction of two multidimensional Arrays VBA

I have a problem with a selfmade vba-code. The makro should solve the following problem: I use a "cockpitfile" It should load the elemts of two worksheets from two different Excel files into two Arrays. The Elements of these Arrays should be subtracted from each other. I want to get the difference from these two elements. As an example: ArrayElm1(1,1) - ArrayElm2(1,1) = ArrayElm3(1,1), ArrayElm1(1,2) - ArrayElm2(1,2) = ArrayElm3(1,2) etc.
On the first sight the code seems to work but when I check the results with my calculater the difference of the elements is wrong. Maybe there is a problem with the UBound because in my Ubound is only Array A?
Hope you can help me!
Sub Differenz1()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'Variabledefinition
Dim i As Long 'Index
Dim j As Long 'Index
Dim k As Long 'Index
Dim ArrayA As Variant 'Array
Dim ArrayB As Variant 'Array
Dim ArrayC(71, 25) As Variant 'Array
Dim myFile1 As String 'Workbookname
Dim myFile2 As String 'Workbookname
Dim wb1 As String 'Workbookname
Dim wb2 As String 'Workbookname
Dim WS_Count1 As Integer 'Count Worksheets
Dim WS_Count2 As Integer 'Count Worksheets
Dim arrays1 As String 'Dimension
Dim arrays2 As String 'Dimension
'Change the actual path
ChDrive "O:\"
ChDir "O:..."
myFile1 = Application.GetOpenFilename
Workbooks.Open Filename:=myFile1, ReadOnly:=True, IgnoreReadOnlyRecommended:=True
wb1 = ActiveWorkbook.Name
WS_Count1 = ActiveWorkbook.Worksheets.Count
myFile2 = Application.GetOpenFilename
Workbooks.Open Filename:=myFile2, ReadOnly:=True, IgnoreReadOnlyRecommended:=True
wb2 = ActiveWorkbook.Name
WS_Count2 = ActiveWorkbook.Worksheets.Count
For k = 1 To WS_Count1
ArrayA = Workbooks(wb1).Worksheets(k).Range("F5:Y75").Value
ArrayB = Workbooks(wb2).Worksheets(k).Range("F5:Y75").Value
For i = LBound(ArrayA, 1) To UBound(ArrayA, 1)
For j = LBound(ArrayA, 2) To UBound(ArrayA, 2)
If Not IsError(ArrayA(i, j)) And Not IsError(ArrayB(i, j)) Then ArrayC(i, j) = ArrayA(i, j) - ArrayB(i, j)
Next j
Next i
ThisWorkbook.Worksheets(k + 1).Range("F5:Y75").Value = ArrayC
Next k
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
You almost had it right, but the issues was that you didn't reset ArrayC
This code creates new sheets in ThisWorkbook for subtractions, and based on your previous question it checks for errors, and performs the subtractions only if both values are numbers
Option Explicit
Public Sub Differenz2()
Const USED_RNG = "F5:Y75" 'Main range
Dim i As Long, j As Long, k As Long, file1 As String, file2 As String, ws1Count As Long
Dim wb1 As Workbook, wb2 As Workbook, arr1 As Variant, arr2 As Variant, arr3 As Variant
'ChDrive "O:\": ChDir "O:..."
file1 = Application.GetOpenFilename: If file1 = "False" Then Exit Sub
file2 = Application.GetOpenFilename: If file2 = "False" Then Exit Sub
Application.ScreenUpdating = False
Set wb1 = Workbooks.Open(Filename:=file1, ReadOnly:=True)
Set wb2 = Workbooks.Open(Filename:=file2, ReadOnly:=True)
ws1Count = wb1.Worksheets.Count
If ws1Count = wb2.Worksheets.Count Then
MakeNewWS ws1Count 'Remove this line if ThisWorkbook is properly setup
For k = 1 To ws1Count
arr1 = wb1.Worksheets(k).Range(USED_RNG).Value
arr2 = wb2.Worksheets(k).Range(USED_RNG).Value
ReDim arr3(1 To 71, 1 To 20) 'reset array, based on USED_RNG ("F5:Y75")
For i = LBound(arr1, 1) To UBound(arr1, 1)
For j = LBound(arr1, 2) To UBound(arr1, 2)
If Not IsError(arr1(i, j)) And Not IsError(arr2(i, j)) Then
If IsNumeric(arr1(i, j)) And IsNumeric(arr2(i, j)) Then
arr3(i, j) = arr1(i, j) - arr2(i, j)
End If
End If
Next
Next
ThisWorkbook.Worksheets(k + 1).Range(USED_RNG) = arr3
Next
End If
wb1.Close False: wb2.Close False: ThisWorkbook.Worksheets(2).Activate
Application.ScreenUpdating = True
End Sub
Private Sub MakeNewWS(ByVal wsCount As Long)
Dim i As Long, ws As Worksheet
With ThisWorkbook.Worksheets
Application.DisplayAlerts = False
For Each ws In ThisWorkbook.Worksheets
If Left(ws.Name, 12) = "Subtraction " Then
If .Count = 1 Then .Add
ws.Delete
End If
Next
Application.DisplayAlerts = True
For i = 2 To wsCount + 1
.Add After:=ThisWorkbook.Worksheets(.Count)
ThisWorkbook.Worksheets(.Count).Name = "Subtraction " & i - 1
Next
End With
End Sub
You can ignore the MakeNewWS() sub if ThisWorkbook contains the proper number of sheets
Also, using arrays does improve performance (significantly)

copy only new data from one workbook to another

Found this code below that copies only "new" data from workbook1 to workbook2. It does what it suppose to but only limited to two columns A and B. My data span all the way to ZQ on every row. I tried to tweak the code for my purpose but its just beyond me. I appreciate any help.
Sub CompareArrays()
Dim arr1() As Variant, arr2() As Variant, arr3() As Variant
Dim i As Long, j As Long, k As Long, nextRow As Long
Dim wb1 As Workbook, wb2 As Workbook
Dim x As Boolean
Set wb1 = Workbooks("Workbook1.xlsm") 'Name of first workbook
Set wb2 = Workbooks("Workbook2.xlsx") 'Name of second workbook
arr1 = wb1.Sheets(1).Range("A2:B" & wb1.Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row).Value
arr2 = wb2.Sheets(1).Range("A2:B" & wb2.Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row).Value
For i = LBound(arr1) To UBound(arr1)
x = True
For j = LBound(arr2) To UBound(arr2)
If arr1(i, 1) = arr2(j, 1) Then
x = False
Exit For
End If
Next j
If x = True Then
k = k + 1
ReDim Preserve arr3(2, k)
arr3(1, k - 1) = arr1(i, 2)
arr3(0, k - 1) = arr1(i, 1)
End If
Next i
With wb2.Sheets(1)
nextRow = .Cells(Rows.Count, "A").End(xlUp).Row + 1
.Range(.Cells(nextRow, 1), .Cells(nextRow + k, 2)) = Application.Transpose(arr3)
End With
End Sub
Try following code:
Sub CompareArrays()
Dim arr1() As Variant, arr2() As Variant, arr3() As Variant
Dim i As Long, j As Long, k As Long, nextRow As Long
Dim wb1 As Workbook, wb2 As Workbook
Dim x As Boolean
Set wb1 = Workbooks("Workbook1.xlsm") 'Name of first workbook
Set wb2 = Workbooks("Workbook2.xlsx") 'Name of second workbook
arr1 = wb1.Sheets(1).Range("A2:A" & wb1.Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row).Value
arr2 = wb2.Sheets(1).Range("A2:A" & wb2.Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row).Value
k = 1
For i = LBound(arr1) To UBound(arr1)
x = True
For j = LBound(arr2) To UBound(arr2)
If arr1(i, 1) = arr2(j, 1) Then
x = False
Exit For
End If
Next j
If x = True Then
k = k + 1
pos = Application.Match(arr1(i, 1), arr1, False) + 1 'get position in array
nextRow = wb2.Sheets(1).Cells(Rows.Count, "A").End(xlUp).Row + 1
wb2.Sheets(1).Rows(nextRow).EntireRow.Value = wb1.Sheets(1).Rows(pos).EntireRow.Value
End If
Next i
End Sub

Resources