1. Working with ZIP files

  1. Working with ZIP files
    1. Some Use cases
    2. Working with EXCEL .xlsx files from FileMaker

Since version 1.7.0.20 - the ACF-plugin has now extended its filesystem functions to also work with files inside ZIP archives. Two new functions have been added:

The open-zip opens the zip archive and returns a short prefix string to be in front of file paths inside the archive. The prefix string is in the form: ZIP<0>: where the zero can be any number or digits. this string is returned from open_zip and should never be tampered with.

All the other file-system functions now work on this new prefix system. If you open a file with this prefix in the path, it will open it in the archive.

Ensure that you use the close_zip function, especially after you have done some modifications to the archive. Otherwise, the archive or the files you added/modified might get corrupted.

The following file-system functions work with both zip paths and regular OS paths.

The markdown functions are not sensitive for zip paths, but the result can be put in a zip file with copy_file afterward.

Note: The filesystem inside ZIP archives has some different properties from the OS filesystem. The files are not organized in folders in the same way. It is just a list of files complete, with directory separators / - like the full path is part of the filename. There are no directory entries in the zip archive. Therefore, functions like directory_exists loop through the file list to find any matches. list_files function uses the path in the argument to filter the list like every file is listed that starts with the path given.

Note: copy_file and move_file  can copy files and folders. If copying to or from the zip archive and the OS filesystem, the path in the zip archive is defined as a folder when it ends with a slash / If the destination is a folder, the files copied will be given the name of the source name.

Examples:

The example below, using the following FileMaker script triggered by a button:

Script_function

function test_zip_archive (string archive, string filename, string content)
    int x, y, z; 
    string path, xcontent; 
    
    // Open the ZIP archive
    string zip = open_zip ( archive ); 
    
    // Check if we got a prefix 
    if ( left (zip, 3) == "ZIP") then
    
    // open two files in the arcive
        x = open ( zip + filename, "w") ; 
        y = open ( zip + "ZipDirectory/Mytestfile6.txt", "w"); 
        
        // Write some content to them .
        write (x, content); 
        write (y, "content into file6"); 
        write (x, "\nSome more content in line two..."); 
        write (y, "\nSome more content in line two into file6"); 
        
        // close the files.
        close (x); 
        close (y);
        
        // Ask for a third file to include in it. 
         path = select_file ( "Select a file to include"); 
         
        // If the user did not hit cancel, but selected a file: 
        if ( path != "") then 
            z = open ( path, "r"); // Regular OS file
            xcontent = read (z); 
            path = Get_FilenameFromPath(path); 
            close (z); 
            
            // Write the content to a file in the archive, 
            z = open ( zip + "ZipDirectory/"+path, "w"); 
            write (z, xcontent); 
            close (z);
        end if
        
        close_zip(zip); 
    else
        alert ( zip ); 
    end if
    return "OK"; 
end

Here is the ZIP file, and unpacked directory to show the files we made.

Zip-functions

1.1. Some Use cases

1.2. Working with EXCEL .xlsx files from FileMaker

As mentioned above, EXCEL spreadsheet files in the .xlsx format are zip archives. This means that we can use the zip functionality described here to open those files directly and work with the content.

if we use the list_files function on such an EXCEL file, like this ACF code:

string path = "~/Desktop/MyExcelFile.xlsx"; 
string zip = open_zip ( path ); 
print list_files(zip); 
close_zip (zip); 

This results in the following list:

[Content_Types].xml
_rels/.rels
xl/_rels/workbook.xml.rels
xl/workbook.xml
xl/sharedStrings.xml
xl/styles.xml
xl/worksheets/sheet1.xml
xl/theme/theme1.xml
docProps/app.xml
docProps/core.xml
xl/calcChain.xml

Now, By looking at the spreadsheet, there are some numbers we want to extract from this sheet.

After a little digging - the file xl/worksheets/sheet1.xml contains what we are looking for. The data is in a structure like this (a little simplified):

<worksheet>
    ...
    <sheetData>
    ...
        <row>
            <c><v>some value</v></c>
            <c><v>some value</v></c>
            <c><v>some value</v></c>
            <c><v>some value</v></c>
        </row>
        <row>
            <c><v>some value</v></c>
            <c><v>some value</v></c>
            <c><v>some value</v></c>
            <c><v>some value</v></c>
        </row>
        ...
        etc

We want Row 5 to Row 9, Column 5

Then the following snippet does exactly that:

string path = "~/Desktop/MyExcelFile.xlsx"; 
int x, i; 
string content; 
XML sheet1;

// Open EXCEL file
string zip = open_zip ( path ); 
// Retrieve the sheet data
x = open ( zip + "xl/worksheets/sheet1.xml","r"); 
content = read (x ) ; 
close  (x); 
close_zip (zip);

// parse XML
sheet1 = content; 

// Extract the content into an array: 
ARRAY STRING colE5_9; 
for (i=5,9 )
        colE5_9[] = string(sheet1["worksheet.sheetData.row["+i+"].c[5].v"]); 
end for

// Return as comma separated values. 
return implode (",", colE5_9); 

Running this function, resulted in the following:

6300,239519,74335,14500,108521

This is exactly what we can see in the spreadsheet.

spreadsheet-colE