Results 1 to 13 of 13
  1. #1
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Code: Function strBreakFileString(strFileName As S

    This function could be placed in a new module Files; my Files module holds not only this function, but a slew of useful cover functions, such as strGetDrive, strGetPath (later!). If you serach the Decls module for "intcDrive" you'll see that I use compile-time constants to map component types.

    I make heavy use of strBreakFileString throughout my applications. So often do I want to get the drive or the path or the extent. I have other functions that will use strBreakFileString to extract the last folder name of the path (the local directory, if you will), and so on.

    For now, this is the code we need for the strGP and strPP functions which manage the INI file; we're getting closer!


    The logic in the function is based on a State Transition Table, a technique I learned back in the good old days when I developed compilers. Essentially you build a table with as many columns as there are input element types (in our case "colon, slash, letter, digit, period, space, other") and then add rows for each state. The initial state is null. You obtain the first (leftmost) character, and if it is a colon, you have an error! If it is a letter you ASSUME it is the drive letter, and then you test the incoming character. If it is a colon, then you HAVE got a drive, otherwise you go to a different state.

    I can draw this state transition table on paper and fax it to someone if they want to post it as a BMP or similar graphic on the lounge.

    This code looks horrible, but it gets the job done.


    <pre>Option Explicit

    Public Function strBreakFileString(strFileName As String, intType As Integer) As String
    ' Procedure : strBreakFileString

    '' Credits: Chris Cubley inspired me with HIS GetFileName
    '' Chris Cubley's code can be found at www.planet-source-code.com.


    ' Description: This code attempts to return the specified portion of a file path and name.
    ' Useful to
    ' Copyright: Chris Greaves Inc.
    ' Inputs: A string, vaguely representing a file path and name.
    ' An integer specifying the type of string to be returned.
    ' Returns: A string.
    ' intType = 0 -- Returns the drive letter
    ' intType = 1 -- Returns the directory path
    ' intType = 2 -- Returns the filename (without the extension)
    ' intType = 3 -- Returns the extension
    ' intType = 4 -- Returns the filename and extension
    ' intType = 5 -- Returns the drive and path
    ' Assumes: The incoming string has been vetted for character content, but not syntax.
    ' Tested: By the calls shown below.

    ' Initialise all temporary results to be zero-length strings
    Dim strDrive As String
    strDrive = ""
    Dim strPath As String
    strPath = ""
    Dim strFile As String
    strFile = ""
    Dim strExtent As String
    strExtent = ""

    Dim lngI As Long ' Pointer along our string. when lngI > len(strFilename) we have finished.
    lngI = 1
    Dim strCh As String ' The latest character delivered by lngI
    Dim strAccum As String ' The accumulated characters buffered to date.
    strAccum = ""
    Dim intErr As Integer
    Null0:
    If lngI > Len(strFileName) Then GoTo Exit9
    strCh = Mid(strFileName, lngI, 1): lngI = lngI + 1
    If boolAlphaOnly(strCh) Then
    strAccum = strAccum & strCh
    GoTo IsDrive1
    Else
    If strCh = strcDriveSeparator Then
    intErr = 1
    GoTo Exit9
    Else
    If strCh = Application.PathSeparator Then
    strPath = strPath & strAccum
    strAccum = ""
    GoTo GotSlash4
    Else
    If strCh = strcExtentSeparator Then
    strAccum = strAccum & strCh
    GoTo GotPeriod5
    Else
    strAccum = strAccum & strCh
    GoTo AccumFile3
    End If
    End If
    End If
    End If
    IsDrive1:
    If lngI > Len(strFileName) Then GoTo Exit9
    strCh = Mid(strFileName, lngI, 1): lngI = lngI + 1
    If strCh = strcDriveSeparator Then
    strDrive = strAccum: strAccum = ""
    GoTo GotDrive2
    Else
    If strCh = Application.PathSeparator Then
    If strPath <> "" Then
    strPath = strPath & Application.PathSeparator
    End If
    strPath = strPath & strAccum: strAccum = ""
    GoTo GotSlash4
    Else
    If strCh = strcExtentSeparator Then
    strAccum = strAccum & strCh
    GoTo GotPeriod5
    Else
    strAccum = strAccum & strCh
    GoTo AccumFile3
    End If
    End If
    End If
    GotDrive2:
    If lngI > Len(strFileName) Then GoTo Exit9
    strCh = Mid(strFileName, lngI, 1): lngI = lngI + 1
    If strCh = strcDriveSeparator Then
    intErr = 2
    GoTo Exit9
    Else
    If strCh = Application.PathSeparator Then
    If strPath <> "" Then
    strPath = strPath & Application.PathSeparator
    End If
    strPath = strPath & strAccum: strAccum = ""
    GoTo GotSlash4
    Else
    If strCh = strcExtentSeparator Then
    strAccum = strAccum & strCh
    GoTo GotPeriod5
    Else
    strAccum = strAccum & strCh
    GoTo AccumFile3
    End If
    End If
    End If
    AccumFile3:
    If lngI > Len(strFileName) Then GoTo Exit9
    strCh = Mid(strFileName, lngI, 1): lngI = lngI + 1
    If strCh = strcDriveSeparator Then
    intErr = 3
    GoTo Exit9
    Else
    If strCh = Application.PathSeparator Then
    If strPath <> "" Then
    strPath = strPath & Application.PathSeparator
    End If
    strPath = strPath & strAccum: strAccum = ""
    GoTo GotSlash4
    Else
    If strCh = strcExtentSeparator Then
    strAccum = strAccum & strCh
    GoTo GotPeriod5
    Else
    strAccum = strAccum & strCh
    GoTo AccumFile3
    End If
    End If
    End If
    GotSlash4:
    If lngI > Len(strFileName) Then GoTo Exit9
    strCh = Mid(strFileName, lngI, 1): lngI = lngI + 1
    If strCh = strcDriveSeparator Then
    intErr = 4
    GoTo Exit9
    Else
    If strCh = Application.PathSeparator Then
    intErr = 5
    GoTo Exit9
    Else
    If strCh = strcExtentSeparator Then
    strAccum = strAccum & strCh
    GoTo GotPeriod5
    Else
    strAccum = strAccum & strCh
    GoTo AccumFile3
    End If
    End If
    End If
    GotPeriod5:
    If lngI > Len(strFileName) Then GoTo Exit9
    strCh = Mid(strFileName, lngI, 1): lngI = lngI + 1
    If strCh = strcDriveSeparator Then
    intErr = 6
    GoTo Exit9
    Else
    If strCh = Application.PathSeparator Then
    If strPath <> "" Then
    strPath = strPath & Application.PathSeparator
    End If
    strPath = strPath & strAccum: strAccum = ""
    GoTo GotSlash4
    Else
    If strCh = strcExtentSeparator Then
    intErr = 7
    GoTo Exit9
    Else
    strAccum = strAccum & strCh
    GoTo InExtent6
    End If
    End If
    End If
    InExtent6:
    If lngI > Len(strFileName) Then GoTo Exit9
    strCh = Mid(strFileName, lngI, 1): lngI = lngI + 1
    If strCh = strcDriveSeparator Then
    intErr = 8
    GoTo Exit9
    Else
    If strCh = Application.PathSeparator Then
    If strPath <> "" Then
    strPath = strPath & Application.PathSeparator
    End If
    strPath = strPath & strAccum: strAccum = ""
    GoTo GotSlash4
    Else
    If strCh = strcExtentSeparator Then
    intErr = 9
    GoTo Exit9
    Else
    strAccum = strAccum & strCh
    GoTo InExtent6
    End If
    End If
    End If
    Exit9:
    If intErr > 0 Then
    strBreakFileString = ""
    Else
    ' At the end, if the last valid character processed was a slash, then we have no file
    If strCh = Application.PathSeparator Then
    strPath = strPath & strAccum
    Else
    strFile = strAccum
    If InStr(1, strFile, strcExtentSeparator) > 0 Then
    strExtent = Right(strFile, Len(strFile) - InStr(1, strFile, strcExtentSeparator))
    strFile = Left(strFile, InStr(1, strFile, strcExtentSeparator) - 1)
    Else
    strExtent = ""
    End If
    End If
    Select Case intType
    Case 0
    strBreakFileString = strDrive & strcDriveSeparator
    Case 1
    strBreakFileString = strPath
    Case 2
    strBreakFileString = strFile
    Case 3
    strBreakFileString = strExtent
    Case 4
    If strExtent = "" Then
    strBreakFileString = strFile
    Else
    strBreakFileString = strFile & strcExtentSeparator & strExtent
    End If
    Case 5
    If strDrive = "" Then
    strBreakFileString = strPath
    Else
    strBreakFileString = strDrive & strcDriveSeparator & Application.PathSeparator _
    & strPath & Application.PathSeparator
    End If
    Case Else
    strBreakFileString = ""
    End Select '
    End If
    'Sub TESTstrBreakFileString()
    'MsgBox strBreakFileString("d:my documentsall this.txt", intcDrive) ' "d:"
    'MsgBox strBreakFileString("d:my documentsall this.txt", intcPath) ' "my documents"
    'MsgBox strBreakFileString("d:my documentsall this.txt", intcName) ' "all this"
    'MsgBox strBreakFileString("d:my documentsall.txt", intcName)
    'MsgBox strBreakFileString("d:my documentsall this.txt", intcExtent) ' "txt"
    'End Sub
    End Function

    </pre>


  2. #2
    Plutonium Lounger
    Join Date
    Dec 2000
    Location
    Sacramento, California, USA
    Posts
    16,775
    Thanks
    0
    Thanked 1 Time in 1 Post

    Re: Code: Function strBreakFileString(strFileName As S

    Chris,

    Here's the method I use to extract the filename from a path. If the path is available on the machine, it uses the Dir() function. Otherwise it steps backward through the string until it hits a back slash. Sorry for all the comments, but I write my code so that a junior programmer can understand it and maintain it if necessary.

    <pre>Public Function GetFilenameFromPath( _
    ByVal strFullPath As String) As String
    'created by Charlotte Foust
    'modified 2/15/2001 - added test for "." in strFullPath
    'returns the filename from a path and filename
    Dim strFilename As String 'holds name of file
    Dim intLength As Integer 'holds the length of the string
    Dim intLoop As Integer 'controls stepping through _
    string

    'only continue if a value passed
    If strFullPath <> "" Then
    'return the filename if the path is valid
    strFilename = Dir(strFullPath)
    End If 'strFullPath <> ""

    'if the path is not valid, parse it out
    If strFilename = "" And _
    InStr(strFullPath, ".") <> 0 Then
    'if the path is not accessible
    'use the string to the right of
    'the last "" in the full path
    intLength = Len(strFullPath)
    For intLoop = intLength To 0 Step -1
    If Mid(strFullPath, intLoop, 1) = "" Then
    strFilename = Mid(strFullPath, intLoop + 1)
    End If 'Mid(strFullPath, intLoop, 1) = ""
    Next intLoop ' = intLength To 0 Step -1
    End If 'strFilename = "" And _
    InStr(strFullPath, ".") <> 0

    GetFilenameFromPath = strFilename
    End Function 'GetFilenameFromPath( _
    ByVal strFullPath As String) As String</pre>

    Charlotte

  3. #3
    Platinum Lounger
    Join Date
    Dec 2000
    Location
    Queanbeyan, New South Wales, Australia
    Posts
    3,730
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    Chris,

    OK, you're getting even with me. I complained about on bit of code being too short to wrap in a function, so you post a blockbuster!

    I did think this was a lot larger and more complex than it needed to be. I am particularly "unfond" of "GoTo".

    This code is not quite complete- it's a throwtogether, and was only tested by your sample calls, and not for all the arguments you have posted- the other 2 are not much more than what's been done.

    I've added a little bit of functionality for foward and backward slashes- they do get interchanged.

    I've attached the code, as it's the best way to preserve formatting, enable copy and pasting, and to preserve forum layout- so click on the Notepad icon to read the code.
    Attached Files Attached Files
    Subway Belconnen- home of the Signboard to make you smile. Get (almost) daily updates- follow SubwayBelconnen on Twitter.

  4. #4
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    > so you post a blockbuster!

    Actually, the joke(?) is that I'd posted this (it's the next required function in my bottom-to-top sequence) before I'd seen your post about too-short code!


    >. I am particularly "unfond" of "GoTo".

    Me too. I used to challenge my COBOL students to find a case where GOTO was necessary. I'm even unfond of the VBA "On Error". In strBreakFileString, the GOTOs result from the direct translation of the State Transition Table.

    > functionality for foward and backward slashes

    Thanks! I should include that in my code. That will represent an extra column in my State Transition Table, which cells will be identical to those for the backward slash. I could include a switch (compile-time? Arguiment to function) that allows/disallows forward slashes.


    > click on the Notepad icon

    I did and it worked. I have to experiment with this. I think that when I closed to text display, Netscape shut down; whatever I did, I had to re-open netscape and work my way back here.


    I think your code will fail if there is an syntax error in the string supplied. What happens if the user has inadvertently included an extra period that ought not be there? Will you detect that and flag it as an error?

  5. #5
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    Charloote, thanks for the reply.

    Your use of the DIR function is interesting. That makes sense if the file really is supposed to exist on the machine. If the file exists and the supplied string is valid, you've got a hit. What happens if the supplied string is valid, but the file has not yet been created? I ask because I'm often using a function like this one to examine strings in other people's documents. In such cases Charloote may send me a document which contains a file string describing a file on her machine, but the file is not on my machine.

    My comments to geoff apply too: what happens if the string ahs a real syntax error within it?

    I'm going to collect all three functions (plus any other candidates) and subject them to a file-off, or whatever it is called. It would be good to compare them for functionality.

  6. #6
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    >extract the filename from a path.

    (later) OK> Would you like to expand it to extract, say, the drive letter, or just the extent? (yeas, that's right! I just saw your post about criticism!!)


    > For intLoop = intLength To 0 Step -1

    I pasted your function into my template and used my 5 test calls to test it, after removing my integer switches. The line of code pasted above failed until I changed the lower limit from a zero to a one, thus:
    > For intLoop = intLength To 1 Step -1


    Also it seemed to return the path-and-filename. I have switches 4 and 5 that return multiple items. I could have switch 6 return path-and-name-and-extent. Can yours be forced to return, say, just the path?

  7. #7
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    The posts by Charlotte and Geoff got me thinking. I could add another option to my code to return last-item-of-path, which would be crudely translated as "local parent directory". Right now I have a different set of string-handlers to return the last item of a delimited string.

    I wrote my code (OK, modified Chris Cubley's code) so that I'd have just one function that could decompose a string and offer up any combination from it. I didn't want a strGetPath and a strGetDrive etc each with their own logic (although I *do* have such functions as cover functions for strBreakFileString).

    Geoff's comment about lack of tests is true. The few I have there are really for a newcomer to have something to step through the code, should they be so brave. The real testing went on eighteen months ago as a shakedown cruise through my Document Cleanser and Files Processor modules. That's when I ironed out the bugs.

    Nonetheless, for a function that plays such a major role in my applications, I ought to have better documented tests, if only to demonstrate its power at detecting errors (I hope) in file locations. (Another use for this sort of function is to wade through a file SUCH AS the system registry and locate strings that look like file names and check to see if they currently exist in the filestore ...)

    I want to continue posting procedures working towards the first useful VBA utility, so I'll plough on.

    In the meantime, if you have any improvements (or competitors) let's have 'em. I'm still quite prepared to arrange a shoot-out to compare the functionality of each submission.

    My main goal is always towards speed of development. How quickly can I drop a tested function into place and use it as a building block.

  8. #8
    Plutonium Lounger
    Join Date
    Dec 2000
    Location
    Sacramento, California, USA
    Posts
    16,775
    Thanks
    0
    Thanked 1 Time in 1 Post

    Re: Code: Function strBreakFileString(strFileName As S

    Chris,

    I admit that I didn't wade through your code to see exactly what it did before I posted mine. Mine works for me, so I don't know why it would return both the path and filename unless it's because of the way you tweaked it.

    I also have functions that return just the drive or just the filename. I don't really care to build one huge function to return alternate parts because I avoid writing huge, Swiss army knife functions. They're too hard to read and I don't see that they serve any particular purpose that isn't served just as well (and more clearly) by separate routines.
    Charlotte

  9. #9
    Plutonium Lounger
    Join Date
    Dec 2000
    Location
    Sacramento, California, USA
    Posts
    16,775
    Thanks
    0
    Thanked 1 Time in 1 Post

    Re: Code: Function strBreakFileString(strFileName As S

    What happens is that the Dir function returns an empty string, so the routine falls through to the portion that simply parses out the path the hard way without validating its existence.

    Well, actually the hard way would be starting at the first position and working to the end. Mine uses the not so hard way of starting at the end and working backward to the first backslash.
    Charlotte

  10. #10
    Super Moderator
    Join Date
    Dec 2000
    Location
    New York, NY
    Posts
    2,970
    Thanks
    3
    Thanked 29 Times in 27 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    <P ID="edit"><FONT SIZE=-1>Edited by Gary Frieder on 01/02/19 12:00.</FONT></P>Chris et al:

    I'm only just catching up on your Code: series of postings.
    Being only a recent graduate from "macro writer" to "developer", I don't have any useful insights to contribute, except:

    This discussion of parsing file paths gave me a sense of deja vu. I've just tracked down the source of this deja vu, which is the feature article, by Romke Soldaat, from the January 2001 edition of MS Office and VBA Developer.

    The article begins by describing using the string and path parsing functions that are available via the Shell Lightweight API, and then takes things much further by introducing a huge set of functions which he has built around these built-in functions.

    There are tables describing each of the functions, and the whole huge slug of code is appended to the article, and even better, available for free download.

    One thing I can observe is that the functions themselves appear to be very spare, just a few lines in most cases.
    If any part of this is applicable to your needs, perhaps it can save you some sweat?

    The article can be viewed <A target="_blank" HREF=http://www.officevba.com/features/2001/01/vba200101hk_f/vba200101hk_f.asp>here</A> - the link to the download can be gotten from there as well.

    As I said, I'm a newbie in this area of coding, so if the above stuff isn't relevant, c'est la vie - just thought it might be useful or of interest.

    Just thought I'd throw in the following notable quote from the above article:
    <hr>Most likely, your function library contains a number of homegrown routines that determine whether a file or folder exists, and that extract file and directory names from path strings. If you have Shlwapi, you can now dump those routines and use lightning fast API calls instead. <hr>
    Gary

  11. #11
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    > I avoid
    writing huge, Swiss army knife functions

    Good practice. In the case of the drive/path/name/extent analysys I made a break and decided that having all the code for the entire (incoming string) unit in one place meant I only had to step through one mass of code.

    I could still partition the biigy into smaller slave functions, but the real reason behind its size is the translation from the one-page State Transition Table.

  12. #12
    Platinum Lounger
    Join Date
    Dec 2000
    Location
    Queanbeyan, New South Wales, Australia
    Posts
    3,730
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    Chris,

    >I'm still quite prepared to arrange a shoot-out ...

    What for?

    It's hardly worth comparing a quick dashed-out and barely tested routine against one which has been in real use for some time.

    I was trying to achieve much of the functionality with a lot more simplicity. I suspect with more time, testing and effort, something workable, robust, and simple to maintain could be achieved. My point was to try to simplify and to make the same functionality much easier to understand.

    You're right that it didn't perform error checking. But hey, you didn't give me a spec, so it performed to specs!
    Subway Belconnen- home of the Signboard to make you smile. Get (almost) daily updates- follow SubwayBelconnen on Twitter.

  13. #13
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Code: Function strBreakFileString(strFileName As S

    >But hey, you didn't give me a spec, so it performed to specs!

    Specs? I wear 'em all the time now .......

    Anyway, the main purpose of my posting in VB/VBA is to get more feedback, and I'm very grateful for all the comments received. I'd not thought of incorporating my "LastNode" code into strBreakFileString. Forward-slashes, yet. Heck! I have the delimiters as compile-time constants; I could make them run-time and hold them in the INI so that the VB code will run on other platforms. Add in a circulation control system, acquisitions. Sell the damn thing to the Library Of Congress ......

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •