Search code examples
iosswiftexcelfile-permissionsxlsx

XlsxReaderWriter creating read only .xlsx file?


I am using XlsxReaderWriter | Objective - C to insert data and generate a .xlsx file. I am using demo.xlsx from bundle directory and then copying to documents directory to insert data and then saving it with a new name. The demo.xlsx has Read and Write for permission for everyone. After generating the new file I am giving an option to the user to export the file to Microsoft Excel app on their device. When I try to open file in Microsoft Excel app it says that it is read only file and my data till column "T" of the sheet is not shown and the sheet shows from column "U" with no data inside. But the data is being shown in other third party apps or document controller, why is this happening ?

The code I tried :

    let fileManager = NSFileManager.defaultManager()

let directory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let path = "\(directory)/file.txt"

let attributes: [String:AnyObject] = [NSFilePosixPermissions: NSNumber(short: 0o666)]
let success = fileManager.createFileAtPath(path, contents: nil, attributes: attributes)
if success && fileManager.isWritableFileAtPath(path) && fileManager.isReadableFileAtPath(path) {
    NSLog("Worked!")
} else {
    NSLog("Failed!")
}

The file was created before I gave it permission instead of "createFileAtPath" The permissions were perfectly set, I checked in documents directory. Just that the Microsoft Excel app on iOS says it's still "Read Only" file.


Solution

  • I'm guessing it's likely that the problem is not anything about the file permissions, but something about the contents of the .xlsx file your app has generated that Microsoft Excel is unhappy about - hence why it is also not displaying all the data. A .xlsx file is just a zip file containing xml.

    You can un-package it using unzip, and then format all the xml for easy reading using a tool like xmllint --format.

    If you produce a very simple xlsx that shows the problem (the simplest example that still shows the problem) from your own app, then create a similar xlsx manually from scratch in Excel, you can do the unzip & format on both of them then do a diff -r to find the differences between them.

    An alternative approach is to load the file that's showing as 'read only' into desktop microsoft excel, make a trivial edit and save it - if that file then loads into the mobile app correctly, you can diff that file against yours.

    There will probably be a reasonable number of differences, so you'll need to apply some brain power to figure out which ones are most likely to cause Excel to make it readonly. Aside from anything obvious like an attribute named 'readonly', I'd look for things like the problem file using older XML namespaces.

    If you find a different you can quickly find if it's the issue by hand editing, rezipping the xml (make sure your editor doesn't leave any backup files behind, as Excel tends to object to unexpected files in the zip), then load it into Excel and see if it's still readonly.

    Here's a script I use to compare the xml for two ooxml documents:

    #!/bin/bash
    
    set -e
    first=$1
    second=$2
    
    # convert to absolute paths
    first=$(cd $(dirname $first); pwd)/$(basename $first)
    second=$(cd $(dirname $second); pwd)/$(basename $second)
    
    WORKDIR=~/tmp.$$
    
    mkdir -p $WORKDIR
    cd $WORKDIR
    mkdir 1
    cd 1
    unzip $first
    cd ..
    mkdir 2
    cd 2
    unzip $second
    cd ..
    for i in `find . -name '*.xml' -o -name '*.vml' -o -name '*.rels'`; do
      xmllint --format $i > $i.new
      mv -f $i.new $i
    done
    
    diff -U 5 -r 1 2 | cat -v
    #or kaleidoscope for better diff display:
    #ksdiff 1 2
    
    echo  $WORKDIR
    rm -rf $WORKDIR