How to create and pass array of strings to sub in Excel VBA?
VBA arrays are new to me, and it seems that there are several ways to create arrays of strings.
- I think I need to create a dynamic array
- But I can't find examples of how to pass dynamic arrays to a subroutine
I know how many elements should be in the array by User range count (so maybe I don't need a dynamic array?). I am having trouble passing an array to another routine.
The thought process looks like this:
- Iterating through a list of usernames
- Create a sheet for everyone
- Store each username in an array as I iterate
- In another subroutine select all sheets I created and save them as PDF
Below is my code. I am getting runtime error 9 - index out of range (refers to an array object)
I appreciate any help! Thank!
Sub CreateAllDashboards(StartDate As Date, EndDate As Date)
'Used to iterate through the list of users and call the Sub to create Dashboards
Dim UserNameRangeStart As Range
Set UserNameRangeStart = Range("UserName")
Dim SheetNames() As String
'Cyle through users
For i = 1 To GetUserNameRange().CounT
'Some code
ReDim Preserve SheetNames(i)
SheetNames(i) = UserNameRangeStart.Offset(i, 0).Value
Next i
Call CreatePDF(EndDate, SheetNames) 'Also tried SheetNames()
End Sub
Sub CreatePDF(FileDate As Date, ByRef SheetNames As Variant)
Dim FilePath As String, FileName As String
FilePath = Application.ActiveWorkbook.Path
FileName = "Production Dashboards - " & Format(FileDate, "mmddyy") & ".pdf"
ThisWorkbook.Sheets(SheetNames).Select
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, FileName:= _
FileName, Quality:=xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, OpenAfterPublish:=True
End Sub
source to share
The array parameter is not a problem, it was passed to the method correctly CreatePDF(...)
. The parameter type can be changed to SheetNames() As String
, but SheetNames As Variant
also works.
Then it Run-time error 9 - Subscript out of range
occurs here ThisWorkbook.Sheets(SheetNames).Select
because the array SheetNames
contains an invalid sheet name, this is the very first element. This element is an empty string and an empty string is not valid as a sheet name.
At the index, the loop For Next
starts at value 1
, but the array starts at 0
. This way the very first element of the array SheetNames
is left untouched and is finally an empty string. To solve this problem, set the lower border ReDim
explicitly to 1
. NTN
(Note: if you omit the lower border, it is used Option Base
, and if not specified Option Base
, then it is used 0
.)
'Cyle through users
For i = 1 To GetUserNameRange().Count
'Some code
ReDim Preserve SheetNames(1 To i)
SheetNames(i) = UserNameRangeStart.Offset(i, 0).value
Next i
source to share
I would change this: Sub CreatePDF(FileDate As Date, ByRef SheetNames As Variant)
To that: Sub CreatePDF(FileDate As Date, SheetNames() As String)
But your problem is this line: ThisWorkbook.Sheets(SheetNames).Select
Edited from dee's post: You can put an array of sheet names in .Sheets()
, but no blank lines. So, in your sub-CreateAllDashboards do the following:
ReDim Preserve SheetNames(i - 1)
SheetNames(i - 1) = UserNameRangeStart.Offset(i, 0).Value
and you can read about arrays in VBA.
source to share
I tested the following using a one page workbook with a range of Users and another FileDate file. He does what you asked.
The error Run-time error 9 - Subscript out of range
is caused by a reference to an array element. ThisWorkbook.Sheets(SheetNames).Select
will throw an error, but ThisWorkbook.Sheets(SheetNames(x)).Select
won't (as long as x is initialized and is within the array)
Sub PopulateArray()
Dim user As Range
Dim SheetNames As Variant
ReDim SheetNames(1 To 1) 'Initialise the array
For Each user In [Users]
ThisWorkbook.Sheets.Add After:=Worksheets(Worksheets.Count)
With Worksheets(Worksheets.Count)
.Name = user.Value2
.[A1] = user.Value2 'you can't print a blank sheet!
End With
SheetNames(UBound(SheetNames)) = user.Value2
ReDim Preserve SheetNames(1 To UBound(SheetNames) + 1)
Next user
ReDim Preserve SheetNames(1 To UBound(SheetNames) - 1) 'Delete the last element
Call CreatePDF([FileDate], SheetNames)
End Sub
Sub CreatePDF(FileDate As Date, ByRef SheetNames As Variant)
Dim FilePath As String, FileName As String
Dim x As Long
FilePath = Application.ActiveWorkbook.Path & "\" 'Note backslash added to path.
FileName = "Amtec Production Dashboards - " & Format(FileDate, "mmddyy")
For x = 1 To UBound(SheetNames)
ThisWorkbook.Sheets(SheetNames(x)).ExportAsFixedFormat Type:=xlTypePDF, FileName:= _
FileName & SheetNames(x) & ".pdf", Quality:=xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, OpenAfterPublish:=True
Next x
End Sub
The above example demonstrates how to parse an array to another under the requested request, but you can also easily integrate the CreatePDF code into the calling sub.
source to share