Анализ данных Excel в Apple Swift

мой текущий рабочий процесс включает в себя использование Applescript для разделения данных Excel и форматирования их в текстовые файлы. Мы продвигаемся к среде Swift, но я еще не нашел никаких наборов для анализа данных Excel в Swift.

единственное, что я могу придумать, это использовать C или что-то еще и обернуть его, но это не идеально. Любые лучшие предложения по разбору этих данных для использования в Swift?

цель состоит в том, чтобы устранить Applescript, но я не уверен если это будет возможно при взаимодействии с файлами Excel. Сценарий Excel с помощью Applescript кажется единственным методом.

EDIT: у меня нет возможности исключить Excel из этого рабочего процесса. Вот как данные будут поступать в приложение, поэтому я должен включить его.

возможность оптимизировать процесс разбора этих данных, а затем их обработки будет иметь первостепенное значение. Я знаю, что Applescript был хорош в прошлом, помогая мне процесс, однако, он слишком закрыт для меня.

Я смотрел на запись чего-то в Swift/Cocoa, но это все еще может потребовать, чтобы данные были извлечены с помощью Applescript, верно?

большим плюсом для нажатия Swift является читаемость. Я не очень хорошо знаю Objective-C, и swift был бы более легким переходом, я чувствую.

мой рабочий процесс на ПК использует COM-объект, который, как было сказано, недоступен в Mac Excel приложение. Я только ищу извлечение данных на данный момент. Некоторые предыдущие приложения выполняли обработку в приложении, но я хочу сделать это очень автономным, таким образом, вся обработка в приложении, которое я разрабатываю. Как только данные будут извлечены из .XLS или .XLSX файлы, я буду делать некоторое редактирование текста через регулярное выражение и, возможно, немного хруст числа. Ничто не слишком сумасшедшим. На данный момент он будет работать на стороне клиента, но я хочу распространить это на серверный процесс.

4 ответов


в Mac OS X 10.6 Snow Leopard Apple представила структуру AppleScriptObjC, которая позволяет очень легко взаимодействовать между Cocoa и AppleScript. Код AppleScript и синтаксис Objective-C могут использоваться в одном исходном файле. Это гораздо удобнее, чем Scripting Bridge и NSAppleScript.

AppleScriptObjC нельзя использовать непосредственно в Swift, потому что команда loadAppleScriptObjectiveCScripts NSBundle не соединен с Swift.

однако вы можете использовать класс моста Objective-C для пример

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.м

#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

создайте исходный файл AppleScript из шаблона AppleScriptObjC

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

ссылка на платформу AppleScriptObjC при необходимости.
Создайте заголовок моста и импортируйте ASObjC.h

затем вы можете вызвать AppleScriptObjC из Swift с помощью

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

или

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

несколько неясно, пытаетесь ли вы устранить Excel как зависимость (что не является необоснованным: это стоит денег, и не у всех это есть) или AppleScript как язык (полностью понятный, но плохой практический шаг, поскольку альтернативы Apple для автоматизации приложений все сосут).

существуют сторонние библиотеки Excel-синтаксического анализа, доступные для других языков, например, я использовал Python openpyxl (for .xlsx файлы) и xlrd (for .xsl) библиотеки успешно в моем собственном проекты. И я вижу сквозь магию Googles, что кто-то написал фреймворк ObjC, DHlibxls, который [при условии отсутствия динамического обмана] должен использоваться непосредственно из Swift, но я не использовал его сам, поэтому не могу сказать вам ничего больше.


можно использовать ScriptingBridge или NSAppleScript для взаимодействия с Apple Scriptable stuff

ScriptingBridge может создать файл заголовка из словаря сценариев Apple.

NSAppleScript может выполнить любой AppleScript для вас, передав String


1. Экспорт в открытый текст CSV

если все, что вы пытаетесь сделать, это экстракт сведения из Excel для использования в другом месте, в отличие от захвата формул Excel и форматирования, то вы, вероятно, не должны пытаться читать .xls-файл. XLS-это сложный формат. Это хорошо для Excel, а не для общего обмена данными.

аналогично, вам, вероятно, не нужно использовать AppleScript или что-либо еще для интеграции с Excel, если все, что вы хотите сделать, это сохранить данные в виде открытого текста. Excel уже знает, как сохранить данные в виде текста. Просто используйте команду Excel "Сохранить как". (Так это называется на Mac. Я не знаю о ПК.)

вопрос в том, какой формат открытого текста использовать. Один очевидный выбор для этого -текстовый файл значений, разделенных запятыми (CSV) потому что это простой де-факто стандарт (в отличие от сложного официального стандарта, такого как XML). Это позволит легко потреблять в Swift или на любом другом языке.

2. Экспорт в кодировке UTF-8, если это возможно, в противном случае как UTF-16

Итак, как вы это делаете? Открытый текст удивительно прост, но одна тонкость, которую вам нужно отслеживать, - это кодировка текста. Текстовая кодировка-это способ представления символов в текстовом файле. К сожалению, вы не можете надежно определить кодировку файла, просто проверив файл, поэтому вам нужно выбрать кодировку при ее сохранении и не забыть использовать эту кодировку при ее чтении. Если вы испортите это, акцентированные символы, кавычки типографа, тире и другие символы, отличные от ASCII, будут искажены. Итак, какую кодировку текста вы должны использовать? Короткий ответ, вы должны всегда используйте UTF-8, если это возможно.

но если вы работаете со старой версией Excel, то вы не сможете использовать UTF-8. В этом случае, вы должны использовать UTF-16. В частности, UTF-16, я считаю, единственный вариант экспорта в Excel 2011 для Mac, который производит предсказуемый результат, который не будет удивительным образом зависеть от неясных параметров локали или специфичных для Microsoft кодировок.

Итак, если вы находитесь в Excel 2011 для Mac, например, выберите "UTF-16 Unicode Text" из команды Excel Save As.

Это заставит Excel сохранить файл, так что каждая строка представляет собой строку текста, а каждый столбец разделен символом вкладки. (Таким образом, технически это файлы значений, разделенные вкладками, а не значение, разделенное запятыми файл.)

3. Импорт с помощью Swift

теперь у вас есть текстовый файл, который, как вы знаете, был сохранен в кодировке UTF-8 (или UTF-16). Итак, теперь вы можете прочитать его и разобрать в Swift.

если ваши данные Excel сложны, вам может понадобиться полнофункциональный парсер CSV. The лучший выбор, вероятно,CHCSVParser.

используя CHCSV, вы можете проанализировать файл со следующим кодом:

NSURL * const inputFileURL = [NSURL fileURLWithPath:@"/path/to/exported/file.txt"];
unichar tabCharacter = '\t';
NSArray *rows = [NSArray arrayWithContentsOfCSVFile:inputFilePath options:CHCSVParserOptionsSanitizesFields
                                          delimiter:tabCharacter];

(вы также можете назвать его от Свифта, конечно.)

С другой стороны, если ваши данные относительно просты (например, у них нет экранированных символов), вам может вообще не понадобиться использовать внешнюю библиотеку. Вы можете написать Swift-код, который анализирует значения, разделенные вкладками, просто читая в файле в виде строки, разделяя на новые строки, а затем разделяя на вкладки.

эта функция будет принимать String представление данных TSV и возврат массива словари:

/**
Reads a multiline, tab-separated String and returns an Array<NSictionary>, taking column names from the first line or an explicit parameter
*/
func JSONObjectFromTSV(tsvInputString:String, columnNames optionalColumnNames:[String]? = nil) -> Array<NSDictionary>
{
  let lines = tsvInputString.componentsSeparatedByString("\n")
  guard lines.isEmpty == false else { return [] }

  let columnNames = optionalColumnNames ?? lines[0].componentsSeparatedByString("\t")
  var lineIndex = (optionalColumnNames != nil) ? 0 : 1
  let columnCount = columnNames.count
  var result = Array<NSDictionary>()

  for line in lines[lineIndex ..< lines.count] {
    let fieldValues = line.componentsSeparatedByString("\t")
    if fieldValues.count != columnCount {
      //      NSLog("WARNING: header has %u columns but line %u has %u columns. Ignoring this line", columnCount, lineIndex,fieldValues.count)
    }
    else
    {
      result.append(NSDictionary(objects: fieldValues, forKeys: columnNames))
    }
    lineIndex = lineIndex + 1
  }
  return result
}

поэтому вам нужно только прочитать файл в строку и передать его этой функции. Этот фрагмент происходит от это суть для преобразователя tsv-в-json. И если вам нужно узнать больше о том, какие текстовые кодировки производят продукты Microsoft, и какие из них Cocoa может автоматически обнаружить, то это РЕПО на кодировку текста содержит исследование на образцах экспорта которые привели к выводу что УТФ-16 путь пойти для старых продуктов Майкрософт на Mac.

(Я понимаю, что я связываюсь со своими собственными репозиториями здесь. Извинения?)