Is there a way to locate a specific Folder?

E

Eldraad

I would like to be able to have the Excel workbook find the "M
Documents" folder automatically when it is opened. At work we hav
changed computers so many times in the last 3 weeks that I am tired o
always having to manually change the address in my macros to point t
the My Documents folder.

Is there a way to program things so it can Find the My Documents folde
automatically? In other words, it would find the My Documents folde
for "Wendy"s desktop when Wendy was logged in, or Toms My Document
folder when HE is logged in...etc.

Thank you..
 
H

Hank Scorpio

I would like to be able to have the Excel workbook find the "My
Documents" folder automatically when it is opened. At work we have
changed computers so many times in the last 3 weeks that I am tired of
always having to manually change the address in my macros to point to
the My Documents folder.

Is there a way to program things so it can Find the My Documents folder
automatically? In other words, it would find the My Documents folder
for "Wendy"s desktop when Wendy was logged in, or Toms My Documents
folder when HE is logged in...etc.

The FileSystemObject in the Scripting Runtime Library has a useful
little method called GetSpecialFolder which can return the Windows,
System or Temp folder. But not, alas, the My Documents folder. The
Environ function is another way of getting some settings, though as
far as I know that won't get you the My Documents folder either. (Yes,
I know that an environment variable can be set for that, but that's
going to be as much of a problem as the original one.)

AFAIK the only way to do it reliably is via an API call. If you "get"
API calls, you can fathom what the following does at your leisure. If
you don't, don't worry about it; just copy and paste the following
code into a module, and call the GetMyDocsFolder function whenever you
need to. You don't really NEED to understand what it's doing to use
it.

As an example,

Sub TestGetMyDocs()

MsgBox GetMyDocsFolder

End Sub

will in my case return

C:\Documents and Settings\Hank Scorpio\My Documents

when I'm logged in under my own name rather than one of my other
accounts. It'll return (say) C:\Documents and Settings\Guest2\My
Documents
if I'm logged in on the Guest2 account.

This is, I presume, what you're after. (I'm on Win XP Professional.)

CAUTION! I ripped this out of one of my VB libraries, and had to take
out substantial chunks of error handling and other "bells and
whistles" code from my original procedure. Hopefully I haven't missed
anything, though; I've tested the code below and it does still seem to
work in the same way as the procedure from which it was ripped. Be
careful of any word wrapping issues as well.

--------------------------------------
Option Explicit

'Registry Constants
Private Const HS_RegDT_REG_SZ As Long = 1
Private Const HS_RegRK_HKEY_CURRENT_USER As Long = &H80000001
Private Const HS_RegAM_KEY_QUERY_VALUE As Long = &H1

'----- Registry open / close functions
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias _
"RegOpenKeyExA" (ByVal hkey As Long, ByVal lpSubKey As String, _
ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As _
Long) As Long

Private Declare Function RegCloseKey Lib "advapi32.dll" _
(ByVal hkey As Long) As Long

'----- Registry data reading functions.
Private Declare Function RegQueryValueExNULL Lib "advapi32.dll" _
Alias _
"RegQueryValueExA" (ByVal hkey As Long, ByVal lpValueName As _
String, ByVal lpReserved As Long, lpType As Long, ByVal lpData _
As Long, lpcbData As Long) As Long

Private Declare Function RegQueryValueExString Lib _
"advapi32.dll" Alias _
"RegQueryValueExA" (ByVal hkey As Long, ByVal lpValueName As _
String, ByVal lpReserved As Long, lpType As Long, ByVal lpData _
As String, lpcbData As Long) As Long


Function GetMyDocsFolder() As String

'Path to the key that we're interested in.
Const SC_MYDOCS_KEY_PATH As String = _
"Software\Microsoft\Windows\CurrentVersion" _
& "\Explorer\Shell Folders\"

'Key that we're interested in
Const SC_MYDOCS_KEY As String = "Personal"

'Key's handle, populated by the Open Key API call.
Dim h_Key As Long

'Data type returned from the Null query.
Dim l_DataType As Long

'Size of the data stored in the key, returned by the Null query.
Dim l_BufferSize As Long

'The return function value from an API call.
Dim l_APIRetVal As Long

'Returned key value from the Read call.
Dim s_ReturnValue As String

'*************************************************************************
'----- Set default value & enable error handler.
GetMyDocsFolder = ""

On Error GoTo ErrorHandler

'*************************************************************************
'----- Use the Open Key API call to return the handle to h_key.
l_APIRetVal = RegOpenKeyEx(HS_RegRK_HKEY_CURRENT_USER, _
SC_MYDOCS_KEY_PATH, 0, HS_RegAM_KEY_QUERY_VALUE, h_Key)

'----- Do a Null call to get the key type and size.
l_APIRetVal = RegQueryValueExNULL(h_Key, SC_MYDOCS_KEY, _
0&, l_DataType, 0&, l_BufferSize)

'----- Read the string.
If l_DataType = HS_RegDT_REG_SZ Then
'Create a string consisting of null bytes. The length of the
'string equals the length of the Registry entry as determined
'via the buffer value above.
s_ReturnValue = String(l_BufferSize, 0)

l_APIRetVal = RegQueryValueExString(h_Key, SC_MYDOCS_KEY, 0&, _
l_DataType, s_ReturnValue, l_BufferSize)

'Remove trailing null. (Strings returned from API calls are C
'strings, not VB strings. This "converts" them.)
s_ReturnValue = Left$(s_ReturnValue, l_BufferSize - 1)

End If

'*************************************************************************
'Assign returned value to the ApplicationDataDirectory property.

GetMyDocsFolder = s_ReturnValue

ExitPoint:
'Ensure that errors do not result in an endless loop.
On Error Resume Next

RegCloseKey (h_Key)

Exit Function

'*************************************************************************
ErrorHandler:

MsgBox "Error reading the My Documents folder. " _
& "Error No: " & Err.Number _
& vbCrLf & Err.Description

Resume ExitPoint

End Function
 
D

Dave Peterson

Another way:

Option Explicit
Sub testme03()

Dim wsh As Object
Dim myPath As String

Set wsh = CreateObject("WScript.Shell")
myPath = wsh.SpecialFolders.Item("mydocuments")

MsgBox myPath

End Sub
 
H

Hank Scorpio

Another way:

Option Explicit
Sub testme03()

Dim wsh As Object
Dim myPath As String

Set wsh = CreateObject("WScript.Shell")
myPath = wsh.SpecialFolders.Item("mydocuments")

MsgBox myPath

End Sub

Hi Dave,

Huh. I must confess that I Did Not Know that one. I'll have to look at
the Windows Scripting Host more closely. The only reason that I
haven't so far is because I know that it's disabled in some corporate
environments because of the .vbs virus issue. I therefore prefer to
avoid it if I can. Still, I may as well see what's on offer...
 
D

Dave Peterson

I used to feel the same way--until I saw how much you could easily do. (and at
work, it's not disabled!)
 
E

Eldraad

These are a lot of good answers.

Patty, Thanks for showing me that one. Have not tried it as th
Textfilepromptonrefresh (whew) has started working properly after
cleaned out a few errors. That seems to get us by as long as the
don't use it on an NT4 machine again! Lol.

Hank Scorpio, WOW! Your dedication to helping people is fantastic!
That is a LOT of information you gave me...I am still having a
overload from it. Lol.

Dave Peterson, I tried your information and all was good with it. M
stumbling block was finding the proper way to slip it into the code
have for each worksheet.

what I was hoping to fix was this For each of 5 worksheets (or do i
once and see if the mypath implanted in each sheet would be enough):

Sub Stat_Convert()
'
' Stat_Convert Macro
' Macro recorded 7/23/2004 by Eldraad
'

'
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;C:\Documents and Settings\administrator\M
Documents\statistical.txt", _
Destination:=Range("A1"))

I was trying to merge the two codes together but managed to mess thng
up big time trying to plant the mypath variable in there. It wa
probably a simple thing but...

Thank you all
 
D

Dave Peterson

You could use a public variable and retrive it once--workbook_open?????

or you could retrieve it each time you needed it:

Option Explicit
Function myDocumentsPath() As String

Dim wsh As Object

Set wsh = CreateObject("WScript.Shell")
myDocumentsPath = wsh.SpecialFolders.Item("mydocuments")

End Function

Sub Stat_Convert()
'
' Stat_Convert Macro
' Macro recorded 7/23/2004 by Eldraad
'

'
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;" & myDocumentsPath() & "\statistical.txt", _
Destination:=Range("A1"))
'....
End With

End Sub

I didn't need the () in this expression: myDocumentspath()
But I think I like them--since it makes it look like a function--not just a
variable.
 
E

Eldraad

Thank you Dave Peterson!

I will pop the search into the workbook and just have each of th
worksheet macros use the variable information.

Again, thank you EVERONE for your help
 
Top