Posted: June 12, 2013 by Transformer in Excel, VBA
Tags: Advanced, Array, Range, Trick of the Week
Sometimes we need to slice an array i.e. fetch a row/column from a multidimensional array. There is no inbuilt function in VBA to do the same and the most common way to do so is using a loop. However it can be done using a worksheet function named Index.
Syntax :
Application.Index(Array, Row_Number, Column_Number)
OR
Application.WorksheetFunction.Index(Array, Row_Number, Column_Number)
To extract a column from the source array, ‘0’ should be passed as row_number argument. Similarly, to extract a row from source array, ‘0’ should be passed as column_number argument.
e.g.
Sub Test()
Dim varArray As Variant
Dim varTemp As Variant
varArray = ThisWorkbook.Worksheets("Sheet1").Range("A1:E10")
varTemp = Application.Index(varArray, 2, 0)
End Sub
In the above example second row of varArray will be fetched in varTemp. We can also extract more then one row/column at the same time. In this case an array of numbers (indicating row/column) should be passed as row_number / column_number argument.
e.g. If in the above example we need to extract 2nd, 4th and 5th rows then row number would be passed as an array:
varTemp = Application.Index(varArray, Array(2, 4, 5), 0)
Similarly, to extract columns:
varTemp = Application.Index(varArray, 0, Application.Transpose(Array(2, 4, 5)))
This function can also be used to fill values in a particular row/column of a range.
Syntax : Application.Index(Range, Row_number , Column_number) = SourceArray/Range
In the same example to fill the values of 2nd column of varArray to 2nd column of range [A1:E10], we would do the following
Application.Index([A1:E10], , 2) = Application.Index(varArray, , 2)
Содержание
- WorksheetFunction.Index method (Excel)
- Syntax
- Parameters
- Return value
- Remarks
- Array form
- Reference form
- Support and feedback
- Метод WorksheetFunction.Index (Excel)
- Синтаксис
- Параметры
- Возвращаемое значение
- Примечания
- Форма массива
- Форма ссылок
- Поддержка и обратная связь
- Useful Gyaan
- Follow us
- Categories:
- Top Tags
- Top Posts & Pages
- Like Us on Facebook
- Authors
- Blogroll
- We Recommend:
- Random Picks
- VBA Trick of the Week :: Slicing an Array Without Loop – Application.Index
- Share this:
- Like this:
- Related
WorksheetFunction.Index method (Excel)
Returns a value or the reference to a value from within a table or range. There are two forms of the Index function: the array form and the reference form.
Syntax
expression A variable that represents a WorksheetFunction object.
Parameters
Name | Required/Optional | Data type | Description |
---|---|---|---|
Arg1 | Required | Variant | Array or Reference — a range of cells or an array constant. For references, it is the reference to one or more cell ranges. |
Arg2 | Required | Double | Row_num — selects the row in array from which to return a value. If row_num is omitted, column_num is required. For references, the number of the row in reference from which to return a reference. |
Arg3 | Optional | Variant | Column_num — selects the column in array from which to return a value. If column_num is omitted, row_num is required. For reference, the number of the column in reference from which to return a reference. |
Arg4 | Optional | Variant | Area_num — only used when returning references. Selects a range in reference from which to return the intersection of row_num and column_num. The first area selected or entered is numbered 1, the second is 2, and so on. If area_num is omitted, Index uses area 1. |
Return value
Variant
Array form
Returns the value of an element in a table or an array, selected by the row and column number indexes.
Use the array form if the first argument to Index is an array constant.
If both the row_num and column_num arguments are used, Index returns the value in the cell at the intersection of row_num and column_num.
If you set row_num or column_num to 0 (zero), Index returns the array of values for the entire column or row, respectively. To use values returned as an array, enter the Index function as an array formula in a horizontal range of cells for a row, and in a vertical range of cells for a column. To enter an array formula, press Ctrl+Shift+Enter.
Row_num and column_num must point to a cell within array; otherwise, Index returns the #REF! error value.
Reference form
Returns the reference of the cell at the intersection of a particular row and column. If the reference is made up of nonadjacent selections, you can pick the selection to look in. If each area in reference contains only one row or column, the row_num or column_num argument, respectively, is optional. For example, for a single row reference, use INDEX(reference,column_num).
After reference and area_num have selected a particular range, row_num and column_num select a particular cell: row_num 1 is the first row in the range, column_num 1 is the first column, and so on. The reference returned by Index is the intersection of row_num and column_num.
If you set row_num or column_num to 0 (zero), Index returns the reference for the entire column or row, respectively.
Row_num, column_num, and area_num must point to a cell within reference; otherwise, Index returns the #REF! error value. If row_num and column_num are omitted, Index returns the area in reference specified by area_num.
The result of the Index function is a reference and is interpreted as such by other formulas. Depending on the formula, the return value of Index may be used as a reference or as a value. For example, the formula CELL(«width»,INDEX(A1:B2,1,2)) is equivalent to CELL(«width»,B1) . The CELL function uses the return value of Index as a cell reference. On the other hand, a formula such as 2*INDEX(A1:B2,1,2) translates the return value of Index into the number in cell B1.
Support and feedback
Have questions or feedback about Office VBA or this documentation? Please see Office VBA support and feedback for guidance about the ways you can receive support and provide feedback.
Источник
Метод WorksheetFunction.Index (Excel)
Возвращает значение или ссылку на значение из таблицы или диапазона. Существует две формы функции Index : форма массива и форма ссылки.
Синтаксис
Выражение Переменная, представляющая объект WorksheetFunction .
Параметры
Имя | Обязательный или необязательный | Тип данных | Описание |
---|---|---|---|
Arg1 | Обязательный | Variant | Массив или ссылка — диапазон ячеек или константы массива. Для ссылок это ссылка на один или несколько диапазонов ячеек. |
Arg2 | Обязательный | Double | Row_num — выбирает строку в массиве, из которой возвращается значение. Если row_num опущен, требуется column_num. Для ссылок — номер строки в ссылке, из которой возвращается ссылка. |
Arg3 | Необязательный | Variant | Column_num — выбирает столбец в массиве, из которого возвращается значение. Если column_num опущен, требуется row_num. Для справки— номер столбца в ссылке, из которого возвращается ссылка. |
Arg4 | Необязательный | Variant | Area_num — используется только при возврате ссылок. Выбирает диапазон в ссылке, из которого возвращается пересечение row_num и column_num. Первая выбранная или введенная область нумеруется 1, вторая — 2 и т. д. Если area_num опущен, индекс использует область 1. |
Возвращаемое значение
Variant
Примечания
Форма массива
Возвращает значение элемента в таблице или массиве, выбранное индексами номеров строк и столбцов.
Используйте форму массива, если первый аргумент index является константой массива.
Если используются аргументы row_num и column_num, индекс возвращает значение в ячейке на пересечении row_num и column_num.
Если для row_num или column_num задано значение 0 (ноль), индекс возвращает массив значений для всего столбца или строки соответственно. Чтобы использовать значения, возвращаемые в качестве массива, введите функцию Index в качестве формулы массива в горизонтальном диапазоне ячеек для строки и в вертикальном диапазоне ячеек для столбца. Чтобы ввести формулу массива, нажмите клавиши CTRL+SHIFT+ВВОД.
Row_num и column_num должны указывать на ячейку в массиве; В противном случае индекс возвращает #REF! значение ошибки.
Форма ссылок
Возвращает ссылку на ячейку на пересечении определенной строки и столбца. Если ссылка состоит из несмежных выделений, можно выбрать выделение для поиска. Если каждая область ссылки содержит только одну строку или столбец, аргумент row_num или column_num соответственно является необязательным. Например, для ссылки на одну строку используйте index(reference,column_num).
После того как ссылка и area_num выбрали определенный диапазон, row_num и column_num выбрать определенную ячейку: row_num 1 — первая строка диапазона, column_num 1 — первый столбец и т. д. Ссылка, возвращаемая индексом , является пересечением row_num и column_num.
Если row_num или column_num задано значение 0 (ноль), индекс возвращает ссылку на весь столбец или строку соответственно.
Row_num, column_num и area_num должны указывать на ячейку в ссылке; В противном случае индекс возвращает #REF! значение ошибки. Если row_num и column_num опущены, индекс возвращает область в ссылке, указанную area_num.
Результат функции Index является ссылкой и интерпретируется как таковой другими формулами. В зависимости от формулы возвращаемое значение Index может использоваться в качестве ссылки или в качестве значения. Например, формула CELL(«width»,INDEX(A1:B2,1,2)) эквивалентна CELL(«width»,B1) . Функция CELL использует возвращаемое значение Index в качестве ссылки на ячейку. С другой стороны, формула, например 2*INDEX(A1:B2,1,2) , преобразует возвращаемое значение Index в число в ячейке B1.
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Источник
Useful Gyaan
Follow us
Categories:
Top Posts & Pages
Like Us on Facebook
Blogroll
We Recommend:
Random Picks
VBA Trick of the Week :: Slicing an Array Without Loop – Application.Index
Sometimes we need to slice an array i.e. fetch a row/column from a multidimensional array. There is no inbuilt function in VBA to do the same and the most common way to do so is using a loop. However it can be done using a worksheet function named Index.
Application.Index(Array, Row_Number, Column_Number)
OR
Application.WorksheetFunction.Index(Array, Row_Number, Column_Number)
To extract a column from the source array, ‘0’ should be passed as row_number argument. Similarly, to extract a row from source array, ‘0’ should be passed as column_number argument.
e.g.
In the above example second row of varArray will be fetched in varTemp. We can also extract more then one row/column at the same time. In this case an array of numbers (indicating row/column) should be passed as row_number / column_number argument.
e.g. If in the above example we need to extract 2nd, 4th and 5th rows then row number would be passed as an array:
Similarly, to extract columns:
This function can also be used to fill values in a particular row/column of a range.
Syntax : Application.Index(Range, Row_number , Column_number) = SourceArray/Range
In the same example to fill the values of 2nd column of varArray to 2nd column of range [A1:E10], we would do the following
Like this:
Why didn’t you post my feedback ?
I’m not sure which feedback you are referring to. Could you please elaborate..
Hi snb…
. Did you tried to post more than one URL link?
. I noticed if you try to do that then the reply does not get posted
Alan
its a good idea to use index to extract elements from array
but it would work if Ubound 1 is not more then 65536, and rows and column which we are going to extract must not contain any value which len is more then 255
You can do this via a Range Object to overcome the Array size limit. See my post below 15th march 2016
[…] the near future I will be having a closer look at: VBA Trick of the Week :: Slicing an Array Without Loop – Application.Index from Useful […]
[…] screenshot below shows Index used to return the 4th row and the 3rd column of the sample data (see Useful Gayaan for more […]
Very nice, thanks for sharing
It works as read/write on range. How can we use it to write to a row or column of an array ?
in case of array we can not write to a row or column.
I’m trying to replicate your example here, but whenever you try to extract more than one row or one column, the method described fails. It only extracts a one-dimensional array with the i-th element specified in the Array(2,4,5) -In other words, the second, fourth and fifth element of the first column or row you specified
Hi “desilussioned with Application.Index says:“
.. maybe my reply July 2 2015 is what you want.
Oh, btw, in your example, varTemp = Application.Index(varArray, 2, 0) does not return the second column, it actually returns the second row. Just clarifying…
There is a method that is way easier.
If you are tryıng to find a variable, such as productname, you can do the following:
Cells.Find(What:=productname, After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
Do While (ActiveCell.Value productname)
Cells.FindNext(After:=ActiveCell).Activate
Loop
i’m trying to understand how your code does the same thing as is done in the post here. I can’t find any similarity.
The post tells about working with an array. We are not trying to ‘find’ any value.
Or did I misinterpret you?
This seems really cool, but is not working for me. Is it possible that this only works when varArray is a range, and not an arbitrary array?
@Philip: it should be working for any type of array. can you share your code with us. you can email it to mistertransformer@gmail.com and we can get back to you.
I to am unable to get this to work when I a want to slice more than one column to a new array. The below code was written to test this and have added comments to show the results for different line items
Sub TestSlicing()
Dim MainArray As Variant
Dim SlicedArray As Variant
‘This is a dynamic named range that is read in to produce a 2D array currently 48 rows, by 4 columns
MainArray = Application.Names(“RequestPrintLookup”).RefersToRange.Value
‘The below justs tests out the array is working as expected and puts out elements 1 and 4 for the 4th record
MsgBox MainArray(4, 1) & ” ” & MainArray(4, 4)
‘——example 1 – working as expected – slices column 4 into the sliced array ——–
SlicedArray = Application.Index(MainArray, 0, 4)
‘Writes out for confirmation the ubound for first dimension, is 48 as expect
MsgBox UBound(SlicedArray, 1), , “Example 1 – Ubound of element 1”
‘Writes out for confirmation the thirtieth element – results are as expect
MsgBox SlicedArray(30, 1), , “Example 1 – Results of sliced array, showing 30th element”
‘———–example 2 not workign as epected, desire is to take columns 3 and 4 from mainarray
SlicedArray = Application.Index(MainArray, 0, Application.Transpose(Array(3, 4)))
‘Writes out for confirmation the ubound for first dimension, now only shows 2 instead of 48 expected
MsgBox UBound(SlicedArray, 1), , “Example 2 – Ubound of element 1)”
‘Writes out for confirmation the thirtieth element – throws “Subscript out of range as there are only
‘2 rows of data, not the expected 48
MsgBox SlicedArray(30, 1), , “Example 2 – Results of sliced array, showing 30th element”
Like Desilussioned and Mark Moore I am also unable to replicate your example to extract more than one column.
Also, why use the transpose function?
Hi DiGiMac
.. maybe my reply July 2 2015 is what you want ? – it gives another alternative for picking out specific rows and columns from an Array
.. my code works as it is , and does not work without the transpose function fort he wanted Column indices. I am also struggling to understand how / why on that one!! : Maybe someone like Transformer could explain or do a good blog on that one?
Alan
i found it really interesting. thanks a lot.
I’m getting run-time error 13, type mismatch. I define my variables like so:
dim data as variant
dim rng as range
set rng = worksheets(1).range(“A1:B2”)
data = rng.value2
And then if I type the following in the immediate window:
?application.index(data, 1, 0)
I get run-time error 13.
application.index(data, 1, 0) will return an array and can not be printed in immediate window.However, you can print its elements like shown below:
e.g. ?Application.Index(data, 1, 0)(1)
?Application.Index(data, 1, 0)(2)
I have also tried to access multiple columns in an array to copy into a sheet range. The method seems to work fine for one column, but fails with several.
Using application.index(thearray,,array(1,3,5)) returns the first row only and repeats it as someone else noted earlier. Real shame. Wanted to avoid looping.
Hi BMG,
..Re ” to access multiple columns in an array to copy into a sheet range. “, maybe my reply July 2 2015 is what you want ? – it gives another alternative for picking out specific rows and columns from an Array
. Alan Elston
Nice Tipp! I deal with this situation rather often, but hadn’t thought of doing this before. Thanks!
Do you know if there are speed advantages ( Or disadvantages ) of this method over a simple looping routine ?
I am also having problems with this
I have (i.e.) this range:
0 10 20 30 40
2 12 22 32 42
4 14 24 34 44
6 16 26 36 46
8 18 28 38 48
10 20 30 40 50
12 22 32 42 52
14 24 34 44 54
16 26 36 46 56
18 28 38 48 58
Sub TEST()
Dim varArray As Variant
Dim varTemp As Variant
varArray = Range(“A1:E10”)
varTemp = Application.Index(varArray, 1, 0)
Range(“F14:J14”) = varTemp
End Sub
the result:
0 10 20 30 40
Also works fine if I get a column
BUT if i try to get more columns
changing varTemp = Application.Index(varArray, Array(1, 2, 5, 6, 8), 0)
The result is a row:
0 2 8 10 14
Right. Need to check for more than columns/rows.
Hi NPueyo,
. I am not sure if this helps: .. But if You are trying to get an Array, or Range output of the rows 1, 2, 5, 6, and 8, then this code will do it.
Sub TESTIE()
10 Dim varArray As Variant
20 Dim varTemp As Variant
30 Dim rws() As String: Let rws() = Split(“1 2 5 6 8″, ” “)
40 Dim clms() As Variant: Let clms() = Application.Transpose(Array(1, 2, 3, 4, 5))
50 varArray = Range(“A1:E10”)
60 varTemp = Application.Index(varArray, rws(), clms())
70 varTemp = Application.Transpose(Application.Index(varArray, rws(), clms()))
80 Range(“F14”).Resize(UBound(varTemp, 1), UBound(varTemp, 2)) = varTemp
End Sub
. For your data it gives in Range(“F14:J18”) this:
0 10 20 30 40
2 12 22 32 42
8 18 28 38 48
10 20 30 40 50
14 24 34 44 54
. Similarly changing line 40 to this,
40 Dim clms() As Variant: Let clms() = Application.Transpose(Array(1, 5))
would give an output of all the rows 1, 2, 5, 6, and 8 , but only give the first and last column in Range(“F14:G18”):
0 40
2 42
8 48
10 50
14 54
…………………
. So you see you can use the code to pick out whichever combination of columns and rows you wish
. I found this out by trial and error whilst answering a Forum Thread. I could not find any written explanation of how the index is working here. So I attempted an explanation myself Here: ( Around Post #13 )
http://www.mrexcel.com/forum/excel-questions/858046-visual-basic-applications-copy-data-another-workbook-based-criteria.html?s=7982a41b9f65830d627de0e137c8210d#post4174322
. Hope that may be of some help to you
Alan Elston
Germany
P.s.
. The code I wrote above will error if you want the output of just one row. (Because line 70 gives a one dimensional Array by virtue of the fact that the transpose function working on a 2 dimensional 1 column Array returns a one dimensional Array.) So lines from 80 would need to be replaces either by the following codes lines , or by replacing the .Transpose with a true Function to Transpose such as described here:
http://www.excelforum.com/excel-new-users-basics/1080634-vba-1-dimensional-horizontal-and-vertical-array-conventions-ha-1-2-3-4-a-2.html#post4094754
….
. Modified code:
80 On Error Resume Next ‘This Error handler surpresses any error – ( No “exception is raised” ) and the program contiunues after the line that would have errored
90 If UBound(varTemp, 2) 0 so we come here ( and do nothing ). Redundant code
120 End If
130 Range(“F14”).Resize(UBound(varTemp, 1), UBound(varTemp, 2)) = varTemp ‘This line will give the full output except for the case that varTemp is a one dimensional Array, in which case this line will error and not be carried out by virtue of the Error Handler
140 On Error GoTo 0 ‘Good practice to use this Statement to turn off ( disable) the current error handler. This is all that is needed in the case of the Error Handler On Error resume Next as no exception has been raised
End Sub
…
. Hope I have not confused the issue too much.
.
. Alan
. Modified code Again as it did not copy correctly:
80 On Error Resume Next ‘This Error handler surpresses any error – ( No “exception is raised” ) and the program contiunues after the line that would have errored
90 If UBound(varTemp, 2) 0 so we come here ( and do nothing ). Redundant code
120 End If
130 Range(“F14”).Resize(UBound(varTemp, 1), UBound(varTemp, 2)) = varTemp ‘This line will give the full output except for the case that varTemp is a one dimensional Array, in which case this line will error and not be carried out by virtue of the Error Handler
140 On Error GoTo 0 ‘Good practice to use this Statement to turn off ( disable) the current error handler. This is all that is needed in the case of the Error Handler On Error resume Next as no exception has been raised
End Sub
…
My last two modified codes would not copy properly and lines 100 – 110 are missing?
. contact me here if you want a copy
Doc.AElstein@t-online.de
Ahh….. Problem was greater than and less than symbols which may have been taken as HTML. So code from line 80 again a bit modified … try again
‘The following lines could be replaced by just Line 130 for most cases….
80 On Error Resume Next ‘This Error handler surpresses any error – ( No “exception is raised” ) and the program contiunues after the line that would have errored: http://www.exce
90 If UBound(varTemp, 2) = 0 Then ‘This will error for the case when varTemp is a one dimensional Array, in which case the next line will be carried out by virtue of the Error Handler
100 Range(“F14”).Resize(1, UBound(varTemp)) = varTemp ‘This line will give the first row output for the case of varTemp is a one dimensional Array
110 Else ‘Either line 90 errored for the case of a 1 dimensional array, so the last line is carried out, Or it did not error in the case of a 2 dimensional array, but did not have a column Upper bound of 0 so we come here ( and do nothing ). Redundant code
120 End If
130 Range(“F14”).Resize(UBound(varTemp, 1), UBound(varTemp, 2)) = varTemp ‘This line will give the full output except for the case that varTemp is a one dimensional Array, in which case this line will error and not be carried out by virtue of the Error Handler
140 On Error GoTo 0 ‘Good practice to use this Statement to turn off ( disable) the current error handler. This is all that is needed in the case of the Error Handler On Error resume Next as no exception has been raised
End Sub
Hi, thanks for the very useful trick. I wonder if is there a way to slice columns something like:
varTemp = Application.Index(varArray, 0, Application.Transpose(Array(2 to 5))) or
varTemp = Application.Index(varArray, 0, Application.Transpose(Array(2:5)))
(unfortunately the two exp. above are not working)
instead of writng one by one like
varTemp = Application.Index(varArray, 0, Application.Transpose(Array(2, 3, 4, 5)))
See my reply 2 July 2015. With the second argument as a 1 column 2 dimensional array of all row indicies, and the third arguments as a 1dimensional Array of the column indicies that you want it should work as you wish
Alan
so for your example, your second argument would look like:
I guess i couldn’t explained well enough. I have an array called
Arr1(1 to 51, 1 to 13) as double
which is created through looping within an excel vba module by some mathematical calculations with option base1.
The first column consists of ID numbers and the next 25 columns are the results that i am seeking for the max and min values where i am trying to get without looping if possible.
Result_Max = WorksheetFunction.Max(Application.Index(Arr1, , Application.Transpose(clms))
works like a charm if i set
clms() = Array(2, 3 , 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25)
which is very cumbersome especially when i consider that the Arr1 boundaries are dynamic and set by the user to adjust the precision.
So, my main problem is that i couldn’t find an easy way to create such clms() array of which elements should be between 2 dynamic integers such as 2 to 25 as given above.
Hi burec.
Thanks for the Feedback.
OK , … I thought it might be something along those line….
The following may still be a bit cumbersome. But maybe you could simplify it and possibly turn it into a function etc…
This will give you your required 1D Array based on the given Upper and lower Column Numbers in variables LB and UB
It converts the column Numbers into the corresponding column Letter.
Then it uses the Method I indicated before in Post 19 and 20 November to give you the sequential numbers you require
Sub burakGenerateSequentialColumnIndiciesFromLetters() ‘Dec 9 usefulgyaan.wordpress.com/2013/06/12/vba-trick-of-the-week-slicing-an-array-without-loop-application-index/
‘Variables for…
Dim LB As Long, UB As Long ‘…User Given start and Stop Column as a Number
Let LB = 2: Let UB = 25
Dim strLtrLB As String, strLtrUB As String ‘…Column Letter corresponding to Column Number
‘There are many ways to get a Column Letter from a Column Number – excelforum.com/tips-and-tutorials/1108643-vba-column-letter-from-column-number-explained.html
Let strLtrLB = Split(Cells(1, LB).Address, “$”)(1) ‘An Address Method
Let strLtrUB = Replace(Replace(Cells(1, UB).Address, “1”, “”), “$”, “”) ‘A Replace Method
‘Obtain Column Indicies using Spreadsheet Function Column via VBA Evaluate Method
Dim clms() As Variant
Let clms() = Evaluate(“column(” & strLtrLB & “:” & strLtrUB & “)”) ‘Returns 1 D “pseudo” Horizontal Array of sequential numbers from column number of LB to UB
‘Or
clms() = Evaluate(“column(” & Split(Cells(1, LB).Address, “$”)(1) & “:” & Replace(Replace(Cells(1, UB).Address, “1”, “”), “$”, “”) & “)”)
End Sub
That is the perfect answer for me… 🙂
Glad to Help
Many Thanks for the Feedback
🙂
Application.Index was unstable for me – I used it a lot in one project and ended up having to transform all instances to resizing via loop. I don’t think it’s the 255 characters limit or 65556 rows – my arrays were usually about 1000×3 with 4 – 10 characters in the fields. Excel would sometimes ! break and if you press F5 then it would run further with no problem. Posting it only as a warning, I don’t have exact reason for the issue, just posting as a warning as I couldn’t find any similar problems on google
Thanks very much for that. I like this method a lot,
But am a bit nervous already, as I can find virtually no explanation of how it works… which makes me very very nervous about using it
I have all but given up on understanding excactly what is going on…..
http://www.mrexcel.com/forum/excel-questions/908760-visual-basic-applications-copy-2-dimensional-array-into-1-dimensional-single-column.html#post4375354
P.S. a) The way I do it is a bit different so may be differently effected by your problem ( Briefly you use Arrays with the full set of indicies required rather than a 1 and a 0. ( http://www.excelforum.com/excel-new-users-basics/1099995-application-index-with-look-up-rows-and-columns-arguments-as-vba-arrays.html )
b) Doing it the way i do you can replace the Input Array with Cells ( adjusting the indicies in the Arrays accordingly ) That might also be effected differntly by your problem
How to assign a variable in place of ’10’ in “Application.Index([A1:E’10’], , 2) = ” ?
‘I do not think you can do this using the [ ] shorthand. I may be wrong.
‘But this demonstrate Different Cuntstructions of First Argument in .Index
Sub IndexFieldReturnDiffCuntFistArgWonk()
Dim vTemp As Variant ‘Variable constructed to accept all info allowing its use for all other variables with the exceptiion of a defined String length greater than 255 http://www.eileenslounge.com/viewtopic.php?f=27&t=22512
Dim FieldReturned As Variant ‘Variable constructed to accept all info allowing its use for all other variables with the exceptiion of a defined String length greater than 255
Dim arr() As Variant ‘Variable to accept a Field ( Array ) of Variant Types to suit that returned when .Index has first argument ( grid ) of Varaint Types
‘ Hard Coding
Let FieldReturned = Application.Index([A1:E10], 0, 2) ‘Using named range
Let FieldReturned = Application.Index(Range(“A1:E10”), 0, 2) ‘Using Spreadsheet range
Let arr() = Application.Index(Evaluate(“If(Row(),A1:E10)”), 0, 2) ‘Using Evaluated spreadsheet values
‘ “Soft” Coding
Dim Rw As Long ‘This variable Type can be fixed from the outset*** to specific memory space: Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647) If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there’s no point using anything but Long.–upon/after 32-bit, Integers (Short) need converted internally anyways, so a Long is actually faster. )
Let Rw = 10 ‘ The Value of the Variable has changed. The “size” ( Memory required space ) has not***
Let FieldReturned = Application.Index(Range(“A1:E” & Rw & “”), 0, 2) ‘Range( Literal string required, which VBA recognises when in Paranthesis ” ” )
Let arr() = Application.Index(Evaluate(“If(Row(),A1:E” & Rw & “)”), 0, 2) ‘In VBA ” & takes you out of and & ” back into the Literal String
‘ The [ ] works slightly differently. It brings you specifically in the Spreadsheet Range as a ( reserved ) name there http://www.mrexcel.com/forum/excel-questions/899117-visual-basic-applications-range-a1-a5-vs-%5Ba1-a5%5D-benefits-dangers-2.html#post4332606
End Sub
‘I do not think you can do this using the [ ] shorthand. I may be wrong.
‘But this demonstrate Different Contstructions of First Argument in .Index
Sub IndexFieldReturnDiffContFistArgWonk()
Dim vTemp As Variant ‘Variable constructed to accept all info allowing its use for all other variables with the exceptiion of a defined String length greater than 255 http://www.eileenslounge.com/viewtopic.php?f=27&t=22512
Dim FieldReturned As Variant ‘Variable constructed to accept all info allowing its use for all other variables with the exceptiion of a defined String length greater than 255
Dim arr() As Variant ‘Variable to accept a Field ( Array ) of Variant Types to suit that returned when .Index has first argument ( grid ) of Varaint Types
‘ Hard Coding
Let FieldReturned = Application.Index([A1:E10], 0, 2) ‘Using named range
Let FieldReturned = Application.Index(Range(“A1:E10”), 0, 2) ‘Using Spreadsheet range
Let arr() = Application.Index(Evaluate(“If(Row(),A1:E10)”), 0, 2) ‘Using Evaluated spreadsheet values
‘ “Soft” Coding
Dim Rw As Long ‘This variable Type can be fixed from the outset*** to specific memory space: Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647) If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there’s no point using anything but Long.–upon/after 32-bit, Integers (Short) need converted internally anyways, so a Long is actually faster. )
Let Rw = 10 ‘ The Value of the Variable has changed. The “size” ( Memory required space ) has not***
Let FieldReturned = Application.Index(Range(“A1:E” & Rw & “”), 0, 2) ‘Range( Literal string required, which VBA recognises when in Paranthesis ” ” )
Let arr() = Application.Index(Evaluate(“If(Row(),A1:E” & Rw & “)”), 0, 2) ‘In VBA ” & takes you out of and & ” back into the Literal String
‘ The [ ] works slightly differently. It brings you specifically in the Spreadsheet Range as a ( reserved ) name there http://www.mrexcel.com/forum/excel-questions/899117-visual-basic-applications-range-a1-a5-vs-%5Ba1-a5%5D-benefits-dangers-2.html#post4332606
End Sub
‘I do not think you can do this using the [ ] shorthand. I may be wrong.
‘But this demonstrate Different Contstructions of First Argument in .Index
Sub IndexFieldReturnDiffContFistArgWonk()
Dim vTemp As Variant ‘Variable constructed to accept all info allowing its use for all other variables with the exceptiion of a defined String length greater than 255
Dim FieldReturned As Variant ‘Variable constructed to accept all info allowing its use for all other variables with the exceptiion of a defined String length greater than 255
Dim arr() As Variant ‘Variable to accept a Field ( Array ) of Variant Types to suit that returned when .Index has first argument ( grid ) of Varaint Types
‘ Hard Coding
Let FieldReturned = Application.Index([A1:E10], 0, 2) ‘Using named range
Let FieldReturned = Application.Index(Range(“A1:E10”), 0, 2) ‘Using Spreadsheet range
Let arr() = Application.Index(Evaluate(“If(Row(),A1:E10)”), 0, 2) ‘Using Evaluated spreadsheet values
‘ “Soft” Coding
Dim Rw As Long ‘This variable Type can be fixed from the outset*** to specific memory space: Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647) If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there’s no point using anything but Long.–upon/after 32-bit, Integers (Short) need converted internally anyways, so a Long is actually faster. )
Let Rw = 10 ‘ The Value of the Variable has changed. The “size” ( Memory required space ) has not***
Let FieldReturned = Application.Index(Range(“A1:E” & Rw & “”), 0, 2) ‘Range( Literal string required, which VBA recognises when in Paranthesis ” ” )
Let arr() = Application.Index(Evaluate(“If(Row(),A1:E” & Rw & “)”), 0, 2) ‘In VBA ” & takes you out of and & ” back into the Literal String
‘ The [ ] works slightly differently. It brings you specifically in the Spreadsheet Range as a ( reserved ) name there
End Sub
Hi
Coming right back to the original codes in this Blog. It might be worth noting that the slicing method actually will work on a Range Object and, importantly return a Range Object for the case of returning a single Row ( or column ). One can then, if only values are wanted apply the .Value property to that returned Range Object to return the same Array of Variant types as in the Array case. But one has the extra flexibility of having in the first instance the range object from which ant to which other Methods can be applied. ( And one does not have the 255 x 65535 limits )
Compare the following code with very original code in this blog. Lines 70 will produce the same Array as the original VarTemp at the start of this Blog.
( Note also my alternative method of Line 90 will not return a Range, but the identical Array is returned in Line 100 )
Further more I have been finding in general that the .Index ( as with .Match ) are slightly quicker when using the form such as in Lines 130 and 135 to return an Array. I expect that may be VBA does some internal conversion of an Array as First Argument in .Index ( Second Argument in .match ) into a “pseudo” Range. These are after all “Worksheet” Functions..
Sub SliceRange()
10 Dim rngIn As Range
20 Set rngIn = Range(“A1:E10”)
30
40 Dim rngOut As Range
50 Set rngOut = Application.Index(rngIn, 2, 0) ‘Returns Range Object Range(“A2:E2”)
60 Dim VarTemp() As Variant ‘ Array to accept Variant Type Fiels Elements returned by applying .Value Property to a Range of more than one cell
70 Let VarTemp() = rngOut.Value ‘Returns 2 D Array ( 1 to 1, 1 to 5 )
80
90 ‘Set rngOut = Application.Index(rngIn, 2, Array(1, 2, 3, 4, 5)) ‘Runtime Error 424 – Object required
100 Let VarTemp() = Application.Index(rngIn, 2, Array(1, 2, 3, 4, 5)) ‘Returns 1 D Array ( 1 to 5 ), same values as Line 70
110
120 Dim vTemp As Variant
130 Let vTemp = Application.Index(rngIn, 2, 0) ‘Returns 2 D Array ( 1 to 1, 1 to 5 ) identical to line 70
135 Let vTemp = Application.Index(rngIn, 2, 0).Value ‘Returns 2 D Array ( 1 to 1, 1 to 5 ) identical to line 70
End Sub
If multiple rows need to slice, this is how it works:
With Application
varTemp = .Transpose(varArray, _
Array(2,4,5), _
.Transpose(Array(1,2,3…n))))
End With
when n – is number of columns in varTemp
This version of your code snippet has a syntax error
With Application
VarTemp = .Transpose(varArray, _
Array(2, 4, 5), _
.Transpose(Array(1, 2, 3))))
End With
This does not have a syntax error, but does not appear to work
With Application
VarTemp = .Transpose(varArray, _
Array(2, 4, 5), _
.Transpose(Array(1, 2, 3)))
End With
Possibly you meant this:
With Application
VarTemp = .Transpose(.Index(varArray, _
Array(2, 4, 5), _
.Transpose(Array(1, 2, 3))))
End With
The above gives the same results as the following, which is the form I have discussed a few times in this Blog
With Application
VarTemp = .Index(varArray, _
Application.Transpose(Array(2, 4, 5)), _
(Array(1, 2, 3)))
End With
Your ( corrected ) version is OK, but has an extra unecerssary .Transpose
_……….
Hi
One quick follow up here….. Following a discussion from Rick here:
http://www.mrexcel.com/forum/general-excel-discussion-other-questions/929381-visual-basic-applications-split-function-third-argument-refers-maximum-outputs-%93when-splitting-stops-%94.html#post4467983
I can see a more pleasantly looking version of my basic code to get selected Rows and columns…
Rather than this:
VarTemp() = Application.Index(varArray, Application.Transpose(Array(2, 4, 5)), (Array(1, 2, 3)))
You can use this to achieve the same
VarTemp() = Application.Index(varArray, [ < 2 ; 4 ; 5 >], [ < 1 , 2, 3 >])
The key is the
[ < 2 ; 4 >]
Representing a 2 Dimension “1 Column” Array.
This possibility is overlooked sometimes maybe, as often we see more often the “1 Dimension” or “row” form represented by things like
= Array(1, 2)
And
Hi Alan, I’m trying to apply your code but I’m finding that there is no output, all “#VALUE!”, so presumably I’m using it incorrectly. My current code is as follows:
Dim vLoadData As Variant, vNewData As Variant
Dim rws() As String: Let rws() = Split(“1 2 3 4 5”, “”)
Dim clms() As Variant: Let clms() = Application.Transpose(Array(2, 20, 6, 28))
vLoadData = Range(Cells(1, iSameDate), Cells(28, iEndDate))
vNewData = Application.Index(vLoadData, rws(), clms())
vNewData = Application.Transpose(Application.Index(vLoadData, rws(), clms()))
Range(Cells(1, iUpdateCell), Cells(5, iUpdateCell + iEndDate – iSameDate)) = vNewData
Is there anything obvious I am missing/doing wrong?
The “i…” variables are all integers that refer to columns (numerically) in the spreadsheet.
Hi Lucus,
A few things:
_1) Please Try to give a full code and reduced size Data, as it makes it easier for me to work on for you.
_2) You are not using my most recent codes. You are using variations possibly of earlier ones. Take a look again through my Posts…..
_ …. I found later that you can do away with one Transpose. The General Formula then is now
arrOut() = Application.Index(arrIn(), rwsT(), clms()) ‘ rwsT() is a 2 Dimension 1 Column Array , clms() is a 1 Dimensional Array.
( _ I use rwsT() currently to remind me that this is a Transpose of rws(), ( if rws() is a 1 Dimension Array ) )
_3) I do not quite understand the followoing Line, ….
Range(Cells(1, iUpdateCell), Cells(5, iUpdateCell + iEndDate – iSameDate)) = vNewData
_ ……and I cannot check the code without having specific values of your “i…” variables…….
_ 3a) Note: Using my codes, you obtain a vNewData which is a new Array reduced in size compared with the original Data Array vLoadData.
_ So, Usually if I chose for example cell AG6 as the Top left of where I want my Output to go, then the Line to output to the Spreadsheet would have the following Form.
Range(“AG6”).Resize(UBound(vNewData, 1), UBound(vNewData, 2)).Value = vNewData
Here the .Resize Property is used to return a new Range increased to the size of the output Array vNewData. So then this new size has the correct size to match to the output Array vNewData. The values of the output Array vNewData can then be assigned to the Spreadsheet Range.
_……………………………………………
Here are some modified versions of your Code. They all appear to work.
I am guessing a bit exactly what you want. I am guessing that you want to have in your output Array, vNewData, is the rows, 1 , 2 , 3, 4, 5 and columns 2, 20, 6, 28 from your Input Array, vLoadData.
Источник
title | keywords | f1_keywords | ms.prod | api_name | ms.assetid | ms.date | ms.localizationpriority |
---|---|---|---|---|---|---|---|
WorksheetFunction.Index method (Excel) |
vbaxl10.chm137090 |
vbaxl10.chm137090 |
excel |
Excel.WorksheetFunction.Index |
4656985a-2864-93ed-31c7-e7a551d68e96 |
05/23/2019 |
medium |
WorksheetFunction.Index method (Excel)
Returns a value or the reference to a value from within a table or range. There are two forms of the Index function: the array form and the reference form.
Syntax
expression.Index (Arg1, Arg2, Arg3, Arg4)
expression A variable that represents a WorksheetFunction object.
Parameters
Name | Required/Optional | Data type | Description |
---|---|---|---|
Arg1 | Required | Variant | Array or Reference — a range of cells or an array constant. For references, it is the reference to one or more cell ranges. |
Arg2 | Required | Double | Row_num — selects the row in array from which to return a value. If row_num is omitted, column_num is required. For references, the number of the row in reference from which to return a reference. |
Arg3 | Optional | Variant | Column_num — selects the column in array from which to return a value. If column_num is omitted, row_num is required. For reference, the number of the column in reference from which to return a reference. |
Arg4 | Optional | Variant | Area_num — only used when returning references. Selects a range in reference from which to return the intersection of row_num and column_num. The first area selected or entered is numbered 1, the second is 2, and so on. If area_num is omitted, Index uses area 1. |
Return value
Variant
Remarks
Array form
Returns the value of an element in a table or an array, selected by the row and column number indexes.
Use the array form if the first argument to Index is an array constant.
If both the row_num and column_num arguments are used, Index returns the value in the cell at the intersection of row_num and column_num.
If you set row_num or column_num to 0 (zero), Index returns the array of values for the entire column or row, respectively. To use values returned as an array, enter the Index function as an array formula in a horizontal range of cells for a row, and in a vertical range of cells for a column. To enter an array formula, press Ctrl+Shift+Enter.
Row_num and column_num must point to a cell within array; otherwise, Index returns the #REF! error value.
Reference form
Returns the reference of the cell at the intersection of a particular row and column. If the reference is made up of nonadjacent selections, you can pick the selection to look in. If each area in reference contains only one row or column, the row_num or column_num argument, respectively, is optional. For example, for a single row reference, use INDEX(reference,column_num).
After reference and area_num have selected a particular range, row_num and column_num select a particular cell: row_num 1 is the first row in the range, column_num 1 is the first column, and so on. The reference returned by Index is the intersection of row_num and column_num.
If you set row_num or column_num to 0 (zero), Index returns the reference for the entire column or row, respectively.
Row_num, column_num, and area_num must point to a cell within reference; otherwise, Index returns the #REF! error value. If row_num and column_num are omitted, Index returns the area in reference specified by area_num.
The result of the Index function is a reference and is interpreted as such by other formulas. Depending on the formula, the return value of Index may be used as a reference or as a value. For example, the formula CELL("width",INDEX(A1:B2,1,2))
is equivalent to CELL("width",B1)
. The CELL function uses the return value of Index as a cell reference. On the other hand, a formula such as 2*INDEX(A1:B2,1,2)
translates the return value of Index into the number in cell B1.
[!includeSupport and feedback]
METHOD 1. Excel INDEX Function using hardcoded values
EXCEL
Result in cell E14 ($5.40) — returns the value in the forth row and second column relative to the specified range. |
=INDEX((B5:C8,B9:C11),3,2,2) |
Result in cell E15 ($7.40) — returns the value in the third row and second column relative to the second range specified in the formula. |
=INDEX((B5:D8,B9:D11),2,3,2) |
Result in cell E16 ($3.00) — returns the value in the second row and third column relative to the second range specified in the formula. |
=INDEX((B5:C8,B9:C11,Index_Defined_Name),2,3,3) |
Result in cell E17 ($2.10) — returns the value in the second row and third column relative to the range specified by the defined name named Index_Defined_Name which comprises a B5:D11 range. |
METHOD 2. Excel INDEX Function using links
EXCEL
=INDEX(B5:C11,B14,C14) |
Result in cell E14 ($5.40) — returns the value in the forth row and second column relative to the specified range. |
=INDEX((B5:C8,B9:C11),B15,C15,D15) |
Result in cell E15 ($7.40) — returns the value in the third row and second column relative to the second range specified in the formula. |
=INDEX((B5:D8,B9:D11),B16,C16,D16) |
Result in cell E16 ($3.00) — returns the value in the second row and third column relative to the second range specified in the formula. |
=INDEX((B5:C8,B9:C11,Index_Defined_Name),B17,C17,D17) |
Result in cell E17 ($2.10) — returns the value in the second row and third column relative to the range specified by the defined name named Index_Defined_Name which comprises a B5:D11 range. |
METHOD 3. Excel INDEX function using the Excel built-in function library with hardcoded values
EXCEL
Formulas tab > Function Library group > Lookup & Reference > INDEX > populate the input box
=INDEX(B5:C11,4,2) Note: in this example we are populating the Array, Row_num and Column_num INDEX function arguments. |
=INDEX((B5:C8,B9:C11),3,2,2) Note: in this example we are only populating all of the INDEX function arguments. |
METHOD 4. Excel INDEX function using the Excel built-in function library with links
EXCEL
Formulas tab > Function Library group > Lookup & Reference > INDEX > populate the input boxes
=INDEX(B5:C11,B14,C14) Note: in this example we are populating the Array, Row_num and Column_num INDEX function arguments. |
=INDEX((B5:C8,B9:C11),B15,C15,D15) Note: in this example we are only populating all of the INDEX function arguments. |
METHOD 1. Excel INDEX function using VBA with hardcoded values
VBA
Sub Excel_Index_Function_Using_Hardcoded_Values()
Dim ws As Worksheet
Set ws = Worksheets(«INDEX»)
ws.Range(«E14»).Value = Application.WorksheetFunction.Index(Range(«B5:C11»), 4, 2)
ws.Range(«E15»).Value = Application.WorksheetFunction.Index(Range(«B5:C8,B9:C11»), 3, 2, 2)
ws.Range(«E16»).Value = Application.WorksheetFunction.Index(Range(«B5:D8,B9:D11»), 2, 3, 2)
ws.Range(«E17»).Value = Application.WorksheetFunction.Index(Range(«B5:C8,B9:C11,Index_Defined_Name»), 2, 3, 3)
End Sub
OBJECTS
Worksheets: The Worksheets object represents all of the worksheets in a workbook, excluding chart sheets.
Range: The Range object is a representation of a single cell or a range of cells in a worksheet.
PREREQUISITES
Worksheet Name: Have a worksheet named INDEX.
Defined Name: Have a defined name named Index_Defined_Name that comprises a B5:D11 range.
ADJUSTABLE PARAMETERS
Output Range: Select the output range by changing the cell references («E14»), («E15»), («E16») and («E17») in the VBA code to any cell in the worksheet, that doesn’t conflict with the formula.
METHOD 2. Excel INDEX function using VBA with links
VBA
Sub Excel_Index_Function_Using_Links()
Dim ws As Worksheet
Set ws = Worksheets(«INDEX»)
ws.Range(«E14»).Value = Application.WorksheetFunction.Index(Range(«B5:C11»), Range(«B14»), Range(«C14»))
ws.Range(«E15»).Value = Application.WorksheetFunction.Index(Range(«B5:C8,B9:C11»), Range(«B15»), Range(«C15»), Range(«D15»))
ws.Range(«E16»).Value = Application.WorksheetFunction.Index(Range(«B5:D8,B9:D11»), Range(«B16»), Range(«C16»), Range(«D16»))
ws.Range(«E17»).Value = Application.WorksheetFunction.Index(Range(«B5:C8,B9:C11,Index_Defined_Name»), Range(«B17»), Range(«C17»), Range(«D17»))
End Sub
OBJECTS
Worksheets: The Worksheets object represents all of the worksheets in a workbook, excluding chart sheets.
Range: The Range object is a representation of a single cell or a range of cells in a worksheet.
PREREQUISITES
Worksheet Name: Have a worksheet named INDEX.
Defined Name: Have a defined name named Index_Defined_Name that comprises a B5:D11 range.
ADJUSTABLE PARAMETERS
Output Range: Select the output range by changing the cell references («E14»), («E15»), («E16») and («E17») in the VBA code to any cell in the worksheet, that doesn’t conflict with the formula.
Indexes in Programming
“Index” is a common term used in all programming languages. It basically acts like a serial number of which an item or value can be referenced. For example, in the picture below, “Great Wall of China” is the 5th item in the series. In programming we say that its index is “5.” In some programming languages the index numbering starts with “0.” If such is the case, the index of the same “Great Wall of China” would be “4” (0, 1 , 2, 3, 4).
In general, “index” can be used to reference the values of an array or a range (in Excel).
The Index Formula in Excel
In MS Excel, index is a formula that helps us find the value in a specified array.
Syntax of the formula:
Index(< array name >, < row number >, [< col number>])
Where
- Array is an array of values (a list of one or more dimensions)/ a reference to an array.
- Row number is the row index being referred to
- Col number is the column index being referred to
Example 1
In this example we are trying to find the value in the 7th position of the lookup range (the parameter used in the formula).
Here the range is B2 to B9 i.e. Starting from the value “Taj Mahal” (position 1) in B2 until “Great Pyramid of Giza” (position in B9. Visually we can see that Petra is the 7th value in the selected range. Hence, it is the value returned by the formula.
Note: S.no is given in the example for easy understanding and it has nothing to do with the Index formula.
Example 2
Let us try to find the price of the 7th item (“Sambar Idly”) sold at a snack bar. There are two columns here, one with the list of items and the other with the respective price.
Note: Paste this table starting with cell A1 on the Excel sheet for the formula’s range to work.
Item | Price |
Ice cream | 5 |
Sweet corn | 6 |
Spinach Candy | 8 |
Banana Cake | 3 |
Peas Pulao | 40 |
Methi Roti | 30 |
Sambar Idly with ghee | 20 |
Veg clear Soup | 40 |
Masala Papad | 10 |
The formula would be =INDEX(A2:B10,7,2)
Where
A2:B10 is the range of data in the table
7 because we are looking for the 7th item (row-wise)
2 because we want the price of the item. The price is in the 2nd col. And the answer would be 20.
The Index Function in VBA
The Index function in VBA is very simple. Just as in the formula, here we also have to pass the array and the position as parameters. The function then returns the value in that position.
Example 1
In the example below, there is an array of students in a class. Let us assume that we know the roll number of the student who has obtained Rank 1. We are asked to find his/her name.
Sub index_demo() ' declare variables Dim arr_students() Dim first_rank ' initialize the arrayarr_students = Array("John Capps", "Michel Pinny", "Kanya Dhan", "Ron Dincy", "Bella", "Mayur", "Jack finner", "Emi Thinner") ' We know that the fourth student in the array has got the first rank. We need to find his name first_rank = Application.WorksheetFunction.Index(arr_students, 4) 'Display the name of the first rank holder in a messagebox MsgBox first_rank & " is the student who got the first rank." End Sub
Example explained:
To start with, we have declared the required variables. Then we have initiated an array (arr_students) with the list of student names as values.
In order to use the Index function, we should have the array and required position number as parameters. As we have created the array already (arr_students) and we know that the name of the student with the roll number “4” is to be fetched, we proceed to use the function.
Application.WorksheetFunction.Index
(arr_students, 4)
Application refers to the Excel application being used currently.
Worksheetfunction refers to the bunch of functions offered by Excel for any worksheet.
Index is also a worksheetfunction which we are learning to use here.
The output/return value of this function is passed/caught in the variable declared earlier — first_rank
.
Finally, the value of the variable is displayed with a description in a message box.
Example 2
In this example, we will use the worksheetfunction index in VBA but the array that we refer to will be a Range of Excel cells.
Scenario: Some sports personalities ran a race and reached the finish line in a particular order. The array of players is in the finishing order. We are asked to find the runner of the race.
Let’s try to find the person who wins the second place in the competition. This will be our position value in the function.
The range of the array is Range(“B2:B9”).
Knowing the required values, we can proceed with writing the code.
Sub index_demo2() ' declare variables Dim arr_players() Dim runner ' initialize the array arr_players = Range("B2:C9") ' We know that the second player in the array is the runner. We need to find his name runner = Application.WorksheetFunction.Index(arr_players, 2) 'Display the name of the runner in a messagebox MsgBox runner(1) & " is the player who won the second place. His email id is " & runner(2) End Sub
Code explained:
As mentioned in Example 1, we have declared and initialized the variables. Then we use the Index function to find runner (2nd place) of the match.
The flow of the program is the same with the difference that here we have been forced to use runner(1) to display value.
Reason: An Excel range is considered a multidimensional array. Because of this, the return value is not just a string. Instead, it is also an array. To find a value in that array, we have to specify index.
(1) is used here since there is only one value (or we have specified only 1 column in the range).
To understand it better, if we had used the range Range (“B2:C9” ) in our code, then the return value of the index would have both values in Range (“B2”) and Range(“C2”) i.e. All values of (various columns) of the second row (position parameter given in the Index function).
The image above clearly shows the value of the runner object (the returned value). It has both the name and the email address. Suppose, I want to display the email address of the runner, I will have to display runner(2) in the messagebox.
MsgBox runner(1) & " is the player who won the second place. His email id is " & runner(2) <!-- /wp:shortcode --> <!-- wp:image {"id":14452,"sizeSlug":"large","linkDestination":"none"} --> <figure class="wp-block-image size-large"><img src="https://software-solutions-online.com/wp-content/uploads/2021/06/unnamed-11.png" alt="Excel message box that reads &quot;Fred is the player who won the second place. His email id is [email protected]&quot;" class="wp-image-14452"/></figure> <!-- /wp:image --> <!-- wp:heading {"level":3} --> <h3>Example 3</h3> <!-- /wp:heading --> <!-- wp:paragraph --> <p>In the example below, we get the capital of a state whose index is known. So, we are using an array of two dimensions. If we use formula, we refer to the 4<sup>th</sup> row and 2<sup>nd</sup> column of the selected range. So the value of the cell turns out to be “Patna”.</p> <!-- /wp:paragraph --> <!-- wp:image {"id":14457,"sizeSlug":"large","linkDestination":"none"} --> <figure class="wp-block-image size-large"><img src="https://software-solutions-online.com/wp-content/uploads/2021/06/unnamed-12-1024x266.png" alt="Example of using array to find capital states." class="wp-image-14457"/></figure> <!-- /wp:image --> <!-- wp:paragraph --> <p>Let us do the same using VBA.</p> <!-- /wp:paragraph --> <!-- wp:shortcode --> Sub IndexMatch_demo1() ' declare variables Dim required_pos, str_capital, arr_states_cap, capital_col ' initialize variables required_pos = 4 capital_col = 2 arr_states_cap = Range("B2:C16") 'use the function to get the capital str_capital = Application.WorksheetFunction.Index([arr_states_cap], required_pos, 2) ' display the result MsgBox str_capital End Sub
Code explained:
Post declaration and initialization of variables, the Index function is used to get the value in the 4th row, 2nd column of the selected state, capital range of cells on the Excel sheet.
Finally, the output that we see in the message box would be “Patna” which is the capital of Bihar.
The Match Formula and Function
Here is my article about the Match formula in Excel and Match function in VBA:
Using the Match Function in VBA and Excel – VBA and VB.Net Tutorials, Education and Programming Services (software-solutions-online.com)
Using the Index Function with the Match Function
As we have already understood, the Index function gives the value in the known index of an array. The Match function does the opposite. It provides the index value of an item in an array or range of values.
It is possible to use one of these functions within the other. i.e. Match within Index (or) Index within Match.
Example 1
Here is a table that has details of States, Capitals and another column to describe when it was formed (“Founded on”). We are asked to find the “Founded on” value of the state “Maharashtra”.
Let us assume that we do not know its index. So, initially we will use the Match function to find its index.
Once we get that index, using Index we can get the respective values of that index (rows) against all columns.
Sub IndexMatch_demo() 'declare variables Dim strstate, arr_states, arr_capitals, arr_founded, rowposition_state, str_capital, str_founded ' initialize variables ( set values for them ) strstate = "Maharashtra" arr_states = Range("B2:B30") arr_capitals = Range("C2:C30") arr_founded = Range("D2:D30") ' find the position of the state in the first array ( 0 here states an exact match) rowposition_state = Application.WorksheetFunction.Match(strstate, ([arr_states]), 0) 'Find the respective capital and "founded on" values of the said state. str_capital = Application.WorksheetFunction.Index([arr_capitals], rowposition_state) str_founded = Application.WorksheetFunction.Index([arr_founded], rowposition_state) ' display all values Debug.Print str_capital(1) Debug.Print str_founded(1) End Sub
Code explained:
The required variables are first declared and then initialized. From these lines, we infer that we are supposed to find the capital and “Founded on” values of the state “Maharashtra.” So, using the Match function in VBA, we find the position of the state ”Maharashtra.” Then using the same value as the index, we find the capital and “Founded on” values from the respective arrays and display the same in the Immediate window (using the debug.print statement).
In order to explain this further, three arrays were created in the example. If the ranges quoted for each of these arrays are not within the same range ( row values), then this concept of using the same index (row num here) for finding values in other arrays will not work. So, let us redo the same with one range as a subset of another range to understand the concept better.
Sub IndexMatch_demo3() 'declare variables Dim strstate, arr_states, start_pos, end_pos, rowposition_state, str_capital, arr_states_captials ' initialize variables ( set values for them ) strstate = "Maharashtra" start_pos = 2 end_pos = 30 'dynamic defining of the arrays from the excel sheet. The rows values are not hardcoded here. arr_states_captials = Range("B" & start_pos & ":D" & end_pos) arr_states = Range("B" & start_pos & ":B" & end_pos) ' find the position of the state in the states array ( 0 here states an exact match) rowposition_state = Application.WorksheetFunction.Match(strstate, [arr_states], 0) 'Find the respective capital and "founded on" values of the said state. str_capital = Application.WorksheetFunction.Index([arr_states_captials], rowposition_state, 2) str_founded = Application.WorksheetFunction.Index([arr_states_captials], rowposition_state, 3) ' display all values Debug.Print str_capital Debug.Print str_founded End Sub
Code explained:
The difference in this modified code lies in the dynamic building of array range. A single dimensional array is defined in order to find the index using the Match function. Then we find the respective values from the other two columns. The Index function here uses both the row position and col position parameter since the array is multidimensional (a complete picture of this is available in the image above).
Conclusion
In my experience, I see that the Index function can be used with multidimensional arrays but when it comes to the Match function, multidimensional arrays have to be sliced using loops and conditions before being passed as parameters. Using a combination of both these functions (Index and Match), it is possible and easy to point to any value/index/any target in a table or an array or a range of Excel cells. Using them wisely can produce great results.