Found solution via the Application.Index
function
I found a solution simply by trying out some unusual variations of the Application.Index
function which I try to resume as a comprehensive generic overview to demonstrate the rich range of application. So any helpful addition is welcome (c.f. @chrisneilsen ‘s comment).
Some peculiarities of the the Application.Index
function
Typically the index function would deliver a well defined item by its row and column position, but there are some not so widely known pecularities:
-
Similarly to the
Worksheet.Index
function you can get the entire column or row items if the row or column number argument is set to zero (0). – Another frequently unknown way to create a 2-dim array by passing a double-zero parameter can be found at How to initialize a 2-dim array in Excel VBA -
Use of array arguments possible – This function allows not only the known index indications by given numbers, but also array parameters to extract “rows” or “columns”, so it’s possible to indicate a wanted set of columns, e.g.
A:C
viaArray(1,2,3)
as column array argument. -
Filtering effects – Furthermore I learnt that it is possible to reduce the choice to some columns (rows) only, e.g. via
Array(1,3) and even to change the internal order, e.g.
Array(3,2,1)`. -
Restructuring – The most surprising fact, however, is that it is possible to repeat a column choice, e.g. via
Array(1,1,2,3)
or evenArray(0,1,2,3)
where the0
item is the same as column 1. This can be used to reach the same effect as a column insertion.
This last restructuring capability of the mentioned Index
function is the key part of my approach:
Code example
Sub AddFirstIndexColumn()
Dim v, i&, ws As Worksheet
Set ws = ThisWorkbook.Worksheets("SourceSheet") ' << change to source sheet name
' [1] get data
v = ws.[A1:C5].Value2
' [2] define column array inserting first column (0 or 1) and preserving old values (1,2,3)
v = Application.Index(v, _
Application.Evaluate("row(1:" & UBound(v) & ")"), _
Array(0, 1, 2, 3)) ' columns array where 0 reinserts the first column
' [3] add an current number in the first column
For i = LBound(v) To UBound(v): v(i, 1) = i: Next i
End Sub
How to test the result
Just insert the following to the code above:
' [4a] test result by debugging in immediate window
For i = LBound(v) To UBound(v)
Debug.Print "#" & i & ": " & Join(Application.Index(v, i, 0), ", ")
Next i
' [4b] test result by writing back to target sheet
Dim ws2 As Worksheet
Set ws2 = ThisWorkbook.Worksheets("TargetSheet") ' << change to target sheet name
ws2.Range("A1").Resize(UBound(v), UBound(v, 2)).Offset(0, 0) = v
Caveat
The found solution seems to be restricted to 65536 rows (possibly similar to array transposing limitation), so that you can’t use it for bigger data.
Some recent Application.Index
examples