Parsing Excel Data in Apple Swift Parsing Excel Data in Apple Swift swift swift

Parsing Excel Data in Apple Swift


In Mac OS X 10.6 Snow Leopard Apple introduced the AppleScriptObjC framework which makes it very easy to interact between Cocoa and AppleScript. AppleScript code and a Objective-C like syntax can be used in the same source file. It's much more convenient than Scripting Bridge and NSAppleScript.

AppleScriptObjC cannot be used directly in Swift because the command loadAppleScriptObjectiveCScripts of NSBundle is not bridged to Swift.

However you can use a Objective-C bridge class for example

ASObjC.h

@import Foundation;@import AppleScriptObjC;@interface NSObject (Excel)- (void)openExcelDocument:(NSString *)filePath;- (NSArray *)valueOfUsedRange;@end@interface ASObjC : NSObject+ (ASObjC *)sharedASObjC;@property id Excel;@end

ASObjC.m

#import "ASObjC.h"@implementation ASObjC+ (void)initialize{    if (self == [ASObjC class]) {        [[NSBundle mainBundle] loadAppleScriptObjectiveCScripts];    }}+ (ASObjC *)sharedASObjC{    static id sharedInstance = nil;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        sharedInstance = [[ASObjC alloc] init];    });    return sharedInstance;}- (instancetype)init{    self = [super init];    if (self) {        _Excel = NSClassFromString(@"ASExcel");    }    return self;}@end

Create a AppleScript source file form the AppleScriptObjC template

ASExcel.applescript

script ASExcel  property parent: class "NSObject"  on openExcelDocument:filePath    set asFilePath to filePath as text    tell application "Microsoft Excel"      set sourceBook to open workbook workbook file name asFilePath      repeat        try          get workbooks          return        end try        delay 0.5      end repeat    end tell  end openDocument  on valueOfUsedRange()    tell application "Microsoft Excel"      tell active sheet        set activeRange to used range        return value of activeRange      end tell    end tell  end valueOfUsedRangeend script

Link to the AppleScriptObjC framework if necessary.
Create the Bridging Header and import ASObjC.h

Then you can call AppleScriptObjC from Swift with

 ASObjC.sharedASObjC().Excel.openExcelDocument("Macintosh HD:Users:MyUser:Path:To:ExcelFile.xlsx")

or

let excelData = ASObjC.sharedASObjC().Excel.valueOfUsedRange() as! Array<[String]>


It's somewhat unclear if you're trying to eliminate Excel as a dependency (which is not unreasonable: it costs money and not everyone has it) or AppleScript as a language (totally understandable, but a bad practical move as Apple's alternatives for application automation all suck).

There are third-party Excel-parsing libraries available for other languages, e.g. I've used Python's openpyxl (for .xlsx files) and xlrd (for .xsl) libraries successfully in my own projects. And I see through the magicks of Googles that someone's written an ObjC framework, DHlibxls, which [assuming no dynamic trickery] should be usable directly from Swift, but I've not used it myself so can't tell you anything more.


You can use ScriptingBridge or NSAppleScript to interact with Apple Scriptable stuff

ScriptingBridge can generate a header file from the Apple Script dictionary.

NSAppleScript can execute any AppleScript for you by passing a String