Google Apps Script からXML データに連携

詳細情報をご希望ですか?

製品について詳細情報や無償トライアルをご案内します:

CData Connect



CData Connect Cloud を使用してGoogle Apps Script のXML データにアクセスします。

Google Apps Script を使用すると、Google Sheets やGoogle Docs を含むGoogle ドキュメント内にカスタム機能を作成できます。CData Connect Cloud を使用すると、XML を含むCData でサポートされている230+ ソースのMySQL インターフェースを取得できます。MySQL プロトコルは、Google Apps Script のJDBC サービスを通じてネイティブにサポートされているため、Connect Cloud を利用することで、Google ドキュメント内のライブXML データにアクセスできます。

この記事では、Connect Cloud でXML の仮想データベースを作成する方法を示し、Google Spreadsheet でXML データを処理するためのサンプルスクリプトを提供します。

スクリプトは、指定されたテーブルからデータを読み取るだけですが、スクリプトを簡単に拡張して更新機能を組み込むことができます。

XML データの仮想MySQL データベースを作成する

CData Connect Cloud は、シンプルなポイントアンドクリックインターフェースを使用してデータソースに接続し、API を生成します。

  1. Connect Cloud にログインし、[Databases]をクリックします。
  2. [Available Data Sources]から[XML]を選択します。
  3. XML に接続するために必要な認証プロパティを入力します。

    See the Getting Started chapter in the data provider documentation to authenticate to your data source: The data provider models XML APIs as bidirectional database tables and XML files as read-only views (local files, files stored on popular cloud services, and FTP servers). The major authentication schemes are supported, including HTTP Basic, Digest, NTLM, OAuth, and FTP. See the Getting Started chapter in the data provider documentation for authentication guides.

    After setting the URI and providing any authentication values, set DataModel to more closely match the data representation to the structure of your data.

    The DataModel property is the controlling property over how your data is represented into tables and toggles the following basic configurations.

    • Document (default): Model a top-level, document view of your XML data. The data provider returns nested elements as aggregates of data.
    • FlattenedDocuments: Implicitly join nested documents and their parents into a single table.
    • Relational: Return individual, related tables from hierarchical data. The tables contain a primary key and a foreign key that links to the parent document.

    See the Modeling XML Data chapter for more information on configuring the relational representation. You will also find the sample data used in the following examples. The data includes entries for people, the cars they own, and various maintenance services performed on those cars.

  4. Test Database]をクリックします。
  5. [Privileges]->[ Add]とクリックし、適切な権限を持つ新しいユーザー(または既存のユーザー) を追加します。

仮想データベースが作成されたら、すべてのMySQL クライアントからXML に接続できるようになります。

Apps Script を用いてのXML データへの接続

この時点で、Connect Cloud でXML の仮想データベースを構成しておく必要があります。あとは、Google Apps Script を使ってConnect Cloud にアクセスし、Google Sheets でサービスを操作するだけです。

このセクションでは、スプレッドシートにXML データを入力するためのスクリプト(スクリプトを呼び出すメニューオプション付き)を作成します。サンプルスクリプトを作成し、様々な部分について説明しました。記事の最後に、生のスクリプトを表示できます。

1.空のスクリプトを作成

Google Sheet のスクリプトを作成するには、Google Sheets メニューから[Tools][Script editor]をクリックします。

2.クラス変数を宣言

スクリプトで作成された関数で使用できるようにいくつかのクラス変数を作成します。

//replace the variables in this block with real values as needed
var address = 'myinstance.cdatacloud.net:port';
var user = 'CLOUD_HUB_USER';
var userPwd = 'CLOUD_HUB_PASSWORD';
var db = 'xmldb';
var serverSslCert = '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----';
var clientSslCert = '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----';
var clientSslKey  = '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----';

var dbUrl = 'jdbc:mysql://' + address + '/' + db + '?useSSL=true';

3.メニューオプションを追加

この関数は、Google Sheet にメニューオプションを追加し、UI を使用して関数を呼び出すことができるようにします。

function onOpen() {
  var spreadsheet = SpreadsheetApp.getActive();
  var menuItems = [
    {name:'Write data to a sheet', functionName: 'connectToXMLData'}
  ];
  spreadsheet.addMenu('XML Data', menuItems);
} 

4.ヘルパー関数の記述

この関数は、スプレッドシートの最初の空の行を検索するために使用します。

/*
 * Finds the first empty row in a spreadsheet by scanning an array of columns
 * @return The row number of the first empty row.
 */
function getFirstEmptyRowByColumnArray(spreadSheet, column) {
  var column = spreadSheet.getRange(column + ":" + column);
  var values = column.getValues(); // get all data in one call
  var ct = 0;
  while ( values[ct] && values[ct][0] != "" ) {
    ct++;
  }
  return(ct+1);
}

5.XML データをスプレッドシートに書き込む関数を記述

以下の関数では、Google Apps Script のJDBC 機能を使用してXML を記述し、Connect Cloud に接続してSELECT データを取得し、スプレッドシートにデータを入力します。スクリプトを実行すると、以下の2つの入力ボックスが表示されます。

最初のものは、データを保持するシートの名前を入力するようにユーザーに要求します。(スプレッドシートがない場合、関数によって作成されます。)

もう一つは、読み込むXML テーブルの名前を入力するようユーザーに要求します。無効なテーブルを選択するとエラーメッセージが表示され、関数が終了します。

この関数は、メニューオプションとして使用するように設計されていますが、スプレッドシートの式として使用するように拡張できます。

/*
 * Reads data from a specified XML 'table' and writes it to the specified sheet.
 *    (If the specified sheet does not exist, it is created.)
 */
function connectToXMLData() {
  var thisWorkbook = SpreadsheetApp.getActive();

  //select a sheet and create it if it does not exist
  var selectedSheet = Browser.inputBox('Which sheet would you like the data to post to?',Browser.Buttons.OK_CANCEL);
  if (selectedSheet == 'cancel')
    return;

  if (thisWorkbook.getSheetByName(selectedSheet) == null)
    thisWorkbook.insertSheet(selectedSheet);
  var resultSheet = thisWorkbook.getSheetByName(selectedSheet);
  var rowNum = 2;

  //select a XML 'table'
  var table = Browser.inputBox('Which table would you like to pull data from?',Browser.Buttons.OK_CANCEL);
  if (table == 'cancel')
    return;

  var conn = Jdbc.getConnection(dbUrl, {
    user: user, 
    password: userPwd, 
    _serverSslCertificate: serverSslCert,
    _clientSslCertificate: clientSslCert,
    _clientSslKey:         clientSslKey
  );

  //confirm that var table is a valid table/view
  var dbMetaData = conn.getMetaData();
  var tableSet = dbMetaData.getTables(null, null, table, null);
  var validTable = false;
  while (tableSet.next()) {
    var tempTable = tableSet.getString(3);
    if (table.toUpperCase() == tempTable.toUpperCase()){
      table = tempTable;
      validTable = true;
      break;
    }
  } 
  tableSet.close();
  if (!validTable) {
    Browser.msgBox("Invalid table name: " + table, Browser.Buttons.OK);
    return;
  }

  var stmt = conn.createStatement();

  var results = stmt.executeQuery('SELECT * FROM ' + table);
  var rsmd = results.getMetaData();
  var numCols = rsmd.getColumnCount();

  //if the sheet is empty, populate the first row with the headers
  var firstEmptyRow = getFirstEmptyRowByColumnArray(resultSheet, "A");
  if (firstEmptyRow == 1) {
    //collect column names
    var headers = new Array(new Array(numCols));
    for (var col = 0; col < numCols; col++){
      headers[0][col] = rsmd.getColumnName(col+1);
    }
    resultSheet.getRange(1, 1, headers.length, headers[0].length).setValues(headers);
  } else {
    rowNum = firstEmptyRow;
  }

  //write rows of XML data to the sheet
  var values = new Array(new Array(numCols));
  while (results.next()) {
    for (var col = 0; col < numCols; col++) {
      values[0][col] = results.getString(col + 1);
    }
    resultSheet.getRange(rowNum, 1, 1, numCols).setValues(values);
    rowNum++;
  }

  results.close();
  stmt.close();
}
  

この機能が完了すると、XML データが入力されたスプレッドシートが作成され、インターネットにアクセスできるあらゆる場所でGoogle Sheets の計算、グラフ化、チャート作成機能を利用できるようになります。


Google Apps Script の完成

//replace the variables in this block with real values as needed
var address = 'myinstance.cdatacloud.net:port';
var user = 'CLOUD_HUB_USER';
var userPwd = 'CLOUD_HUB_PASSWORD';
var db = 'xmldb';
var serverSslCert = '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----';
var clientSslCert = '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----';
var clientSslKey  = '-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----';

var dbUrl = 'jdbc:mysql://' + address + '/' + db + '?useSSL=true';

function onOpen() {
  var spreadsheet = SpreadsheetApp.getActive();
  var menuItems = [
    {name:'Write table data to a sheet', functionName: 'connectToXMLData'}
  ];
  spreadsheet.addMenu('XML Data', menuItems);
}

/*
 * Finds the first empty row in a spreadsheet by scanning an array of columns
 * @return The row number of the first empty row.
 */
function getFirstEmptyRowByColumnArray(spreadSheet, column) {
  var column = spreadSheet.getRange(column + ":" + column);
  var values = column.getValues(); // get all data in one call
  var ct = 0;
  while ( values[ct] && values[ct][0] != "" ) {
    ct++;
  }
  return(ct+1);
}

/*
 * Reads data from a specified 'table' and writes it to the specified sheet.
 *    (If the specified sheet does not exist, it is created.)
 */
function connectToXMLData() {
  var thisWorkbook = SpreadsheetApp.getActive();

  //select a sheet and create it if it does not exist
  var selectedSheet = Browser.inputBox('Which sheet would you like the data to post to?',Browser.Buttons.OK_CANCEL);
  if (selectedSheet == 'cancel')
    return;

  if (thisWorkbook.getSheetByName(selectedSheet) == null)
    thisWorkbook.insertSheet(selectedSheet);
  var resultSheet = thisWorkbook.getSheetByName(selectedSheet);
  var rowNum = 2;

  //select a XML 'table'
  var table = Browser.inputBox('Which table would you like to pull data from?',Browser.Buttons.OK_CANCEL);
  if (table == 'cancel')
    return;

  var conn = Jdbc.getConnection(dbUrl, {
    user: user, 
    password: userPwd, 
    _serverSslCertificate: serverSslCert,
    _clientSslCertificate: clientSslCert,
    _clientSslKey:         clientSslKey
  );

  //confirm that var table is a valid table/view
  var dbMetaData = conn.getMetaData();
  var tableSet = dbMetaData.getTables(null, null, table, null);
  var validTable = false;
  while (tableSet.next()) {
    var tempTable = tableSet.getString(3);
    if (table.toUpperCase() == tempTable.toUpperCase()){
      table = tempTable;
      validTable = true;
      break;
    }
  } 
  tableSet.close();
  if (!validTable) {
    Browser.msgBox("Invalid table name: " + table, Browser.Buttons.OK);
    return;
  }

  var stmt = conn.createStatement();

  var results = stmt.executeQuery('SELECT * FROM ' + table);
  var rsmd = results.getMetaData();
  var numCols = rsmd.getColumnCount();

  //if the sheet is empty, populate the first row with the headers
  var firstEmptyRow = getFirstEmptyRowByColumnArray(resultSheet, "A");
  if (firstEmptyRow == 1) {
    //collect column names
    var headers = new Array(new Array(numCols));
    for (var col = 0; col < numCols; col++){
      headers[0][col] = rsmd.getColumnName(col+1);
    }
    resultSheet.getRange(1, 1, headers.length, headers[0].length).setValues(headers);
  } else {
    rowNum = firstEmptyRow;
  }

  //write rows of XML data to the sheet
  var values = new Array(new Array(numCols));
  while (results.next()) {
    for (var col = 0; col < numCols; col++) {
      values[0][col] = results.getString(col + 1);
    }
    resultSheet.getRange(rowNum, 1, 1, numCols).setValues(values);
    rowNum++;
  }

  results.close();
  stmt.close();
}