| | | Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte | | | | PNY WIRD VON NVIDIA ZUM HÄNDLER DES JAHRES GEWÄHLT, eine Pressemitteilung
|
Autor
|
Thema: FINDFILE in vba (3039 mal gelesen)
|
tappenbeck Mitglied Vermessungsingenieur
Beiträge: 1217 Registriert: 30.05.2002 AutoCAD (Map)2024, Topobase, MapEdit, Lisp, .vb.net
|
erstellt am: 12. Jul. 2006 16:04 <-- editieren / zitieren --> Unities abgeben:
|
Carsten1210 Mitglied staatl. geprüfter Holztechniker
Beiträge: 1358 Registriert: 24.07.2002
|
erstellt am: 12. Jul. 2006 16:28 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Jan, Hier mal eine Nachgebaute FindFile-Funktion: Function AcadFindFile(fname As String) As String Dim envpath As Variant, i As Integer, FSO As FileSystemObject, srchfname As String envpath = Split(Application.ActiveDocument.GetVariable("Acadprefix"), ";") Set FSO = New FileSystemObject For i = LBound(envpath) To UBound(envpath) srchfname = FSO.BuildPath(envpath(i), fname) If FSO.FileExists(srchfname) Then AcadFindFile = srchfname Exit For End If Next End Function Sub test() MsgBox AcadFindFile("acad.cui") End Sub Gruß, Carsten Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
tappenbeck Mitglied Vermessungsingenieur
Beiträge: 1217 Registriert: 30.05.2002 AutoCAD (Map)2024, Topobase, MapEdit, Lisp, .vb.net
|
erstellt am: 13. Jul. 2006 09:24 <-- editieren / zitieren --> Unities abgeben:
|
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 21. Jul. 2006 13:00 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
|
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 21. Jul. 2006 13:18 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
|
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 21. Jul. 2006 13:26 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Aber nochmal ne Frage: Warum ist die VBA-Hilfefunktion im Bereich FileSystemObject so schlecht? Bei allen Stichwörtern, die ich dazu suche (z.B. jetzt wieder: BuildPath), kommt erstmal "Schlüsselwort nicht gefunden", ebenso andere Anweisungen wie readline, writeline u.ä. Letztlich findet man dann doch irgendwas, aber erst wird man in der Hilfe immer abgewimmelt. Brauche ich vielleicht andere / zusätzliche Hilfe-Dateien? MfG wwwilli Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Carsten1210 Mitglied staatl. geprüfter Holztechniker
Beiträge: 1358 Registriert: 24.07.2002
|
erstellt am: 21. Jul. 2006 17:05 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Willi, Du musst unter Extras/VErweise den Verweis auf die Microsoft Scripting Runtime setzen, dann funktioniert es. Nun zur zweiten Frage mit der Hilfe: Gehe mal in die VBA-IDE und drücke dort F1. Jetzt öffnet sich die Visual Basic Referenz. Hier kannst du unter FilesystemObject alles zum Thema finden. Gruß, Carsten Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 24. Jul. 2006 11:49 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Carsten, danke. 1) Mit den Verweisen würde aber heißen, jeder andere, der das nicht auch angehakt hat, kann das Makro nicht ausführen, oder? 2) Wie gehe ich denn bitte in die VBA-IDE bzw. was ist das? MfG, wwwilli Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 24. Jul. 2006 12:09 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Nochmal was zum Thema, ich habe für meine Zwecke eine vergleichsweise einfache rekursive Dateisuche mit FileSystemObject zusammengekupfert und auseinandergebosselt: Private Sub findMyFiles(myPath As String, myFileSpec As String _ , myArray() As String, nF As Integer, nD As Integer) 'Durchsucht alle Verzeichnisse unter myPath nach myFileSpec. 'myPath=Pfad ohne \, myFileSpec=gesuchtes Dateimuster, auch mit ?* 'myArray=Zielliste, nF=Fileanzahl-1, vorher -1 setzen, 'nD=durchsuchte Verzeichnisse, vorher 0 setzen. Dim myFolder, myFolderLoop, FSO Dim myFilNam As String On Error GoTo fehlerende Set FSO = CreateObject("Scripting.FileSystemObject") Set myFolder = FSO.GetFolder(myPath) myFilNam = Dir$(FSO.BuildPath(myFolder.Path, myFileSpec), _ vbNormal Or vbHidden Or vbSystem Or vbReadOnly) Do While Len(myFilNam) > 0 nF = nF + 1 If nF >= 1000 Then Exit Sub myArray(nF) = FSO.BuildPath(myFolder.Path, myFilNam) myFilNam = Dir$() Loop nD = nD + 1 If myFolder.SubFolders.Count > 0 Then For Each myFolderLoop In myFolder.SubFolders If nF < 1000 Then findMyFiles myFolderLoop.Path, myFileSpec, myArray, nF, nD Next myFolderLoop End If fehlerende: End Sub Aufruf der Sub bei mir etwa mit Dim myArray(1000) As String, nF As Integer, nD As Integer nF = -1 nD = 0 Call findMyFiles("C:\TEMP", "*.TMP", myArray, nF, nD) If nf > -1 Then MsgBox str(nF+1) + " Files in" + str(nD) + " Folders." '...
(Die Grenze habe ich auf 1000 gesetzt, könnte man dynamisch machen, war mir aber zu kompliziert, weil ich in diesem Fall nur wenige Dateinamen erwarte und weiter bearbeiten kann.) Nun meine ich aber, dass die Suche auf diese Weise bei vielen vorhandene Unterverzeichnissen ziemlich lange dauert. Hatte hier nicht mal jemand geforscht, wie so etwas mit FSO und mit API und sonstwie lang dauert? Ich finde das nicht mehr. Jemand eine Idee? MfG, wwwilli
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Carsten1210 Mitglied staatl. geprüfter Holztechniker
Beiträge: 1358 Registriert: 24.07.2002
|
erstellt am: 24. Jul. 2006 12:10 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Willi, Der Verweis wird im Projekt gespeichert, daher kann jeder das Makro ausführen (So lange die Datei auf dem Rechner vorhanden ist. Die VBA-IDE ist die Programmierumgebung von Visual Basic for Applications (Also das, worin du deinen Code schreibst). Du sartest diese ja auch über Alt+F11 oder per Befehl "vbaide". Gruß, Carsten Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 24. Jul. 2006 12:25 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Carsten, 1) danke für den Hinweis zum Verweis. 2) Also ICH gehe immer mit Extras / Makro / VisualBasic-Editor dahin. Was ich derzeit mache, läuft unter 5 verschiedenen Anwendungen, da sind die Shortcuts nicht immer gleich, und "vbaide" tippe ich hier zum ersten Mal. Aber eben in dem, was man anscheinend VBA-IDE nennt, kommt bei allem, was ich mit F1 zum FileSystemObject wissen will, immer erstmal "Schlüsselwort wurde nicht gefunden". Auch werden keine Großbuchstaben in die Anweisungen eingefügt. fs.deletefile bleibt beispielsweise so klein wie von mir eingetippt. Wird aber anscheinend doch richtig ausgeführt. Ist das bei Euch anders? MfG, wwwilli Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Carsten1210 Mitglied staatl. geprüfter Holztechniker
Beiträge: 1358 Registriert: 24.07.2002
|
erstellt am: 24. Jul. 2006 12:54 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Willi, Sobald du den Verweis in deinem Projekt gesetzt hast und in den Option "Elemente auflisten" angehakt hast wirst du bei der Eingabe des Codes schon das FileSystemObject angeboten bekommen. In der VisualBasic Hilfe solltest du mal unter Index Filesystemobjesct eingeben. Da wirst du es finden. Gruß, Carsten Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 24. Jul. 2006 13:54 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo, ich möchte nochmals meine obige Frage zur Dateisuche wiederholen: ...Nun meine ich aber, dass die Suche auf diese Weise bei vielen vorhandenen Unterverzeichnissen ziemlich lange dauert. Hatte hier nicht mal jemand geforscht, wie lang so etwas mit FSO und mit API und sonstwie dauert? Ich finde das nicht mehr. Jemand eine Idee? MfG wwwilli Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Carsten1210 Mitglied staatl. geprüfter Holztechniker
Beiträge: 1358 Registriert: 24.07.2002
|
erstellt am: 24. Jul. 2006 15:00 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Willi, Eine schnellere Lösung findest du hier. Die musst du dir nur anpassen. Das müsste eigentlich die schnellste Möglichkeit sein ddie Verzeichnisse zu durchsuchen. Kannst ja mal einen Vergleich machen und das Ergebnis hier posten. Gruß, Carsten Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Stelli1 Moderator Verm.-Ing.
Beiträge: 1526 Registriert: 17.08.2005 Map 2000-2014, Rasterdesign, MapGuide, Autodesk Topobase, VS6, VS.net 2013
|
erstellt am: 24. Jul. 2006 16:50 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo wwwilli, mach dir doch eine Quick&Dirty Funktion rein. mit "dir /s /b regit.bat > mydir.txt" als Shell werden alle Dateien (im Beispiel regit.bat) aus allen Unterverzeichnissen in die Datei mydir.txt geschrieben. Die liest du ein und fertig. Stelli ------------------ Warum lisp'eln wenn's auch anders geht. www.ib-stelberg.de Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 25. Jul. 2006 12:12 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Ja, Stelli, das hatte ich auch schon selbst mal. Trotzdem danke. Ich glaube, da gab es dann ein Umlautproblem, wenn die Herren und Damen Kollegen meinen, "äöüß" und anderes in Dateinamen verwenden zu müssen. Außerdem hatte ich Gefummel, festzustellen, wann DOS (oder wer auch immer) mit dem DIR fertig ist und ich in VBA die Datei (z.B. mydir.txt) aufmachen kann. Das geht alles schon irgendwie, aber ich wollte es eben jetzt Quick & Clean mit VBA machen. Man kriegt ja Ansprüche, mit der Zeit. Ist es denn amtlich, dass der Umweg über Shell tatsächlich schneller ist? Würde ich nicht denken... MfG wwwilli Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 25. Jul. 2006 12:23 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Carsten, es ist zum Verzweifeln. Eigentlich sucht man eine Anweisung, die etwa myArray = DirRec(path, filespec) heißen sollte. Und man kriegt einen 200-zeiligen Code mit Anweisungen, die man nie gehört hat und nie verstehen wird. Ich danke trotzdem herzlich und werde mich damit in den nächsten Wochen beschäftigen. MfG wwwilli Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
wwwilli Mitglied Ingenieur
Beiträge: 410 Registriert: 21.03.2006 ACAD MAP 3D 2012. VestraCAD. Win 7 64bit SP 1, FD 100 GB, Xeon 2,8 GHz, 12 GB.
|
erstellt am: 25. Jul. 2006 12:52 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Also, mit Shell und dir/b/s geht die Suche Quick&Dirty BEI VIELEN UNTERVERZEICHNISSEN tatsächlich mindestens doppelt so schnell als FSO. Allerdings ist die FSO-Variante bei sehr wenigen Unterverzeichnissen sofort da, während meine Shell-Variante ein bis zwei Sekunden braucht, um fertig zu werden. Bei der Shell-Variante kriege ich die Anzahl der durchsuchten Unterverzeichnisse nicht ermittelt. Das ist bei mir jetzt verzichtbar. Aber das Umlautproblem bleibt. Alles, was in ASCII und ANSI unterschiedlich ist, kommt falsch. Ich öffne die Datei,(z.B. mydir.txt) mit Set fsFile = fs.OpenTextFile(txtFile, 1, False, 0) Ist das richtig? Oder kann ich an den Umlauten etwas ändern mit anderen Parametern? MfG wwwilli
[Diese Nachricht wurde von wwwilli am 25. Jul. 2006 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
Carsten1210 Mitglied staatl. geprüfter Holztechniker
Beiträge: 1358 Registriert: 24.07.2002
|
erstellt am: 25. Jul. 2006 13:52 <-- editieren / zitieren --> Unities abgeben: Nur für tappenbeck
Hallo Willi, Hier noch mal die Version aus dem Link von oben: Option Explicit Private Declare Function FindFirstFile Lib "kernel32" _ Alias "FindFirstFileA" (ByVal lpFileName As String, _ lpFindFileData As WIN32_FIND_DATA) As Long Private Declare Function FindNextFile Lib "kernel32" _ Alias "FindNextFileA" (ByVal hFindFile As Long, _ lpFindFileData As WIN32_FIND_DATA) As Long Private Declare Function FindClose Lib "kernel32" (ByVal _ hFindFile As Long) As Long Private Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Const MAX_PATH As Long = 259& Private Type WIN32_FIND_DATA dwFileAttributes As Long ftCreationTime As FILETIME ftLastAccessTime As FILETIME ftLastWriteTime As FILETIME nFileSizeHigh As Long nFileSizeLow As Long dwReserved0 As Long dwReserved1 As Long cFileName As String * MAX_PATH cAlternate As String * 14 End Type Const FILE_ATTRIBUTE_DIRECTORY As Long = &H10& Public Function GetAllFiles(ByVal Root As String, _ ByVal Such As String, ByRef Field() As String, _ Optional DoRecursion As Boolean = False, _ Optional UsedField As Long = 0) As Long Dim File As String Dim hFile As Long Dim FD As WIN32_FIND_DATA ' Evtl. Array vergrößern? If (UsedField = UBound(Field)) Then ReDim Preserve Field(UBound(Field) + 100) End If DoEvents 'Backslash ergänzen If Right(Root, 1) <> "\" Then Root = Root & "\" ' Die erste Datei suchen hFile = FindFirstFile(Root & "*.*", FD) ' Es konnte nichts gefunden werden If hFile = 0 Then GetAllFiles = 0 Exit Function End If ' Für jede Datei Do ' Den Dateinamen extrahieren File = Left(FD.cFileName, InStr(FD.cFileName, Chr(0)) - 1) ' Ist die Datei ein Verzeichnis? If (FD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) _ = FILE_ATTRIBUTE_DIRECTORY Then ' . und .. ignorieren If (File <> ".") And (File <> "..") Then ' Unterordner auch durchsuchen? If DoRecursion Then ' Unterordner rekursiv erfassen GetAllFiles = GetAllFiles + GetAllFiles(Root & File, _ Such, Field, DoRecursion, UsedField) Else ' Ergebnis speichern ' Verzeichnis: ">>" kann entfernt werden, ' da nur zur Visualisierung Field(UsedField) = ">>" & Root & File GetAllFiles = GetAllFiles + 1 UsedField = UsedField + 1 ' Evtl. Array vergrößern If (UsedField = UBound(Field)) = 0 Then ReDim Preserve Field(0 To UBound(Field) + 100) End If End If End If Else ' Passt das Suchmuster? If (Such Like Right$(UCase$(File), Len(Such))) Or Such = _ "*" Then ' Ergebnis speichern ' Datei: " " kann entfernt werden, ' da nur zur Visualisierung Field(UsedField) = " " & Root & File GetAllFiles = GetAllFiles + 1 UsedField = UsedField + 1 ' Evtl. Array vergrößern If (UsedField = UBound(Field)) Then ReDim Preserve Field(0 To UBound(Field) + 100) End If End If End If ' Nächste Datei suchen Loop While FindNextFile(hFile, FD) ' Suchhandle wieder freigeben - Suche beenden Call FindClose(hFile) End Function Private Sub test() Dim Files() As String Dim i As Long Dim Such As String Dim DatCnt As Integer, DirCnt As Integer Dim Max As Long Dim ergebnis As String ' Ein Einfaches Suchmuster erstellen Such = Trim$(UCase$(".tmp")) If Left$(Such, 1) = "*" Then Such = Right$(Such, Len(Such) - _ InStr(Such, ".")) ReDim Files(0 To 0) Max = GetAllFiles(LCase("c:\"), Such, Files, True) ' Die Ergebnisse auflisten
For i = 0 To Max - 1 ergebnis = ergebnis & Files(i) & vbCr 'List1.AddItem Files(i) 'Alternativ Lisbox befüllen. If Left$(Files(i), 2) = ">>" Then DirCnt = DirCnt + 1 Else DatCnt = DatCnt + 1 End If Next i End Sub Hier funktioniert es auch mit den Umlauten. Kannst ja noch einen Geschwindigkeitsvergleich machen. Gruß, Carsten Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
| Anzeige.:
Anzeige: (Infos zum Werbeplatz >>)
|