Excel vba array of user defined types

Создание пользовательских типов данных в VBA Excel. Оператор Type, его описание и параметры. Создание массива «одномерных массивов» с пользовательскими данными.

Определение пользовательских типов данных

Пользовательский тип данных в VBA Excel представляет из себя набор элементов, каждому из которых пользователем присваивается свой тип данных. Другими словами, пользовательский тип данных — это набор данных разного типа, который может быть присвоен одной переменной.

Если простую переменную (не массив) объявить с пользовательским типом данных, она будет представлять из себя «одномерный массив»* с элементами разных типов данных, определенных пользователем.

Если с пользовательским типом данных объявить переменную массива, она будет представлять из себя массив «одномерных массивов»* пользовательских данных.

* Выражение «одномерный массив» взято в кавычки, так как фактически это не массив, а набор пользовательских данных, но для практического применения это не имеет значения.

Синтаксис оператора Type

Type <strong>Name</strong>

<strong>Element</strong>_1 as <strong>Tip</strong>

<strong>Element</strong>_2 as <strong>Tip</strong>

<strong>Element</strong>_3 as <strong>Tip</strong>

<strong>Element</strong>_n as <strong>Tip</strong>

End Type

Пользовательский тип данных в VBA Excel может быть объявлен с ключевым словом Public или Private, которое явно укажет зону его видимости. Если ключевое слово опущено, конструкция с оператором Type по умолчанию объявляется с зоной видимости Public.

Параметры оператора Type

Параметр Описание
Name Имя пользовательского типа данных, по которому этот тип данных будет присваиваться переменным.
Element Наименование отдельного элемента пользовательского типа данных.
Tip Тип данных отдельного элемента (стандартный тип VBA).

Применение пользовательских типов данных

Применение пользовательских типов данных в VBA Excel рассмотрим на примере домиков для животных.

Объявление пользовательского типа данных

Объявление пользовательского типа данных (конструкция с оператором Type) размещается в самом начале модуля в разделе Declarations.

Пример 1

Type Domik

naimenovaniye As String

obyem_m3 As Single

material As String

kolichestvo As Long

End Type

В этом примере:

  • Domik — имя, по которому этот тип данных будет присваиваться переменным;
  • naimenovaniye — наименование домика для животных;
  • obyem_m3 — объем домика в куб. метрах;
  • material — материал, из которого сделан домик;
  • kolichestvo — количество домиков на складе.

Заполнение данными массива

Обычно в качестве контейнеров для пользовательских типов данных в VBA Excel используются массивы. В простую переменную можно уместить только один набор пользовательских данных, а в массив — сколько нужно. В следующем примере мы заполним трехэлементный массив тремя наборами пользовательских данных.

Если представить набор пользовательских данных как «одномерный массив», то таким образом мы создадим массив «одномерных массивов» с пользовательскими данными.

Пример 2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

Sub Primer2()

‘Объявляем трехэлементный массив

‘с пользовательским типом данных

Dim a(1 To 3) As Domik

‘Заполняем первый элемент массива

a(1).naimenovaniye = «Скворечник»

a(1).obyem_m3 = 0.02

a(1).material = «сосна»

a(1).kolichestvo = 15

‘Заполняем второй элемент массива

a(2).naimenovaniye = «Собачья будка»

a(2).obyem_m3 = 0.8

a(2).material = «береза»

a(2).kolichestvo = 5

‘Заполняем третий элемент массива

a(3).naimenovaniye = «Клетка кролика»

a(3).obyem_m3 = 0.4

a(3).material = «металл»

a(3).kolichestvo = 6

End Sub

Обращение к пользовательским данным в массиве

Для обращения в коде VBA Excel к пользовательским данным в массиве используется та же конструкция, что и при записи: указывается элемент массива и через точку наименование элемента пользовательских данных.

Пример 3

‘Считываем информацию из массива

Dim b As Variant

b = a(2).naimenovaniye

MsgBox b

b = a(3).obyem_m3

MsgBox b

b = «Мы продаем следующие товары: « _

& a(1).naimenovaniye & «, « _

& a(2).naimenovaniye & » и « _

& a(3).naimenovaniye

MsgBox b

Для наглядной демонстрации вставьте строки кода Примера 3 перед строкой End Sub Примера 2.


User-defined types are composite data types containing one or more variables of other data types. User-defined types can be used to return multiple values from a function, pass a struct to a DLL procedure, improve efficiency when used in place of a class, and to make code more organized and readable.

User-Defined Types Vs Classes

Although user-defined types can sometimes take the place of using a class, they have several key differences from classes:

  • Classes can define methods, user-defined types cannot
  • Classes can be instantiated, user-defined types cannot
  • Classes require their own dedicated modules, user-defined types do not
  • Class instances can be added to a Collection object, user-defined types cannot
  • User-defined types are more efficient than classes

Although there are some limitations with user-defined types when compared to classes, user-defined types can be a more efficient and light-weight alternative when all that is needed is a structure containing data fields. User-defined types do not have the overhead of a dedicated module and can help keep the size of a VBA project small when defining a number of data structures. Using a user-defined type with an array is more efficient than using a user-defined class with a Collection object. If a data structure does not need methods or instances then one should consider using a user-defined type instead of a class.

Declaring User-Defined Types

User-defined types are declared using the Type statement. There are a number of rules when declaring user-defined types:

  • Must be declared above all procedures in a module.
  • Must have at least one member.
  • When Public or Private is not specified, user-defined types are Public by default.
  • Public types cannot be declared in class modules.
  • Private types in a class module cannot be used as parameters for public procedures.
  • Private types in a class cannot be return types for public procedures of the class.
  • Private types in class modules cannot be public member variables of the class.
  • Types cannot contain a member that is declared as its own type. No circular dependencies.
  • When a type contains another type as a member, the member’s type must be declared first.
'Standard Module

Option Explicit

Public Type TExample1
    Message As String
    Number  As Double
End Type

Public Type TExample2
    Message As String
    T1      As TExample1
End Type

Public Sub Example()

    Dim T1 As TExample1
    T1.Message = "MT1 Message"
    T1.Number = 3.5

    Dim T2 As TExample2
    T2.Message = "T2 Message"
    T2.T1 = T1

    Debug.Print T2.Message, T2.T1.Message, T2.T1.Number
    
End Sub

In a standard code module, Private user-defined types can be accessed publicly as a member variable of a Public user-defined type.

'Standard Module: Module1

Option Explicit

Private Type TPrivate
    Message  As String
    Number   As Double
End Type

Public Type TPublic
    Message  As String
    Priv     As TPrivate
End Type

'Standard Module: Module2

Option Explicit

Public Sub Example()

    Dim T As TPublic

    T.Priv.Message = "Hello, World!"
    T.Priv.Number = 3.5

    Debug.Print T.Priv.Message
    Debug.Print T.Priv.Number

End Sub

Multiple Return Values

There are times when it may be necessary for a function to return more than one value. A user-defined type can be used to return multiple values from a function.

Option Explicit

Public Type TExample
    Message As String
    Number  As Double
End Type

Public Function GetData() As TExample
    GetData.Message = "Hello, World!"
    GetData.Number = 3.5
End Function

Public Sub Example()

    Dim E As TExample
    E = GetData()

    Debug.Print E.Message
    Debug.Print E.Number

End Sub

User-Defined Type Parameter

User-defined types can be used as parameters of procedures.

Option Explicit

Public Type TExample
    Message As String
    Number  As Double
    Bool    As Boolean
End Type

Public Sub PrintTExample(T As TExample)
    Debug.Print T.Message, T.Number, T.Bool
End Sub

Public Sub Example()

    Dim T As TExample

    T.Message = "Hello, World!"
    T.Number = 3.5
    T.Bool = True

    PrintTExample T

End Sub

Pass Struct To DLL Procedure

User-defined types can be used to pass or return structs to and from DLL procedures.

// C++ 64-bit DLL

#define DLLExport __declspec(dllexport)

struct RECTANGLE {
    int s1;
    int s2;
};

extern "C" {

    DLLExport int __stdcall CppRectangleArea(RECTANGLE* rect) {
        return rect->s1 * rect->s2;
    }

}

Option Explicit

Public Type TRectangle
    S1 As Long
    S2 As Long
End Type

Public Declare PtrSafe Function CppRectangleArea _
    Lib "C:ExampleDLL.dll" (ByRef Rect As TRectangle) As Long

Public Sub Example()

    Dim Rect As TRectangle
    Rect.S1 = 10
    Rect.S2 = 20

    Dim Area As Long
    Area = CppRectangleArea(Rect)

    Debug.Print Area

End Sub

Arrays and User-Defined Types

Using an array with a user-defined type is an excellent way of storing tabular data in a type-safe, meaningful, and memory efficient way. Using a user-defined type array instead of a multi-dimensional array of type Variant provides the correct explicit data type for each field, a clear meaning for what each field represents, and saves memory when compared to using Variants. Consider the example below using a multi-dimensional array of type Variant and then again using an array with a user-defined type.

Note: Arrays of user-defined types cannot be iterated over using a For Each loop.

Option Explicit

Public Sub Example()

    Dim PersonInfoArray(0 To 2, 0 To 2) As Variant

    PersonInfoArray(0, 0) = "Bill"
    PersonInfoArray(0, 1) = #01/01/1992#
    PersonInfoArray(0, 2) = "New York"

    PersonInfoArray(1, 0) = "Bob"
    PersonInfoArray(1, 1) = #01/01/1993#
    PersonInfoArray(1, 2) = "Chicago"

    PersonInfoArray(2, 0) = "Ben"
    PersonInfoArray(2, 1) = #01/01/1994#
    PersonInfoArray(2, 2) = "Los Angeles"

    Dim i As Long
    For i = LBound(PersonInfoArray, 1) To UBound(PersonInfoArray, 1)
        Debug.Print PersonInfoArray(i, 0), PersonInfoArray(i, 1), PersonInfoArray(i, 2)
    Next i

End Sub

Option Explicit

Public Type TPersonInfo
    FirstName As String
    BirthDate As Date
    HomeTown  As String
End Type

Public Sub Example()

    Dim PersonInfoArray(0 To 2) As TPersonInfo

    With PersonInfoArray(0)
        .FirstName = "Bill"
        .BirthDate = #01/01/1992#
        .HomeTown = "New York"
    End With

    With PersonInfoArray(1)
        .FirstName = "Bob"
        .BirthDate = #01/01/1993#
        .HomeTown = "Chicago"
    End With

    With PersonInfoArray(2)
        .FirstName = "Ben"
        .BirthDate = #01/01/1994#
        .HomeTown = "Los Angeles"
    End With

    Dim i As Long
    For i = LBound(PersonInfoArray) To UBound(PersonInfoArray)
        With PersonInfoArray(i)
            Debug.Print .FirstName, .BirthDate, .HomeTown
        End With
    Next i

End Sub

LSet

LSet can be used with User-Defined Types to assign the values in one type with the values of another type.

Note: It is not recommended to use LSet with user-defined types because there is no guarantee that the members of both types are the same.

Option Explicit

Public Type TExample1
    Message As String * 15
    Number  As Double
End Type

Public Type TExample2
    Message As String * 15
    Number  As Double
End Type

Public Sub Example()

    Dim T1 As TExample1
    T1.Message = "Hello, World!"
    T1.Number = 3.5

    Dim T2 As TExample2
    LSet T2 = T1

    Debug.Print T2.Message
    Debug.Print T2.Number

End Sub

Option Explicit

'''VBA does not ensure that user-defined types match

Public Type TExample1
    Message As String * 15
    Number  As Double
End Type

Public Type TExample2
    Number  As Long
    Message As String * 15
End Type

Public Sub Example()

    Dim T1 As TExample1
    T1.Message = "Hello, World!"
    T1.Number = 3.5
    
    Dim T2 As TExample2
    LSet T2 = T1
    
    Debug.Print T2.Number  'Prints: '6619208
    Debug.Print T2.Message 'Prints: 'llo, World!

End Sub

  1. 04-25-2017, 07:11 PM


    #1

    whburling is offline


    Forum Contributor


    how return an array of user defined datatype

    Question How return an array of User defined Types

    Context of question:
    Within one module associated with a single workbook
    I have defined a user data type:
    Type FieldData
    ID As Integer
    Elevation As Double
    DataType As String * 2
    End Type

    outside of several subroutines written in the code section
    I wrote a function which I would like to return an array of the above data type

    IF I were to write a function which returned just one element of my user defined data type I would have no
    problem writing the function. Function Boo (wrkshtPtr as worksheet, something as integer, etc) as FieldData

    BUT if I wanted to return an array of FieldData, I have no idea how to write the function returning an array of
    Field Data
    ie: Function Boo (WrkShtPtr as worksheet, something as integer, etc) Array as FieldData


  2. 04-25-2017, 07:13 PM


    #2

    Re: how return an array of user defined datatype

    Please use CODE tags when posting code.

    Entia non sunt multiplicanda sine necessitate


  3. 04-25-2017, 07:32 PM


    #3

    whburling is offline


    Forum Contributor


    Re: how return an array of user defined datatype

    SHG,

    Thank you for replying.

    Please help me understand your answer.

    the term «Array» as used in your example…..is it a keyword that has special meaning in VBA or is it an arbitrary term
    and the () after FieldData is the clue to VBA that «Array» is an array?

    Thank you for replying so quickly. Much appreciated.

    bil


  4. 04-25-2017, 08:09 PM


    #4

    Re: how return an array of user defined datatype

    That tells VBA that it’s an array, yes.


  5. 04-26-2017, 09:00 AM


    #5

    whburling is offline


    Forum Contributor


    Re: how return an array of user defined datatype

    shg,

    I apologize….I still do not understand your answer. please be patient with me.

    is this how the function would be written?

    Function Boo (args) FieldDataArray() as FieldData

    what is baffling for me is that normally i would write a function as:
    function Boo (args) as datatype
    but in your example, it seems as if i am writing more than datatype after Boo(args)

    please be patient with me.
    bil


  6. 04-26-2017, 11:14 AM


    #6

    Re: how return an array of user defined datatype

    No, it would be written as shown in post #2 (with the args detailed).


  7. 04-26-2017, 11:20 AM


    #7

    Re: how return an array of user defined datatype

    Hi,

    You would omit the Array keyword

    the brackets on the end indicate that an array is to be returned.

    Don
    Please remember to mark your thread ‘Solved’ when appropriate.


  8. 04-26-2017, 11:48 AM


    #8

    whburling is offline


    Forum Contributor


    Re: how return an array of user defined datatype

    xlnitwit and shg……thank you so much for having spent so much time with my problem

    I hope both of you have a wonderful day.

    Bil


  9. 04-26-2017, 03:04 PM


    #9

    Re: how return an array of user defined datatype

    My bad, missed that, sorry.


In my last week’s Blog post I elaborated on data types and their use in VBA.

Beyond using the readily available native data types we’re all familiar with, such as Integer, Date, String and Boolean, we can define our own, user-defined data type.

What is a User-Defined Data Type?

Simply put, a user-defined data type is a group of variables of native data types.

Here’s an example of grouping together several variables to define a new data type representing (or holding) information about a vehicle:

Type Vehicle

   VIN as Long

   Make as String

   Model as String

   Year as Integer

End Type

That’s it! As simple as that.

We can now dimension variables of type Vehicle:

Dim vehLeasedCar as Vehicle

We now have a kind of a hierarchy: a variable of type Vehicle containing sub-variables of different (native) types: Long, String and Integer in this example.

We can think of the sub-variables as properties of the Vehicle-type variable and use the “dot” to address each of these sub-variables. Let’s assign some values to our vehLeasedCar variable:

vehLeasedCar.VIN = 4656418

vehLeasedCar.Make = “Ford”

vehLeasedCar.Model = “Taurus”

vehLeasedCar.Year = 2001

In the same way, we can read the values of our variable (or its sub-variables). Let’s print out our vehicle’s model:

Debug.Print vehLeasedCar.Model

Why use User-Defined Data Types?

I can think of two main reasons to make use of user-defined data types:

  1. They are suitable for records arrangement in a readable format
  2. They are very efficient to process, even more than collections

Think of a process that needs to store and manipulate 5,000 vehicles.

One way would be to have a two-dimensional array store a table-like structure of the vehicles. This is valid (and you know how much I love arrays), and even performant. However, it would not be that clear by viewing the code what we are doing. What do you find more telling in your code: arrCars(i,j) or arrCars(i).Model?

Let’s define another data type to store information about an employee:

Private Type TEmployeeRecord

    Name As String

    DOB As Date

    Age As Integer

    City As String

    Score As Integer

End Type

Consider how readable and self-explanatory the following Sub is, tasked with printing out all data of an employee, passed over as a TEmployeeRecord type variable:

Sub PrintEmployeeReport(employee As TEmployeeRecord)

    With employee

        Debug.Print .Name, .City, .DOB, .Age, .Score

    End With

End Sub

Storing Many Records in an Array

Of course, storing a single record, as in the above examples, is not very helpful. We typically need to store many records of data in our program.

For this, we can combine our own defined data type (record structure) with a one-dimensional array.

To illustrate this in an example, let’s pick up a list of employees with some data on them from an Excel table and arrange it in an array of employees’ records. Our table look like this:

Excel VBA User Defined Data Types

We first use a 2-dimensional array as an interim structure to quickly read the table from the Worksheet:

Dim arrEmployees() As Variant

arrEmployees = ThisWorkbook.Worksheets("Scores").Range("ScoresTable[#Data]").Value

Next, we loop our array and transfer each employee (“row”) in the array into a new, 1-dimentional array, holding employees’ records:

Dim employees(5) As TEmployeeRecord

Dim i As Integer

For i = LBound(arrEmployees, 1) To UBound(arrEmployees, 1)

        With employees(i - 1)

            .Name = arrEmployees(i, 1)

            .DOB = arrEmployees(i, 2)

            .Age = arrEmployees(i, 3)

            .City = arrEmployees(i, 4)

            .Score = arrEmployees(i, 5)

        End With

Next i

With that, we have an efficient array of employees to work with.

We can now write a function to return the score of an employee, given a pointer to the array of employees we prepared and the employee name to look for.

Function GetScoreOfEmployee(strName As String, employees() As TEmployeeRecord) As Integer

    Dim i As Integer  

    GetScoreOfEmployee = 0 

    For i = LBound(employees) To UBound(employees)

        With employees(i)

            If (.Name = strName) Then

                GetScoreOfEmployee = .Score

                Exit For

            End If

        End With

    Next i

End Function

See how elegant and clear this function is? We’re looping the employees array, checking each employee name to match strName we’re looking for, returning his score upon a successful match.

Here’s how we can make use of the above function to ask the user for a name of an employee and get his score (we’ll store his score in the intScore variable). We’re making use of the employees array we have populated earlier with our employees:

Dim strName As String

Dim intScore As Integer

strName = InputBox("Name of employee:", "Query Employee Form")

intScore = GetScoreOfEmployee(strName, employees)

If (intScore = 0) Then

   MsgBox "Employee not found", vbOKOnly + vbInformation, "Employee Error"

Else

   MsgBox strName & "'s score: " & intScore, vbOKOnly + vbInformation, "Employee Score Result"

End If

By the way, if you are not familiar with the InputBox function, I have a detailed Blog post about it for you here. Similarly, the MsgBox function is explained here.

Unfortunately, Excel VBA doesn’t allow us to add user-defined type variables to a collection, therefore we’re missing out on a potentially very useful and efficient data structure. One can argue that if a collection is our best structure to maintain our records, we can implement our records as objects defined in a Class Module instead of a user-defined data type. Yes, I have a series of Blog posts about objects and Class Modules starting right here.

The above examples are featured in my flagship on-line course: Computer Programming with Excel VBA, in case they seemed familiar to you 😉.

Hey, a small request from me to you: please share this Blog post so that we can help more colleagues with Excel VBA.

In the previous article, we learned how to use the User Defined Types. User Defined Type refers to a named grouping of built-in data types. Today we will learn to create an Array of User Defined Types. We will learn how to use a UDT and store records from a Table into an Array of UDT.

What is an Array of User Defined Type?

A UDT is a collection of different built-in data type variables known as sub-variables. We need to instantiate a User Defined Type. We can create several user defined type variables by using an array. Each variable of type UDT would have its copy of sub-variables in the computer’s memory. An array of variables of UDT would correspond to several records and each record would correspond to a single element of an array.

Table of Contents

  1. What is an Array of User Defined Type?
  2. Syntax – UDT Array
    1. Type Declaration
    2. Creating an Array of User Defined Type
    3. Accessing Sub Vairbles of Array Elements
  3. Example – Store Values from Table into an Array of UDT

infographics array of user defined type in vba

You can also download the practice workbook to follow along.

Syntax – UDT Array

Here were have defined the syntax to use an Array of User Defined Data Type.

Type Declaration

To create a User Defined Array type, we must declare a Type.

'syntax of type declaration
Type <UDT_name>
    <var1> As <data_type>
    <var2> As <data_type>
    <var3> As <data_type>
    .
    .
    .
    <varN> As <data_type>
End Type

Here, <var1> or <varn> refer to the sub-variables of the Type.

Creating an Array of User Defined Type

Once we define a UDT, we can declare an array of variables to use it.

Dim <arr_name>([<lower_limit> to] <upper_limit) As <UDT_name>

The following points contain information to make an array of UDT.

  • <arr_name> – This is the name of the UDT array.
  • <lower_limit> – It is the index of the first array element. This is an optional argument and by default, its value is zero.
  • <upper_limit> – This is the index of the last element of the User Defined Type array.
  • <UDT_name> – This is the name of the UDT whose array we are about to create.

Accessing Sub Vairbles of Array Elements

The array <arr_name> would contain several elements. We can access the specific elements of an array using its index. Thereafter, we use the dot operator followed by the name of the sub-variable to access it.

<arr_name>(index).<varn>=expression

Example – Store Values from Table into an Array of UDT

In this example, you are going to learn how to store each record of the table in the elements of UDT Array. Follow these steps to learn.

  • Prepare a student record data as follows.
Example - Store Values from Table into an Array of User Defined Type
  • Select the range A1:E6 and press the Ctrl T keys to create a table from this data. Make sure you mark the checkbox for Table Headers.
Example - Store Values from Table into an Array of User Defined Type create a table
  • Now select the table and go to the Table Design tab on the ribbon. Change the name of the table to MyData.
Example - Store Values from Table into an Array of User Defined Type change the name of table
  • Press Alt and F11 keys to open the VBE. Go to the Insert tab and take a new module. Open the module and add the following code to the module.
'define the user defined type
Private Type Student
    rno As Integer
    name As String
    class As String
    marks As Byte
    fname As String
End Type

Sub exDataFromTableIntoUDTArray()
'array to hold data from table
Dim myArray As Variant
'store the table records into myArray, sheet1 contains the table
myArray = ThisWorkbook.Worksheets("Sheet1").Range("MyData[#Data]").value
'declare an array of UDT
Dim student_arr(4) As Student
'store value from myArray into User Defined Type Array
For i = LBound(myArray, 1) To UBound(myArray, 1)
    With student_arr(i - 1)
        'accessing the sub variables and assigning values from myArray
        .rno = myArray(i, 1)
        .name = myArray(i, 2)
        .class = myArray(i, 3)
        .marks = myArray(i, 4)
        .fname = myArray(i, 5)
    End With
Next i
For i = 0 To UBound(student_arr, 1)
    With student_arr(i)
        'printing the values stored in sub variables of elements of student_arr UDT
        MsgBox "Roll Number: " & .rno
        MsgBox "Student's Name: " & .name
        MsgBox "Class: " & .class
        MsgBox "Marks: " & .marks
        MsgBox "Father Name: " & .fname
    End With
Next i
End Sub

Here myArr is variant type.

The UBOUND Function returns the upper limit of specified dimension of an array. It takes two arguments, the array name and the dimension number.

  • Place the cursor in sub procedure exDataFromTableIntoUDTArray and press F8 key to execute this line by line or you can just run this sub procedure.
Example - Store Values from Table into an Array of User Defined Type result

This brings us to an end.

Thank you for reading.

RELATED POSTS

  • For Each Loop VBA – Excel

  • Arrays in VBA – Excel

  • Multidimensional Arrays in VBA – Excel

  • Data Types of Variables in VBA

  • Collections in VBA – Create, Add, Remove Items

  • Variant Data Type in VBA Excel

Let’s say you are trying to create a school management system. Here, you will have different types of variables like student name, student roll no, class, etc. A school also has teachers, so there will be teacher names, teacher subject, classes, etc. Similarly, there will be many other objects like, librarian, classes, principle etc. Now having different variables for each entity in school will be messy work. How about creating a data type of student, teacher, classes, etc that stores values related to them. For this we can use defined data types of VBA.

In this article, we will learn  how you can create your own data type in VBA. They are referred to as UDTs of VBA. 

Defining a User Defined Data Type

To define a structure or UDTs in VBA we use Type___End Type block. Here’s the syntax of a UDT.

Type Tname_Of_Data_Type

   var1 as datatype   'datatype can be anything, int, array,or even UDT

   var2 as datatype

   Var3() as datatype

   ---

   VarN() as datatype

End Type

So to define a custom data type in VBA we start with Type Keyword. Then we write the name of our custom data type. It is convention to use T before the Name of Data Type so that you can differentiate between vba collections and UDTs. 

The DataTypes can be anything. And Integer, String, Variant, another UDT, Arrays, collections, anything.

To use your UDT in the program declare its variable like any other variable.

Sub UseUDT

'Declaring variable of user defined data type 

Dim myVar1 as Tname_Of_Data_Type

 Dim myVar2 as Tname_Of_Data_Type

End Sub

Simple. Now to use the variables within this UDT we use dot operator. Use the name of the data type followed by a dot and name of variable within.

Sub UseUDT

'Declaring variable of user defined data type 

 Dim myVar1 as Tname_Of_Data_Type

 Dim myVar2 as Tname_Of_Data_Type

 

 myVar1.var1="Abcd"

 myVar2.Var2="xyvz"

End Sub

Enough of the theory, let’s jump into an example to see how it works.

Create A Student Variable that Stores Information Related to Student

So we have a task to create a user defined data type that stores information related to students.

A student has a first name, last name, roll number, date of birth, class, section, subjects.

So let’s create it.

'Created a Public Student Data Type

Public Type Tstudent  

  fName As String       'For First Name

  lName As String       'For Last Name

  rNo As Integer        'For Roll Number

  clss As string        'For Class

  section As String     'For Section Name   

  subjects() As String  'For Subjects of student

End Type

'Use this Tstudent type in subroutine

Sub StudentsInfo()

 

'Creating and initializing student type variable

 Dim student1 As Tstudent

 student1.fName = "Manish"

 student1.lName = "Singh"

 student1.rNo = 12334

 student1.clss = 10

 student1.section = "A"

 ReDim student1.subjects(2)

 student1.subjects(0) = "physics"

 student1.subjects(1) = "Math"

 

 'Printing student details.

 Debug.Print (student1.fName)

 Debug.Print (student1.lName)

 Debug.Print (student1.rNo)

 Debug.Print (student1.clss)

 Debug.Print (student1.section)

 Debug.Print (student1.subjects(0))

 Debug.Print (student1.subjects(1))

End Sub

When you run the above sub it will print the result as shown below:

Manish

Singh

12334 

10 

A

physics

Math

Creating an Array of UDTs and Accessing Elements

Similarly you can create as many as variables of Tstudent type you need. You can even create an array of  Tstudent type like any other data type.

Public Type Tstudent  

  fName As String       'For First Name

  lName As String       'For Last Name

  rNo As Integer        'For Roll Number

  clss As string        'For Class

  section As String     'For Section Name   

  subjects() As String  'For Subjects of student

End Type

'Creating an arrays of Tstudents type

Sub SchoolInfo()

Dim schoolName As String

Dim students() As Tstudent

schoolName = "Senior School"

ReDim students(10)

For i = 0 To 9

 students(i).fName = "name" & Str(i + 1)

 students(i).rNo = i + 1

Next i

Debug.Print ("Name : Roll No")

For i = 0 To 9

 Debug.Print (students(i).fName & " : " & students(i).rNo)

Next i

End Sub

When you run this code, this will be printed in the immediate window.

Name : Roll No

name 1 : 1

name 2 : 2

name 3 : 3

name 4 : 4

name 5 : 5

name 6 : 6

name 7 : 7

name 8 : 8

name 9 : 9

name 10 : 10

In the above code, first defined UDT structure before and the sub (I’ll explain later why). The we just created an array using a dim keyword like we do for any variable in VBA. 

Then we used Redim to define the size of arrays. Afterwards we use a for loop to initialize the array.

To access the structure’s  elements we use another for loop. That is it.

Why Did We Declare UDT on Top of the Module?

If we declare a UDT first in a module, outside of any subroutine or function, it is available to all the modules in the workbook. It means if you have a hundred subs and functions in a module all of them can declare Student type variables in their body. 

If the UDT is not private, it will be available to all the modules in the workbook. If want a structure (UDT) to be available only to a containing module, declare it private.

Private Type Tstudent

  fName As String

  lName As String

  rNo As Integer

  clss As Integer

  section As String

  subjects() As String

End Type

You can’t have UDT on a procedural level. It means you can’t define a user defined data type inside a subroutine or function.

Nested User Defined Types

Let’s say you have UDT called a car. Car has its own elements. Similarly you have a UDT called a bike that can have its own properties.

Now let’s say you need a data type called vehicle. Vehicle can have a car and bike as its elements. Can we do this? Yes we can do this. See the below code

Private Type Tcar

 seats As Integer

 ac As Boolean

 typ As String

 color As String

 manufacturer As String

 Dop As Date

 rc_no As String

End Type

Private Type Tbike

 seats As Integer

 typ As String

 color As String

 manufacturer As String

 Dop As Date

 rc_no As String

End Type

Private Type Tvehicle

 number_of_Vehicle As Integer

 bike As Tbike

 car As Tcar

End Type

Sub vehicleVarification()

 Dim myVehicles As Tvehicle

 

 myVehicles.number_of_Vehicle = 2

 myVehicles.bike.seats = 1

 myVehicles.bike.typ = "Racing"

 myVehicles.car.seats = "4"

 myVehicles.car.ac = True

 

 Debug.Print myVehicles.number_of_Vehicle

 Debug.Print myVehicles.bike.typ

 Debug.Print myVehicles.car.ac

End Sub

Here, we have defined three user defined data type. First is Tcar that contains some information related to cars. Second is bike, it also contains some information about bike.

The third UDT is Tvehicle. It contains one variable to store number of vehicles and two variables of Tcar and Tbike type.

Private Type Tvehicle

 number_of_Vehicle As Integer

 bike As Tbike

 car As Tcar

End Type

To access variables of Tcar and Tbike we can use Tvehicle data type. In the sub, we have defined only one variable of Tvehicle type as myVehicles. When we create this variable VBA creates variables of Tcar and Tbike too.

To initialize and access variables of Tcar and Tcar, we can use myVehicle variable. As you can see in the code.

 myVehicles.number_of_Vehicle = 2

 myVehicles.bike.seats = 1

 myVehicles.bike.typ = «Racing»

 myVehicles.car.seats = «4»

 myVehicles.car.ac = True

When we run the sub, this how result occurs.

This feature really increases the power of programming VBA exponentially. You can structure your data type like real world entities. You can create relationships between data types which can be useful in a big project.

So yeah guys, this is how you can create and use a user defined data type or structure in VBA. I hope I was able to explain it. If you have any questions regarding this article or any other VBA related questions, ask me in the comments section below. I’ll be really happy to hear from you.

Related Articles:

VBA variables in Excel| VBA stands for Visual Basic for Applications. It is a programming language from Microsoft. It is used with Microsoft Office applications such as MSExcel, MS-Word and MS-Access whereas VBA variables are specific keywords.

Excel VBA Variable Scope| In all the programming languages, we have variable access specifiers that define from where a defined variable can be accessed. Excel VBA is no Exception. VBA too has scope specifiers.

ByRef and ByVal Arguments | When an argument is passed as a ByRef argument to a different sub or function, the reference of the actual variable is sent. Any changes made into the copy of the variable, will reflect in the original argument.

Delete sheets without confirmation prompts using VBA in Microsoft Excel | Since you are deleting sheets using VBA, you know what you are doing. You would like to tell Excel not to show this warning and delete the damn sheet.

Add And Save New Workbook Using VBA In Microsoft Excel 2016| In this code, we first created a reference to a workbook object. And then we initialized it with a new workbook object. The benefit of this approach is that you can do operations on this new workbook easily. Like saving, closing, deleting, etc

Display A Message On The Excel VBA Status Bar| The status bar in excel can be used as a code monitor. When your VBA code is lengthy and you do several tasks using VBA, you often disable the screen update so that you don’t see that screen flickering.

Turn Off Warning Messages Using VBA In Microsoft Excel 2016| This code not only disables VBA alerts but also increases the time efficiency of the code. Let’s see how.

Popular Articles:

50 Excel Shortcuts to Increase Your Productivity | Get faster at your task. These 50 shortcuts will make you work even faster on Excel.

The VLOOKUP Function in Excel | This is one of the most used and popular functions of excel that is used to lookup value from different ranges and sheets. 

COUNTIF in Excel 2016 | Count values with conditions using this amazing function. You don’t need to filter your data to count specific values. Countif function is essential to prepare your dashboard.

How to Use SUMIF Function in Excel | This is another dashboard essential function. This helps you sum up values on specific conditions.

Probably you have heard something about PHP. If you have, then you know that it supports arrays (and lists and anything you like) and you may declare any type of data in these. In VBA, usually the case is a little different. If you have a list of integers, then you can have only integers in it, and if you have a list of doubles – only doubles.

Anyway, sometimes you may wish that VBA was a little bit like PHP, where you could have declared a list of various variables. Actually, this is possible 🙂

WIth a little work around. You should declare a Private Type, in which you may put strings, integers and anything. Let’s take a look at the example:

formula1Ranking

Imagine you have to organize a Formula1 Grand Prix. You declare the following private types:

Private Type custCar

    sCarModel       As String

    iCarSpeed       As Integer

    iCarCylinders   As Integer

End Type

Private Type custRoad

    sRoadName       As String

    sRoadLocation   As String

    dRoadDate       As Date

    aRoadCars(8)    As custCar

End Type

Private aCustRoads(8) As custRoad

Then you simply decide to assign values to these types and to let it run. In the following example I have “created” two “roads” with two cars per road. This is how it looks like:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

Sub Formula1()

    Dim iCustRoad   As Integer

    Dim iCustCar    As Integer

    Dim iLoop       As Integer

    Dim iLoop2      As Integer

    Dim bPrintMe    As Boolean

    iCustRoad = 0

    iCustCar = 0

    aCustRoads(iCustRoad).sRoadName = «The road close to Sofia.»

    aCustRoads(iCustRoad).sRoadLocation = «Close to Sofia.»

    aCustRoads(iCustRoad).dRoadDate = Now()

    aCustRoads(iCustRoad).aRoadCars(iCustCar).sCarModel = «Ford»

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarSpeed = 90

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarCylinders = 8

    iCustCar = 1

    aCustRoads(iCustRoad).aRoadCars(iCustCar).sCarModel = «Lada»

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarSpeed = 80

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarCylinders = 4

    iCustRoad = 1

    iCustCar = 0

    aCustRoads(iCustRoad).sRoadName = «The road close to Plovdiv.»

    aCustRoads(iCustRoad).sRoadLocation = «Close to Plovdiv.»

    aCustRoads(iCustRoad).dRoadDate = Now()

    aCustRoads(iCustRoad).aRoadCars(iCustCar).sCarModel = «Ferrari»

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarSpeed = 95

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarCylinders = 10

    iCustCar = 1

    aCustRoads(iCustRoad).aRoadCars(iCustCar).sCarModel = «Moskvich»

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarSpeed = 81

    aCustRoads(iCustRoad).aRoadCars(iCustCar).iCarCylinders = 2

    bPrintMe = True

    For iLoop = 0 To 1 Step 1

        For iLoop2 = 0 To 1 Step 1

        If (bPrintMe) Then

            Debug.Print aCustRoads(iLoop).sRoadName

            Debug.Print aCustRoads(iLoop).sRoadLocation

            Debug.Print aCustRoads(iLoop).dRoadDate

        End If

        Debug.Print aCustRoads(iLoop).aRoadCars(iLoop2).sCarModel

        Debug.Print aCustRoads(iLoop).aRoadCars(iLoop2).iCarSpeed

        Debug.Print aCustRoads(iLoop).aRoadCars(iLoop2).iCarCylinders

        bPrintMe = False

        Next iLoop2

        bPrintMe = True

        Debug.Print ‘this is for space

    Next iLoop

End Sub

This is the result in the immediate window:

ImmediateFormula

It is actually cool, if you can use it. 🙂 Or at least, you can use it to show, that you can put various types of data in a List or array. Which is a good usage as well 😀

Понравилась статья? Поделить с друзьями:
  • Excel vba array length
  • Excel vba array index
  • Excel vba array filter
  • Excel vba array add
  • Excel vba argument not optional что это