Парсинг данных Excel в Apple Swift



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



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

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



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



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



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



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



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

882   4  

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 bridge для пример

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

Создайте исходный файл 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'S openpyxl (for .xlsx файлы) и xlrd (для .xsl) библиотеки успешно работают в моих собственных проектах. И я смотрите сквозь магию Гуглов, что кто-то написал фреймворк ObjC, DHlibxls, который [предполагая отсутствие динамического обмана] должен использоваться непосредственно из Swift, но я сам не использовал его, поэтому не могу сказать вам ничего больше.

Вы можете использовать ScriptingBridge и NSAppleScript, чтобы взаимодействовать с Apple сценарных материалов

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. лучший выбор, вероятно, 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, конечно.)

С другой стороны, если ваши данные относительно просты (например, в них нет экранированных символов), то вы возможно, вообще не потребуется использовать внешнюю библиотеку. Вы можете написать некоторый 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-to-json. И если вам нужно знать больше о том, какие текстовые кодировки производят продукты Microsoft, и какие из них Cocoa может автоматически обнаруживать, тогда это репо по текстовому кодированию содержит исследования по экспортным образцам, которые привели к выводу, что UTF-16-это способ пойти для старых продуктов Microsoft на Mac.

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

Comments

    Ничего не найдено.