Портирование Applescript в Scripting Bridge: невозможно получить значение диапазона в Excel 2008
Мне нужно переместить некоторый код Applescript в Scripting Bridge, чтобы воспользоваться некоторыми перехватчиками Cocoa без необходимости в Applescript-ObjC.
Используя Excel 2008 с Applescript, получить значение диапазона очень просто:
set myList to GetValuesFromColumnRange("A", 1, 100)
on GetValuesFromColumnRange(ColumnLetter, FirstRow, LastRow) -- (string, integer, integer) as list
set theList to {}
tell application "Microsoft Excel"
set theRange to ColumnLetter & FirstRow & ":" & ColumnLetter & LastRow
set AppleScript's text item delimiters to {return}
set theList to (get value of range theRange as list)
set AppleScript's text item delimiters to {""}
end tell
set theList to ConvertItemizedListToValueList(theList) of me -- Note this dependency due to how MSE2008 returns the data
return theList
end GetValuesFromColumnRange
Но в Scripting Bridge у меня проблема с получением ячеек листа на основе диапазона. Вот что я имею до сих пор.
Excel2008Application *excelApp = [SBApplication applicationWithBundleIdentifier:@"com.microsoft.Excel"];
Excel2008Workbook *workbook = excelApp.activeWorkbook;
SBElementArray *sheets = [workbook sheets];
Excel2008Sheet *targetSheet;
int thisSheet = 0;
int lastSheet = [sheets count];
for (thisSheet = 0; thisSheet < lastSheet; thisSheet++) {
Excel2008Sheet *currentSheet = [sheets objectAtIndex:thisSheet];
NSString *currentSheetName = currentSheet.name;
if ([currentSheetName isEqualToString:@"Metadata"]) {
targetSheet = currentSheet;
[targetSheet retain];
}
}
Excel2008Range *range = [[[excelApp classForScriptingClass:@"range"] alloc] initWithProperties:[NSDictionary dictionaryWithObjectsAndKeys:@"A1:A10", @"formulaR1c1", nil]];
[[targetSheet ranges] addObject:range];
range = [[targetSheet ranges] lastObject]; // not null; stated class in log: MicrosoftExcelRange
Excel2008Sheet *valueSheet = range.worksheetObject; // supposed to be new worksheet based upon values within the range; not null; stated class in log: MicrosoftExcelSheet
[valueSheet retain];
SBElementArray *valueCells = [valueSheet cells]; // not null, but count is 0
[valueCells retain];
Проблема возникает с последней строкой, когда я на самом деле получаю клетки от valueSheet
во что вернулся SBElementArray
не является нулевым, но он также не содержит никаких объектов. То же самое касается получения клеток в targetSheet
также.
Документация для этого, насколько я могу судить по всем моим поискам, не существует, и я сделал это настолько далеко, насколько смогу.
1 ответ
Решаемые.
NSString *rangeName = @"A1:A10";
Excel2008Range *range = [[[excelApp classForScriptingClass:@"range"] alloc] initWithProperties:[NSDictionary dictionaryWithObjectsAndKeys:rangeName, @"name", nil]];
[[targetSheet ranges] addObject:range];
Excel2008Range *currentRange;
if ([[[targetSheet ranges] objectWithName:rangeName] exists]) {
currentRange = [[targetSheet ranges] objectWithName:rangeName];
}
NSLog(@"[currentRange.value get] = %@", [currentRange.value get]);
// result: ((key),(1),(2),(3),(4),(5),(6),(7),(8),(9)) = NSArray
Кажется, дело в том, чтобы установить строку диапазона в name
собственность Excel2008Range
, Единственная ловушка, которую я нашел, работая над этим, состоит в том, чтобы никогда не заполнять formulaR1c1
диапазона - как в [NSDictionary dictionaryWithObjectsAndKeys:rangeName, @"formulaR1c1", nil]
- потому что он заполнит диапазон значением строки диапазона.
Оглядываясь назад, это действительно имеет смысл при чтении синтаксиса одной и той же команды в обоих приложениях...
tell application "Microsoft Excel"
set theValues to get value of range "A1:A10"
end tell
... и objc-appscript...
NSString *rangeString = @"A1:A10"
MEApplication *microsoftExcel = [MEApplication applicationWithName: @"Microsoft Excel"];
MEReference *cells = [[[microsoftExcel ranges] byName:rangeString] value];
NSArray *cellValues = [cells getItem];
В обоих случаях значение диапазона получается путем получения диапазона значений с его именем. Но с помощью Scripting Bridge, насколько я могу судить, имя должно применяться явно при создании объекта диапазона.
Я уверен, что есть лучший способ сделать это (обычно есть), но по крайней мере это работает.