ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 19.09.2000

Diese Seite wurde zuletzt aktualisiert am 19.09.2000
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicAddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zur AVB-Web-Site, Kontakt und Impressum

Zurück...

Sortierte Maskerade

Zurück...

(-hg) mailto:hg_maskedfilesfolders@aboutvb.de

Alles oder nichts - das eigentlich recht praktische und bequeme MSDN Library - VB FileSystemObjectFileSystemObject aus der Microsoft Scripting Runtime kann nicht anders: Entweder liefert es Ihnen alle Dateien oder alle Unterordner eines Ordners, oder keine. Und das Ergebnis wird Ihnen dann auch noch völlig unsortiert geliefert (natürlich trifft das nur für das "Alles"-Ergebnis zu...).

Wie Sie immerhin recht einfach eine Sortierung erhalten können, indem Sie die File- oder Folder-Objekte in eine sortierte Collection einfügen, sehen Sie

in Sortierte Dateien und Ordner"Sortierte Dateien und Ordner". Da bleibt nun noch der Wunsch nach einer Filterung über eine Dateimaske (z.B. *.* oder *.TXT oder A*.EXE oder ABC??* usw.). Eine derartige Filterung kennen Sie sicher vom Betriebssystem (DOS) her. Auch die auf andere Weise wiederum unpraktische MSDN Library - VB DirDir-Funktion von Visual Basic erlaubt die Filterung über eine Dateimaske.

Fassen wir doch einmal beide Wünsche zusammen und erfüllen sie uns in einer diesen Komfort bietenden Klasse, jeweils eine eigene für Dateien (File-Objekte) und für Ordner (Folder-Objekte). Die beiden Klassen gleichen sich in Ihrer Funktionsweise und ihren Features. Die Dateien-Klasse (MaskedFiles) beruht auf der Files-Collection eines Folder-Objekts und enthält selbst nur File-Objekte. Die Ordner-Klasse beruht dagegen (MaskedFolders) auf der SubFolders-Collection eines Ordners und enthält dementsprechend nur Folder-Objekte. Die File- bzw. Folder-Objekte werden in der internen Collection mItems gehalten. In dieser Hinsicht verhält sich die Klasse wie eine einfache Collection. Sie können über die Standard-Eigenschaft Item unter Angabe eines Schlüssel oder eines Index ein Element auslesen, über die Eigenschaft Count die Anzahl der aktuell enthaltenen Elemente erhalten, und auch in einer MSDN Library - VB For...EachFor...Each-Schleife über die Funktion NewEnum die Elemente durchlaufen.

Private mItems As Collection

Public Property Get Count() As Long
  Count = mItems.Count
End Property

Public Property Get Item(KeyIndex As Variant) As File ' bzw. Folder
  On Error Resume Next
  Set Item = mItems(KeyIndex)
End Property

Public Function NewEnum() As IUnknown
  Set NewEnum = mItems.[_NewEnum]
End Function

Die interne Collection mItems wird im Class_Initialize-Ereignis erstmals instanziert und der Ordnung halber im Class-Terminate-Ereignis wieder zerstört.

Private Sub Class_Initialize()
  ' ...
  Set mItems = New Collection
End Sub

Private Sub Class_Terminate()
  Set mItems = Nothing
End Sub

Über die Eigenschaft Folder setzen Sie den Basis-Ordner, dessen Files- bzw. SubFolders-Collection als Quelle dienen soll.

Private pFolder As Folder 

Public Property Get Folder() As Folder
  Set Folder = pFolder
End Property

Public Property Set Folder(New_Folder As Folder)
  Set pFolder = New_Folder
  zReadItems
End Property

Nach der Zuweisung des neuen Folder-Objekts wird die Prozedur zReadItems aufgerufen, die die Files bzw. die SubFolders-Collection des neuen Folder-Objekts erneut auswertet und der Maske entsprechend die File- bzw. Folder-Objekte in die interne Collection mItems einliest. Auf die Prozedur zReadItems werde ich weiter unten noch näher eingehen.

Über die Eigenschaft Mask setzen Sie die Dateimaske. Deren Auswertung wird intern über den Visual Basic-Operator MSDN Library - VB LikeLike vorgenommen. Sie können daher die Filtermasken nach deren Muster übergeben und gewinnen somit sogar noch ein wenig mehr Komfort gegenüber den üblichen Dateimasken. Damit die vom Betriebssystem nicht unterschiedene Groß-/Kleinschreibung unberücksichtigt bleibt, wird für die Klasse übergeordnet

Option Compare Text 

gesetzt.

Private pMask As String 

Public Property Get Mask() As String
  Mask = pMask
End Property

Public Property Let Mask(New_Mask As String)
  If pMask <> New_Mask Then
    pMask = New_Mask
    zReadItems
  End If
End Property

Wenn sich die neue Maske von der alten unterscheidet, wird sie gesetzt. Dann wird auch hier die Prozedur zReadItems zum erneuten Einlesen der File- bzw. Folder-Objekte aufgerufen, um die interne Collection entsprechend der Maske zu aktualisieren.

Im Class_Initialize-Ereignis wird die Maske als Voreinstellung auf "*.*" gesetzt.

Private Sub Class_Initialize()
  pMask = "*.*"
  ' ...
End Sub

Neben der Dateimaske steht die Sortierung auf unserer Wunschliste. Der Sortier-Modus wird über die Eigenschaft SortMode gesetzt. Zulässig ist einer der Konstantwerte aus der Enumeration mfiSortModeConstant (in MaskedFiles) bzw. mfoSortModeConstant (in MaskedFolders).

Public Enum mfiSortModeConstants
  mfiUnsorted
  mfiSortByName
  mfiSortBySize
  mfiSortByDateCreated
  mfiSortByDateLastAccessed
  mfiSortByDateLastModified
End Enum

Private pSortMode As mfiSortModeConstants

Public Property Get SortMode() As mfiSortModeConstants
  SortMode = pSortMode
End Property

Public Property Let SortMode(New_SortMode As mfiSortModeConstants)
  Select Case New_SortMode
    Case mfiUnsorted To mfiSortByDateLastModified
      pSortMode = New_SortMode
      zRefreshItems
    Case Else
      Err.Raise 380
  End Select
End Property

Falls ein ungültiger Wert als SortMode übergeben wird, wird der abfangbare VB-eigene Laufzeitfehler 380 ausgelöst ("Ungültiger Eigenschaftswert"). Anderenfalls wird der neue Sortier-Modus übernommen, und wie bei den Eigenschaften Folder und Mask wird wieder über eine Prozedur der Inhalt der internen Collection aktualisiert. Hier wird jedoch die Prozedur zRefreshItems aufgerufen. Denn hier ist es ja nicht notwendig, die der Maske entsprechenden File- bzw. Folder-Objekte aus der Files- bzw. SubFolders-Collection des internen Folder-Objekts erneut auszulesen. Es ist lediglich notwendig, die in mItems enthaltenen Objekte umzusortieren. Auch auf die Prozedur zRefreshItems werde ich weiter unten noch näher eingehen.

Schließlich gibt es noch die Eigenschaft KeyMode. Über sie legen Sie fest, ob beim Einfügen der File- bzw. Folder-Objekte in die interne Collection mItems der Datei- bzw. Ordner-Name (Namne-Eigenschaft) oder der Pfad (Path-Eigenschaft) als Schlüssel verwendet werden soll. Standard ist die Verwendung des Namens als Schlüssel.

Public Enum mfiKeyModeConstants
  mfiKeyModeName
  mfiKeyModePath
End Enum

Private pKeyMode As mfiKeyModeConstants

Public Property Get KeyMode() As mfiKeyModeConstants
  KeyMode = pKeyMode
End Property

Public Property Let KeyMode(ByVal New_KeyMode As mfiKeyModeConstants)
  Select Case New_KeyMode
    Case pKeyMode
    Case mfiKeyModeName, mfiKeyModePath
      pKeyMode = New_KeyMode
      zRefreshItems
    Case Else
      Err.Raise 380
  End Select
End Property

Auch hier ist wieder nur eine Reorganisation der internen Collection mItems notwendig, so dass der Aufruf der Prozedur zRefreshItems ausreicht.

Da jedes Setzen der Eigenschaften Folder, Mask, SortMode und KeyMode ein Neueinlesen bzw. eine Reorganisation der internen Collection mItems nach sich zieht, bietet es sich zur Steigerung der Performance an, eine Methode zur Verfügung zu stellen, über die alles auf einmal gesetzt werden kann. Alle Parameter sind optional, so dass Sie beliebige Kombinationen neu setzen können.

Public Sub SetFolder(Optional Folder As Folder, _
 Optional Mask As String, _
 Optional ByVal SortMode As mfiSortModeConstants, _
 Optional ByVal KeyMode As mfiKeyModeConstants)

  If Not(Folder Is Nothing) Then
    Set pFolder = Folder
  End If
  If StrPtr(Mask) <> 0 Then
    pMask = Mask
  End If
  Me.SortMode = SortMode
  Select Case SortMode
    Case pSortMode
    Case mfiUnsorted To mfiSortByDateLastModified
      pSortMode = SortMode
    Case Else
      Err.Raise 380
  End Select
  Select Case KeyMode
    Case pKeyMode
    Case mfiKeyModeName, mfiKeyModePath
      pKeyMode = KeyMode
    Case Else
      Err.Raise 380
  End Select
  zReadItems
End Sub

Da allerdings sowohl eine Änderung der Maske als auch des Basis-Ordners ein komplettes Neueinlesen der File- bzw. Folder-Objekte in die interne Collection mItems erfordert, wird hier zum Abschluss wieder zReadItems aufgerufen. Ein Aufruf von SetFolder ohne Parameter kommt daher einem Aufruf der Methode Refresh gleich - in dieser wird daher auch lediglich zReadItems aufgerufen.

Public Sub Refresh()
  zReadItems
End Sub

Da die interne Sortierung auf den Funktionen des Moduls modCollAddSortedFileFolders.bas (siehe oben, aus Sortierte Dateien und Ordner"Sortierte Dateien und Ordner") beruht, kann zunächst immer nur in aufsteigender Reihung sortiert werden. Eine absteigende Sortierung erhalten Sie mit dem Aufruf der Methode Revert. In ihr wird lediglich die Reihenfolge der internen Collection mItems umgekehrt. Dabei werden aus dieser die Elemente von hinten her ausgelesen und in eine neue, frisch instanzierte Collection eingelesen. Danach wird die neue Collection der Variablen mItems zugewiesen und damit zur aktuellen Collection, während die alte automatisch freigegeben und aufgelöst wird.

Public Sub Revert()
  Dim nItem As File ' bzw. Folder
  Dim nItems As Collection
  Dim l As Long
  
  Set nItems = New Collection
  Select Case pKeyMode
    Case mfoKeyModeName
      With nItems
        For l = mItems.Count To 1 Step -1
          .Add mItems(l), mItems(l).Name
        Next 'l
      End With
    Case mfoKeyModePath
      With nItems
        For l = mItems.Count To 1 Step -1
          .Add mItems(l), mItems(l).Path
        Next 'l
      End With
  End Select
  Set mItems = nItems
End Sub

Betrachten wir nun die private Prozedur zReadItems. Sie liest die Files- bzw. SubFolders-Collection des Basis-Folder-Objekts aus und fügt die mit der Maske übereinstimmenden File- bzw Folder-Objekte entsprechend der Sortierung in die Collection mItems ein. Genauer gesagt wird zunächst die neu Collection nItems gefüllt, die erst zum Abschluss der Prozedur der Variablen mItems zugewiesen wird. Dieser Zwischenschritt ist notwendig, um den alten Inhalt von mItems erst einmal unberührt zu lassen, falls die Prozedur im Fehlerfall vorzeitig verlassen werden sollte.

Private Sub zReadItems()
  Dim nItem As Folder
  Dim nItems As Collection
  Dim nMask As String
  
  If Right$(pMask, 1) = "." Then
    nMask = Left$(pMask, Len(pMask) - 1)
  Else
    nMask = pMask
  End If
  Set nItems = New Collection
  If Not (pFolder Is Nothing) Then
    Select Case pSortMode
      Case mfoUnsorted
        With nItems
          Select Case pKeyMode
            Case mfoKeyModeName
              For Each nItem In pFolder.SubFolders
                If nItem.Name Like nMask Then
                  .Add nItem, nItem.Name
                End If
              Next
            Case mfoKeyModePath
              For Each nItem In pFolder.SubFolders
                If nItem.Name Like nMask Then
                  .Add nItem, nItem.Path
                End If
              Next
          End Select
        End With
      Case mfoSortByName
        For Each nItem In pFolder.SubFolders
          If nItem.Name Like nMask Then
            zAddFolderSorted nItems, nItem, pKeyMode
          End If
        Next
      Case mfoSortBySize
        For Each nItem In pFolder.SubFolders
          If nItem.Name Like nMask Then
            zAddFolderSortedBySize nItems, nItem, pKeyMode
          End If
        Next
      Case mfoSortByDateCreated
        For Each nItem In pFolder.SubFolders
          If nItem.Name Like nMask Then
            If zAddFolderSortedByDateCreated(nItems, nItem, pKeyMode) _
             Then
              Err.Raise mfoErrCannotSortByDateCreated, , _
               "mfoErrCannotSortByDateCreated"
              Exit Sub
            End If
          End If
        Next
      Case mfoSortByDateLastAccessed
        For Each nItem In pFolder.SubFolders
          If nItem.Name Like nMask Then
            If zAddFolderSortedByDateLastAccessed(nItems, nItem, _
             pKeyMode) Then
              Err.Raise mfoErrCannotSortByDateLastAccessed, , _
               "mfoErrCannotSortByDateLastAccessed"
              Exit Sub
            End If
          End If
        Next
      Case mfoSortByDateLastModified
        For Each nItem In pFolder.SubFolders
          If nItem.Name Like nMask Then
            zAddFolderSortedByDateLastModified nItems, nItem, _
             pKeyMode
          End If
        Next
    End Select
  End If
  Set mItems = nItems
End Sub

Die beiden Fehler-Ausstiege sind notwendig, da nicht alle File- bzw. Folder-Objekte anhand der DateCreated- und DateLastAccessed sortiert werden können. Bei im DOS-Modus erzeugten Dateien und Ordnern löst nämlich ein Zugriff auf diese Eigenschaften einen Fehler aus, da sie hier nicht verfügbar sind.

Die Prozedur zRefreshItems sieht ähnlich aus. Hier entfällt allerdings in jeder der Schleifen die Prüfung der Dateimaske, da RefreshItems nur aufgerufen wird, wenn die Dateimaske mit Sicherheit unverändert geblieben ist. Die interne Collection mItems enthalt somit bereits alle übereinstimmenden Elemente, die nur neu sortiert werden oder entsprechend der KeyMode-Einstellung mit dem gewünschten Schlüssel neu eingelesen werden. Auch hier erfolgt wieder der Zwischenschritt über die neu instanzierte Collection nFiles, die erst zum Abschluss der Prozedur der Variablen mItems zugewiesen und damit zur aktuellen Collection wird.

Private Sub zRefreshItems()
  Dim nItem As File
  Dim nItems As Collection
  
  Set nItems = New Collection
  Select Case pSortMode
    Case mfiUnsorted
      With nItems
        Select Case pKeyMode
          Case mfiKeyModeName
            For Each nItem In mItems
              .Add nItem, nItem.Name
            Next
          Case mfiKeyModePath
            For Each nItem In mItems
              .Add nItem, nItem.Path
            Next
        End Select
      End With
    Case mfiSortByName
      For Each nItem In mItems
        zAddFileSorted nItems, nItem, pKeyMode
      Next
    Case mfiSortBySize
      For Each nItem In mItems
        zAddFileSortedBySize nItems, nItem, pKeyMode
      Next
    Case mfiSortByDateCreated
      For Each nItem In mItems
        If zAddFileSortedByDateCreated(nItems, nItem, pKeyMode) _
         = -1 Then
          Err.Raise mfiErrCannotSortByDateCreated, , _
           "mfiErrCannotSortByDateCreated"
          Exit Sub
        End If
      Next
    Case mfiSortByDateLastAccessed
      For Each nItem In mItems
        If zAddFileSortedByDateLastAccessed(nItems, nItem, _
         pKeyMode) Then
          Err.Raise mfiErrCannotSortByDateLastAccessed, , _
           "mfiErrCannotSortByDateLastAccessed"
          Exit Sub
        End If
      Next
    Case mfiSortByDateLastModified
      For Each nItem In mItems
        zAddFileSortedByDateLastModified nItems, nItem, pKeyMode
      Next
  End Select
  Set mItems = nItems
End Sub

Die Funktionen zum sortierten Einfügen der File- bzw. Folder-Objekte in die mItems-Collection werden hier nicht dargestellt. Sie sind aber in den Klassen-Modulen als private Funktionen enthalten und stammen aus dem bereits erwähnten Modul Sortierte Dateien und OrdnermodCollAddSortedFileFolders.bas.

Im folgenden Beispiel sehen Sie, wie Sie alle Dateien mit der Datei-Erweiterung .EXE in umgekehrt nach dem Namen sortierter Reihenfolge erhalten und in eine ListBox einlesen können:

Private mFSO As New FileSystemObject
Private mMaskedFiles As MaskedFiles

Private Sub Command1_Click()
  Dim nFolder As Folder
  Dim nFile As File
  
  Set nFolder = mFSO.GetSpecialFolder(WindowsFolder)
  Set mMaskedFiles = New MaskedFiles
  On Error Resume Next
  mMaskedFiles.SetFolder nFolder, "*.EXE", mfiSortByName
  If Err.Number Then
    MsgBox Err.Description, vbCritical, Err.Number
  Else
    mMaskedFiles.Revert
    With List1
      .Clear
      For Each nFile In mMaskedFiles
        .AddItem nFile.Name
      Next
    End With
  End If
End Sub


Klassen MaskedFiles und MaskedFolders (maskedfilesfolders.zip - ca. 5 KB)



Komponenten-Übersicht

Schnellsuche



Zum Seitenanfang

Copyright © 1999 - 2023 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...