I have biomechanics data (i.e. a person walking) that is collected with video recordings and stored as 3 columns of data for each frame number. In a separate data table in the same worksheet, I have data that tells me which excel row number each biomechanic event happens (i.e. the foot strikes the ground or comes up off of the ground). I am trying to take the biomechanics data that is stored in one spreadsheet in rows, and transpose it so that each step is in its own column. However, each biomechanic event (i.e. each step) is a different number of rows.
The biomechanics raw data can be seen here: biomechanics raw data
What I want it to do is copy individual events (steps) to a second worksheet like this: desired biomechanic event output
Instead, the code runs through the loop successfully for each biomechanic event, but places the data in the same place, "A4". This is because I do not know how to use offset within a loop and based on a variable: current biomechanic event output with undesired overlay of data
The code I have currently is here:
Private Sub CommandButton1_Click()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
Dim LeftStrike As Range, FrameLTD As Range, FrameLTDx As Range
Dim lrL As Long, LastFrame As Long
Dim LeftTD As Variant
Dim LeftTDx As Variant
lrL = ws.Range("H" & ws.Rows.Count).End(xlUp).Row
LastFrame = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Set LeftStrike = ws.Range("H2:H" & lrL)
For Each FrameLTD In LeftStrike
If InStr(FrameLTD, "Foot Strike") Then
LeftTD = FrameLTD.Offset(0, 2)
'COMMENT: Set LeftTDx = LeftTD + 1
ws.Range("A" & LeftTD, "D" & LastFrame).Copy ws2.Range("A4")
' COMMENT: ws.Range("A" & LeftTDx, "D" & LastFrame).Copy ws2.Range("FrameLTD").Offset(0, 5)
End If
Next FrameLTD
End Sub
What I want the program to do is:
1. Find the string "Foot Strike" and tell me the value 2 columns over and call it LeftTD (it does this).
2. Starting at the row number value of LeftTD, copy cells in columns A through D and past it into a new worksheet starting at A4 (it does this).
3. For the next "Foot Strike" and all remaining, do the same thing in steps 1 and 2, but then copy the cells with an offset(0,5) from the previous copy & pasted event (it does not do this).
4. Do this until column H is empty (it does do this).
My thought was that if I declare the variables as "variant" then I could tell it to count the next LeftTD as LeftTD +1, then tell it to offset the range of the range variable by 5, it would work. But if I un-comment those lines, then I get a type mismatch error. Also, interestingly, if I hit F8 and run through the program step by step, it only copies each biomechanic event (each step) on the 2nd, 5th, 7th, and 9th time through the program.
So my specific question is, how do I use a variable offset within a For loop that is looping through a range variable?
I thought about using .Find and .FindNext, but the information available on the web is really lacking for an example that is close to what I need to do. Indeed, finding information on copy and paste with both variable rows and variable offset columns is also difficult for me to find. Any offered insight would be greatly appreciated. Thank you!!!!
Add a counter to identifying the destination
Dim DestCol As Long
'...
DestCol = 1
For Each FrameLTD In LeftStrike
If InStr(FrameLTD, "Foot Strike") Then
LeftTD = FrameLTD.Offset(0, 2)
ws.Range("A" & LeftTD, "D" & LastFrame).Copy ws2.Cells(4, DestCol)
DestCol = DestCol + 5
End If
Next FrameLTD
Related
Edit: This question has been re-worked to provide better clarity of my problem.
There's 2 factors to my question.
First Factor: I have a validation list in a sheet called "Admin Sheet". In that list are 'Tasks'.
I would like to cross reference those tasks in the "list", against those contained in a range (rangeString) taken from another sheet and count the number of 'Occurrences' for each item.
i.e. Task 1 appears 3 times, Task 2 appears 1 time, etc etc..
Factor 2: For each item within the list I would also like to gather the number of 'Hours' spent on that task.
For example:
Task 1 may appear 3 times on 3 different rows within the range. On each row in another column are the hours spent on that particular task. I would like to 'Sum' those hours from the 3 rows and I'd like to do this for all the 'Tasks'.
Note: The range is variable and will change daily.
Note: The columns that contain the info are: 'F' - Tasks and 'K' for Hours.
My current attempt at just capturing 'one' Task and its Hours associated with it:
Dim PaintWWArray() As Variant
Dim PHoursCnt As Long
Set srchRng = ActiveSheet.Range(rangeString)
Set rngfindValue = srchRng.find(what:="AD PAINTING W/W", Lookat:=xlPart)
'Find all the Tasks and Hours
If Not rngfindValue Is Nothing Then
rngFirstAddress = rngfindValue.Address
Do
PaintWWCnt = PaintWWCnt + 1
PHoursCnt = rngfindValue.Offset(0, 4).Value
ReDim Preserve PaintWWArray(PHoursCnt)
PaintWWArray(PHoursCnt) = PHoursCnt
Set rngfindValue = srchRng.FindNext(rngfindValue)
Loop Until rngfindValue Is Nothing Or rngfindValue.Address = rngFirstAddress
PWWSum = Application.WorksheetFunction.Sum(PaintWWArray)
MsgBox PWWSum
End If
Once I have collected the number of 'Occurrences' for each Task and the Sum of the hours for each task, I want to pass them into another sheet.
Worksheets("Weekly Data").Range("C6").Value = PaintWWCnt
Worksheets("Weekly Data").Range("D6").Value = PWWSum
I hope this is clearer...
I would suggest using a Dictionary.
Assuming you want to count all words:
Dim myDict
Set myDict = CreateObject("Scripting.Dictionary")
' Go through the array
For Each addDuty In arr
' If you only want to count specific words, add in IF statement here
myDict(addDuty) = myDict(addDuty) + 1
Next addDuty
If you only want to count words in an exiting set, it becomes slightly more elaborate.
It's not entirely clear what you want to achieve but the code below should give you the data you need. It's very fast. Please try it.
Private Sub STO_Answer()
' 024
' this procedure requires a reference to be set to
' Microsoft Scripting Runtime
Dim Counter As Scripting.Dictionary ' store task names and their count
Dim Arr As Variant ' an array of the data in Rng
Dim CellVal As Variant ' temporary storage of each cell value
Dim R As Long ' row counter
Dim Key As Variant ' a dictionary Key
Arr = ActiveSheet.Range("C2:D27").Value ' change to name the sheet
' adjust the range to suit
Set Counter = New Scripting.Dictionary
With Counter
For R = 1 To UBound(Arr) ' loop through all rows
AddToCounter Arr(R, 1), Counter ' first column of cell range
AddToCounter Arr(R, 2), Counter ' second column of cell range
Next R
For Each Key In Counter.Keys
Debug.Print Key, Counter.Item(Key)
Next Key
End With
End Sub
Private Sub AddToCounter(CellVal As Variant, _
Counter As Scripting.Dictionary)
' 024
With Counter
If .Exists(CellVal) Then
.Item(CellVal) = .Item(CellVal) + 1
Else
.Add CellVal, 1
End If
End With
End Sub
A Dictionary is a data structure which holds two related values. Here it's used to hold the task name and the number of times it occurs. Make sure you enable the reference to Microsoft Scripting Runtime in Tools > References. You don't specify if there is any relationship- between the tasks in the first column and the second. The above code counts both independently for now.
The result is printed to the Immediate Window. Of course, you might use this result in any other way in your code. Your question doesn't cover your intentions.
You won't be able to escape from the necessity to present your count in some way forever. As it turns out, there is only one efficient way to do it. This one:-
All duties are in column A and all added duties are in row 2.
Of course, you might use rather elaborate VBA to do the counting but Excel has a better way using a worksheet function. In order to set up COUNTIF() to work I created two named ranges as follows.
["Duties"] =OFFSET(Sheet2!$C$2,0,0,COUNTA(Sheet2!$C:$C)-1)
and
["AddDuties"] =OFFSET(Duties,0,1)
Sheet2!$C$2 is where my data started. Replace with the first cell of the first column of your data range. COUNTA(Sheet2!$C:$C)-1 makes this range dynamic. The function counts how many entries there are in that same column, -1 because the count would include a caption (modify if you have more or fewer headers).
AddDuties is simply defined as "same as Duties" but removed by one column to the right. You could move it elsewhere. As you add or delete rows in the column of Duties, AddDuties expands or contracts right along.
Now the formula in B3 is shown below. It's copied down and across as required. Please observe the $ signs.
[B3] =COUNTIFS(Duties,$A3,AddDuties,B$2)
This will probably generate a lot of zeroes. It did in my example and I didn't like them. Therefore I formatted B3 with the Custom cell format 0;; before copying to the other cells, which hides them.
Now this list would automatically update as you make entries in your data. You will never have to run code and the list will always be ready.
Finally, one recommendation. All your added duties, like "AD PAINITNG H/R", are hard to type correctly. Therefore the user should select them from a validation drop-down when entering them in the data. Most probably, you already have a list somewhere which feeds such drop-downs. The captions in the count list must be taken from the same source. But that creates redundancy. The better way is to make the list in B2:H2 of the count list the "original". Name the range and make it dynamic and you will never have to think about this subject again.
i think a better approach would be to use for each loops, this way you won't have to hardcode the conditions via IfElse. If you have the values in column A of a sheet and wants to go through those values and get their adjacent value in column B, you can use For Each looping to go through each values defined in A to get B.
just to add, regarding on counting of occurrence, you can define a counter that would add up for each occurrence of a unique value in column A.
I do not have time to wait for clarifications I asked... I prepared a piece of code, starting from the assumption that your strings to be counted are in column "F:F", and the value to be calculated is in column "K:K". The processing result is dropped on the last available column of the active pages, starting from row 2. If you prefer some relevant headers for the two involved columns, this can be easily automated. I used "Tasks and "Time...
It is able to deal with as many 'task' strings you will have in the future.
I commented the code lines, where I thought you do not understand what they do:
Sub CountOccurrencesAndValues()
Dim sh As Worksheet, rngF As Range, arrOcc As Variant, lastRow As Long, lastCol As Long
Dim arr As Variant, arrFin As Variant, countI As Long, valH As Double, j As Long, k As Long, i As Long
Set sh = ActiveSheet
lastRow = sh.Range("F" & Rows.count).End(xlUp).Row
lastCol = sh.UsedRange.Columns.count + 1
Set rngF = sh.Range("F2:F" & lastRow) 'the range where from to extract the unique values
arr = sh.Range("F2:K" & lastRow) 'the array to be processed
'Extract the unique values. Use for that a not used column:
rngF.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=sh.Cells(1, lastCol), Unique:=True
'Put the unique values (sttrings) in an array:
arrOcc = sh.Range(sh.Cells(1, lastCol), sh.Cells(sh.Cells(Rows.count, lastCol).End(xlUp).Row, lastCol)).value
'Clear the temporary used array:
sh.Range(sh.Cells(1, lastCol), sh.Cells(sh.Cells(Rows.count, lastCol).End(xlUp).Row, lastCol)).Clear
ReDim arrFin(1 To UBound(arrOcc, 1), 1 To 3)
k = 1
'Processing the range by iteration:
For i = 1 To UBound(arrOcc, 1)
For j = 1 To UBound(arr, 1)
If arr(j, 1) = arrOcc(i, 1) Then
'count the occurrences and the value
countI = countI + 1: valH = valH + arr(j, 6)
End If
Next j
'put the data in the final array
arrFin(k, 1) = arrOcc(i, 1): arrFin(k, 2) = countI: arrFin(k, 3) = valH
countI = 0: valH = 0: k = k + 1
Next i
'Drop the data from array in the last available column:
'sh.Cells(1, lastCol).value = "Tasks": sh.Cells(1, lastCol + 1).value = "Count": sh.Cells(1, lastCol + 2).value = "Time"
'sh.Cells(2, lastCol).Resize(UBound(arrFin, 1), UBound(arrFin, 2)).value = arrFin
Dim ws As Worksheet
Set ws = Worksheets("Weekly Data")
'Drop the data from array in "Weekly Data" worksheet:
ws.Range("C6").value = "Tasks": ws.Range("D6").value = "Count": ws.Range("E6").value = "Time"
ws.Range("C7").Resize(UBound(arrFin, 1), UBound(arrFin, 2)).value = arrFin
End Sub
Given the lack of elegance with the data
the record sheet continues for many MANY rows, each entry having its own set of identical headings
I was hoping to just extract the data from rows 7, 14 and so on, then populate the data into a simple table to be used on the 'Protocol Summary' form, then sort them all into alphanumeric order based on the data that is in the A column so they all become grouped by 'Event Type'.
Because the potential data that could be under the 'Event Type' heading can vary a lot (generally has the format of [number 1-32/letter/number 1-30] but can also be all letters, with a few thousand possibilities, I thought it might be easier to filter the other lines OUT, given they don't change. I would love to redesign the table, but unfortunately it's not my table so I have to work with what I'm given.
Thanks for your time.
This will loop over your sheet up to the last used row, starting from Row 7 and stepping 7 rows each iteration.
Within each iteration, each cell in the row is written into an array which is then written to another sheet ready for sorting (however you want to do that).
This code is sample and may not work by copy/paste.
I have written this in the Sheet1 code module, so Me refers to ThisWorkbook.Sheets("Sheet1").
I have made this from a blank workbook and did not rename any sheets therefore you will need to make adjustments to any sheet references to match your appropriate sheet names.
The code will only reference columns A, B and C in the TargetRow (I only tested with 3 columns of data as I don't know your working range). I'll reference what to update to extend this after the code block.
Currently the array is put back into Sheet2 starting from cell A2. This is assuming row 1 contains table headers as this will write the data directly into the table format. Naturally if you want to change where the data is written, change the cell it is written to (when writing an array to sheet, you only need to define the top left cell of the range it is written to, Excel works out the rest based on the size and dimensions of the array).
Sub WriteEverySeventhRowToAnotherSheet()
Dim SeventhRowCount As Long
Dim myArray() As Variant
Dim lastrow As Long
Dim TargetCell As Variant
Dim TargetRow As Range
Dim ArrFirstDimension As Long
Dim ArrSecondDimension As Long
lastrow = Me.Range("A" & Me.Rows.Count).End(xlUp).Row
ReDim myArray(1 To lastrow / 7, 1 To 3)
ArrFirstDimension = 1
ArrSecondDimension = 1
'------------------Loop over every 7th row and enter row data to array---------------
For SeventhRowCount = 7 To lastrow Step 7
Set TargetRow = Me.Range("A" & SeventhRowCount & ":C" & SeventhRowCount)
For Each TargetCell In TargetRow
If Not ArrSecondDimension > UBound(myArray) Then
myArray(ArrFirstDimension, ArrSecondDimension) = TargetCell
'Debug.Print TargetCell
ArrSecondDimension = ArrSecondDimension + 1
End If
Next TargetCell
ArrFirstDimension = ArrFirstDimension + 1
ArrSecondDimension = 1
Set TargetRow = Nothing
Next SeventhRowCount
'---------------------Write array to another sheet------------------
Dim Destination As Range
Set Destination = ThisWorkbook.Sheets("Sheet2").Range("A2")
Destination.Resize(UBound(myArray, 1), UBound(myArray, 2)).Value = myArray
End Sub
To extend the number of columns the loop will write to the array, change the following instance of C to the correct column letter (in the below line the range is set from Column A to Column C):
Set TargetRow = Me.Range("A" & SeventhRowCount & ":C" & SeventhRowCount)
Also change the 2nd dimension of the Array to match the number of the Column set above (i.e Column E = 5 and Column L = 13 etc.) - You need to replace the number 3 with the correct number.
ReDim myArray(1 To lastrow / 7, 1 To 3)
In Excel I have two worksheets.
The first lists my comments on a Word file each with a code (in the form ABC and a number), a comment, and other information.
Another links these codes to a comment in Word. This has been collected using a macro, which returns the page number of each of the word Comments (which is stored in the second column).
I now want to copy the page numbers into the original worksheet.
My problem is that the two sets of data are not commensurable, so the data can not be simply pasted. Thus ref. A104 in the first worksheet has a page reference (15) in the second workbook, but A105 does not. Also, some references (A106) for instance have multiple page references so occur multiple times in the second workbook but only once in the first.
In the first worksheet, col. A contains the references, and col. F is where I want to paste the page numbers (the other columns contain various other data).
In the second worksheet, the data in col. A corresponds to the refs. in Sheet1:column A, and col. B contains the page references.
In short, I want to copy data from sheet 2:col.B into sheet1:colF only where Sheet 1:col. A corresponds to sheet 2:col A. Is this possible?
Okay. This is not difficult. You could do it too, or at least try to. That's what we value here - seeing efforts. So next time, please, show some effort first and post your code when you actually have a real coding issue.
In your case, I assumed that your sheets are named "Sheet1" and Sheet2".
Don't forget to check the checkmark if the answer is helpful. And please read our Tour page.
Sub ttt()
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Worksheets("Sheet2")
Dim i As Long, j As Long
Dim str As String
For i = 1 To ws1.UsedRange.Rows.Count
For j = 1 To ws2.UsedRange.Rows.Count
If ws1.Range("A" & i).Value = ws2.Range("A" & j).Value Then
str = str & ws2.Range("B" & j).Value & ", "
End If
Next
If Len(str) > 1 Then
str = Left(str, Len(str) - 2)
ws1.Range("F" & i).Value = str
End If
str = vbNullString
Next
End Sub
[Edited]
I have a Excel workbook (.xlsx) with two worksheets (Sheet 1 & Sheet 2). Sheet 1 has 7 columns of data (each with about 70k rows) while Sheet 2 only has 5 columns with about 250-500 rows. The first column of each sheet contains a timestamp of when the data was collected in the format (yyyy-mm-dd_hh:mm:ss).
The discrepancy is that the data in Sheet 1 has data points spaced at 8 second intervals. Sheet 2, however, has sporadic data entries. There might be 4 or 5 entries that happen in a burst (say 5 second interval) and then not another entry for another couple of hours.
What I'd like to do is reorganize Sheet 2 so that the timestamps align with Sheet 1. The reason for this is that when I graph the data in sheet 1, the visualization looks appropriate because the data is evenly spaced throughout. However, I can not graph the data in Sheet 2 the same way because the data points occur at sporadic intervals.
I'm comfortable in C# and considering trying to create a program which will read in a csv file of each sheet and do the batch processing... but even there I'm a bit stuck as to what the proper procedure would be. Is there a way this can be handled directly in Excel? Any advice would be welcome.
A bit of background. I tested this on three sheets. First sheet has 100k dates with 8-second intervals. Second sheet, I have 5 columns of 300 data points, with first column containing the dates with sporadic intervals. I've decided against mangling the second sheet so my output is in a third sheet for testing purposes.
Our logic is locating the largest value that's smaller than our target date. This way, we're inside the 8 seconds between this located date and the next one. We then get that value's row from the first sheet, then we use that row as the same row number in our results sheet. We then "transfer" the values from the second sheet to the proper row in the results sheet.
Runtime is negligible on my machine. Hopefully, this runs for you properly as well. Kindly test on a copy of your workbook.
Sub Align()
Dim RefWS As Worksheet, ListWS As Worksheet, ResWS As Worksheet
Dim RngOne As Range, RngTwo As Range
Dim RngVal As Variant, Elem As Variant
Dim LRowOne As Long, LRowTwo As Long, LRowThree As Long
Dim LocRow As Long, RowCt As Long
Dim PopRng As Range, StartRow As Long
With ThisWorkbook
Set RefWS = .Sheets("Sheet1") 'Modify as necessary.
Set ListWS = .Sheets("Sheet2") 'Modify as necessary.
Set ResWS = .Sheets("Sheet3") 'Modify as necessary.
End With
LRowOne = RefWS.Range("A" & Rows.Count).End(xlUp).Row
LRowTwo = ListWS.Range("A" & Rows.Count).End(xlUp).Row
'Make sure to change based on whether you have headers or not.
Set RngOne = RefWS.Range("A1:A" & LRowOne) 'Modify as necessary.
Set RngTwo = ListWS.Range("A1:A" & LRowTwo) 'Modify as necessary.
RngVal = RngTwo.Value
'Change RowCt to 2 if you have headers.
RowCt = 1
For Each Elem In RngVal
LocRow = Application.Match(CDbl(Elem), RngOne, 1)
ResWS.Range("A" & LocRow & ":E" & LocRow).Value = ListWS.Range("A" & RowCt & ":E" & RowCt).Value
RowCt = RowCt + 1
Next Elem
'Autopopulate.
With ResWS
LRowThree = .Range("A" & Rows.Count).End(xlUp).Row
Do
StartRow = .Range("A" & LRowThree).End(xlUp).Row
If StartRow > 1 Then StartRow = StartRow + 1
Set PopRng = .Range("A" & StartRow & ":E" & LRowThree)
.Range("A" & LRowThree & ":E" & LRowThree).Copy
PopRng.PasteSpecial xlPasteValues
LRowThree = StartRow - 1
Loop Until StartRow = 1
End With
Application.CutCopyMode = False
End Sub
It's also important to note that if two values are matched, it's going to get the latest value rather than the closest one. Let me know first what happens to your data after running this.
EDIT: Code updated as per chat.
Am trying to parse an excel file using Excel VBA.
Here is the sample sata
I did some research and found you can assign ranges to array like
Arrayname = Range("A1:D200")
But am looking for some thing more dynamic, like add the below multiple ranges to a single array.
and my final array will be a single array/table with n is number of rows from all ranges and 4 columns.
Can any one please prvide me a example.
Thank you in adavance.
I think you are asking for more information about moving data between ranges and variables so that is the question I will attempt to answer.
Create a new workbook. Leave Sheet1 empty; set cell B3 of Sheet2 to "abc" and set cells C4 to F6 of Sheet3 to ="R"&ROW()&"C"&COLUMN()
Open the VB Editor, create a module and copy the follow code to it. Run macro Demo01().
Option Explicit
Sub Demo01()
Dim ColURV As Long
Dim InxWkSht As Long
Dim RowURV As Long
Dim UsedRangeValue As Variant
' For each worksheet in the workbook
For InxWkSht = 1 To Worksheets.Count
With Worksheets(InxWkSht)
Debug.Print .Name
If .UsedRange Is Nothing Then
Debug.Print " Empty sheet"
Else
Debug.Print " Row range: " & .UsedRange.Row & " to " & _
.UsedRange.Row + .UsedRange.Rows.Count - 1
Debug.Print " Col range: " & .UsedRange.Column & " to " & _
.UsedRange.Column + .UsedRange.Columns.Count - 1
End If
UsedRangeValue = .UsedRange.Value
If IsEmpty(UsedRangeValue) Then
Debug.Print " Empty sheet"
ElseIf VarType(UsedRangeValue) > vbArray Then
' More than one cell used
Debug.Print " Values:"
For RowURV = 1 To UBound(UsedRangeValue, 1)
Debug.Print " ";
For ColURV = 1 To UBound(UsedRangeValue, 2)
Debug.Print " " & UsedRangeValue(RowURV, ColURV);
Next
Debug.Print
Next
Else
' Must be single cell worksheet
Debug.Print " Value = " & UsedRangeValue
End If
End With
Next
End Sub
The following will appear in the Immediate Window:
Sheet1
Row range: 1 to 1
Col range: 1 to 1
Empty sheet
Sheet2
Row range: 3 to 3
Col range: 2 to 2
Value = abc
Sheet3
Row range: 4 to 6
Col range: 3 to 5
Values:
R4C3 R4C4 R4C5
R5C3 R5C4 R5C5
R6C3 R6C4 R6C5
If you work through the macro and study the output you will get an introduction to loading a range to a variant. The points I particularly want you to note are:
The variable to which the range is loaded is of type Variant. I have never tried loading a single range to a Variant array since the result may not be an array. Even if it works, I would find this confusing.
Sheet1 is empty but the used range tells you than cell A1 is used. However, the variant to which I have loaded the sheet is empty.
The variant only becomes an array if the range contains more than one cell. Note: the array will ALWAYS be two dimensional even if the range is a single row or a single column.
The lower bounds of the array are ALWAYS 1.
The column and row dimensions are not standard with the rows as dimension 1 and the columns as dimension 2.
If there is any doubt about the nature of the range being loaded, you must use IsEmpty and VarType to test its nature.
You may also like to look at: https://stackoverflow.com/a/16607070/973283. Skim the explanations of macros Demo01() and Demo02() which are not relevant to you but set the context. Macro Demo03() shows the advanced technique of loading multiple worksheets to a jagged array.
Now create a new worksheet and leave it with the default name of Sheet4.
Add the follow code to the module. Run macro Demo02().
Sub Demo02()
Dim ColOut As Long
Dim OutputValue() As String
Dim Rng As Range
Dim RowOut As Long
Dim Stg As String
ReDim OutputValue(5 To 10, 3 To 6)
For RowOut = LBound(OutputValue, 1) To UBound(OutputValue, 1)
For ColOut = LBound(OutputValue, 2) To UBound(OutputValue, 2)
OutputValue(RowOut, ColOut) = RowOut + ColOut
Next
Next
With Worksheets("Sheet4")
Set Rng = .Range("A1:D6")
End With
Rng.Value = OutputValue
With Worksheets("Sheet4")
Set Rng = .Range(.Cells(8, 2), .Cells(12, 4))
End With
Rng.Value = OutputValue
With Worksheets("Sheet4")
Stg = "C" & 14 & ":G" & 20
Set Rng = .Range(Stg)
End With
Rng.Value = OutputValue
End Sub
Although this macro writes an array to a worksheet, many of the points apply for the opposite direction. The points I particularly want you to note are:
For output, the array does not have to be Variant nor do the lower bounds have to be 1. I have made OutputValue a String array so the values output are strings. Change OutputValue to a Variant array and rerun the macro to see the effect.
I have used three different ways of creating the range to demonstrate some of your choices.
If you specify a range as I have, the worksheet is one of the properties of the range. That is why I can take Rng.Value = OutputValue outside the With ... End With and still have the data written to the correct worksheet.
When copying from a range to a variant, Excel sets the dimensions of the variant as appropriate. When copying from an array to a range, it is your responsibility to get the size of the range correct. With the second range, I lost data. With the third range, I gained N/As.
I hope the above gives you an idea of your options. If I understand your requirement correctly, you will have to:
Load the entire worksheet to Variant
Create a new Array of the appropriate size
Selectively copy data from the Variant to the Array.
Come back withh questions if anything is unclear.