Iterate through multiple sheets from stored array - arrays

I've seen multiple posts about this, but none seem to directly address what i'm looking to do (in a way that I understand atleast).
I'm looking to iterate through my various sheets and format the data in each sheet into a table; seemingly very simple, but i'm struggling with storing the sheets into an array for easy iteration through a for loop.
I'm passing in the formatSheetsArray from the main, which has the following data stored in it: formatTablesArray = Array(lo.Name, wa.Name, sevenA.Name, oh.Name, at.Name, ob.Name, ra.Name, cvr.Name, ln.Name)
The sheets have all had their code names changed for easier manipulation, but now i'm confused how I should iterate through them from an array standpoint. There are other sheets in the workbook so I can't use sheets.count and I attempted to use For Each Worksheet In formatSheetArray and I received the same error I'm receiving now, which is Error 424 Object required. Any thoughts?
Private Sub FormatOiTables(ByVal formatSheetsArray As Variant, ByRef cmeBook As Workbook)
Dim loopCounter As Integer, lastRow As Integer
For loopCounter = 0 To UBound(formatSheetsArray)
lastRow = cmeBook.Sheets(formatSheetsArray(loopCounter)).Cells(formatSheetsArray(loopCounter).Rows.Count, "A").End(xlUp).Row
Next
End Sub

You can make and use an array of worksheet-objects:
formatTablesArray = Array(lo, wa, sevenA....)
and then do
for each tbl in formaTablesArray
tbl.
next

Solution that I just got working for the problem above. As #Siddhart pointed out as well I had a typo for my cmeDataBook Workbook, which was initially typed in as cmeBook. Thanks to all!
Private Sub FormatOiTables(ByVal formatSheetsArray As Variant, ByRef cmeDataBook As Workbook)
Dim WshtNameCrnt As Variant
Dim lastRow As Integer
For Each WshtNameCrnt In formatSheetsArray
cmeDataBook.Sheets(WshtNameCrnt).Activate
With Worksheets(WshtNameCrnt)
lastRow = .Cells(Worksheets(WshtNameCrnt).Rows.Count, "A").End(xlUp).Row
End With
MsgBox (lastRow & " " & WshtNameCrnt)
Next WshtNameCrnt
End Sub

Related

Using arrays in a loop

Each page (01,02...11,12) represents a month of the year.
Each page has different staff and salaries. I want to see the workers data on these pages in one page. While doing this, I need to do some operations. Since it would be slow in terms of speed, I wanted to do the operations inside the arrays instead of copying this data to a page and performing the operations there.
What I actually want to do and learn.
We can navigate pages one by one in a loop. I want to do the same for arrays (1st array, 2nd array, ... 11 array, 12 array).
Option Explicit
Option Base 1
Dim d1() As Variant, d2() As Variant, d3() As Variant, d4() As Variant, d5() As Variant, d6() As Variant
Dim d7() As Variant, d8() As Variant, d9() As Variant, d10() As Variant, d11() As Variant, d12() As Variant
Dim personel As Collection, sonuc() As Variant, d() As Variant
Sub Example()
Dim i As Integer
For i = 1 To Worksheets.Count
Debug.Print Worksheets(i).Name
Next i
End Sub
Sub Example2()
Dim i As Integer
For i = 1 To 12
' ???? d & i = Worksheets(i).Range("A1:AA34")
Next i
End Sub
I recommend creating a 2 dimensional array of data where each elemnt holds the information for a single worksheet.
Creating an Employee class would make the life easier in the long run. WatchClass Modules Explained in Simple English (with examples)
Sub Main()
Dim Data As Variant
Data = AllWorkSheetData
Stop
End Sub
Function AllWorkSheetData() As Variant()
Dim Result As Variant
ReDim Result(1 To Worksheets.Count)
Dim i As Long
For i = 1 To Worksheets.Count
Result(i) = Worksheets(i).Range("A1:AA34")
Next i
AllWorkSheetData = Result
End Function
Do you need 12 different arrays for your operation?
If you want to paste the data one after the other on a single sheet, you can use a single array and reassign values in each iteration.
Dim d() As Variant, i As Integer
For i = 1 to Worksheets.Count
d = Worksheets(i).Range("A1:AA34").Value2
'Do your calculations with d array.
'
'
'
'Paste d array in aggregate sheet.
Next i
Also, use Excel object datatypes along with For Each loop instead of integers. It is much better to understand.
Dim ws As Worksheet
Dim d() As Variant
For Each ws In Worksheets
d = ws.Range("A1:AA34").Value2
'Do your calculations with d array.
'
'
'
'Paste d array in aggregate sheet.
Next ws
You need to create an array to hold variants that you are connecting on to the data from your sheet:
Dim d(1 To 12) As Variant
Dim i As Integer
For i = 1 To 12
d(i) = Worksheets(i).Range("A1:AA34")
Debug.Print d(i)(1, 1) ' access one the value from one cell of the sheet that has been read into the array.
Next i
End Sub

Create a VBA Array from Column Headers?

I have a an export "NewExport" that always randomizes the columns of data I receive. I need these columns to align with the order of columns in "TheOrder", so this code will help to re-organize the export to align with the column headers I've already built.
I have 132 columns that need re-alignment, and while I can type it all out, there must be an easier way to align with the column headers I've already created. It should be noted that the below code is shamelessly copy/pasted from another StackOverflow answer.
Sub OrderColumns(ByVal NewExport As Workbook, ByVal TheOrder As Worksheet)
Dim correctOrder() As Variant
Dim lastCol As Long
Dim headerRng As Range, cel As Range
Dim mainWS As Worksheet
Set mainWS = NewExport.Worksheets("Sheet1")
'Need to figure out how to make this an array based on a Range
correctOrder() = Array(TheOrder.Range("A1:A132").Value)
With mainWS
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
Set headerRng = .Range(.Cells(1, 1), .Cells(1, lastCol))
End With
Dim newWS As Worksheet
Set newWS = Ninja.Sheets.Add
newWS.Name = "Rearranged Sheet"
Dim col As Long
With newWS
For col = 1 To lastCol
For Each cel In headerRng
If cel.Value = correctOrder(col - 1) Then
mainWS.Columns(cel.Column).Copy .Columns(col)
Exit For
End If
Next cel
Next col
End With
End Sub
While it's not as automated as I would have liked (and requires one piece of hard-coding), I was able to find a solution as such:
Dim correctOrder(132) As Variant
'132 will need to be changed if there's ever any more/less columns added/excluded
For i = 1 To 132
correctOrder(i - 1) = TheOrder.Range("A" & i).Value
Next
This solution gave me the array I was looking for for use later on.
I recently wrote a 'column finder' function for a project of mine.
I've modified it to suit your requirements below.
The function requires you pass the workbook your correct ordered headings are in to capture. You could modify this to require your TargetWorksheet instead so it's a bit more dynamic.
The function returns a single dimension Array.
The function finds the last used Column in the Target Worksheet allowing for changes in the number of column headings (as mentioned in your own answer which has the column number hard coded).
Public Function CorrectOrderHeadingsArrayFunction(ByRef TargetWorkbook As Workbook) As Variant()
With TargetWorkbook.Sheets(1) 'Change this to target your correct sheet
Dim LastColumn As Long
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
CorrectOrderHeadingsArrayFunction= Application.Transpose(Application.Transpose(.Range(.Cells(1, 1), .Cells(1, LastColumn)).Value)) 'This returns the array as single dimension rather than 2D
End With
End Function
As an example, below is some sample 'Test' code to show the concept of using this function .
You could call it like so, and loop through each element perhaps comparing another arrays elements to the correct order elements and do something when the correct order value is found.
Sub TestSub()
Dim CorrectOrderArray As Variant
Dim TargetCorrectOrderElement As Variant
Dim RandomOrderArray As Variant
Dim TargetRandomOrderElement As Variant
CorrectOrderArray = CorrectOrderHeadingsArrayFunction(Workbooks("Export (4).csv")) 'Change this to target your correct workbook
RandomOrderArray = Sheet1.Range("A1:AZ1000") 'Change this to target the correct range for your data.
For Each TargetCorrectOrderElement In CorrectOrderArray
For TargetRandomOrderElement = LBound(RandomOrderArray) To UBound(RandomOrderArray)
If RandomOrderArray(TargetRandomOrderElement) = TargetCorrectorderValue Then
'Do some code to write that column to your worksheet
Exit For 'Leaves the current iteration of the random order array loop to go to the next iteration of the correct order array
End If
Next TargetRandomOrderElement
Next TargetCorrectOrderElement
End Sub

Create One-Dimensional array from evaluate

Background:
I'm trying to loop through a series of sheets in a workbook from an Array given certain sheets names.
Code
Instead of the more conventional:
Sub test()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets(Array("Sheet1", "Sheet2", "Sheet3"))
Debug.Print ws.Name
Next ws
End Sub
I'm using a different method that makes it all a bit easier to extend the array to like 10 worksheets, or start at another number, like so:
Sub test()
Dim ws As Worksheet
Dim arr As Variant: arr = ["Sheet"&ROW(1:3)]
For Each ws In ThisWorkbook.Sheets(arr)
Debug.Print ws.Name
Next ws
End Sub
Problem:
However ["Sheet"&ROW(1:3)] will create a two-dimensional array which will throw an Error 13 on the start of the For each... loop because the array expects a one-dimensional array.
I can addres this problem using a simple TRANSPOSE like:
Sub test()
Dim ws As Worksheet
Dim arr As Variant: arr = [TRANSPOSE("Sheet"&ROW(1:3))]
For Each ws In ThisWorkbook.Sheets(arr)
Debug.Print ws.Name
Next ws
End Sub
Question:
Maybe my brain is tired but right now I fail to understand why ["Sheet"&ROW(1:3)] would not create a one-dimensional array. Does anybody know?
I'm afraid the answer is simple, and I'll have one of those "Ahaaaa" moments.
In Short:
ROW(1:3) is a Range. Ranges that contain more than one cell are two dimensional arrays. Thus you get a two dimensional return.

Delete all contents except for first row for specific sheets in Excel

Please assist. I have this code here and it works for first sheet however, does not execute in the 2nd sheet. I think i'm missing a sheet syntax. thanks.
Dim arrSheets As Variant, sht As Variant
arrSheets = Array("tl_1", "tl_2")
For Each sht In arrSheets
Sheets(sht).UsedRange.Offset(1).ClearContents
Next sht
My 2 cents: do not rely on worksheet names. Instead, work with their (Name) property as seen from the Visual Basic Editor. Note that you can give significant names yourself instead of the default Sheet1..N ones. This way, your code will survive modifications to the names as seen from Excel, in the tabs at the bottom.
Option Explicit
Public Sub DoTheClearThing()
Dim loopVariant As Variant
Dim loopWorksheet As Excel.Worksheet
Dim worksheetsToConsider As Variant
'Use the (Name) property, as seen from the Visual Basic Editor, of the worksheets you're interested in.
'The array below is not a string array; it is an array of worksheet objects.
worksheetsToConsider = Array(TL_1, TL_2)
'The For's variable must be a Variant; you can then Set it to a variable of the Worksheet type and enjoy Intellisense.
For Each loopVariant In worksheetsToConsider
Set loopWorksheet = loopVariant
loopWorksheet.UsedRange.Offset(1).ClearContents
Next
End Sub
Here's what the worksheets' (Name) properties look like in my test Excel workbook:
From within your workbook's code, you can directly interact with worksheet objects using their (Name) property. Avoid ThisWorkbook.Worksheets("tl_1").SomeMethod and directly go with TL_1.SomeMethod. By the way, a worksheet's (Name) property can be read by code using its CodeName property.
Option Explicit
'This will do something to your target sheets,
'just make sure your "something" is what you want
Dim N As Long
Dim wsName As String
'Optional if included
For N = 1 To ThisWorkbook.Sheets.Count
wsName = ThisWorkbook.Worksheets(N).Name
If wsName = "tl_1" or wsName = "tl_2" Then
ThisWorkbook.Worksheets(N).UsedRange.Offset(1).ClearContents
Else 'Do Nothing
End If
Next N
Note: This is very worksheet name dependent and users can change those if you are not the only user. You may want to CodeName your sheets (properties Explorer and change the Name) then pull the CodeName.
You can use an array to hold the sheets names but it seems like more trouble than its worth unless you are going to load the names into the array.
-WWC
Worksheet.UsedRange does not always return the correct address. Consider the results of the test below:
Test Used Range
Sub Test()
Application.ScreenUpdating = False
Dim cell As Range, target As Range
Debug.Print "Data Range", "|"; "UsedRange"
Debug.Print String(24, "_")
With Worksheets.Add
Set target = .Range("B2:D2")
target.Value = 1
Debug.Print target.Address, "|"; .UsedRange.Address
End With
With Worksheets.Add
.Range("A1:G10").Interior.Color = 65535
Set target = .Range("B2:D2")
target.Value = 1
Debug.Print target.Address, "|"; .UsedRange.Address
End With
End Sub
Clear Non-Headers
Sub ClearNonHeaderRows()
Dim arrSheets As Variant, sht As Variant
Dim cell As Range
arrSheets = Array("tl_1", "tl_2")
For Each sht In arrSheets
With Worksheets(sht).UsedRange
Set cell = .Find("*", .Cells(1, 1))
If Not cell Is Nothing Then
cell.Offset(1).Resize(.Cells.Rows.Count - cell.row + .Cells(1, 1).row).EntireRow.ClearContents
End If
End With
Next sht
End Sub

Assign range to an array and paste data to the array

i am very new to coding and recently attended a few beginner training to VBA. i started learning array and was thinking to assign a range to it and use this array in my excel function(copy paste) like below.. im sure thisis not the right way to do it since i got an error with my range...
Dim lastrow As String
Dim Myarr As Variant
lastrow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
Myarr = ActiveSheet.Range("S6, U6, W6")
Range("D6").Select
Selection.Copy
Range(Myarr & lastrow).Select
Selection.PasteSpecial xlPasteFormats
You will need to load the ranges as strings:
"S6:S"
As the & concatenates a string. So Lastrow being a number one needs to include the S for then end cell.
Also avoid using .Select it slows the code down.
You will also need to loop through the array. It will not work as one shot.
Dim lastrow As String
Dim Myarr() As Variant
Dim str As Variant
lastrow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
Myarr = Array("S6:S", "U6:U", "W6:W")
Range("D6").Copy
For Each str In Myarr
Range(str & lastrow).PasteSpecial xlPasteFormats
Next str

Resources