Google Apps Script
Google Apps Script は、クラウドスクリプティング JavaScript 言語であり、製品 Google やサードパーティサービス間でタスクを自動化し、ウェブアプリケーションを構築する簡単な方法を提供します。
組み込みのTargetprocess REST APIを使用することで、Targetprocessアカウントからデータを取得し、スプレッドシート Google 文書に書き出すことが可能です。 更新アクションもサポートされており、以下に説明します。
最初の統合スクリプトの作成と実行方法
スプレッドシート Google を開いてください。
プレスツールスクリプトエディタ

新しく作成したプロジェクトの名前を変更します。

ファイル Code.gs のソースコードをエディタ領域にコピーしてください。 以下の記事にある 「Targetprocessからのデータ取得」 の例を使用してください。
ホスト名と認証トークンの値を、ご自身のTargetprocessカスタマーアカウント固有のものに置き換えてください。

警告: トークンの取得方法 パラメータ isTokenSetFromUserProfileTab には、次の2つのオプションのいずれかを使用してください。 トークンが Targetprocess の [ユーザープロファイル ] > [アクセストークン] タブから発行された場合に
true 使用してください。 トークンが REST API /api/v1/authentication エンドポイントから発行された場合に false 使用します。ドロップダウンから実行する関数を選択 fetchTargetprocessData してください。

印刷実行。

このスクリプトに要求された権限を付与してください。 この操作は一度だけ行う必要があります。

成功! ターゲットプロセスエンティティがスプレッドシートに追加されました。

Targetprocessからデータを取得する
このスクリプトはトークンベース認証を使用してTargetprocess myaccount.tpondemand.com アカウントに接続し、ユーザーストーリーのリストをクエリします。 読み込まれたストーリーの詳細は、最初にクリアされた Google スプレッドシートに追加されます。
function fetchTargetprocessData() {
var hostname = 'https://myaccount.tpondemand.com';
var authenticationToken = 'MTpFQUVXMHdRVGRMN0x1OXJPYWRXZWZaRkc2aDJaSkRyVWdyWm9rK2tFcldBPS==';
var isTokenSetFromUserProfileTab = true;
//use 'true' if token is issued from User Profile > Access Tokens tab
//use 'false' when token is issued from /api/v1/Authentication API endpoint
var takeCount = 10;
var entityTypeResourceName = 'userstories';
var filter = '';
var includeFields = '';
//use the example below to specify exact set of fields to include
//var includeFields = '[ID,Name,Project[Name],EntityState[Name],CustomFields]';
var dateFormat = 'yyyy-MM-dd';
//to see times with dates, use 'yyyy-MM-dd HH:mm';
var dataUrl = hostname + '/api/v1/' + entityTypeResourceName + '?format=json' + '&where=' + filter + '&take=' + takeCount + (includeFields.length > 0 ? '&include=' + includeFields : '') + '&' + (isTokenSetFromUserProfileTab ? 'access_token' : 'token') + '=' + authenticationToken;
var options = {
'method': 'get'
};
var response = UrlFetchApp.fetch(dataUrl, options);
var json = response.getContentText();
var data = JSON.parse(json);
var entities = data.Items;
var sheet = SpreadsheetApp.getActiveSheet();
//initial cleanup of the sheet
sheet.clear();
//creates column names row
var entity = entities[0];
var columnNames = Object.keys(entity);
var customFieldsColumnIndex = 0;
for (var i = 0; i < columnNames.length; i++) {
if (columnNames[i] == 'CustomFields') {
customFieldsColumnIndex = i;
}
}
if (customFieldsColumnIndex > 0) {
var entityArray = Object.keys(entity).map(function(k) { return entity[k] });
var customFieldsData = entityArray[customFieldsColumnIndex];
for (var k = 0; k < customFieldsData.length; k++) {
var fieldsPairData = customFieldsData[k];
columnNames.push(fieldsPairData.Name);
}
}
sheet.appendRow(columnNames);
//appends data line by line
for (var i = 0; i < entities.length; i++) {
var entity = entities[i];
var entityArray = Object.keys(entity).map(function(k) { return entity[k] });
if (customFieldsColumnIndex > 0) {
//format custom fields
var customFieldsData = entityArray[customFieldsColumnIndex];
var fieldValues = '';
for (var j = 0; j < customFieldsData.length; j++) {
var fieldsPairData = customFieldsData[j];
entityArray.push(fieldsPairData.Value);
}
entityArray[customFieldsColumnIndex] = customFieldsData.length;
}
//add data formatting functions there
for (var j = 0; j < entityArray.length; j++) {
var cellValue = entityArray[j];
if (typeof cellValue == 'string') {
if (cellValue.indexOf("Date") > -1) {
var milliseconds = cellValue.substring(6, cellValue.length - 7);
var originTimeZone = cellValue.substring(cellValue.length - 7, cellValue.length - 4);
var dateObject = new Date(parseInt(milliseconds) + originTimeZone * 1000 * 60 * 60);
entityArray[j] = Utilities.formatDate(dateObject, originTimeZone, dateFormat);
}
}
if (typeof cellValue == 'object') {
var keys = [];
var resourceType = '';
var name = '';
var items = null;
for(var key in cellValue) {
keys.push(key);
if (key == "ResourceType") {
resourceType = cellValue[key];
}
if (key == "Name") {
name = cellValue[key];
}
};
if (
resourceType == "Project"
|| resourceType == "EntityState"
|| resourceType == "EntityType"
|| resourceType == "Priority"
|| resourceType == "Feature"
|| resourceType == "Epic"
|| resourceType == "UserStory"
|| resourceType == "Program"
|| resourceType == "Release"
|| resourceType == "Iteration"
|| resourceType == "TeamIteration"
) {
entityArray[j] = name;
}
}
}
sheet.appendRow(entityArray);
}
}
Targetprocessのデータを更新する
このスクリプトはトークンベース認証を使用して myaccount.tpondemand.com Targetprocessアカウントに接続し、プロジェクト#2に新しいユーザーストーリーエンティティを作成します。 ユーザーストーリーの数値ID、名前、説明、および作成時刻が、初期状態でクリア Google されたスプレッドシートに追加されます。function updateTargetprocessData() {
var payload = {
"Project" : {"ID" : 2},
"Name": "Test Google Script Story Name",
"Description": "Test Google Script Story Description"
};
var hostname = 'https://myaccount.tpondemand.com';
var authenticationToken = 'MTozemxBMjI4dkNPMFVqbmlWV21WUVlSb0RYTTAzbkhQZ1lvaTJKanMvQWFBPS==';
var isTokenSetFromUserProfileTab = true;
//use 'true' if token is issued from User Profile > Access Tokens tab
//use 'false' when token is issued from /api/v1/Authentication API endpoint
var entityTypeResourceName = 'userstories';
var resultIncludeFields = '[Id,Name,Description,CreateDate]';
var dateFormat = 'yyyy-MM-dd HH:mm'; //to see no times with dates, use 'yyyy-MM-dd';
var dataUrl = hostname + '/api/v1/' + entityTypeResourceName + '/?format=json'
+ '&resultInclude=' + resultIncludeFields
+ '&' + (isTokenSetFromUserProfileTab ? 'access_token' : 'token') + '=' + authenticationToken;
var options = {
'method': 'POST',
'payload': JSON.stringify(payload),
'contentType' : 'application/json',
};
var response = UrlFetchApp.fetch(dataUrl, options);
var sheet = SpreadsheetApp.getActiveSheet();
//initial cleanup of the sheet
sheet.clear();
var json = response.getContentText();
var data = JSON.parse(json);
var entities = data;//data.Items; for multiple objects
var entity = entities;//entities[0]; for multiple objects
var columnNames = Object.keys(entity);
var customFieldsColumnIndex = 0;
for (var i = 0; i < columnNames.length; i++) {
if (columnNames[i] == 'CustomFields') {
customFieldsColumnIndex = i;
}
}
if (customFieldsColumnIndex > 0) {
var entityArray = Object.keys(entity).map(function(k) { return entity[k] });
var customFieldsData = entityArray[customFieldsColumnIndex];
for (var k = 0; k < customFieldsData.length; k++) {
var fieldsPairData = customFieldsData[k];
columnNames.push(fieldsPairData.Name);
}
}
sheet.appendRow(columnNames);
var entity = entities;//entities[i]; for multiple objects
var entityArray = Object.keys(entity).map(function(k) { return entity[k] });
if (customFieldsColumnIndex > 0) {
//format custom fields
var customFieldsData = entityArray[customFieldsColumnIndex];
var fieldValues = '';
for (var j = 0; j < customFieldsData.length; j++) {
var fieldsPairData = customFieldsData[j];
entityArray.push(fieldsPairData.Value);
}
entityArray[customFieldsColumnIndex] = customFieldsData.length;
}
//add data formatting functions there
for (var j = 0; j < entityArray.length; j++) {
var cellValue = entityArray[j];
if (typeof cellValue == 'string') {
if (cellValue.indexOf("Date") > -1) {
var milliseconds = cellValue.substring(6, cellValue.length - 7);
var originTimeZone = cellValue.substring(cellValue.length - 7, cellValue.length - 4);
var dateObject = new Date(parseInt(milliseconds) + originTimeZone * 1000 * 60 * 60);
entityArray[j] = Utilities.formatDate(dateObject, originTimeZone, dateFormat);
}
}
if (typeof cellValue == 'object') {
var keys = [];
var resourceType = '';
var name = '';
var items = null;
for(var key in cellValue) {
keys.push(key);
if (key == "ResourceType") {
resourceType = cellValue[key];
}
if (key == "Name") {
name = cellValue[key];
}
};
if (
resourceType == "Project"
|| resourceType == "EntityState"
|| resourceType == "EntityType"
|| resourceType == "Priority"
|| resourceType == "Feature"
|| resourceType == "Epic"
|| resourceType == "UserStory"
|| resourceType == "Program"
|| resourceType == "Release"
|| resourceType == "Iteration"
|| resourceType == "TeamIteration"
) {
entityArray[j] = name;
}
}
}
sheet.appendRow(entityArray);
}
応答内のエンティティの数
デモサンプルでは、最初に一致するユーザーストーリーを10件取得します。 クエリ対象エンティティ数はスクリプトヘッダーにエンコードされています:var takeCount = 10;パラメータを最大 takeCount 1000まで増加させることが可能です。 クエリに一致するエンティティが1000件を超える場合、ページングパラメータを使用して複数のAPI呼び出しを行い、取得したデータを結合するスクリプトを作成する必要があります。フィルタリング
Excelとの連携時には、より高度なREST API技術(フィルタリング、追加フィールド、コレクションなど)を含めることも可能です。 フィルターの詳細については、Targetprocess REST API フィルター説明書をご参照ください。 以下は、フィルタをサポートするためにソースコードを変更する例です。 カスタムフィールドの「日付範囲」欄に:var filter = '(\'CustomFields.Next Date\' gte \'2017-01-09\') and (\'CustomFields.Next Date\' lte \'2017-01-16\')';
参考資料
Apps Google Script ガイドを参照するか、サポートチームにお問い合わせください。注: 代替オプション: Zap ierコネクタ内では、Targetprocessエンティティを Google スプレッドシート文書と同期することも可能です。