I have no clue how to do this so any help will be awesome. Using an array, I send row by row to an excel workbook, which does numerous calculations (too many to be programmed) and spits out 13 values which I want to store into another array. Is this possible?
Dim aP() as Variant
Dim wbR as Workbook
Dim wsR as Worksheet
Dim i as Long
Set wbR = Workbooks.Open([directory])
Set wsR = wbR.Sheets("Sheet1")
aP = Application.Transpose(Activesheet.Range("A1:Z100"))
For i = 1 to 100
wsR.Range("A1:A26") = Application.Index(aP, [row(1:26)], i)
'this is where I need help. Want to paste range C1:C13 into another array,
'so that I can paste it back into the activesheet. I do not wish to paste it
'straight back to the worksheet, but accumulate all the data into array and
'and then paste the array into the activesheet
Next i
Exit Sub
It seems like you're are trying to make your code ultra efficient. I made a few changes that may speed it up.
Sub BuildArrayR100C26()
Dim arData(99, 12)
Dim arCalculations
Dim i As Integer, j As Integer
Dim wbR As Workbook
Dim wsR As Worksheet
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set wbR = Workbooks.Open([directory])
Set wsR = wbR.Sheets("Sheet1")
For i = 0 To 99
wsR.Range("A1:A26").Value = Application.Transpose(ActiveSheet.Range("A1:Z1").Offset(i))
Application.Calculate
arCalculations = wsR.Range("C1:C13").Cells(j + 1)
For j = 0 To 12
arData(i, j) = arCalculations(j + 1, 1)
Next
Next i
Sheet2.Range("A1").Resize(UBound(arData, 1), UBound(arData, 2)).Value = arData
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
This line paste the range into wsR one row at a time.
wsR.Range("A1:A26").Value = Application.Transpose(ActiveSheet.Range("A1:Z1").Offset(i))
This loop copies your calculations into an array
For j = 0 To 12
arData(i, j) = wsR.Range("C1:C13").Cells(j + 1)
Next
Turn off ScreenUpdating and Calculation
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Recalculate after we paste the new data to be calculated
Application.Calculate
Related
I am looking for if it is possible to get the data and headers from a table as in the example image and have the output go to two columns with the first column being a repeating header? I did try the transpose however the email row kept populating up to column E.
Please, try the next way. It uses arrays being fast even for large ranges, mostly working in memory. It returns starting from "F2". It is able to process any other columns you (may) need, after "Status":
Sub TransposeMails()
Dim sh As Worksheet, lastR As Long, lastCol As Long
Dim arrH, arr, arrFin, i As Long, j As Long, k As Long
Set sh = ActiveSheet 'use here the necessary sheet
lastR = sh.Range("A" & sh.rows.count).End(xlUp).row 'last row
lastCol = sh.cells(1, sh.Columns.count).End(xlToLeft).column 'last column
arrH = Application.Transpose(sh.Range(sh.cells(1, 1), sh.cells(1, lastCol)).Value2) 'place headers in an array
arr = sh.Range("A2", sh.cells(lastR, lastCol)).Value2 'place the range to be processed (except headers) in an array for faster iteration/processing
ReDim arrFin(1 To (UBound(arrH) + 1) * UBound(arr), 1 To 2) 'Redim the final array (keeping the processed result)
'+ 1 for the empty rows in between...
For i = 1 To UBound(arr)
For j = 1 To UBound(arrH)
k = k + 1
arrFin(k, 1) = arrH(j, 1): arrFin(k, 2) = arr(i, j)
Next j
k = k + 1 'for the empty row between groups...
Next i
'drop the processed array content:
sh.Range("G2").Resize(UBound(arrFin), 2).Value2 = arrFin
End Sub
The code can be easily adapted to return anywhere (another sheet, workbook, range etc).
The range to be processed must start from "A1" ("Email" header) and not having any other record after the last header (on the first row)...
Transpose Data
Sub TransposeData()
Const SRC_NAME As String = "Sheet1"
Const DST_NAME As String = "Sheet1"
Const DST_FIRST_CELL As String = "A8"
Const EMPTY_COLS As Long = 0
Const EMPTY_ROWS As Long = 1
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Sheets(SRC_NAME)
Dim srg As Range: Set srg = sws.Range("A1").CurrentRegion
Dim drOffset As Long: drOffset = srg.Columns.Count + EMPTY_ROWS
Dim dcOffset As Long: dcOffset = 1 + EMPTY_COLS
Dim dws As Worksheet: Set dws = wb.Sheets(DST_NAME)
Dim dfCell As Range: Set dfCell = dws.Range(DST_FIRST_CELL)
Application.ScreenUpdating = False
Dim srrg As Range, shrg As Range
Dim IsHeaderReady As Boolean, IsFirstRowDone As Boolean
For Each srrg In srg.Rows
If Not IsHeaderReady Then
srrg.Copy
dfCell.PasteSpecial Transpose:=True
Set shrg = dfCell.Resize(srg.Columns.Count) ' transpose no more
IsHeaderReady = True
Else ' header is ready; it's already copied for the first data row
If IsFirstRowDone Then shrg.Copy dfCell Else IsFirstRowDone = True
srrg.Copy
dfCell.Offset(, dcOffset).PasteSpecial Transpose:=True
Set dfCell = dfCell.Offset(drOffset)
End If
Next srrg
Application.ScreenUpdating = True
MsgBox "Data transposed.", vbInformation
End Sub
If I understand you correctly
Sub test()
'set the range of the header as rg variable
'count how many data under EMAIL header as cnt variable
Dim rg As Range: Set rg = Range("A1", Range("A1").End(xlToRight))
Dim cnt As Integer: cnt = Range(rg, rg.End(xlDown)).Rows.Count - 1
Dim i As Integer: Dim rslt As Range
'loop to each range with data as many as the cnt value
'prepare the result range as rslt variable
'put the value of header name to rslt range
'put the looped range value to rslt.offset(0,1)
For i = 1 To cnt
Set rslt = Range("A" & Rows.Count).End(xlUp).Offset(3, 0) _
.Resize(rg.Columns.Count, 1)
rslt.Value = Application.Transpose(rg)
rslt.Offset(0, 1).Value = Application.Transpose(rg.Offset(i, 0))
Next
End Sub
Please note, the code must be run where the sheet contains the data is active.
When I run this code, it is getting a subscript out of range error in this specific line:
If i = ws_External_Test_Matrix.Cells(ws_External_Test_Matrix.Rows.Count, 1).End(xlUp).Row Then
arr_Test_Case_Rows(2, UBound(arr_Test_Case_Rows, 2)) = i ' <-- This line
End If
I unfortunately did not write this code, but my understanding is that i is supposed to be the upper bound of the array above. I've tried troubleshooting a bit and it appears that arr_Test_Case_Rows(2, UBound(arr_Test_Case_Rows, 2)) = 0 which would suggest that the Array is unallocated and therefore the error is coming from somewhere above this line. From what I have read it could be from the redim portions but I've tried ReDim arr_Test_Case_Rows(1 To 2, 1 To 1) right before the error line and while it ran, the results did not populate as expected. Anything I can do here to fix this?
Sub Populate_Test_Matrix()
Dim str_External_Test_Matrix_Name As String
Dim ws_External_Test_Matrix As Worksheet
Dim ws_TestMatrix_Tab As Worksheet
Dim ws_ItemInputs As Worksheet
Dim ws_ItemOutputs As Worksheet
Dim rng_Header_Copy_Start As Range
Dim rng_Header_Copy_End As Range
Dim rng_Copy_Start As Range
Dim rng_Copy_End As Range
Dim rng_Paste_Start As Range
Dim i As Long
Dim j As Long
Dim arr_Test_Case_Rows() As Variant
Dim boo_Empty_Row_Ind As Boolean
Dim xlx As XlXmlExportResult
Dim xmlmp As XmlMap
Dim str_Replace_String As String
Dim arr_XML_String_Holder() As Variant
Dim str_XML_Save_Name As String
Dim str_Record As String
Dim str_State As String
Dim int_Test_Case_Start_Row As Long
Application.ScreenUpdating = False
str_External_Test_Matrix_Name = Open_Workbook(ThisWorkbook.Sheets("Macro_Menu").Range("Test_Case_Matrix_Path").Value)
Set ws_External_Test_Matrix = Workbooks(str_External_Test_Matrix_Name).Sheets("MATRIX")
Set ws_TestMatrix_Tab = ThisWorkbook.Sheets("TESTMatrix")
Set ws_ItemInputs = ThisWorkbook.Sheets("ITEMINPUTS")
Set ws_ItemOutputs = ThisWorkbook.Sheets("ITEMOUTPUTS")
'Get start and end row numbers of test cases from External Test Matrix, and record into array
boo_Empty_Row_Ind = False
'Determine first row (header row) of Test Cases, to determine which row to begin looping from when
'finding Test Cases
int_Test_Case_Start_Row = ws_External_Test_Matrix.Range("A:A").Find(what:="Record", LookIn:=xlValues, LookAt:=xlWhole, After:=ws_External_Test_Matrix.Cells(ws_External_Test_Matrix.Rows.Count, 1)).Row
For i = int_Test_Case_Start_Row To ws_External_Test_Matrix.Cells(ws_External_Test_Matrix.Rows.Count, 1).End(xlUp).Row
'If 0, then row is empty
If (Application.CountA(ws_External_Test_Matrix.Cells(i, 1).EntireRow) = 0) And _
(ws_External_Test_Matrix.Cells(i, 1).EntireRow.Interior.ColorIndex = 1) Then 'If 1, then row is colored black
If boo_Empty_Row_Ind = False And (Not Not arr_Test_Case_Rows) <> 0 Then 'Array is allocated
arr_Test_Case_Rows(2, UBound(arr_Test_Case_Rows, 2)) = i - 1
End If
boo_Empty_Row_Ind = True
Else 'Row is NOT empty
'If we previously hit empty row and current row is now non-empty, we have test case to record
If boo_Empty_Row_Ind = True Then
boo_Empty_Row_Ind = False
If (Not Not arr_Test_Case_Rows) = 0 Then 'if 0, then array is unallocated
ReDim arr_Test_Case_Rows(1 To 2, 1 To 1)
Else
ReDim Preserve arr_Test_Case_Rows(1 To 2, 1 To UBound(arr_Test_Case_Rows, 2) + 1)
End If
'arr_Test_Case_Rows(1, X) = start row of test case
'arr_Test_Case_Rows(2, X) = end row of test case
arr_Test_Case_Rows(1, UBound(arr_Test_Case_Rows, 2)) = i
End If
End If
'If I = last row of loop counter
If i = ws_External_Test_Matrix.Cells(ws_External_Test_Matrix.Rows.Count, 1).End(xlUp).Row Then
arr_Test_Case_Rows(2, UBound(arr_Test_Case_Rows, 2)) = i ' <-- This line
End If
Next i
The business case context- the broader program that this module is in takes in a sheet of data and reformats it to be uploaded in another program.
The sheet is made up of one header row followed by rows of records of varying size (1 record could be 1 row, all the way up to 7). The blank rows are used to separate when one record ends and another begins.
This particular module is recording where records exist (not blank row) and the line where it breaks is referring to the final non blank row in the sheet.
In this screenshot it is 40 rows, but the actual case is 55.
Here's a slightly different approach using a Collection instead of an array:
Sub Populate_Test_Matrix()
Dim wb As Workbook, extWb As Workbook, wsExtTM As Worksheet, colRecs As Collection
Dim inRecord As Boolean, firstRecordRow, lastRow As Long
Dim rw As Range, rec, startRow As Long
'better for Open_Workbook to return a reference to the workbook, instead of its name...
Set extWb = Open_Workbook(wb.Sheets("Macro_Menu").Range("Test_Case_Matrix_Path").Value)
Set wsExtTM = extWb.Sheets("MATRIX")
firstRecordRow = Application.Match("Record", wsExtTM.Columns("A"), 0)
If IsError(firstRecordRow) Then
MsgBox "'Record' not found in ColA", vbCritical
Exit Sub
End If
Set colRecs = New Collection 'using a collection seems simpler
inRecord = False
Set rw = wsExtTM.Rows(firstRecordRow)
lastRow = wsExtTM.Cells(wsExtTM.Rows.Count, 1).End(xlUp).Row
Do While rw.Row <= lastRow
If Not RowIsEmpty(rw) Then
If Not inRecord Then
startRow = rw.Row 'save the start row
inRecord = True
End If
Else
If inRecord Then 'were we previously in a record?
colRecs.Add Array(startRow, rw.Row - 1)
inRecord = False
End If
End If
Set rw = rw.Offset(1, 0) 'next row
Loop
colRecs.Add Array(startRow, lastRow) 'close the last record
For Each rec In colRecs
Debug.Print "Start row:" & rec(0), "End row:" & rec(1)
Next rec
End Sub
'factored out a bit of logic...
Function RowIsEmpty(rw As Range) As Boolean
'using color not colorindex...
RowIsEmpty = Application.CountA(rw) = 0 And rw.Interior.Color = vbBlack
End Function
I have two data workbooks. One dataset is of refused orders and the other dataset is for current orders. I want to find if i can match orders so that i can utilize the orders that I have in refused file. This way i wont have to make the current order and can simultaneously reduce my stack of orders that have been refused by customers. Here is my Data sheets for refused and current/printed orders.
Current/Printed Orders
Here is datasheet for the refused orders.
Refused Orders
I need to match orders on three things. First the design name needs to match, the product name needs to match and the size needs to match in order to get an "order match".
How can I use excel vba to find matches and create a new excel worksheet in the current order workbook that can show the orders that match between both data sets. The final data output would be order number against order number from both the files.
I am just beginning to learn vba but this is a complex problem that i can not solve. Please help. I wrote a code but it does not run. It says object not defined. Code that i wrote is :
Sub Comparetwosheets()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim ws1row As Long, ws2row As Long, w1scol As Integer, ws2col As Integer
Dim report As Worksheet
Dim row As Long, col As Integer
Dim R1 As Range
Set R1 = Union(col(5), col(7), col(10))
Set report = Worksheet.Add
'Set numrows = number of rows of data
NumRows = Range("A1", Range("A1").End(xlDown)).Rows.Count
' Select cell a1.
Range("A1").Select
' Establish "For" loop to loop "numrows" number of times.
For x = 1 To NumRows
x = 2
Do While x < NonBlank
x = x + 1
Do While (ws1.R1 = ws2.R1)
If ws1.rw2 = ws2.rw2 Then
report.Cells(1, 1).Value = "Match"
Else: x = x + 1
Loop
Loop
'Selects cell down 1 row from active cell.
ActiveCell.Offset(1, 0).Select
End Sub
This should be able to do it for you. You are able to set the following variables in the CompareWorksheet subroutine to what you need then to be (dataSet1, dataSet2, colPos1, colPos2, rowStart1, rowStart2). I am using a random dataset from the world bank.
Sub CompareWorksheet()
Dim dataSet1, dataSet2 As Variant
Dim workbook1, workbook2 As String
Dim worksheet1, worksheet2 As String
Dim rowStart1, rowStart2 As Integer
'Get the data into the dataSet variable using a function that goes through each workbook/sheet
workbook1 = "dashboard-data-latest1.xlsx"
worksheet1 = "2. Harmonized Indicators"
dataSet1 = SheetToDataSet(workbook1, worksheet1)
'Get the data into the dataSet variable using a function that goes through each workbook/sheet
workbook2 = "dashboard-data-latest.xlsx"
worksheet2 = "2. Harmonized Indicators"
dataSet2 = SheetToDataSet(workbook2, worksheet2)
'Set this do what columns you are interested in comparing
colPos1 = Array(1, 2, 3)
colPos2 = Array(1, 2, 3)
'Set for where you want to start 1 would be row 1/now Header.
rowStart1 = 2
rowStart2 = 2
'Compares the dataSets
Compare2Sheets dataSet1, dataSet2, colPos1, colPos2, rowStart1, rowStart2
End Sub
Function Compare2Sheets(dataSet1 As Variant, dataSet2 As Variant, colPos1 As Variant, colPos2 As Variant, rowStart1 As Variant, rowStart2 As Variant)
If UBound(colPos1) = UBound(colPos2) Then
For I = rowStart1 To UBound(dataSet1, 1)
For j = rowStart2 To UBound(dataSet2, 1)
matchFlag = 0
For k = 0 To UBound(colPos1)
If dataSet1(I, colPos1(k)) = dataSet2(j, colPos2(k)) Then
matchFlag = matchFlag + 1
End If
Next k
If matchFlag = (UBound(colPos1) + 1) Then
Debug.Print ("Match found in Workbook 1 at row " & I & " and Workbook 2 at row " & j)
End If
Next j
Next I
End If
End Function
Function SheetToDataSet(workbookName As Variant, worksheetName As Variant) As Variant
'SET PAGE CHARACTERISTICS
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
'DECLARE VARIABLE
Dim x_matrix As Range
Dim x_copyrange As String
Dim length, lastColumn As Integer
'DEFINE VARIABLE
Workbooks(workbookName).Worksheets(worksheetName).Activate
length = 0
lastColumn = 0
For I = 1 To 10
If length < Workbooks(workbookName).Worksheets(worksheetName).Cells(Rows.Count, I).End(xlUp).Row Then
length = Workbooks(workbookName).Worksheets(worksheetName).Cells(Rows.Count, I).End(xlUp).Row
End If
If lastColumn < Workbooks(workbookName).Worksheets(worksheetName).Cells(I, Columns.Count).End(xlToLeft).Column Then
lastColumn = Workbooks(workbookName).Worksheets(worksheetName).Cells(I, Columns.Count).End(xlToLeft).Column + 10
End If
Next I
'Let x_copyrange = .Range(.Cells(1, 1), .Cells(length, lastColumn))
'Return
SheetToDataSet = Workbooks(workbookName).Worksheets(worksheetName).Range(Cells(1, 1), Cells(length, lastColumn))
End Function
I'm currently working with a workbook containing 34 different tabs.
I'm trying to extract Monthly Data from each of the tabs and Transpose it into daily figures for each specific city.
I have put all the dates within the year 2019 as columns in order to present it as daily figures. (See example in img below)
Each tab contains data for each specific city.
I always want to extract the data present on row 20 from column 4 to 15 in each tab for each specific city. ( see 2nd image below highlighted in yellow)
Public Sub CreateArray()
Dim myArrayOfMonths(11) As Double
Dim currentWorkbook As Workbook
Dim currentSheet As Worksheet
Dim otherSheet As Worksheet
Dim i As Integer
Dim r As Integer
Dim c As Integer
Dim j As Integer
Set currentWorkbook = ActiveWorkbook
Set otherSheet = currentWorkbook.Worksheets("Output")
i = 1
For Each currentSheet In currentWorkbook.Worksheets
r = 20
j = 0
For c = 4 To 15
myArrayOfMonths(j) = ActiveSheet.Cells(r, c)
j = j + 1
Next c
Debug.Print myArrayOfMonths(0)
i = i + 1
Next currentSheet
Set currentSheet = Nothing
Set currentWorkbook = Nothing
End Sub
In my code I'm trying to run through all of the tabs with a loop
and with a 2nd loop check the date (row 16, column 4 to 15) and extract it on my template (Similiar to a vlookup) Unfortunately, it never passes through the first tab as i=0 always for some reason.
Could you please advise?
Would you be able to do something like this?
Option Explicit
Public Sub PopulateOutput()
Dim outputSheet As Worksheet
Dim i As Integer
Set outputSheet = ActiveWorkbook.Worksheets("Output")
' starting at index 2 since output sheet looks like index 1
For i = 2 To ActiveWorkbook.Worksheets.Count
With ActiveWorkbook.Worksheets(i)
outputSheet.Range("B" & i & ":M" & i).Value = .Range("D20:O20").Value
End With
Next
End Sub
Does this suit your needs?
Public Sub CreateArray()
Dim myArrayOfMonths(11) As Double
Dim currentWorkbook As Workbook
Dim currentSheet As Worksheet
Dim otherSheet As Worksheet
Dim r As Integer
Dim c As Integer
Set currentWorkbook = ActiveWorkbook
Set otherSheet = currentWorkbook.Worksheets("Output")
For Each currentSheet In currentWorkbook.Worksheets
r = 20
For c = 4 To 15
myArrayOfMonths(c - 4) = myArrayOfMonths(c - 4) + currentSheet.Cells(r, c)
Next c
Next currentSheet
otherSheet.Range("B1:M1").Value = myArrayOfMonths
Set currentSheet = Nothing
Set currentWorkbook = Nothing
End Sub
Use currentSheet.Cells(r,c) instead of ActiveSheet
or use currentSheet.Activate and then myArrayOfMonths(j) = ActiveSheet.Cells(r, c), but try to avoid ActiveSheet.
Hopefully i've phrased that right...
I came across something online stating that copy and pasting wastes precious time. It's better to assign values more directly, without using excel functions.
I found a section in a VBA book explaining how to store a range in a 2D array.
Now what if I wanted to copy and paste a range from a dynamic number of worksheets into another one main sheet with this method?
In my head, I imagine stacking more and more values into an array, then dumping the array where I'd like it to go, into a range whose size is defined by the dimensions of the big array.
In practice, all I have managed to create is something like the below, performing the same simple action for each worksheet in turn.
Is it possible to do this better? That runs faster? Help a brother out!
Sub arrayCopyPaste()
Dim Obj As Range
Dim Data As Variant
Dim ws As Worksheet
Dim sheetCount As Integer
Dim LR As Integer
sheetCount = Sheets.Count
Set ws = Sheets.Add
ws.Move After:=Worksheets(Worksheets.Count)
For i = 1 To sheetCount
Data = Sheets(i).Range("A1:B9")
LR = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Set Obj = ws.Range("A" & LR)
Set Obj = Obj.Resize(UBound(Data, 1), UBound(Data, 2))
Obj.Value = Data
Next i
End Sub
With just about any code I use, I like to make a call to this routine I made:
Sub SpeedupCode(Optional ByVal Val As Boolean = True)
With Application
If Val = True Then
.ScreenUpdating = False
.Calculation = xlCalculationManual
Else
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End If
End With
End Sub
So, in your code you would simply use it as follows:
Sub arrayCopyPaste()
Dim Obj As Range
Dim Data As Variant
Dim ws As Worksheet
Dim sheetCount As Integer
Dim LR As Integer
SpeedupCode
sheetCount = Sheets.Count
Set ws = Sheets.Add
ws.Move After:=Worksheets(Worksheets.Count)
For i = 1 To sheetCount
Data = Sheets(i).Range("A1:B9")
LR = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Set Obj = ws.Range("A" & LR)
Set Obj = Obj.Resize(UBound(Data, 1), UBound(Data, 2))
Obj.Value = Data
Next i
SpeedupCode False
End Sub
While this does not necessarily optimize your code, it can significantly improve the performance on every project that you do. In the event that your code requires a newly calculated variable in your worksheet, you can always use Application.Calculate before you grab that variable, but generally, it shouldn't be needed.
I'd be inclined to use your current approach and just boil it down a bit.
Sub arrayCopyPaste()
Dim ws As Worksheet
Set ws = Sheets.Add(After:=Worksheets(Worksheets.Count))
For i = 1 To Sheets.Count - 1
With Sheets(i).Range("A1:B9")
ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(1, 0).Resize( _
.Rows.Count, .Columns.Count).Value = .Value
End With
Next i
End Sub
This version is slightly more efficient due to writing the results all at once, though you probably won't notice much of a difference unless you're working with very large ranges.
Sub test()
'Same as original: final array is 2 columns wide, (3 * number of sheets) rows long
Call mergeRangeValues("A1:B3", "Results", True)
'Alternate version: final array is 3 rows long, (2 * number of sheets) columns wide
'Call mergeRangeValues("A1:B3", "Results", False)
End Sub
Sub mergeRangeValues(rngString As String, newWSName As String, stackRows As Boolean)
'Merges the same range (rngString) from all sheets in a workbook
'Adds them to a new worksheet (newWSName)
'If stackRows = True, values are stacked vertically
'If stackRows = False, values are stacked horizontally
Dim sheetCount As Long
Dim newWS As Worksheet
sheetCount = ThisWorkbook.Sheets.Count
Set newWS = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(sheetCount))
newWS.Name = newWSName
Dim numCols As Long
Dim numRows As Long
numCols = newWS.Range(rngString).Columns.Count * IIf(stackRows, 1, sheetCount)
numRows = newWS.Range(rngString).Rows.Count * IIf(stackRows, sheetCount, 1)
ReDim resultsArr(1 To numRows, 1 To numCols) As Variant
'''Longer version:
'If stackRows Then
'numCols = newWS.Range(rngString).Columns.Count
'numRows = newWS.Range(rngString).Rows.Count * sheetCount
'Else
'numCols = newWS.Range(rngString).Columns.Count * sheetCount
'numRows = newWS.Range(rngString).Rows.Count
'End If
'''ie "If you want to stack the results vertically, make the array really long"
'''or "If you want to stack the results horizontally, make the array really wide"
Dim i As Long
For i = 0 To sheetCount - 1
Dim tempArr As Variant
tempArr = ThisWorkbook.Sheets(i + 1).Range(rngString).Value
Dim j As Long
Dim k As Long
If stackRows Then
For j = LBound(tempArr, 1) To UBound(tempArr, 1)
For k = LBound(tempArr, 2) To UBound(tempArr, 2)
resultsArr(j + i * (numRows / sheetCount), k) = tempArr(j, k)
Next
Next
Else
For j = LBound(tempArr, 1) To UBound(tempArr, 1)
For k = LBound(tempArr, 2) To UBound(tempArr, 2)
resultsArr(j, k + i * (numCols / sheetCount)) = tempArr(j, k)
Next
Next
End If
Next
With newWS
.Range(.Cells(1, 1), .Cells(numRows, numCols)).Value = resultsArr
End With
End Sub