Novell is now a part of Micro Focus

Novell Controls for ActiveX and Microsoft Excel: Migrating Directory Entries between NDS and LDAP Directories Using Worksheets

Articles and Tips: article

VijayaKumar Balakrishnan
Senior Software Engineer
Novell Product Group, India
bvijayakumar@novell.com

Vidula K
Technical Writer
Novell Product Group, India
kvidula@novell.com

01 Aug 2000


This AppNote describes how to migrate user and person data from Novell Directory Services (NDS) to LDAP directories or vice-versa using Novell Controls for ActiveX with the help of a sample program. The unique feature of this sample program is its implementation in Microsoft Excel.

This article is targeted at developers with fundamental Visual Basic programming knowledge.

Introduction

This article demonstrates the ease and flexibility provided by Novell's ActiveX Controls for developing various kinds of network applications in an Integrated Development Environment (IDE) that supports ActiveX technology, including Visual Basic, Delphi, PowerBuilder, C++, Visual C++, and Microsoft Office. The controls (21 as of this printing) provide diverse features including full access and search mechanism to Novell Directory Services (NDS), Internet (LDAP) directories, and administration capabilities for NetWare servers, catalog objects, print queues, printers, volumes, and so on.

The complete set of controls can be downloaded from http://developer.novell.com/ndk/ocx.htm. Documentation in the form of Windows Help is included in the download.

Complete documentation can also be viewed at http://developer.novell.com/ndk/doc.htm.

NDS tutorials are available at http://developer.novell.com/ndk/demo.htm and provide a good source of information for programming fundamentals. Check out the tutorial titled "Programming NDS with the Novell Controls for ActiveX and Visual Basic."

Additionally, you can read the series of articles by Morgan Adair in Developer Notes. The articles begin in June 1999 with "Programming with the Novell Controls for ActiveX and Visual Basic: Getting Started" through to the last article of the series "Reading and Writing NDS Stream Fields" in the March 2000 issue. http://support.novell.com/techcenter/articles/dnd19990601.html, and http://support.novell.com/techcenter/articles/dnd20000301.html

Features of the Sample Program

The sample program in this article is developed using Microsoft Excel Visual Basic for Applications. It uses Novell Directory Control, Novell Internet Directory Control, and Novell Network Selector Control.

This sample program allows you to retrieve user or person information such as surname, e-mail, and telephone number from NDS or LDAP directories into an Excel worksheet. You can migrate these entries to any directory. Before migration you can add or modify entry information in the worksheet, if required.

Microsoft Excel exposes its workbooks, worksheets, and cells through programmable objects. You can program to these objects using the Microsoft Excel Visual Basic for Applications. When Novell's Directory and Internet Directory Control are used in Excel, the worksheet is enabled with the power of a directory.

To manage directory operations in the sample program, the menu bar in Microsoft Excel is customized to include a new menu named "Directory." This makes the tasks intuitive and simple.

Note: It is important to know the terminology differences between LDAP and NDS. The following table compares some of the terms and attributes used by NDS and LDAP.


LDAP Term

NDS Term

Entry

Both Object and Entry

Attribute

Attribute

Person object

User object


LDAP Attribute

NDS Attribute

commonName

CN

fullName

Full Name

description

Description

facsimileTelephoneNumber

Facsimile Telephone Number

mail

Internet EMail Address

postalAddress

Postal Address

postalCode

Postal Code

sn, surname

Surname

telephoneNumber

Telephone Number

title

Title

For extensive information on NDS and LDAP, see http://developer.novell.com/ndk/cldap.htm.

Controls Used in this Sample Program

The following controls are used in this sample program:

  • Directory Control (NWDir.ocx)

  • Internet Directory Control (NWIDir.ocx)

  • Selector Control (NWSelect.ocx)

Setup Requirements

Windows 95/98/NT/2000 operating system, the appropriate Novell Client for the operating system, Microsoft Office 97/2000, and Novell Controls for ActiveX.

Sample Program

This sample program is created through the following steps:

  1. Customizing the workbook

  2. Creating UserForms

  3. Enabling migration

To edit a Visual Basic Application in Excel, select the Visual Basic Editor from Tools > Macro > Visual Basic Editor or by pressing Alt+F11.

The Project Explorer contains a list of the projects and the Excel objects contained in each project as shown in Figure 1.

Figure 1: The Project Explorer.

Customizing the Workbook

To manage directory operations in the sample program, a custom menu named "Directory" is added to the Excel menu bar. It contains four menu items to load and migrate data. The "Directory" menu is implemented in such a way that it is added when the workbook is opened and removed when the workbook is closed. The Workbook object's "Open" and "BeforeClose" events occur when the workbook is opened and closed respectively.

To add the new menu to the Excel menu bar:

  1. Double-click the "ThisWorkbook" object in the Project Explorer.

  2. In the ThisWorkbook (code) window, select the "Workbook" object from the Object box and "Open" event from the Events box.

  3. Enter the following code.

' Workbook_Open - Event
' Called when the workbook is opened
Private Sub Workbook_Open()
    Dim cstmDir, cstmMenuItem As CommandBarControl

    ' Add the Directory menu to the Excel worksheet menu bar
    Set cstmDir = Application.CommandBars("Worksheet Menu Bar").Controls.Add _
    (Type:=msoControlPopup, Before:=9, Temporary:=True)
    cstmDir.Caption = "Director&y"

    ' Add individual menu items to the Directory menu
    ' The menu items to be added are,
    ' 1) Load Data from NDS
    ' 2) Load Data from LDAP
    ' 3) Migrate Data to NDS
    ' 4) Migrate Data to LDAP
    Set cstmMenuItem = cstmDir.Controls.Add(Type:=msoControlButton)
    cstmMenuItem.Caption = "Load Data from &NDS"
    ' The event function implemented in Sheet1, will be called
    ' when a menu item is selected
    cstmMenuItem.OnAction = "Sheet1.OnNDSLoad"
    Set cstmMenuItem = cstmDir.Controls.Add(Type:=msoControlButton)
    cstmMenuItem.Caption = "Load Data from &LDAP"
    cstmMenuItem.OnAction = "Sheet1.OnLDAPLoad"
    Set cstmMenuItem = cstmDir.Controls.Add(Type:=msoControlButton)
    cstmMenuItem.Caption = "Migrate Data to N&DS"
    cstmMenuItem.OnAction = "Sheet1.OnNDSMigrate"
    Set cstmMenuItem = cstmDir.Controls.Add(Type:=msoControlButton)
    cstmMenuItem.Caption = "Migrate Data to LDA&P"
    cstmMenuItem.OnAction = "Sheet1.OnLDAPMigrate"
End Sub

To remove the Directory menu when the workbook is closed:

  1. Select "BeforeClose" from the Events box.

  2. Enter the following code.

' Workbook_BeforeClose - Event
' Called before the workbook closes
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Dim ctrlsDir As CommandBarControls
    Dim cstmDir As CommandBarControl

    If Not Cancel Then 'If the close operation is not cancelled
        Set ctrlsDir = Application.CommandBars("Worksheet Menu Bar").Controls
        ' Find the "Directory" menu and remove it
        For Each cstmDir In ctrlsDir
            If cstmDir.Caption = "Director&y" Then
                cstmDir.Delete
            End If
        Next
    End If
End Sub

Creating UserForms

Customized UserForms or dialog boxes are included in the sample program. These forms are used for user interaction and to get the required inputs.

The sample program uses three UserForms:

  • The Load Data from NDS and Load Data from LDAP form loads directory information from NDS and LDAP respectively into the worksheet.

  • The Migrate Data to NDS form migrates data from the worksheet to NDS.

  • The Migration Data to LDAP form migrates data from the worksheet to LDAP directories.

To create a new UserForm:

  1. Click Insert > UserForm.

  2. To display the Toolbox click View > Toolbox. The Toolbox is displayed.

  3. To add Novell's ActiveX Controls to the Toolbox, right-click the Toolbox > click Additional Controls. From the Additional Controls dialog box, select Novell Directory Control, Novell Internet Directory Control, and Novell Selector Control from the list of controls > click OK.

  4. Design the UserForm as required.

Enabling Migration

Enabling migration is divided into two sections:

  • Migrating data to LDAP

  • Migrating data to NDS

Migrating Data to LDAP

Directory entries from NDS or LDAP can be loaded into the worksheet using the form shown in Figure 2. To display the Load Data form select Directory > Load Data from NDS or Load Data from LDAP. While creating the Field Names list box, set the MultiSelect property to fmMultiSelectExtended. This allows sections of multiple field names.

Figure 2: Load data form.

Declare a public flag variable, which will indicate whether the form is to be displayed for NDS or LDAP. The following global declarations are to be included to the frmLoad form.

Public fNDSLoad As BooleanOption Base 0

The declaration Option Base 0 should be declared in the beginning of each form.

The Load and Migrate forms should be displayed when the menu items are selected. The following procedures should be implemented in Sheet 1 of the Worksheet object to show the forms when the menu items are selected.

' OnNDSLoad - Procedure
' Called when the "Load Data from NDS"
' menu item is selected from the "Directory" menu
Sub OnNDSLoad()
    frmLoad.fNDSLoad = True
    frmLoad.Show
End Sub

' OnLDAPLoad - Procedure
' Called when the "Load Data from LDAP"
' menu item is selected from the "Directory" menu
Sub OnLDAPLoad()
    frmLoad.fNDSLoad = False
    frmLoad.Show
End Sub

' OnNDSMigrate - Procedure
' Called when the "Migrate Data to NDS"
' menu item is selected from the "Directory" menu
Sub OnNDSMigrate()
    frmNDSMigrate.Show
End Sub

' OnLDAPMigrate - Procedure
' Called when the "Migrate Data to LDAP"
' menu item is selected from the "Directory" menu
Sub OnLDAPMigrate()
    frmLDAPMigrate.Show
End Sub

Enter the code given below for the Activate event. The Full Name text box is initialized with the default full name using the Directory Control's FullName property.

' UserForm_Activate - Event
' Called when this form becomes the active window
Private Sub UserForm_Activate()
    ' Display the dialog caption based on the mode,
    ' which can be NDS or LDAP
    If fNDSLoad Then
        frmLoad.Caption = "Load Data from NDS"
        txtFullName.Text = NWDir1.FullName
        cmdBrowse.Enabled = True
    Else
        frmLoad.Caption = "Load Data from LDAP"
        ' LDAP entries cannot be browsed through
        ' the Selector dialog. So disable the Browse button
        cmdBrowse.Enabled = False
    End If
End Sub

The Novell Network Selector Control is a visual control used to browse and select the desired tree and context. The FullName specifies the location of the User or Person object in an NDS or LDAP directory. For example, consider NDS:\\APPS_AXJB\novell\docs\peter. Here, the tree name is APPS_AXJB, the context is docs.novell and the user name is peter.

Figure 3: The Selector dialog.

The Browse button displays the Selector Dialog using the following code.

' cmdBrowse_Click - Event
' Called when the Browse button is clicked
Private Sub cmdBrowse_Click()
    On Error GoTo errExit

    NWSelect1.FullName = txtFullName.Text
    ' Show the selector dialog to select the NDS Tree and context
    If NWSelect1.Show Then
        ' If the selection is successful, set the selected fullname
        ' in the Text Box
        txtFullName.Text = NWSelect1.FullName
    End If

    Exit Sub

errExit:
    MsgBox Str(Err.Number) + Err.Description
End Sub

When you switch to the Field Names list box, all the field names available for the User or Person object should be listed. Becaues this list box supports multiple-selection, the user can select all the required fields. The AfterUpdate event occurs whenever the data in a text box changes. The following code is required to initialize the Field Names list box. The NWLayoutDescription object of Directory and Internet Directory Controls are used to get the layout description of an object in the directory. Through this object, the layout of NDS User object and LDAP Person object is retrieved. The NWLayoutDescription.Fields property returns the NWFieldDescriptions collection, which contains the field information. The individual NWFieldDescription objects in this collection will contain the field names and types.

' txtFullName_AfterUpdate - Event
' Called when the FullName Text Box is set with a full name
' and the user presses the <TAB> key
Private Sub txtFullName_AfterUpdate()
    Dim ndsField As NWDirLib.NWFieldDescription
    Dim ndsFields As NWDirLib.NWFieldDescriptions
    Dim ldapField As NWIDirLib.NWFieldDescription
    Dim ldapFields As NWIDirLib.NWFieldDescriptions
    Dim ndsUser As NWDirLib.NWLayoutDescription
    Dim ldapUser As NWIDirLib.NWLayoutDescription

    On Error GoTo errExit

    lstFields.Clear
    If fNDSLoad Then ' Fill the List Box with NDS field names
        NWDir1.FullName = txtFullName.Text
        Set ndsUser = NWDir1.Layouts.Item("User")
        ' Get the fields of the NDS User object
        Set ndsFields = ndsUser.fields
        ' List all the String fields
        For Each ndsField In ndsFields
            If ndsField.TypeName = "String" Then
                lstFields.AddItem ndsField.Name
            End If
        Next
    Else
        NWIDir1.FullName = txtFullName.Text
        Set ldapUser = NWIDir1.Layouts.Item("person")
        ' Get the fields of the LDAP person object and list them
        Set ldapFields = ldapUser.fields
        For Each ldapField In ldapFields
            lstFields.AddItem ldapField.Name
        Next
    End If

    Exit Sub

errExit:
    MsgBox Str(Err.Number) + Err.Description
End Sub

The Load button populates the worksheet with the directory entries and field values. Each entry is filled in one row, and the first row displays the selected field names. The Directory Control is set with the filter "User" and the Internet Directory Control is set with "Person" as the filter to retrieve user information. The NWEntries collection will contain the directory entries. From each NWEntry object in this collection, call the GetFieldValue method to get the selected field values.

' cmdLoad_Click - Event
' Called when the Load button is clicked
Private Sub cmdLoad_Click()
On Error GoTo errExit

Dim ndsEntry As NWDirLib.NWEntry
Dim ndsEntries As NWDirLib.NWEntries
Dim ldapEntry As NWIDirLib.NWEntry
Dim ldapEntries As NWIDirLib.NWEntries
Dim selFields() As String
Dim i, j, count, fldCount As Integer
Dim cell As Range
Dim varValue As Variant

count = lstFields.ListCount
j = 0
' Store the field names selected from the List Box,
' in the selFields array
For i = 0 To count - 1
If lstFields.Selected(i) Then
ReDim Preserve selFields(j + 1)
selFields(j) = lstFields.List(i)
j = j + 1
End If
Next
fldCount = j

' Clear the existing values in the worksheet
Sheet1.Cells.ClearContents

' Highlight the first row, and display the field names there
' as column headings
Set cell = Sheet1.Cells(1)
cell.Font.Size = 12
cell.Font.Color = RGB(0, 64, 255)
cell.Value = "CN"
For i = 0 To fldCount - 1
Set cell = Sheet1.Cells(i + 2)
cell.Font.Size = 12
cell.Font.Color = RGB(0, 64, 255)
cell.Value = selFields(i)
Next

If fNDSLoad Then ' NDS Load
NWDir1.FullName = txtFullName.Text
NWDir1.Filters = "User" ' In NDS load User objects
Set ndsEntries = NWDir1.entries

' Start from the second row, because the first row
' contains the field names as column headings
i = 2
' Each row in the worksheet will contain one directory entry
        For Each ndsEntry In ndsEntries
            Set cell = Sheet1.Cells(i, 1)
            cell.Value = ndsEntry.ShortName
            ' For each entry, the values of the selected fields
            ' will be filled in the columns
            For j = 0 To fldCount - 1
                varValue = ndsEntry.GetFieldValue(selFields(j), "", True)
                Set cell = Sheet1.Cells(i, j + 2)
                cell.Value = varValue(0)
            Next
            i = i + 1
        Next
    Else ' LDAP Load
        NWIDir1.FullName = txtFullName.Text
        NWIDir1.Filter = "person" ' In LDAP load person objects
        Set ldapEntries = NWIDir1.entries

        i = 2
        For Each ldapEntry In ldapEntries
            Set cell = Sheet1.Cells(i, 1)
            cell.Value = ldapEntry.ShortName
            For j = 0 To fldCount - 1
                varValue = ldapEntry.GetFieldValue(selFields(j), True, "")
                Set cell = Sheet1.Cells(i, j + 2)
                ' If the value returned is an array of strings,
                ' show the first value
                If VarType(varValue) = vbArray + vbString Then
                    cell.Value = varValue(0)
                Else
                    cell.Value = varValue
                End If
            Next
            i = i + 1
        Next
    End If

    frmLoad.Hide

    Exit Sub

errExit:
    MsgBox Str(Err.Number) + Err.Description
End Sub

Before the entries in the worksheet are migrated to an LDAP directory, the user must be authenticated to the target server. Design the form as shown in Figure 4 to gather authentication details. The user must have administrator privileges on the target server to be able to migrate the entries.

Figure 4: Migrate to LDAP form.

When the Migrate button is clicked, the LDAP directory updates the directory entries and their field values given in the worksheet. Since the format of the field names is different in LDAP and NDS, modify the field names displayed in the first row accordingly before you start the migration. For example, the 'Internet Email Address' field in NDS is equivalent to 'mail' in LDAP. The Add method in the NWEntries collection adds a new entry to the directory. For each NWEntry object, call the SetFieldValue method for the fields in the worksheet and finally call Update to update the fields to the selected directory. Refer to the "Features of the Sample Program" section for a list of NDS and LDAP field names.

' cmdMigrate_Click - Event
' Called when the Migrate button is clicked
Private Sub cmdMigrate_Click()
    On Error GoTo errExit

    Dim ldapEntry As NWIDirLib.NWEntry
    Dim ldapEntries As NWIDirLib.NWEntries
    Dim i, j, rowCount, colCount As Long
    Dim entries, entry, fields, field As Range
    Dim cell As Range

    NWIDir1.FullName = txtFullName.Text
    NWIDir1.UserName = txtUserName.Text
    NWIDir1.Password = txtPassword.Text

    Set ldapEntries = NWIDir1.entries

    ' All the entry names are in Column A
    Set entries = Sheet1.Range("A:A")
    ' All the field names are in Row 1
    Set fields = Sheet1.Range("1:1")

    rowCount = entries.Rows.count
    For i = 2 To rowCount
        ' Get all the entry names from the first Column
        Set entry = entries(i, 1)
        If Not IsEmpty(entry) Then
            ' Add a new person object to the given LDAP search base
            Set ldapEntry = ldapEntries.Add("person", entry.Value)
            colCount = fields.Columns.count
            ' For each entry, get the field values from its
            ' corresponding row
            For j = 2 To colCount
                ' Get the field names from the first row
                Set field = fields(1, j)
                If IsEmpty(field) Then Exit For
                ' Get the field value from the worksheet cell
                ' in the entry's row and field's column
                Set cell = Sheet1.Cells(entry.Row, field.Column)
                ' Set the value to the directory entry's field
                ldapEntry.SetFieldValue field.Value, cell.Value
            Next
            ' Update the directory entry
            ldapEntry.Update
        Else
            ' End of entry names in Column A
            Exit For
        End If
    Next

    frmLDAPUpdate.Hide

    Exit Sub

errExit:
    MsgBox Str(Err.Number) + Err.Description
End Sub

Migrating Data to NDS

After looking into how user or person information is retrieved to the worksheet, we will see how data is migrated to NDS. The Migrate Data to NDS form is shown in Figure 5.

Figure 5: Migrate to NDS form.

The Browse button displays the Selector dialog for the desired tree and context to be updated.

' UserForm_Activate - Event
' Called when this form becomes the active window
Private Sub UserForm_Activate()
    txtFullName.Text = NWDir1.FullName
End Sub

' cmdBrowse_Click - Event
' Called when the Browse button is clicked
Private Sub cmdBrowse_Click()
    On Error GoTo errExit

    NWSelect1.FullName = txtFullName.Text
    ' Show the selector dialog to select the NDS Tree and context
    If NWSelect1.Show Then
        ' If the selection is successful, set the selected fullname
        ' in the Text Box
        txtFullName.Text = NWSelect1.FullName
    End If

    Exit Sub

errExit:
    MsgBox Str(Err.Number) + Err.Description
End Sub

To migrate the directory entries to NDS, add the following code. The code is similar to the Migrate Data to LDAP section.

' cmdMigrate_Click - Event
' Called when the Migrate button is clicked
Private Sub cmdMigrate_Click()
    On Error GoTo errExit

    Dim ndsEntry As NWDirLib.NWEntry
    Dim ndsEntries As NWDirLib.NWEntries
    Dim i, j, rowCount, colCount As Long
    Dim entries, entry, fields, field As Range
    Dim cell As Range

    NWDir1.FullName = txtFullName.Text
    Set ndsEntries = NWDir1.entries
    ' All the entry names are in Column A
    Set entries = Sheet1.Range("A:A")
    ' All the field names are in Row 1
    Set fields = Sheet1.Range("1:1")

    rowCount = entries.Rows.count
    For i = 2 To rowCount
        ' Get all the entry names from the first Column
        Set entry = entries(i, 1)
        If Not IsEmpty(entry) Then
            ' Add a new User object to the NDS context
            Set ndsEntry = ndsEntries.Add("User", entry.Value)
            colCount = fields.Columns.count
            ' For each entry, get the field values from its
            ' corresponding row
            For j = 2 To colCount
                ' Get the field names from the first row
                Set field = fields(1, j)
                If IsEmpty(field) Then Exit For
                ' Get the field value from the worksheet cell
                ' in the entry's row and field's column
                Set cell = Sheet1.Cells(entry.Row, field.Column)
                ' Set the value to the directory entry's field
                ndsEntry.SetFieldValue field.Value, cell.Value
            Next
            ' Update the directory entry
            ndsEntry.Update
        Else
            ' End of entry names in Column A
            Exit For
        End If
    Next

    frmNDSUpdate.Hide

    Exit Sub

errExit:
    MsgBox Str(Err.Number) + Err.Description
End Sub

Conclusion

Isn't it simple? This sample program demonstrates the versatility provided by Novell's ActiveX Controls for developing directory-enabled solutions of your choice. Diverse applications can be developed in Microsoft Excel using the controls.

For a wide range of sample applications created using Novell Controls for ActiveX see:

http://support.novell.com/techcenter/articles/ana20000807.html

http://developer.novell.com/ndk/doc/samplecode/ocx_sample/index.htm

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates