PDA

Vollständige Version anzeigen : Wie kann man einen Dateipfad zerlegen?


Stefan Kulpa
11.01.2003, 13:08
Oft steht man vor dem Problem, einen kompletten Dateipfad vorliegen zu haben, aus dem man allerdings nur einen Teil benötigt. Generell setzt sich ein Dateipfad aus vier Teilen zusammen:

1. Laufwerksbuchstabe
2. Verzeichnispfad
3. Dateiname
4. Dateierweiterung

Um nun diesen Pfad in seine Einzelteile zerlegen zu können, kann man auf verschiedene Art und Weise vorgeben:

Lösung 1: Nutzung des Windows Scripting Host
Um den Windows Scripting Host benutzen zu können, muss man entweder einen Verweis auf die entsprechende DLL-Datei (SCRRUN.DLL im System-Verzeichnis) setzen, oder aber mit LateBinding (sprich: CreateObject) arbeiten.

<div><link href="http://www.ms-office-forum.de/ubb/codeconv.css" rel="stylesheet"><pre><span class="TOKEN">Sub</span> SplitPath(<span class="TOKEN">ByVal</span> sSourcePath <span class="TOKEN">As</span> String, <span class="TOKEN">ByRef</span> sDrive <span class="TOKEN">As</span> String, _
<span class="TOKEN">ByRef</span> sPath <span class="TOKEN">As</span> String, <span class="TOKEN">ByRef</span> sFilename <span class="TOKEN">As</span> String, _
<span class="TOKEN">ByRef</span> sExtension <span class="TOKEN">As</span> <span class="TOKEN">String</span>)
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Die Variablen sDrive, sPath, sFilename und sExtension m&uuml;ssen ByRef</span>
<span class="REM">'// &uuml;bergeben werden (was standardm&auml;&szlig;ig der Fall ist, und hier nur</span>
<span class="REM">'// exemplarisch dargestellt ist), damit diese als R&uuml;ckgabewerte fungieren</span>
<span class="REM">'// k&ouml;nnen. ByVal &uuml;bergibt eine Kopie und ist somit nicht f&uuml;r die R&uuml;ckgabe</span>
<span class="REM">'// geeignet.</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Variante 1 MIT Verweis auf die Microsoft Scripting Runtime.</span>
<span class="REM">'// Hier ist ein Verweis auf die SCRRUN.DLL im System-Verzeichnis notwendig.</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="TOKEN">Dim</span> objFso <span class="TOKEN">As</span> <span class="TOKEN">New</span> FileSystemObject
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// ODER Variante 2 OHNE Verweis auf Microsoft Scripting Runtime</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="TOKEN">Dim</span> objFso <span class="TOKEN">As</span> Object
<span class="TOKEN">Set</span> objFso = CreateObject(&quot;Scripting.FileSystemObject&quot;)
<span class="REM">'// ------------------------------------------------------------------------</span>
sDrive = objFso.GetDriveName(sSourcePath)
sPath = objFso.GetParentFolderName(sSourcePath)
sFilename = objFso.GetBaseName(sSourcePath)
sExtension = objFso.GetExtensionName(sSourcePath)
&nbsp;
<span class="TOKEN">End</span> <span class="TOKEN">Sub</span>
&nbsp;
<span class="TOKEN">Sub</span> Beispiel()
&nbsp;
<span class="TOKEN">Dim</span> sDrive <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sPath <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sFilename <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sExtension <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sSourcePath <span class="TOKEN">As</span> <span class="TOKEN">String</span>
&nbsp;
sSourcePath = &quot;C:\Programme\Microsoft Office\Office10\WINWORD.EXE&quot;
<span class="TOKEN">Call</span> SplitPath(sSourcePath, sDrive, sPath, sFilename, sExtension)
<span class="REM">'// Ausgabe ----------------------------------------------------------------</span>
<span class="TOKEN">Debug.Print</span> &quot;Originalpfad: &quot;; sSourcePath
<span class="TOKEN">Debug.Print</span> &quot;Laufwerk: &quot;; sDrive
<span class="TOKEN">Debug.Print</span> &quot;Pfad: &quot;; sPath
<span class="TOKEN">Debug.Print</span> &quot;Dateiname: &quot;; sFilename
<span class="TOKEN">Debug.Print</span> &quot;Dateierweiterung: &quot;; sExtension
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Originalpfad: C:\Programme\Microsoft Office\Office10\WINWORD.EXE</span>
<span class="REM">'// Laufwerk: C:</span>
<span class="REM">'// Pfad: C:\Programme\Microsoft Office\Office10</span>
<span class="REM">'// Dateiname: WINWORD</span>
<span class="REM">'// Dateierweiterung: EXE</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="TOKEN">End</span> <span class="TOKEN">Sub</span></pre></div>
Code eingefügt mit dem MOF Code Converter (http://www.ms-office-forum.net/forum/codeconverter.php)

Hinweis: man muss sich für eine Variante entscheiden und den entsprechenden Teil im Beispiel deaktivieren oder löschen.

Lösung 2: String-Manipulation mit VBA-Hausmitteln

Unter Berücksichtigung von VBA-Version < 6 wird auf die neue Funktion InStrRev() aus VBA 6.0 in folgendem Beispiel verzichtet:

<div><link href="http://www.ms-office-forum.de/ubb/codeconv.css" rel="stylesheet"><pre><span class="TOKEN">Sub</span> SplitPath(<span class="TOKEN">ByVal</span> sSourcePath <span class="TOKEN">As</span> String, <span class="TOKEN">ByRef</span> sDrive <span class="TOKEN">As</span> String, _
<span class="TOKEN">ByRef</span> sPath <span class="TOKEN">As</span> String, <span class="TOKEN">ByRef</span> sFilename <span class="TOKEN">As</span> String, _
<span class="TOKEN">ByRef</span> sExtension <span class="TOKEN">As</span> <span class="TOKEN">String</span>)
&nbsp;
<span class="TOKEN">Dim</span> iOffset <span class="TOKEN">As</span> <span class="TOKEN">Integer</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Zun&auml;chst den ersten Backslash suchen</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
iOffset = InStr(sSourcePath, &quot;\&quot;)
<span class="TOKEN">If</span> iOffset = 0 <span class="TOKEN">Then</span> <span class="TOKEN">Exit Sub</span> <span class="REM">'da ung&uuml;ltiger Dateipfad</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Laufwerksbuchstaben ohne Backslash merken</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
sDrive = Left(sSourcePath, iOffset - 1)
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Jetzt den Ordner ermitteln</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
sPath = Mid(sSourcePath, iOffset + 1)
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// In String f&uuml;r den Ordner befindet sich jetzt noch der Dateiname,</span>
<span class="REM">'// also den String bis zum letzten Backslash r&uuml;ckw&auml;rts durchsuchen</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="TOKEN">For</span> iOffset = Len(sPath) <span class="TOKEN">To</span> 1 <span class="TOKEN">Step</span> -1
<span class="TOKEN">If</span> Mid(sPath, iOffset, 1) = &quot;\&quot; <span class="TOKEN">Then</span>
<span class="REM"> '// Letzten Backslash gefunden</span>
sFilename = Mid(sPath, iOffset + 1)
sPath = Left(sPath, iOffset - 1)
<span class="TOKEN">Exit For</span>
<span class="TOKEN">End</span> <span class="TOKEN">If</span>
<span class="TOKEN">Next</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Dateiendung ermitteln; da es mehrere Punkte in einem Dateinamen</span>
<span class="REM">'// geben darf, z&auml;hlt hier nur der letzte.</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="TOKEN">If</span> Len(sFilename) &gt; 0 <span class="TOKEN">Then</span>
<span class="TOKEN">For</span> iOffset = Len(sFilename) <span class="TOKEN">To</span> 1 <span class="TOKEN">Step</span> -1
<span class="TOKEN">If</span> Mid(sFilename, iOffset, 1) = &quot;.&quot; <span class="TOKEN">Then</span>
<span class="REM"> '// Letzten Punkt gefunden</span>
sExtension = Mid(sFilename, iOffset + 1)
sFilename = Left(sFilename, iOffset - 1)
<span class="TOKEN">Exit For</span>
<span class="TOKEN">End</span> <span class="TOKEN">If</span>
<span class="TOKEN">Next</span>
<span class="TOKEN">End</span> <span class="TOKEN">If</span>
&nbsp;
<span class="TOKEN">End</span> <span class="TOKEN">Sub</span>
&nbsp;
<span class="TOKEN">Sub</span> Beispiel()
&nbsp;
<span class="TOKEN">Dim</span> sDrive <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sPath <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sFilename <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sExtension <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sSourcePath <span class="TOKEN">As</span> <span class="TOKEN">String</span>
&nbsp;
sSourcePath = &quot;C:\Programme\Microsoft Office\Office10\WINWORD.EXE&quot;
<span class="TOKEN">Call</span> SplitPath(sSourcePath, sDrive, sPath, sFilename, sExtension)
<span class="REM">'// Ausgabe ----------------------------------------------------------------</span>
<span class="TOKEN">Debug.Print</span> &quot;Originalpfad: &quot;; sSourcePath
<span class="TOKEN">Debug.Print</span> &quot;Laufwerk: &quot;; sDrive
<span class="TOKEN">Debug.Print</span> &quot;Pfad: &quot;; sPath
<span class="TOKEN">Debug.Print</span> &quot;Dateiname: &quot;; sFilename
<span class="TOKEN">Debug.Print</span> &quot;Dateierweiterung: &quot;; sExtension
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Originalpfad: C:\Programme\Microsoft Office\Office10\WINWORD.EXE</span>
<span class="REM">'// Laufwerk: C:</span>
<span class="REM">'// Pfad: Programme\Microsoft Office\Office10</span>
<span class="REM">'// Dateiname: WINWORD</span>
<span class="REM">'// Dateierweiterung: EXE</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="TOKEN">End</span> <span class="TOKEN">Sub</span></pre></div>
Code eingefügt mit dem MOF Code Converter (http://www.ms-office-forum.net/forum/codeconverter.php)

Lösung 3: API

Die hier vorgestellte API Lösung setzt voraus, dass auf dem System die Datei Shlwapi.dll in der Version 4.71 oder höher vorliegt. Dies in dann der Fall, wenn der Internet Explorer 4.0 oder höher installiert ist. Wie man nachfolgend sehen kann, ist der API-Weg deutlich aufwendiger:

<div><link href="http://www.ms-office-forum.de/ubb/codeconv.css" rel="stylesheet"><pre><span class="TOKEN">Declare</span> <span class="TOKEN">Function</span> PathFindExtension <span class="TOKEN">Lib</span> &quot;shlwapi&quot; <span class="TOKEN">Alias</span> _
&quot;PathFindExtensionA&quot; _
(<span class="TOKEN">ByVal</span> pPath <span class="TOKEN">As</span> <span class="TOKEN">String</span>) <span class="TOKEN">As</span> <span class="TOKEN">Long</span>
&nbsp;
<span class="TOKEN">Declare</span> <span class="TOKEN">Function</span> PathFindFileName <span class="TOKEN">Lib</span> &quot;shlwapi&quot; <span class="TOKEN">Alias</span> _
&quot;PathFindFileNameA&quot; _
(<span class="TOKEN">ByVal</span> pPath <span class="TOKEN">As</span> <span class="TOKEN">String</span>) <span class="TOKEN">As</span> <span class="TOKEN">Long</span>
&nbsp;
<span class="TOKEN">Declare</span> <span class="TOKEN">Function</span> PathFindNextComponent <span class="TOKEN">Lib</span> &quot;shlwapi&quot; <span class="TOKEN">Alias</span> _
&quot;PathFindNextComponentA&quot; _
(<span class="TOKEN">ByVal</span> pPath <span class="TOKEN">As</span> <span class="TOKEN">String</span>) <span class="TOKEN">As</span> <span class="TOKEN">Long</span>
&nbsp;
<span class="TOKEN">Declare</span> <span class="TOKEN">Function</span> PathStripToRoot <span class="TOKEN">Lib</span> &quot;shlwapi&quot; <span class="TOKEN">Alias</span> _
&quot;PathStripToRootA&quot; _
(<span class="TOKEN">ByVal</span> pPath <span class="TOKEN">As</span> <span class="TOKEN">String</span>) <span class="TOKEN">As</span> <span class="TOKEN">Long</span>
&nbsp;
<span class="TOKEN">Declare</span> <span class="TOKEN">Function</span> lstrcpyA <span class="TOKEN">Lib</span> &quot;kernel32&quot; _
(<span class="TOKEN">ByVal</span> RetVal <span class="TOKEN">As</span> String, _
<span class="TOKEN">ByVal</span> Ptr <span class="TOKEN">As</span> <span class="TOKEN">Long</span>) <span class="TOKEN">As</span> <span class="TOKEN">Long</span>
&nbsp;
<span class="TOKEN">Declare</span> <span class="TOKEN">Function</span> lstrlenA <span class="TOKEN">Lib</span> &quot;kernel32&quot; _
(<span class="TOKEN">ByVal</span> Ptr <span class="TOKEN">As</span> Any) <span class="TOKEN">As</span> <span class="TOKEN">Long</span>
&nbsp;
<span class="TOKEN">Sub</span> SplitPath(<span class="TOKEN">ByVal</span> sSourcePath <span class="TOKEN">As</span> String, <span class="TOKEN">ByRef</span> sDrive <span class="TOKEN">As</span> String, _
<span class="TOKEN">ByRef</span> sPath <span class="TOKEN">As</span> String, <span class="TOKEN">ByRef</span> sFilename <span class="TOKEN">As</span> String, _
<span class="TOKEN">ByRef</span> sExtension <span class="TOKEN">As</span> <span class="TOKEN">String</span>)
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Laufwerk extrahieren</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
sDrive = sSourcePath
<span class="TOKEN">Call</span> PathStripToRoot(sDrive): sDrive = TrimNull(sDrive)
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Dateiname extrahieren</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
sFilename = GetStrFromPtrA(PathFindFileName(sSourcePath))
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Dateiendung extrahieren</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
sExtension = GetStrFromPtrA(PathFindExtension(sSourcePath))
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Verzeichnis ermitteln</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
sPath = sSourcePath
sPath = GetStrFromPtrA(PathFindNextComponent(sPath))
sPath = Left(sPath, Len(sPath) - (Len(sFilename) + 1))
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Dateiname ohne Extension ermitteln</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
sFilename = Left(sFilename, Len(sFilename) - Len(sExtension))
&nbsp;
<span class="TOKEN">End</span> <span class="TOKEN">Sub</span>
&nbsp;
<span class="TOKEN">Private Function</span> TrimNull(sItem <span class="TOKEN">As</span> <span class="TOKEN">String</span>)
&nbsp;
<span class="REM">'// Sucht das erste Chr(0)-Zeichen im String und gibt den</span>
<span class="REM">'// String bis zu dieser Position zur&uuml;ck.</span>
<span class="REM">'// Kommt kein Chr(0)-Zeichen vor, wird der ganze String zur&uuml;ckgegeben.</span>
<span class="TOKEN">Dim</span> iPos <span class="TOKEN">As</span> <span class="TOKEN">Integer</span>
iPos = InStr(sItem, Chr$(0))
<span class="TOKEN">If</span> iPos <span class="TOKEN">Then</span>
TrimNull = Left$(sItem, iPos - 1)
Else: TrimNull = sItem
<span class="TOKEN">End</span> <span class="TOKEN">If</span>
&nbsp;
<span class="TOKEN">End</span> <span class="TOKEN">Function</span>
&nbsp;
<span class="TOKEN">Function</span> GetStrFromPtrA(<span class="TOKEN">ByVal</span> lpszA <span class="TOKEN">As</span> <span class="TOKEN">Long</span>) <span class="TOKEN">As</span> <span class="TOKEN">String</span>
&nbsp;
<span class="REM">'// Anhand der Speicheradresse einer Variablen wird</span>
<span class="REM">'// deren Wert ausgelesen und als String zur&uuml;ckgegeben</span>
GetStrFromPtrA = String$(lstrlenA(<span class="TOKEN">ByVal</span> lpszA), 0)
<span class="TOKEN">Call</span> lstrcpyA(<span class="TOKEN">ByVal</span> GetStrFromPtrA, <span class="TOKEN">ByVal</span> lpszA)
&nbsp;
<span class="TOKEN">End</span> <span class="TOKEN">Function</span>
&nbsp;
<span class="TOKEN">Sub</span> Beispiel()
&nbsp;
<span class="TOKEN">Dim</span> sDrive <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sPath <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sFilename <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sExtension <span class="TOKEN">As</span> <span class="TOKEN">String</span>
<span class="TOKEN">Dim</span> sSourcePath <span class="TOKEN">As</span> <span class="TOKEN">String</span>
&nbsp;
sSourcePath = &quot;C:\Programme\Microsoft Office\Office10\WINWORD.EXE&quot;
<span class="TOKEN">Call</span> SplitPath(sSourcePath, sDrive, sPath, sFilename, sExtension)
<span class="REM">'// Ausgabe ----------------------------------------------------------------</span>
<span class="TOKEN">Debug.Print</span> &quot;Originalpfad: &quot;; sSourcePath
<span class="TOKEN">Debug.Print</span> &quot;Laufwerk: &quot;; sDrive
<span class="TOKEN">Debug.Print</span> &quot;Pfad: &quot;; sPath
<span class="TOKEN">Debug.Print</span> &quot;Dateiname: &quot;; sFilename
<span class="TOKEN">Debug.Print</span> &quot;Dateierweiterung: &quot;; sExtension
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="REM">'// Originalpfad: C:\Programme\Microsoft Office\Office10\WINWORD.EXE</span>
<span class="REM">'// Laufwerk: C:\</span>
<span class="REM">'// Pfad: Programme\Microsoft Office\Office10</span>
<span class="REM">'// Dateiname: WINWORD</span>
<span class="REM">'// Dateierweiterung: .EXE</span>
<span class="REM">'// ------------------------------------------------------------------------</span>
<span class="TOKEN">End</span> <span class="TOKEN">Sub</span></pre></div>
Code eingefügt mit dem MOF Code Converter (http://www.ms-office-forum.net/forum/codeconverter.php)

tomsic
20.07.2008, 11:07
Wenn wir die Pfadangabe in einer Variable haben, brauchen wir nicht mehr nach dem "Backslash" zu suchen. Einfach die Länge des Pfadangabennamens + 1 Offset herausschneiden, oder? ;)



sFilename = Mid(sPath, Len(sSourcePath) + 1)

filunski
31.07.2013, 09:42
Hallo @all
In einer seit ca. 10 Jahren aufgebauten "selbstgestrickten" Briefmarken-Datenbank geht es um tausende von Briefmarken-Bildern, die in einem filigranen Ordnersystem auf der FP verteilt sind.
Alles funktionierte Einwandfrei bis vor Jahr und Tag nach einem Wechsel von MS Update Version 2007 auf 2010 irgendwann die Anlagefelder integriert worden sind.
Jetzt habe ich zwei Probleme.
1. Man sieht wesentliche Teile des Bildpfades nicht mehr. Klicke ich in meinem DB auf das Anlage-Feld, sehe ich nur den Dateinamen und nicht mehr den dazugehörenden Pfad. Früher konnte ich mit der "Suchen und Ersetzen" Funktion den Bildpfad anpassen, wenn ich Ordner auf der FP verschoben oder im Namen geändert habe.
2. Die alte Aufruf-Prozedur für ein neues Bild funktioniert nicht mehr. Es funktioniert nur die neue Anlagefeld - Prozedur von Access2010.
http://www.briefmarken-museum.de/access2010/2013_DB-Problem_Bildpfad.jpg
Zur Veranschaulichung habe ich einen Screenshot gemacht, in der zwei Briefmarken abgebildet sind, die größe Marke links hat den alten Bildpfad zur Basis, der ist als Textfeld sichtbar. Die Master-ID = MID ist Teil des Bildnamens.
Die "alte Einlesprozedur" wurde durch einen MS-Update außer Kraft gesetzt und ich war gezwungen die neue Prozedur zu benutzen (kleine Briefmarke) rechts.
Wem kommt das Problem mit den beiden inkopatiblen Prozeduren bekannt vor und hat eventuell eine Lösung, wie man/ich die jetzt doppelten Detaipfade in zwei Feldern angesiedelt wieder verschmelzen kann....

momal
03.09.2014, 09:20
Angenehm finde ich es, in diesem Fall den Haken bei "Automatische Syntaxüberprüfung" zu entfernen. Access markiert dann weiterhin fehlerhafte Programmsyntax, allerdings ohne jedesmal ein separates Fehlerfenster zu öffnen.