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.
Related
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
I'm trying to search for a substring within an array using the filter function and then creating a new array of strings which include that substring. When I try, I get a type mismatch runtime error 13 message. I've read that filter can only be used on a 1-dimensional array and that populating an array with a range automatically creates a 2-dimensional array, but I thought I'd read I could get around this problem if I transposed the array when creating it. I think I might be wrong about that as it still doesn't seem to work for me.
Before the bug strikes, the headerTitles array is populated with the following strings:
vaccination_date
year
month
day
site
dose
vaccine
vaccination_setting
This is all using Excel 2010.
Thanks for any help.
Sub dateInHeaderTitle()
Dim ws As Worksheet
Dim lastCol As Integer
Dim headerTitles As Variant
Dim dateTitles As Variant
Set ws = ThisWorkbook.Worksheets(1)
With ws
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
headerTitles = Application.Transpose(.Range(.Cells(1, 1), .Cells(1, Lastcol)).Value2)
End With
dateTitles = Filter(headerTitles, "date", , vbTextCompare)
Set ws = Nothing
End Sub
In order to obtain a 1D array, starting from a column range, you should use:
headerTitles = Application.Transpose(Application.Transpose(.Range(.cells(1, 1), .cells(1, lastCol)).Value2))`
Debug.Print Join(headerTitles, "|") 'just to see it...
I have a code in a userform in vba excel:
Dim TimeArray() As Variant
TimeArray = Worksheets("Data").Range("E1:E30").Value
MsgBox TimeArray(0)
The error is
"Subscript is out of range"
while my range (E1:E3) have data.
Converting range to array is a standard procedure in VBA. In general, when you do it explicitly like this TimeArray = Worksheets("Data").Range("E1:E30").Value, VBA translates it to a 2D-array. Thus, to get the first value you have to ask TimeArray(1, 1), because the cells in Excel start with column 1 and row 1:
Sub TestMe()
Dim TimeArray() As Variant
TimeArray = Worksheets(1).Range("E1:E30")
MsgBox TimeArray(1, 1)
End Sub
With Application.Transpose(), you can force a 1-dimensional array from one column:
Sub TestMeAndTransposeMe()
Dim TimeArray() As Variant
TimeArray = Application.Transpose(Worksheets(1).Range("E1:E30"))
MsgBox TimeArray(1)
Dim i As Long
For i = LBound(TimeArray) To UBound(TimeArray)
Debug.Print i; TimeArray(i)
Next i
End Sub
You can see additional examples of the useage of Application.Transpose() here:
How to populate array from a sheet column in Excel
quick question on why the below vba for printing won't work... If I have it set up individually (Sheet1.PrintOut) it prints out fine, but if I do it as array(Sheet1, Sheet2, Sheet3).PrintOut it doesn't work. Can anyone explain why?
Sub printnow()
Dim Sheet1 As Worksheet
Dim Sheet2 As Worksheet
Dim Sheet3 As Worksheet
With ThisWorkbook
Set Sheet1 = .Sheets("database1")
Set Sheet2 = .Sheets("database2")
Set Sheet3 = .Sheets("database3")
'Setting up the print setup
Sheet3.PageSetup.PaperSize = xlPaperLegal
Sheet3.PageSetup.Orientation = xlPortrait
'Print
End With
Array(Sheet1,Sheet2.Sheet3).PrintOut Copies:=1
End Sub
The Array function call returns a Variant() containing Sheet1, Sheet2, and Sheet3. A Variant() doesn't have a .PrintOut method - it isn't an object. If you want to call .PrintOut on each of the objects in the array, just loop over it:
Dim sheet As Variant
For Each sheet In Array(Sheet1, Sheet2, Sheet3)
sheet.PrintOut Copies:=1
Next
You can pass an array of sheet names to Sheets and it will process them.
Sheets(Array("database1", "database2", "database3")).Printout Copies:=1
You can also use the Sheet.Name:
Sheets(Array(Sheet1.Name, Sheet2.Name, Sheet3.Name)).Printout Copies:=1
Or you can use the sheet's indices:
Sheets(Array(1,2,3)).Printout Copies:=1
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