2017-06-21 9 views
1

私のアドインでは、HTTPリクエストを行い、出力を受け取ります。私はその出力をバインディングに配置し、必要に応じてバインディングを拡張したいと考えています。なぜなら、ユーザーは出力が何行x x列あるかを必ずしも知る必要がないからです。これをどうやってやりますか?現在、範囲にバインドしていますが、その範囲が提供している[[]]のサイズと一致しない場合、データはシートに表示されません。したがって、これにより、ユーザーは出力のサイズを知る必要があります。セル範囲の出力を動的に作成する

次のように私は角度を使用して、現在やっていること(これは、出力が常にユーザーは、スプレッドシートで選択していることOffice.BindingType.Matrixと同じサイズではないということでの問題)である:

私は次のように出力が置かれるべき場所への結合を作成する:

inputBindFromPrompt(parameterId: number): Promise<IOfficeResult> { 
     let bindType: Office.BindingType; 
     if(this.inputBindings[parameterId].type != 'data.frame' && this.inputBindings[parameterId].type != 'vector') { 
      bindType = Office.BindingType.Text; 
     } else { 
      bindType = Office.BindingType.Matrix; 
     } 
     return new Promise((resolve, reject) => { 
      this.workbook.bindings.addFromPromptAsync(bindType, { id: this.inputBindings[parameterId].name }, 
      (addBindingResult: Office.AsyncResult) => { 
       if(addBindingResult.status === Office.AsyncResultStatus.Failed) { 
        reject({ 
         error: 'Unable to bind to workbook. Error: ' + addBindingResult.error.message 
        }); 
       } else { 
        this.inputBindings[parameterId].binding = addBindingResult.value; 
        resolve({ 
         success: 'Created binding ' + addBindingResult.value.type + ' on ' + addBindingResult.value.id 
        }); 
       } 
      }) 
     }) 
    } 

ユーザがボタンを介して送信するときに、入力はその後、ANに私が処理出力を受信HTTP要求サービスに渡されます。 Office.BindingType.Matrixに入ることができるように配列の配列:

outputSetText(parameterId: number, data: any): Promise<IOfficeResult> { 
    return new Promise((resolve, reject) => { 
     if(this.outputBindings[parameterId].binding) { 
      this.outputBindings[parameterId].binding.setDataAsync(data, function (result: Office.AsyncResult) { 
       if(result.status == Office.AsyncResultStatus.Failed) { 
        reject({ error: 'Failed to set value. Error: ' + result.error.message }); 
       } else { 
        let test: Office.Binding; 
        resolve({ 
         success: 'successfully set value' 
        }); 
       } 
      }) 
     } else { 
      reject({ 
       error: 'binding has not been created. bindFromPrompt must be called' 
      }); 
     } 
    }) 
} 
this.isBusy = true; 
     this.feedback = 'submitted'; 
     // Grab the values from the form 
     // Send as a POST and receive an output 
     // Put the output in the Excel sheet 
     this.webServicesService.postWebServices(this.service, this.inputParameters) 
     .subscribe(
      (data: any) => { 
      // Correctly received data 
      // Access the data by name while looping through output parameters 
      this.error = false; 
      this.feedback = 'received data'; 
      let i = 0; 
      this.outputParameters.forEach(element => { 
       // temporary name to identify the parameter 
       let name = element.name; 
       // Set the data value in the parameter 
       if(element.type == 'data.frame') { 
       let parameter = data[name]; 
       this.feedback = parameter; 
       let excelData = []; 
       for(var key in parameter) { 
        if(parameter.hasOwnProperty(key)) { 
        var val = parameter[key]; 
        excelData.push(val); 
        } 
       } 

       element.value = excelData; 

       } 
       else { 
       element.value = data[name]; 
       } 
       // Set value in the form 
       let param = (<FormArray>this.serviceForm.controls['outputParameters']).at(i); 
       param.patchValue({ 
       value: element.value 
       }); 
       // Set value in the spreadsheet 
       this.excelService.outputSetText(i, element.value) 
       .then((result: IOfficeResult) => { 
        this.onResult(result); 
        i++; 
       }); 

      }, (result: IOfficeResult) => { 
        this.onResult(result); 
       }); 
      }, 
      (error) => { 
      if(error.status == 400 || error.status == 401) { 
       // Return user to authentication page 
       this.authService.logout(); 
       this.router.navigate(['/']); 
      } else { 
       // Tell user to try again 
       this.error = true; 
      } 
      } 
     ); 
その上の行がOffice.Matrix.Bindingに値を設定しているは、Excelサービスでこのメソッドを呼び出すthis.excelService.outputSetText(I、element.value)、あります

基本的にaddFromPromptAsync()を使用して、HTTPリクエストの出力場所を設定しています。次にユーザーは要求を送信し、データを受信して​​配列配列[[]]に処理し、Office.BindingType.Matrixの正しいデータ形式になるようにします。ただし、これが最初に選択したバインディングと同じ数の行と列でない場合は、シートには表示されません。だから、私はそれを与えるデータに基づいて動的に成長するバインディングタイプはありますか?または、現在のバインディングを解放し、HTTPレスポンスデータのサイズに応じて新しいバインディングを作成するだけでいいですか?

+0

これまでに行ったことのあるコード(理想的には[Script Lab](https://aka.ms/scriptlab)スニペット)を貼り付けてください。リクエスト/レスポンス部分を "偽造"し、JSONオブジェクトまたは配列を使用してください。 –

+0

@ MichaelZlatkovsky-Microsoft私がAngularで行っていることの上にコードを掲載しました。 – codex

答えて

1

「共有」(Office 2013)APIを使用している限り、この問題が発生します。

しかし、ホスト固有の(2016+)APIでは、ニーズに合わせて範囲を変更することで簡単に問題を解決できます。またはより正確には、バインディングを取得し、その範囲を求め、その後、単に最初(左上)のセルを取得し、それをリサイズ:

await Excel.run(async (context) => { 
     let values = [ 
      ["", "Price"], 
      ["Apple", 0.99], 
      ["Orange", 1.59], 
     ]; 

     let firstCell = context.workbook.bindings.getItem("TestBinding").getRange().getCell(0, 0); 
     let fullRange = firstCell.getResizedRange(
      values.length - 1, values[0].length - 1); 
     fullRange.values = values; 

     await context.sync(); 
    }); 

あなたは文字通り5回のクリックで、ライブこのスニペットを試すことができます新しいスクリプトラボ(https://aka.ms/getscriptlab)。 Script Labアドイン(無料)をインストールし、ナビゲーションメニューで「インポート」を選択し、次のGIST URL(https://gist.github.com/Zlatkovsky/5a2fc743bc9c8556d3eb3234e287d7f3)を使用するだけです。 more info about importing snippets to Script Labを参照してください。

+0

ありがとう、これはまさに私が探していたものでした。私はまだプロンプトからバインドを行い、新しいapisとのバインディングをつかんでサイズを変更できるはずです。 – codex

関連する問題