2010-12-07 39 views
3

J'ai besoin de déplacer du code Applescript vers Scripting Bridge pour tirer parti de certains hooks Cocoa sans avoir besoin d'Applescript-ObjC.Portage Applescript à Scripting Bridge: impossible d'obtenir la valeur de plage dans Excel 2008

l'aide d'Excel 2008 avec AppleScript, obtenir la valeur d'une plage est facile:

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 

Mais dans Bridge script, je vais avoir un problème à obtenir les cellules d'une feuille de calcul basée sur une plage. Ce qui suit est ce que j'ai jusqu'à présent.

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]; 

Le problème est livré avec la dernière ligne, quand je reçois effectivement les cellules de valueSheet, en ce que le retour SBElementArray est non nul, mais il ne contient pas non plus d'objets. La même chose vaut pour obtenir les cellules dans targetSheet ainsi.

La documentation pour faire ceci, presque comme je peux dire de toutes mes recherches, n'existe pas et j'ai pris ceci à propos autant que je peux.

Répondre

1

Résolu.

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 

Il semble que l'astuce est de définir la chaîne de gamme dans la propriété name du Excel2008Range. Le seul piège que j'ai trouvé en travaillant dessus est de ne jamais remplir le formulaR1c1 de la gamme - comme dans [NSDictionary dictionaryWithObjectsAndKeys:rangeName, @"formulaR1c1", nil] - car cela remplira la plage avec la valeur de la chaîne de plage.

En recul, cela fait réellement sens lors de la lecture de la syntaxe de la commande exactement le même dans les deux AppleScript ...

tell application "Microsoft Excel" 
    set theValues to get value of range "A1:A10" 
end tell 

... et objc-appscript ...

NSString *rangeString = @"A1:A10" 
MEApplication *microsoftExcel = [MEApplication applicationWithName: @"Microsoft Excel"]; 
MEReference *cells = [[[microsoftExcel ranges] byName:rangeString] value]; 
NSArray *cellValues = [cells getItem]; 

En Dans les deux cas, la valeur de la plage est obtenue en obtenant une plage de valeurs avec son nom. Mais avec Scripting Bridge, si je peux dire, le nom a à appliquer explicitement lors de la création de l'objet range.

Je suis sûr qu'il existe une meilleure façon d'accomplir cela (il en existe habituellement), mais au moins cela fonctionne.