Jump to content

Recommended Posts

Posted

Hi all!

This should be an easy one for all of you programmers out there...

I have a directory of .pdf files, each with a name and a series number, i.e.:

file_01.pdf

file_02.pdf

text_01.pdf

text_02.pdf

text_03.pdf

document_01.pdf

document_02.pdf

I'm trying to build an array of each set of files, i.e.:

array1 = file_01.pdf, file_02.pdf

array2 = text_01.pdf, text_02.pdf, text_03.pdf

array3 = document_01.pdf, document_02.pdf

The code I've written works until I reach the last file in the directory. I'm running into a problem with the line...

$comp2=StringSplit($bdOFL[$y+1],"_")

...it breaks when $y + 1 goes greater than the number of files in the the directory.

Here's the code:

#include <file.au3>
#include <string.au3>
#include <array.au3>

HotKeySet("^!x", "MyExit"); hotkey to exit = CTRL+ALT+X

$bdSD = "C:\Practice Folder\"

$bdOFL = _FileListToArray($bdSD,"*.pdf"); build an array of files in the source directory
$x=$bdOFL[0]; number of files in source directory
$y = 1; current position counter

While $y < $x+1
    Dim $bdFL[100]; unlikely to group more than 100 files
    $z=1; number of files in current grouping
    Do 
        $bdFL[$z-1]=$bdOFL[$y]      
        $comp1=StringSplit($bdOFL[$y],"_"); loads filename up to the underscore
        $comp2=StringSplit($bdOFL[$y+1],"_"); loads filename up to the underscore
        $z=$z+1
        $y=$y+1
    Until $comp1[1]<>$comp2[1]; are the filenames up to the underscore different?
    ReDim $bdFL[$z-1]
    _ArrayDisplay($bdFL,"$bdFL"); debug code
WEnd

Func MyExit()
    Exit 
EndFunc

Any suggestions? Thanks in advance!

Brian

Posted

Why not just use better wildcard patterns and get them straight to the arrays?

#include <file.au3>
#include <array.au3>

Global $bdSD = "C:\Practice Folder\"

$avFileList = _FileListToArray($bdSD, "file_*.pdf")
$avTextList = _FileListToArray($bdSD, "text_*.pdf")
$avDocList = _FileListToArray($bdSD, "document_*.pdf")
$TotalFiles = $avFileList[0] + $avTextList[0] + $avDocList[0]

If MsgBox(64 + 4, "Results", "There are a total of " & $TotalFiles & " selected .pdf files." & @CRLF & _
        "file_*.pdf files:  " & $avFileList[0] & @CRLF & _
        "text_*.pdf files:  " & $avTextList[0] & @CRLF & _
        "document_*.pdf files:  " & $avDocList[0] & @CRLF & _
        "Do you want to see them listed?") = 6 Then
    _ArrayDisplay($avFileList, "file_*.pdf files")
    _ArrayDisplay($avTextList, "text_*.pdf files")
    _ArrayDisplay($avDocList, "document_*.pdf files")
EndIf

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Posted

Well...perhaps I was too generic with my problem statement. The working directory has lots of different files with different names. They all take the format of name datestamp_##.pdf, but I don't think setting up standing wildcards is what I want to do. Here's a list of actual files in the working directory:

ATT 20070405_1.PDF

ATT 20070405_2.PDF

ATT 20070405_3.PDF

Chase MC 20070412_1.PDF

Chase MC 20070412_2.PDF

Dish Network 20070511_1.PDF

Dish Network 20070511_2.PDF

GECU 20070331_1.PDF

GECU 20070331_2.PDF

GPFCU 20070331_1.PDF

GPFCU 20070331_2.PDF

Here's the Menu_1.PDF

Here's the Menu_2.PDF

Here's the Menu_3.PDF

Here's the Menu_4.PDF

Here's the Menu_5.PDF

JCAD Notice of Appraised Value 20070423_1.PDF

JCAD Notice of Appraised Value 20070423_2.PDF

LPM 20070508_1.PDF

LPM 20070508_2.PDF

OSB 20070405_1.PDF

OSB 20070405_2.PDF

OSB 20070405_3.PDF

OSB 20070405_4.PDF

OSB 20070505_1.PDF

OSB 20070505_2.PDF

OSB 20070505_3.PDF

OSB 20070505_4.PDF

Save the Earth While Saving Some Money_1.PDF

Save the Earth While Saving Some Money_2.PDF

Save the Earth While Saving Some Money_3.PDF

Save the Earth While Saving Some Money_4.PDF

Trailer Title_1.PDF

Trailer Title_2.PDF

Trailer Title_3.PDF

This is a partial list. The purpose of my original script is to form arrays, which will be used to make delimited strings, which will be fed to a program to combine each group of .pdfs into a single .pdf. So, once I process these files, I will eventually re-fill the directory with new files (with different file names).

Sorry for the confusion.

Brian

Posted

I threw this together for you, it only matches filenames if the datestamps AND the title match, just run it in the folder with all of your files

#include <Array.au3>

; Shows the filenames of all files in the current directory.
$search = FileFindFirstFile("*.PDF")

Dim $ARRAY[1]
$last = ""
Dim $X = 0

; Check if the search was successful
If $search = -1 Then
    MsgBox(0, "Error", "No files/directories matched the search pattern")
    Exit
EndIf

;Loop until error
While 1
    $file = FileFindNextFile($search) 
    If @error Then ExitLoop
    
    ;Return portion of file name before underscore
    $splitfilename = StringSplit ( $file, "_" )
    
    ;If beginning of filename matches beginning of last filename
    If $splitfilename[1] = $last Then 
        
        ;Concat current filename to last array element with comma
        $ARRAY[Ubound($ARRAY) - 1] &= "," & $file
    
    ;If no match, create a new array element
    Else        
        ;Manually assign first element, due to ARRAYADD skipping element zero
        If $X = 0 Then
            $ARRAY[$X] = $file
        Else
            _ArrayAdd( $ARRAY, $file)
        EndIf
        $X += 1
    EndIf
    
    ;Update last file name
    $last = $splitfilename[1]
WEnd

;Display array
_ArrayDisplay ( $ARRAY, "ARRAY CONTENTS")

; Close the search handle
FileClose($search)
Posted

Thanks weaponx!

I tried your code. Slight modification, and viola! While it doesn't do what I was originally attempting (separate array for each set of files), I can use it's output quite easily.

Thanks again.

Brian

Posted

Well...perhaps I was too generic with my problem statement. The working directory has lots of different files with different names. They all take the format of name datestamp_##.pdf, but I don't think setting up standing wildcards is what I want to do. Here's a list of actual files in the working directory:

This is a partial list. The purpose of my original script is to form arrays, which will be used to make delimited strings, which will be fed to a program to combine each group of .pdfs into a single .pdf. So, once I process these files, I will eventually re-fill the directory with new files (with different file names).

Sorry for the confusion.

Brian

I saved your list to Test_1.txt and ran this on it:

#include <file.au3>

$hFile = FileOpen("Test_1.txt", 0)
While 1
    $Line = FileReadLine($hFile)
    If @error Then ExitLoop
    _FileCreate("C:\Temp\" & $Line)
WEndoÝ÷ Ù*«ÞÊ«{¶X¬¶ßW¬p´÷dÞh¦V²Â+aN¬~éܶ*'+Þ³*.jX¬¶è­ë§«~)^©®-²Ú-ë§uêìrÞªê-ªê-jëh×6#include <file.au3>
#include <array.au3>

$TargetDir = "C:\Temp"
$avNameList = _ListPDFs($TargetDir)
_ArrayDisplay($avNameList, "List of PDF name roots")

Func _ListPDFs($sDir)
    Local $avFiles = _FileListToArray($sDir, "*.pdf", 1)
    _ArraySort($avFiles, 0, 1) ; Sort ascending from [1]
    Local $n
    For $n = 1 To $avFiles[0]
        $avFiles[$n] = StringLeft($avFiles[$n], StringInStr($avFiles[$n], "_"))
    Next
    For $n = $avFiles[0] To 1 Step - 1
        If $avFiles[$n] = "" Or $avFiles[$n] = $avFiles[$n - 1] Then _ArrayDelete($avFiles, $n)
    Next
    $avFiles[0] = UBound($avFiles) - 1
    Return $avFiles
EndFunc   ;==>_ListPDFs

Hope that helps.

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Posted

Glad I could help. Also there is no way to create arrays dynamically, at runtime, so you have to have an array with each element being a CSV string.

Posted

Also there is no way to create arrays dynamically, at runtime, so you have to have an array with each element being a CSV string.

Well, not that it's applicable to this topic, but that's actually one of the few useful things I can imagine about arrays in arrays. You can use _ArrayAdd() to add elements to a single array, and each of those elements can contain a copy of a dynamic array from something like _FileReadToArray() or IniReadSection(). You can iterate through the parent array, copying out each element to a working array.

There are, of course, speed and resource penalties for doing it that way... but it can be done. This demo reads the contents of all .txt files in a directory to an array, then saves the arrays in an array. After a prompt, it reads each array out of the parent array and displays them:

#include <array.au3>
#include <file.au3>

Global $avFiles[1] = [0]

_TxtArrayAddDir(@DocumentsCommonDir)

If MsgBox(32 + 4, "Question", "Do you want to see the contents of all " & $avFiles[0] & " .txt files?") = 6 Then
    _TxtArrayDisplay()
EndIf

; Add FileReadToArray arrays of .txt files to the $avFiles array
Func _TxtArrayAddDir($sDir)
    Local $FileName, $avFileList, $avWorking
    For $FileName In _FileListToArray($sDir, "*.txt", 1)
        If IsNumber($FileName) Then
            $avFiles[0] = $avFiles[0] + $FileName ; Save count
            ContinueLoop
        EndIf
        _FileReadToArray($sDir & "\" & $FileName, $avWorking)
        $avWorking[0] = $sDir & "\" & $FileName
        _ArrayAdd($avFiles, $avWorking)
    Next
EndFunc   ;==>_TxtArrayAddDir

; List contents of each array in the $avFiles array
Func _TxtArrayDisplay()
    Local $avWorking, $FileName
    For $avWorking In $avFiles
        If Not IsArray($avWorking) Then ContinueLoop
        $FileName = $avWorking[0]
        $avWorking[0] = UBound($avWorking) - 1
        _ArrayDisplay($avWorking, $FileName)
    Next
EndFunc   ;==>_TxtArrayDisplay

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Posted

PsaltyDS - one of my next steps was to build a filename for each group of consolidated files - obviously I'd use the left part of the filename up to the underscore. I was going to play around with this, but you've basically solved that for me - thanks!

Posted

Actually, I have another question for PsaltyDS and Zedna - I noticed that both of you use or suggest _ArraySort(). It seems that _FileListToArray() will build a sorted array (I assume because windows lists files alphabetically). Is there a reason to add _ArraySort(), or a time when you can't depend on _FileListToArray() to build a sorted array?

Brian

Posted

Actually, I have another question for PsaltyDS and Zedna - I noticed that both of you use or suggest _ArraySort(). It seems that _FileListToArray() will build a sorted array (I assume because windows lists files alphabetically). Is there a reason to add _ArraySort(), or a time when you can't depend on _FileListToArray() to build a sorted array?

Never, never, never trust a Microsoft product to do something consistent and logical like always listing the files in order...

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Posted

Never, never, never trust a Microsoft product to do something consistent and logical like always listing the files in order...

:)

Touche - I'll update my code appropriately.

Thanks again for your help.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...