Solved

recursive - can this be done?

Posted on 2002-03-06
24
288 Views
Last Modified: 2008-02-01
hi,

i have table that holds all the folders for a drive.
The table is made up like this:

FolderID  (autonumber - Pr.Key)
Foldername (name of the folder...)
FolderLevel (C: = 0, Winnt = 1, System32 = 2, etc)
FolderParentID (FolderID of the parentfolder, if Winnt
                has folderid 15, then system32 will
                have 15 as folderparentID)


this way i am able to use this table several times in one query to show a folder-structure.
Another table holds the nt-security-settings for each folder (with the local and global groups)

but, u guessed, this is not exactly a nice way of working

so i was thinking of loading this into a treeview,
and i assume i will need some sort of recursive function(s) for it to accomplish.

is this correct?
if so, has anyone have any experience with this  kind of thing?
again, if so, any directions...?

cheers
Ricky
0
Comment
Question by:Paurths
  • 8
  • 7
  • 5
  • +4
24 Comments
 
LVL 45

Expert Comment

by:aikimark
ID: 6845630
Not really.  You aren't bound to use a recursive function. I'm not entirely sure I understand your problem or why you're changing something that already works.

Are you looking for alternatives?
Is your problem mostly a processing problem?
Performance problem?
Directory name/parentage data gathering problem?

I assume you need to support cascading security, group security, as well as user-specific security.  If I'm wrong, please let me know.

What are the details of this application?
0
 
LVL 45

Expert Comment

by:aikimark
ID: 6845651
In addition:

What do you want to do with hidden and system directories?

What does the user need to do?  I ask this question because the Treeview control can slow your application needlessly if the user doesn't need to access this information.
0
 
LVL 12

Author Comment

by:Paurths
ID: 6845687
hi akimark,

actually, i am still developing this program,
it has all (i hope) the issues about network.
routers, outlets, patchpanel, computers, printers, printservers (jet-direct and axis), desks, users, devisions, locations, local groups, global groups, etc...

this is only a small part of the entire program.
What i would like to do is:
if i could fill a treeview with all the folders, click on a node (e.g. a folder on a shared folder) immediatly know what groups, users, have what permissions.
I know i can retrieve this information in my form where the folders are shown/added.
I was just wondering if it can be done. (i would probably be the only person on this planet using this program, but i figured it would be good excercice...)

cheers
Ricky
0
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 45

Expert Comment

by:aikimark
ID: 6845718
The quickest/easiest development effort will use a Directory (intrinsic) control.  When the user selects a directory, you gather the permissions and display them.

If you gather all the permissions, you can either loop through them, looking for candidates with the LIKE operator, or place them in a table and use SQL with a WHERE LIKE search criteria.

You will possibly have several rules that will cascade (apply) to the selected directory.
0
 
LVL 14

Expert Comment

by:puranik_p
ID: 6846412
Dim ParentFolder as Scripting.Folder
Dim oFolder as Scripting.Folder

Private Sub Form_Load()
    Dim oFSO as Scripting.FileSystemObject
    Set oFolder = oFSO.GetFolder("your\path")
    Call DoTree(oFolder)
End Sub

Private Function DoTree(oFolder as Scripting.Folder)
    For Each Folder In oFolder.Folders
        'Code to Process the folder
        Call DoTree(oFolder)
    Next
End Function
0
 
LVL 1

Expert Comment

by:matthewroberts
ID: 6846432
Here is a snippet I just did in an Access Module (referencing mscomctl.ocx) for loading an employee hierachy from the CEO down..

This assumes you have an MSAccess table called "tblEmp"
Fields:
EmpID (Long)
EmpName (Text)
ParentEmpID (Long)

Whack the following functions in a vb module or form class and call the function:

BuldTree TreeView1

in Form_Load event

Change the following code to loop your FileSystemObjects instead of the tblEmp table records... good luck!

Option Explicit

Public Sub BuildTree(oTreeView As TreeView)
   
    Dim sql         As String
    Dim rs          As Recordset
    Dim NodX        As Node
   
On Error GoTo ET


'    With oTreeView
'        .Font = 1 ' .Font = "Tahoma"
'        .Font.Size = "12"
'        .Font.Bold = True
'        '.Indentation = "500"
'        .LabelEdit = False
'        '.LineStyle = 1
'        '.Style = 7
'        '.FullRowSelect = True
'    End With

'The following comments is a sample of adding nodes to the tree
       
'    Set nodX = oTreeView.Nodes.Add(, , "R", "Root")
'    Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C1", "Child 1")
'    Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C2", "Child 2")
'    Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C3", "Child 3")
'    Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C4", "Child 4")
'    Set nodX = oTreeView.Nodes.Add("C4", tvwChild, "C5", "Child 5")
'    Set nodX = oTreeView.Nodes.Add("C5", tvwChild, "C6", "Child 6")
'    nodX.EnsureVisible
   
'Add Parent Root Node ie. CEO

    'assume CEO's EmpID=1
    Set NodX = oTreeView.Nodes.Add(, , "Key=1", DLookup("EmpName", "tblEmp", "EmpID = 1"))

    AddChildNodes oTreeView, 1

    NodX.Bold = True
    NodX.ForeColor = 255
   
    Exit Sub

ET:
    MsgBox Err.Number & " - " & Err.Description, vbCritical
End Sub

Private Sub AddChildNodes(oTreeView As TreeView, EmpID As Integer)
   
    Dim rs      As Recordset
    Dim sql     As String
    Dim NodX    As Node
   
    sql = "SELECT EmpID, EmpName, ParentEmpID"
    sql = sql & " FROM tblEmp"
    sql = sql & " WHERE ParentEmpID = " & EmpID
    sql = sql & " ORDER BY EmpID;"
    Set rs = CurrentDb.OpenRecordset(sql, dbOpenForwardOnly)
   
    Do Until rs.EOF
        Set NodX = oTreeView.Nodes.Add("Key=" & EmpID, tvwChild, "Key=" & rs!EmpID, rs!EmpName)
        AddChildNodes oTreeView, rs!EmpID
        rs.MoveNext
    Loop
    rs.Close
    Set rs = Nothing

End Sub

Public Sub DelTree(oTreeView As TreeView)

    Do While oTreeView.Nodes.Count > 0
        oTreeView.Nodes.Remove (1)
    Loop
   
End Sub
0
 
LVL 45

Accepted Solution

by:
aikimark earned 50 total points
ID: 6846656
In order to get the puranik_p example to work:
1. add the Microsoft Scripting Runtime reference to your project.
2.
Option Explicit

Dim Folder As Scripting.Folder  'Not ParentFolder

'Dim strDirectories(12000) As String
'Dim intDircount As Integer

Private Function DoTree(oFolder As Scripting.Folder)
   For Each Folder In oFolder.SubFolders  'not oFolder.Folders
       'Code to Process the folder
       'intDircount = intDircount + 1
       'strDirectories(intDircount) = Folder.Path
       Call DoTree(Folder)
   Next
End Function

Private Sub Form_Load()
    Dim oFolder As Scripting.Folder
    Dim oFSO As New Scripting.FileSystemObject  'NEW
    Set oFolder = oFSO.GetFolder("c:\")
    Call DoTree(oFolder)
End Sub

=========================================
Here is a low-tech approach to gather the directory tree data:
1. shell a batch file with the following statement
dir c:\ /ad /b /s > dirlist.txt
2. when the batch file is finished, read the contents of the file into your program

=========================================
Alternatively, you could also use the Windows API calls to collect the directory data if performance is an issue.  The Scripting Runtime library wraps these APIs, so you could remove one of the layers.

=========================================
If you use the directory control, you wait until the user selects the directory to gather and display data.  This should provide the best user-perceived performance, since the user begins using the application with the least amount of delay, due to postponed and avoided processing.
0
 
LVL 18

Expert Comment

by:mdougan
ID: 6851121
I wrote a form to do pretty much what you are asking.  First off, yes, you can use recursion to go through all folders and load them into a treeview but a word of warning, it's very slow.  You might not realize it but there are maybe hundreds or thousands of folders under Program Files, WINNT or some of the major folders.  Even if you are just looking at directories, it can take a long time to load the tree.

I finally settled on loading one level at a time.  So, first load all of the top level folders.  Then, as you expand a folder just get it's direct child folders etc.

My example was also trying to track the folder sizes to help me locate disk-hogs.  Here is some of the code.  If you want the stuff that actually gets the directory size let me know.  With a little tinkering this should do what you want.

Open a projet with a Treeview, a ListView, a Drive File List, name them appropriatly and paste in this code.  You might have to comment out the calls to GetDirectorySize.

Private Sub Drive1_Change()
Dim oNode As Node
    tvwDirectory.Nodes.Clear
    Set Node = tvwDirectory.Nodes.Add(, , Left$(Drive1.Drive, 1) & ":", Left$(Drive1.Drive, 1) & ":", 1)
    GetDirContents Left$(Drive1.Drive, 1) & ":"
    tvwDirectory_NodeClick tvwDirectory.Nodes(1)
    tvwDirectory.Nodes(1).Expanded = True
End Sub

Private Sub Form_Load()
    FormLoading = True
    lvwDisplay.View = lvwReport
    lvwDisplay.ColumnHeaders.Add , , "Name", lvwDisplay.Width * 0.3, lvwColumnLeft
    lvwDisplay.ColumnHeaders.Add , , "Size", lvwDisplay.Width * 0.2, lvwColumnRight
    lvwDisplay.ColumnHeaders.Add , , "Relative", lvwDisplay.Width * 0.5, lvwColumnLeft
   
    Drive1.Drive = "C:"
    Drive1_Change
    FormLoading = False
       
End Sub

Private Sub GetDirContents(sPath As String)
Dim oNode As Node
Dim sTemp As String
Dim sMatch As String

    If tvwDirectory.Nodes(sPath).Children > 0 Then Exit Sub
   
    If Right$(sPath, 1) = "\" Then
        sTemp = sPath
    Else
        sTemp = sPath & "\"
    End If
   
    sMatch = Dir$(sTemp & "\*.", vbDirectory)
   
    Do While sMatch <> ""
        If sMatch <> "." And sMatch <> ".." Then
            If ((GetAttr(sTemp & sMatch) And vbDirectory) = vbDirectory) Then
                Set Node = tvwDirectory.Nodes.Add(sPath, tvwChild, sTemp & sMatch, sMatch, 2)
            End If
        End If
        sMatch = Dir$()
    Loop
   

End Sub

Private Sub tvwDirectory_Collapse(ByVal Node As MSComctlLib.Node)
    Node.Image = 2
End Sub

Private Sub tvwDirectory_Expand(ByVal Node As MSComctlLib.Node)
Dim oNode As Node
Dim vIndex As Variant
    Node.Image = 3
    GetDirContents Node.Key
    If Node.Children > 0 Then
        Set oNode = Node.Child
'        GetDirContents oNode.Key
        If Not oNode.LastSibling Is Nothing Then
            vIndex = oNode.LastSibling.Index
            Do While Not oNode Is Nothing
                GetDirContents oNode.Key
                If oNode.Index <> vIndex Then
                    Set oNode = oNode.Next
                Else
                    Set oNode = Nothing
                End If
            Loop
        End If
    End If

End Sub

Private Sub tvwDirectory_NodeClick(ByVal Node As MSComctlLib.Node)
Dim oNode As Node
Dim oListItem As ListItem
Dim vIndex As Variant
Dim dblDirSize As Double
Dim dblTemp As Double

    lvwDisplay.ListItems.Clear
   
    GetDirContents Node.Key
    Set oListItem = lvwDisplay.ListItems.Add(, , "Files", 4, 4)
 '   dblDirSize = GetDirectorySize(Node.Key)
    oListItem.SubItems(1) = Format((dblDirSize + 1) / 1000, "###,###,###,##0") & "KB"
    oListItem.SubItems(2) = "*****"
    If Node.Children > 0 Then
        Set oNode = Node.Child
'        GetDirContents oNode.Key
        If Not oNode.LastSibling Is Nothing Then
            vIndex = oNode.LastSibling.Index
            Do While Not oNode Is Nothing
                GetDirContents oNode.Key
                Set oListItem = lvwDisplay.ListItems.Add(, , oNode.Text, 2, 2)
                dblDirSize = GetDirectorySize(oNode.Key)
                oListItem.SubItems(1) = Format((dblDirSize + 1) / 1000, "###,###,###,##0") & "KB"
                oListItem.SubItems(2) = "*****"
                If oNode.Index <> vIndex Then
                    Set oNode = oNode.Next
                Else
                    Set oNode = Nothing
                End If
            Loop
        End If
    End If
    dblDirSize = 0
    For i = 1 To lvwDisplay.ListItems.Count
        Set oListItem = lvwDisplay.ListItems(i)
        dblDirSize = dblDirSize + CDbl(Left(oListItem.SubItems(1), Len(oListItem.SubItems(1)) - 2))
    Next i
    For i = 1 To lvwDisplay.ListItems.Count
        Set oListItem = lvwDisplay.ListItems(i)
        dblTemp = CDbl(Left(oListItem.SubItems(1), Len(oListItem.SubItems(1)) - 2))
        If dblTemp > 0 Then
            oListItem.SubItems(2) = String(((dblTemp / dblDirSize) * 100), "*")
        End If
    Next i
   
End Sub
0
 
LVL 12

Author Comment

by:Paurths
ID: 6852232
hi all,

actually, this one works for me:

code provided by ameba:

**************************************
To load a tree, I suggest Chris Eastwood's code, which first adds all nodes to root, and later reparents
them. .Tag property is used to cache ParentID.


Private Sub FillTree()
   Dim lCount As Long
   Dim rsSections As Recordset
   Dim sParent As String
   Dim sKey As String
   Dim sText As String
   Dim bBookMark As Boolean
   Dim nNode As Node
   On Error GoTo vbErrorHandler
'
' Populate our TreeView Control with the Data from our database
'
   Set rsSections = mDB.OpenRecordset("select * from codeitems order by parentid")
   
   Set tvCodeItems.ImageList = Nothing
   Set tvCodeItems.ImageList = ImageList1

   If rsSections.BOF And rsSections.EOF Then
       tvCodeItems.Nodes.Add , , "ROOT", "Code Library", "VIEWBOOKMARKS"
       BoldTreeNode tvCodeItems.Nodes("ROOT")
       Exit Sub
   End If
       
   TreeRedraw tvCodeItems.hwnd, False
   
   rsSections.MoveFirst
   Set tvCodeItems.ImageList = Nothing
   Set tvCodeItems.ImageList = ImageList1
'
' Populate the TreeView Nodes
'

   With tvCodeItems.Nodes
       .Clear
       .Add , , "ROOT", "Code Library", "VIEWBOOKMARKS"
'
' Make our Root Item BOLD
'
       BoldTreeNode tvCodeItems.Nodes("ROOT")
'
' Now add all nodes into TreeView, but under the root item.
' We reparent the nodes in the next step
'
       Do Until rsSections.EOF
           sParent = rsSections("ParentID").Value
           sKey = rsSections("ID").Value
           sText = rsSections("Description").Value
           Set nNode = .Add("ROOT", tvwChild, "C" & sKey, sText, "FOLDER")
'
' Record parent ID
'
           nNode.Tag = "C" & sParent
           rsSections.MoveNext
       Loop
   
   End With
'
' Here's where we rebuild the structure of the nodes
'
   For Each nNode In tvCodeItems.Nodes
       sParent = nNode.Tag
       If Len(sParent) > 0 Then        ' Don't try and reparent the ROOT !
           If sParent = "C0" Then
               sParent = "ROOT"
           End If
           Set nNode.Parent = tvCodeItems.Nodes(sParent)
       End If
   Next
'
' Now setup the images for each node in the treeview & set each node to
' be sorted if it has children
'
   For Each nNode In tvCodeItems.Nodes
       If nNode.Children = 0 Then
           nNode.Image = "CHILD"
       Else
           nNode.Sorted = True
       End If
   Next
   
   Set rsSections = Nothing
'
' Expand the Root Node
'
   tvCodeItems.Nodes("ROOT").Sorted = True
   tvCodeItems.Nodes("ROOT").Expanded = True
   
   TreeRedraw tvCodeItems.hwnd, True
   Exit Sub

vbErrorHandler:
   TreeRedraw tvCodeItems.hwnd, True
   MsgBox Err.Number & " " & Err.Description & " " & Err.Source
End Sub

Private Sub TreeRedraw(ByVal lHwnd As Long, ByVal bRedraw As Boolean)
   SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0
End Sub

************************




all agree that this solves it for me? (i agree, b/c it did exactly what i wanted...)

0
 
LVL 18

Expert Comment

by:mdougan
ID: 6852837
ameba, I hadn't heard of this technique before.  Is it faster to load this way?  Or does is just simplify retrieving the data so that you don't have to order the recordset with all children following their parents.
0
 
LVL 45

Expert Comment

by:aikimark
ID: 6852929
Paurths,

What advantage is there to recreate the function/contents of the DirectoryList box?  Messing with a Treeview control is slower and performs unnecessary to iterate/add-node for a directory the user isn't interested in seeing.
0
 
LVL 12

Author Comment

by:Paurths
ID: 6853011
that is correct aikimark,

but there wont be no users using this program.
its for my use only.
comment of Date: 03/06/2002 03:47PM PST
****************************
What i would like to do is:
if i could fill a treeview with all the folders, click on a node (e.g. a folder on a shared folder)
immediatly know what groups, users, have what permissions.
I know i can retrieve this information in my form where the folders are shown/added.
I was just wondering if it can be done. (i would probably be the only person on this planet using this
program, but i figured it would be good excercice...)
*****************************

since the database will hold all the users, global groups, local groups, folders, permissions on folders it would / could give me a quick view 'who can do what' when i click a folder.
Sometimes when i receive a call from any user of our network asking me why on earth (s)he can not write/delete/access a certain folder i need to look up permissions. The way it is done now takes too long.
with a click on folder in the treeview i want to see why this user calls me.
In the end there wont be that many folders in this database.
Only the folders where the shared data is, will be present. (for several servers tho) So i'm not talking about a couple of thousand folders. (perhaps in the future)
Since the security only goes 3 or 4 levels deep, this must be managable.
If a user adds a folder at level e.g. 7 just for her/his sake i dont need that in the database. (for now)


like i said, there might be programs out there that have a solution for this, but i really want a total program where i can also place computers on desks. (using Visio for the graphical interface of the building / offices --> is build automatically on the click of a button, nice tool, when a desk gets moved i give it other co-ordinates in the program and it will show up at the correct place in the graphical overview --> once it is finished that is!)
connect computers to outlets, the outlets to the swichtes,
desks have several outlets at their disposal, so u can connect computers to a desk/outlet, printers and printservers.
there are several other issues in it, but i cant name them all or i'll fill at least 3 pages here...

It is big...

cheers
Ricky

0
 
LVL 18

Expert Comment

by:mdougan
ID: 6855642
ameba,

I tried the code above but the declaration for the API SendMessageLong is missing.  I tried pasting SendMessage from the API text viewer, re-aliasing it to SendMessageLong.  I also set the lParam value to ByVal as this sometimes causes problems if it's passed ByRef, but still the call is appearantly failing.

What happens is that the tree keeps trying to redraw, and this makes the process incredibly slow.  The SendMessageLong returns a zero, so, it looks like it works...

I tried every combination I could think of for SendMessage and still no luck.  Finally, I found an alternative API for LockWindowUpdate.  This worked perfectly.


'Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Private Const WM_SETREDRAW = &HB

Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long

Private Sub TreeRedraw(ByVal lHwnd As Long, ByVal bRedraw As Boolean)

'    SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0
'    SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, &O0
'    SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0&
'    SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, ByVal 0&
'    SendMessageLong lHwnd, WM_SETREDRAW, -CLng(bRedraw), 0&
'    SendMessageLong lHwnd, WM_SETREDRAW, Abs(CLng(bRedraw)), 0&

   
    If bRedraw Then
        LockWindowUpdate 0
    Else
        LockWindowUpdate lHwnd
    End If
End Sub
0
 
LVL 12

Author Comment

by:Paurths
ID: 6855813
there is more,

'BoldTreeNode tvCodeItems.Nodes("ROOT")
is replaced by (b/c VB6)
tvCodeItems.Nodes("ROOT").Bold = True
       
0
 
LVL 12

Author Comment

by:Paurths
ID: 6857915
i guess its time to close this one.

any suggestions?

cheers
Ricky
0
 
LVL 18

Expert Comment

by:mdougan
ID: 6858843
Despite the slight omissions in the code, I think ameba's answer fits your needs.  It also taught me a new and valuable trick.  I've often gone to great lengths to try to order my rows in a hierarchical self-referencing table in order to add them to the tree in the proper order, and now I know that I can add them in any order and then re-parent them.  It's orders of magnitude faster than whatever I've done before.... so, it's a technique well worth the points.
0
 
LVL 12

Author Comment

by:Paurths
ID: 6870719
have already given ameba the points for his solution on 03/07/2002.
http://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20274655

cheers
Ricky
0
 
LVL 45

Expert Comment

by:aikimark
ID: 6872013
Paurths,

What are you going to do with THIS question?

Please close this question if we've answered it.  If you have questions, please consult the Community Support TA and ask them what you should do.
0
 
LVL 18

Expert Comment

by:mdougan
ID: 6872831
Paurths,

It's important to award the point to the expert inside of the question.  Because then the question gets saved to the Previously Asked Questions area and someone else will eventually "buy" the question and get the benefit of the excellent advice you've received here.  If you award the points in some other question without the technical stuff, then this question ends up deleted and then all of the good advice gets lost for others.......
0
 
LVL 12

Author Comment

by:Paurths
ID: 6872951
0
 
LVL 45

Expert Comment

by:aikimark
ID: 6873038
Did you leave someone out?
If not, you will probably need to lower your points from 200 to 150 to be evenly divisible into three 50-point slices.
0
 
LVL 1

Expert Comment

by:Computer101
ID: 6873278
Points refunded and reduced to 50 for a point split.  Now you can accept an experts comment as an answer and make questions in this topic area for the other experts.

Computer101
E-E Moderator
0
 
LVL 12

Author Comment

by:Paurths
ID: 6873661
0
 
LVL 15

Expert Comment

by:ameba
ID: 6874356
Oh, sorry, I didn't participate in this thread.
- the function I suggested in another thread is not recursive, so I didn't want to jump in here.

The sample is somewhere on codeguru, but I don't have the exact link, and it works only for version 5 of the Common Controls.


mdougan,

> I tried the code above but the declaration for the API SendMessageLong is missing

You have the right version of SendMessageLong, but it is possible it doesn't work with version 6 of the TreeView.
LockWindowUpdate can work OK in most cases.  Or if there are not too many items, "tv.Visible = False" can work.

I don't use Treeview often, but for Listview, I got best results when sending WM_SETREDRAW message to PARENT FORM:

' from caList class
Public Property Let Redraw(ByVal Redraw As Boolean)
    Dim rc As RECT, ret As Long
   
    If Redraw Then
        Call SendMessage(ListView.Parent.hwnd, WM_SETREDRAW, REDRAWON, 0&)
        ' this is a bit less flicker
        ret = GetClientRect(ListView.hwnd, rc)
        ret = InvalidateRect(ListView.hwnd, rc, 0&)
    Else
        Call SendMessage(ListView.Parent.hwnd, WM_SETREDRAW, REDRAWOFF, 0&)
    End If
End Property
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question