Hallo an alle,
ich habe ein - möglicherweise - unlösbares Problem mit dem scripting.dictionary., ja hab ich, werde aber nicht wirklich schlau daraus.
Aufgabenstellung:
Ich lese einen ganzen Verzeichnisbaum ein, durchwandere diesen (anhand vom scripting.dictionary) top down, drucke verschiedene Dateitypen aus (xls,doc,pdf,jpg - alle andere werden übergangen). Jedesmal wenn das Verzeichnis wechselt wird ein Zwischenblatt (aus einem anderem Druckerschacht mit andersfarbigem Papier) mit dem Verzeichnisnamen (letzter Verzeichnisnamenteil des Pfades) in groß drauf, ausgedruckt.
Ein Statusfenster sowie eine Logdatei werden mitgeführt.
Ich verwende das um sehr große Dokumentationen (> 30.000 Seiten) über Nacht auszudrucken (deshalb auch die Log-Funktion ..).
Funktioniert auch soweit ... ABER: die Reihenfolge stimmt nicht ganz.
Ich bekomme:
C:\1AA\2bb,
C:\1AA\2bb\3ab,
C:\1AA\2bb\3ab\verweis auf andere stelle in der doku.pdf, 4 kB
C:\1AA\2bb\3ab\verweis auf externe doku.pdf, 5 kB
C:\1AA\2bb\3bb, 5 kB
C:\1AA\2bb\3bb\4bb, 5 kB
C:\1AA\2bb\3bb\4bb\5ab, 5 kB
C:\1AA\2bb\3bb\4bb\5ab\verweis auf externe doku.pdf, 5 kB
C:\1AA\2bb\3bb\4bb\5bb, 5 kB
C:\1AA\2bb\3bb\4bb\5bb\verweis auf andere stelle in der doku.pdf, 4 kB
C:\1AA\2bb\3bb\verweis auf andere stelle in der doku.pdf, 4 kB
c:\1AA\2bb\3bb\verweis auf externe doku.pdf, 5 kB
C:\1AA\2bb\verweis auf externe doku.pdf, 5 kB
möchte aber:
C:\1AA\2bb,
C:\1AA\2bb\verweis auf externe doku.pdf, 5 kB
C:\1AA\2bb\3ab,
C:\1AA\2bb\3ab\verweis auf andere stelle in der doku.pdf, 4 kB
C:\1AA\2bb\3ab\verweis auf externe doku.pdf, 5 kB
C:\1AA\2bb\3bb, 5 kB
C:\1AA\2bb\3bb\verweis auf externe doku.pdf, 5 kB
C:\1AA\2bb\3bb\verweis auf andere stelle in der doku.pdf, 4 kB
C:\1AA\2bb\3bb\4bb, 5 kB
C:\1AA\2bb\3bb\4bb\5ab, 5 kB
C:\1AA\2bb\3bb\4bb\5ab\verweis auf externe doku.pdf, 5 kB
C:\1AA\2bb\3bb\4bb\5bb, 5 kB
C:\1AA\2bb\3bb\4bb\5bb\verweis auf andere stelle in der doku.pdf, 4 kB
hier habe ich den entscheidenden Schnipsel der das Einlesen - scripting.dictionary - erledigt:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Change2CUI=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
;
; sort keys in dictionary
; https://stackoverflow.com/questions/35505931/sort-keys-in-dictionary
;
#include-once
#include <FileConstants.au3>
#include <Array.au3>
Global $sFileSelectFolder = FileSelectFolder("Verzeichnis auswählen", "c:\")
; damit bekommen alle Pfade (ohne Dateien) hinten einen \ dazu - damit weiß ich das das ein Directory ==> Verzeichniszwischenblatt, ist
$sFileSelectFolder = $sFileSelectFolder & "\"
Local $oFiles = _FileListToDict($sFileSelectFolder, True, -3, False, 100, 0)
ConsoleWrite(@CRLF & @CRLF)
ConsoleWrite(@extended & " Dateien" & @CRLF)
If Not @error Then
For $vFiles In $oFiles.Keys
ConsoleWrite($vFiles & ", " & $oFiles($vFiles) & @CRLF)
Next
EndIf
MsgBox(0x0, "", 'Items Count : ' & $oFiles.count)
;===============================================================================
;
; Function Name: _FileListToDict($vFolder[, $bRec[, $iFileInformation[, $bRelative[, $iMaxDepth[, $iFilesAndOrFolders]]]]])
; Description: Speichert Dateien, optional mit einer gewählten Eigenschaft, in einerm Dictionary-Objekt.
; Parameter(s): $vFolder = Ein Startverzeichnis oder ein eindimensionales Array von Startverzeichnissen für die Dateisuche.
; $bRec = Rekursive Dateisuche bei $bRec = True (Standardwert)
; $iFileInformation = In $oFiles.Items kann eine gewählte Datei-Information gespeichert werden.
; |-1 = Keine Information. $oFiles.Items = True. (Standardwert).
; | 0 = Bearbeitungszeitpunkt
; | 1 = Erstellzeitpunkt
; | 2 = Letzte Zugriffszeit
; |-2 = Dateigröße in bytes
; |-3 = Dateigröße in größter erreichter Einheit.
; $bRelative = $oFiles.Keys haben relativem Dateipfad bei $bRelative = True (Standardwert = False).
; $iMaxDepth = Anzahl der ausgelesenen Unterverzeichnisse unterhalb der/des Startverzeichniss(es) (Standardwert = 100).
; $iFilesAndOrFolders = $oFiles.Keys haben relativem Dateipfad bei $bRelative = True (Standardwert = False).
; |0 = Dateien und Ordner
; |1 = Nur Dateien
; |2 = Nur Ordner
; Return Value(s): Zurückgegeben wird ein Objekt mit den kompletten oder relativen Dateipfaden als Key (abhängig von $bRelative)
; und in Abhängigkeit von $iFileInformation mit True oder Datei-Information als Item.
;
; @error kann folgende Werte annehmen (Kombinationen möglich, BitOr):
; 0 = kein Fehler aufgetreten, alle Dateien wurden korrekt kopiert
; 1 = Der übergebene Pfad ist kein existierendes Verzeichnis
; 2 = Startverzeichnis-Array ist nicht eindimensional
; Author(s): autoiter
; Modified:
; Remarks:
;=============================================================================== beides
Func _FileListToDict($vFolder, $bRec = True, $iFileInformation = -1, $bRelative = False, $iMaxDepth = 100, $iFilesOrFolders = 0)
If $iFileInformation <> -1 Then
Switch $iFileInformation
Case 0
$iFileInformation = $FT_MODIFIED
Case 1
$iFileInformation = $FT_CREATED
Case 2
$iFileInformation = $FT_ACCESSED
Case -2, -3 ; FileGetSize
Case Else
$iFileInformation = -1
EndSwitch
EndIf
If $bRec Then
If $iMaxDepth < 1 Or Int($iMaxDepth) = 0 Then $iMaxDepth = 1
EndIf
If IsArray($vFolder) Then
If UBound($vFolder, 2) > 1 Then Return SetError(2)
Local $iMaxIndex = UBound($vFolder)
Local $aFolder[$iMaxIndex], $iCount = 0
For $i = 0 To $iMaxIndex - 1
If Not StringInStr(FileGetAttrib($vFolder[$i]), "D") Then ContinueLoop
$aFolder[$iCount] = $vFolder[$i]
$iCount += 1
Next
If $iCount = 0 Then Return SetError(1)
$iMaxIndex = $iCount
ReDim $aFolder[$iMaxIndex]
Else
Local $iMaxIndex = 1
Local $aFolder[$iMaxIndex]
If Not StringInStr(FileGetAttrib($vFolder), "D") Then Return SetError(1)
$aFolder[0] = $vFolder
EndIf
Local $oFiles = ObjCreate("Scripting.Dictionary")
Local $aSearchFile[256], $sFile, $iDepth, $iInfo, $sFolder, $sStartFolder
For $i = 0 To $iMaxIndex - 1
$iDepth = 1
$sFolder = StringRegExpReplace($aFolder[$i], "\\$", "")
$sStartFolder = $sFolder ; Startfolder wird zur Bildung des vollen Dateipfades gespeichert.
$aSearchFile[$iDepth] = FileFindFirstFile($sFolder & "\*.*")
While $iDepth >= 0 ; In dieser Schleife werden alle Dateien/Ordner abgehandelt
$sFile = FileFindNextFile($aSearchFile[$iDepth])
If @extended And $bRec And $iDepth < $iMaxDepth Then ; Wenn es sich um ein Ordner handelt wird in diesem weiter gesucht - solange max. Rekursionstiefe nicht erreicht.
$iDepth += 1
$sFolder &= "\" & $sFile
If $iFilesOrFolders <> 1 Then $oFiles($sFolder) = $iInfo
$aSearchFile[$iDepth] = FileFindFirstFile($sFolder & "\*.*")
ElseIf @error Then ; Wenn keine Dateien mehr im Ordner vorhanden sind wird das "Handle" Freigegeben
FileClose($aSearchFile[$iDepth])
$iDepth -= 1
$sFolder = StringRegExpReplace($sFolder, "\\[^\\]*$", "")
Else
If $iFilesOrFolders <> 0 Then
If $iFilesOrFolders = 1 And StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then ContinueLoop
If $iFilesOrFolders = 2 And Not StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then ContinueLoop
EndIf
If $iFileInformation <> -1 Then
$iInfo = ""
Switch $iFileInformation
Case 0, 1, 2
$iInfo = FileGetTime($sFolder & "\" & $sFile, $iFileInformation, $FT_STRING)
Case -2
If Not StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then $iInfo = FileGetSize($sFolder & "\" & $sFile)
Case -3
If Not StringInStr(FileGetAttrib($sFolder & "\" & $sFile), "D") Then $iInfo = __FileListToDict_ByteSuffix(FileGetSize($sFolder & "\" & $sFile))
EndSwitch
If @error Then ContinueLoop
If Not $bRelative Then
$oFiles($sFolder & "\" & $sFile) = $iInfo
Else
$oFiles(StringReplace($sFolder, $sStartFolder, "") & "\" & $sFile) = $iInfo
EndIf
Else
If Not $bRelative Then
$oFiles($sFolder & "\" & $sFile) = True
Else
$oFiles(StringReplace($sFolder, $sStartFolder, "") & "\" & $sFile) = True
EndIf
EndIf
EndIf
WEnd
Next
Return SetError(0, $oFiles.Count, $oFiles)
EndFunc ;==>_FileListToDict
Func __FileListToDict_ByteSuffix($iBytes) ; Aus der Hilfe zu FileGetSize.
Local $iIndex = 0, $aArray = [' bytes', ' kB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB']
While $iBytes > 1023
$iIndex += 1
$iBytes /= 1024
WEnd
Return Round($iBytes) & $aArray[$iIndex]
EndFunc ;==>__FileListToDict_ByteSuffix
Alles anzeigen
Ist das mit dem Objekt scripting.dictionary überhaupt möglich (ohne Umwege über dictionary -> array und wieder zurück zu nehmen)?
Mit _filetoarrayrec würde es funktionieren (getestet ) aber da verliere ich ein paar Möglichkeiten und müßte vor allem das ganze Programm ändern. Natürlich ist mir die Sortierung erst aufgefallen als alles fertig war
.
Ich bin schon für Hinweise - geht/geht nicht - dankbar.
Grüße
GML