Parsing Excel Data in Apple Swift

后端 未结 5 791
说谎
说谎 2020-12-14 05:17

My current workflow involves using Applescript to essentially delimit Excel data and format it into plain text files. We\'re pushing towards an all Swift environment, but I

5条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-14 05:43

    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 valueOfUsedRange
    
    end 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]>
    

提交回复
热议问题