変換後のコードのエラーを修正する

Macro Converter アドオンは、ほとんどの変換プロセスを自動化しますが、コードを確定するために、一部の API やその他の項目の調整が必要になることがあります。

このガイドでは、プロジェクトに追加された Apps Script ファイル(GS ファイル)の概要、さまざまなエラーの種類の解釈、エラーの修正方法について説明します。

プロジェクトに追加された Apps Script ファイルについて

Apps Script プロジェクトには、次のような GS ファイルも追加できます。

  • Apps Script には存在しない VBA 定数や値を定義できます。
  • 変換されていない API を実装します。
  • バリアントを解決する。

次の GS ファイルが Apps Script プロジェクトに追加されます。

  • Library.gs
  • Unimplemented_constructs.gs
  • Variant_resolutions.gs

Library.gs

通常は、library.gs ファイルを変更する必要はありません。

library.gs ファイルは、VBA コード内で使用されていた、Apps Script には存在しない関数と定数を定義します。これにより、新しい Apps Script コードが VBA コードに類似しています。また、library.gs ファイル内の関数または定数を使用するたびに定義を繰り返す必要もありません。

Unimplemented_constructs.gs

unimplemented_constructs.gs ファイルは、Macro Converter によって変換できなかった構造または API に対応します。コードを意図したとおりに動作させるには、このファイルの変更が必要になる場合があります。

例: Window.Activate()

以下は、Window.Activate() というサポートされていない API の例です。Macro Converter は、類似した名前で新しい Apps Script 関数を作成し、unimplemented_constructs.gs ファイルで定義します。VBA 関数はサポートされていないため、新しい Apps Script 関数は例外をスローします。

この新しい関数は、VBA コードで元の API が使用されていたすべての場所で、変換後の Apps Script コードに追加されます。

元の API の動作を再現するための回避策が見つかった場合は、unimplemented_constructs.gs ファイル内の関数の定義を更新するだけで済みます。ここで関数を定義すると、Apps Script プロジェクト内で関数が表示されるすべての場所に適用されます。

コードの例を以下に示します。

元の VBA コード

Window.activate()

変換済みの Apps Script コードをインラインで追加

_api_window_activate();

unimplemented_constructs.gs ファイルに追加された関数定義

/**
 * Could not convert window.activate API. Please add relevant code in the
 * following function to implement it.
 * This API has been used at the following locations in the VBA script.
 *     module1 : line 3
 *
 * We couldn't find an equivalent API in Apps Script for this VBA API. Please
 * reconsider if this function call is critical, otherwise consider implementing
 * it in a different way.
 */
function _api_window_activate(CallingObject) {
  ThrowException("API window.activate not supported yet.");
}

Variant_resolutions.gs

オブジェクトのタイプを特定できない場合、variant_resolutions.gs ファイルは Apps Script プロジェクトに追加されます。これには複数の理由があります。たとえば、API に複数の戻り値の型がある場合や、オブジェクトがバリアントとして宣言されている場合などです。

Macro Converter は、__handle_resolve_<api>() という新しい関数をこのファイルに追加します。対象の API は、この関数に置き換えられ、オブジェクト タイプを判別するのに役立ちます。

場合によっては、オブジェクト タイプを手動で宣言するために __handle_resolve_<api>() 関数の更新が必要になることがあります。サポートされていないオブジェクト タイプをご覧ください。

例: name()

VBA の多くのオブジェクト タイプで name() API が定義されています。通常、Apps Script の同等の機能は getName() ですが、すべてのオブジェクト タイプに当てはまるわけではありません。代替ケースは複数考えられます。

  • オブジェクトに対応する API は、getName() とは異なる呼び出しが行われます。
  • このオブジェクトには、名前を取得するための Apps Script API がありません。
  • 同等の Apps Script オブジェクトはありません。

オブジェクト タイプが決定されない場合、Macro Converter は __handle_resolve_name という新しい関数を variant_resolutions.gs ファイルに作成します。

コードの例を以下に示します。

元の VBA コード

a = Selection.name

この場合、現在の選択で API name() が呼び出されます。シート オブジェクトまたはシェイプ オブジェクトを選択できます。スプレッドシート オブジェクトの場合、翻訳は getName() ですが、シェイプ オブジェクトの場合、Apps Script には同等のものがありません。

変換済みの Apps Script コードをインラインで追加

a = __handle_resolve_name({}, getActiveSelection(), {});

さまざまなオブジェクト タイプを解決するため、以下の __handle_resolve_name() 関数を variant_resolution.gs ファイルに追加しています。この関数はオブジェクト タイプをチェックし、サポートされている場合は getName() を使用し、getName() がサポートされていない場合はエラーをスローします。

variant_resolution.gs ファイルに追加された関数定義

function __handle_resolve_name(ExecutionContext, CallingObject, params_map) {
  var found_api_variant = false;
  var return_value;
  if (String(CallingObject) == "Sheet") {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (CallingObject instanceof ChartInSheet) {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (!found_api_variant) {
    ThrowException("API .name not supported yet.");
  }
  return return_value;
}

エラーを探す

変換された Apps Script コードでエラーが発生すると、メッセージの種類とエラーの場所が示されます。エラー メッセージの形式は、使用している Apps Script ランタイムによって異なります。

デフォルトの V8 ランタイムを使用している場合は、次のようなエラーが表示されます。

_api_windows_active (unimplemented_constructs:2:3)

つまり、エラーは unimplemented_constructs.gs ファイルの 2 行目、3 文字目にあります。

非推奨の Rhino ランタイムを使用している場合は、次のようなエラーが表示されます。

unimplemented_constructs:2 (_api_windows_active)

つまり、エラーは unimplemented_constructs.gs ファイルの 2 行目にあります。

エラーの種類

上記の unimplemented_constructs.gs ファイルと variant_resolution.gs ファイルで発生するほとんどのエラーは修正できます。

発生する可能性のあるエラーには、次のようなものがあります。

未実装の API

未実装の API とは、Macro Converter で VBA から Apps Script に変換できず、API の既知の回避策がない API のことを指します。

実装されていない API は通常、空の関数として(空の署名を持つ場合もあります)unimplemented_constructs.gs ファイルに追加されます。オブジェクト タイプを特定できなかった場合、代わりに、実装されていない API が variant_resolution.gs ファイルに追加されていることがあります。

コンバージョンの前に生成された互換性レポートでは、この API に [さらなる調査が必要] というラベルが付きます。

ファイルを変換する前に VBA コード内でこの種の API を修正しなかった場合、Apps Script プロジェクトでの API は次のようになります。

/**
* Could not convert . Please add relevant code in the following
* function to implement it.
* This API has been used at the following locations in the VBA script.
*      : 
* We couldn't find an equivalent API in Apps Script for this VBA API. Please
* reconsider if this function call is critical, otherwise consider implementing
* it in a different way.
* @param param1 {}
* @param param2 {}
* ...
* @return {}
*/
function _api_(param1, param2, ....) {
  ThrowException("API  not supported yet.");
}

未実装 API エラーを修正する

既存の Apps Script API または JS ライブラリで、実装されていない API を定義します。 それには、次の手順を実施します。

  1. エラーがある箇所の変換済みの Apps Script コードを開きます。エラーの検索をご覧ください。
  2. 関数の上に、追加されたコメントを読みます。場合によっては、このコメントで Apps Script での API の実装方法を提案することがあります。
  3. Apps Script に API を実装する方法が見つからない場合は、コードから削除することを検討してください。
  4. 回避策が見つからない場合、またはコードからこの API を削除できず、マクロがこのエラーをスローした場合、このマクロを変換できません。

未実装の API エラーの例

API が実装されていない場合の例と、その修正方法は次のとおりです。

  • 対応する Apps Script はありません: Chart.Protect(Apps Script には存在しない API)の間接的な回避策が示されています。
  • 不明なオブジェクト タイプ: 変数であるオブジェクト タイプを処理する方法と、Apps Script で再作成できるサポートされていないオブジェクト タイプを実装する方法について説明します。
例 1: 同等の Apps Script または不明な API がない

この例では、Google スプレッドシート内にグラフを保護する方法がないため、Chart.Protect は自動的に変換されませんでした。

/**
* Could not convert chart.protect API. Please add relevant code in the following
* function to implement it.
*
* This API has been used at the following locations in the VBA script.
*     sheet1 : line 3
* You can use the following Apps Script APIs to convert it.
*
* Comments : Auto conversion of Chart.Protect is not supported yet. If the API is
* critical for the workflow the user can implement the unimplemented handler
* method in the generated code, else comment out the throw statement.
*
* @param {Object} CallingObject represents the parent object using which the API
* has been called.
* @param {string} Password
* @param {boolean} DrawingObjects
* @param {boolean} Contents
* @param {boolean} Scenarios
* @param {boolean} UserInterfaceOnly
*
*/
function _api_chart_protect(
   CallingObject, Password, DrawingObjects, Contents, Scenarios,
   UserInterfaceOnly) {
 ThrowException('API chart.protect not supported yet.');
}
グラフを保護することはできませんが、グラフのデータ範囲を保護して、データを変更できないようにすることは可能です。

範囲の保護の実装例を以下に示します。
/**
* Could not convert chart.protect API. Please add relevant code in the following
* function to implement it.
* This API has been used at the following locations in the VBA script.
*     sheet1 : line 3
*
* You can use the following Apps Script APIs to convert it.
* Comments : Auto conversion of Chart.Protect is not supported yet. If the API
* is critical for the workflow the user can implement the unimplemented handler
* method in the generated code, else comment out the throw statement.
*
* @param {Object} CallingObject represents the parent object using which the API
* has been called.
* @param {string} Password
* @param {boolean} DrawingObjects
* @param {boolean} Contents
* @param {boolean} Scenarios
* @param {boolean} UserInterfaceOnly
*/
function _api_chart_protect(
  CallingObject, Password, DrawingObjects, Contents, Scenarios, UserInterfaceOnly) {
var ranges = CallingObject.getChart().getRanges();
for (var i = 0; i < ranges.length; i++) {
  // Note that this does not lock the range for the document owner.
  ranges[i].protect();
}
}
例 2: サポートされていないオブジェクト タイプ

オブジェクト タイプが不明な場合、未実装 API エラーが variant_resolution.gs ファイルに追加されます。次の例は、上記の VBA name() API の例を拡張したものです。variant_resolution.gs をご覧ください。

この例では、次のことを学習します。

  1. name() API が variant_resolution.gs ファイル内の新しい関数に変換される仕組み
  2. 変換後のコードで新しい関数が呼び出される方法
  3. Apps Script でサポートされていないオブジェクト タイプである CommandBar の回避策を作成する方法

1. 変換後のコードは、name() が呼び出される正確なオブジェクト タイプを特定できないため、Macro Converter は以下に示すように __handle_resolve_name という新しい関数を作成します。

function __handle_resolve_name(ExecutionContext, CallingObject, params_map) {
 var found_api_variant = false;
 var return_value;
  if (String(CallingObject) == "Sheet") {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (CallingObject instanceof ChartInSheet) {
    if (!ExecutionContext.isLhs) {
      return_value = CallingObject.getName();
      found_api_variant = true;
    }
  }
  if (!found_api_variant) {
    ThrowException('API .name not supported yet.');
  }
  return return_value;
}

2. VBA コードで、name() API を呼び出す PrintName() 関数を定義しているとします。VBA コードは次のとおりです。

‘Defining a function that prints the name of the object in parameter
Sub PrintName(obj as Variant)
  Debug.Print obj.Name
End Sub
「name()」は変数であるオブジェクトで呼び出されるため、変換後のコードは変換時のオブジェクト型を認識しません。変換された Apps Script コードは、「__handle_resolve_name」関数を呼び出します。
function PrintName(obj) {
  Logger.log(_handle_resolve_name(obj));
}

3. VBA コードが、オブジェクト タイプ CommandBarPrintName() 関数を呼び出すとします。VBA コードは次のとおりです。

PrintName Application.CommandBars.item("Standard")
CommandBar は Apps Script ではサポートされていないため、上記の VBA コードで使用されている 2 つのメソッドもサポートされていません。
  • Application.CommandBars(): VBA では、すべての CommandBar オブジェクトのリストを返します。
  • CommandBars.item(): VBA では、特定の CommandBar オブジェクトを返します。
このオブジェクト タイプは Apps Script ではサポートされていないため、変換後のコードにより、定義する必要のある「unimplementationed_constructs.gs」ファイルに次の関数が作成されます。
  • _api_application_commandbars()
  • _api_commandbars_item()
以下に示すように、変換されたコードで関数は呼び出されます。
PrintName(_api_commandbars_item(_api_application_commandbars(), "Standard")))

Here’s how the new functions are added to the unimplemented_construct.gs file:

function _api_application_commandbars(CallingObject) {
  ThrowException('API application.commandbars not supported yet.');
}
function _api_commandbars_item(CallingObject, index) {
  ThrowException('API commandbars.item not supported yet.');
}

新しい関数を動作させる手順は次のとおりです。

3.1 CommandBars の機能を作成する新しいオブジェクト タイプと、VBA に存在するものと同様の CommandBars の新しいコレクションを定義する。

3.2 新しいオブジェクト タイプの getName() メソッドを追加する。

ステップ 3.1 と 3.2 を以下のコードに示します。メニュー オブジェクトは、CommandBars の動作を模倣した新しいオブジェクト タイプとして作成されます。

// Our Implementation of CommandBar using Menu objects.

function CommandBar(name) {
  this.name = name;
  // Create a menu object to represent the commandbar.
  this.menu = SpreadsheetApp.getUi().createMenu(name);
  // Create methods for retrieving or updating the name of the object
  this.getName = function() {
    return this.name;
  };
  this.updateName = function(name) {
    this.name = name;
  };
  // ========================================================================
  // Implement other methods of CommandBar objects that are used in the script.
  // =====================================================================
  return this;
}
// Our implementation of the collection of CommandBars that exists in VBA
function CommandBars() {
  this.commandBars = [];
  this.getCommandBar = function(name) {
    for (var i = 0; i < this.commandBars.length; i++) {
      if (!this.commandBars[i].getName() == name) {
        return this.commandBars[i];
      }
    }
    // No commandBar with the name exists, create a new one and return.
    var commandBar = new CommandBar(name);
    this.commandBars.push(commandBar);
    return commandBar;
  };
  return this;
}
// Create a global object that represents CommandBars collection.
var GlobalCommandBars = new CommandBars();

3.3 新しいオブジェクト タイプを処理するように、variant_resolution.gs ファイルの __handle_resolve_name 関数を変更する。次に示すように、関数にセクションを追加します。

function __handle_resolve_name(ExecutionContext, CallingObject, params_map) {
 var found_api_variant = false;
 var return_value;
 if (String(CallingObject) == "Sheet") {
   if (!ExecutionContext.isLhs) {
     return_value = CallingObject.getName();
     found_api_variant = true;
   }
 }
 if (CallingObject instanceof ChartInSheet) {
   if (!ExecutionContext.isLhs) {
     return_value = CallingObject.getName();
     found_api_variant = true;
   }
 }
 // New section added below
 // ========================================================================
 if (CallingObject instanceof CommandBar) {
   objectExtend(params_map, {VALUETOSET: params_map.param0});
   if (ExecutionContext.isLhs) {
     // Call the setter method.
     CallingObject.updateName(params_map.VALUETOSET);
     found_api_variant = true;
   } else {
     // Getter is called, return the commandbar name,
     return_value = CallingObject.getName();
     found_api_variant = true;
   }
 }
 // ========================================================================
 // New section added above
 if (!found_api_variant) {
   ThrowException('API .name not supported yet.');
 }
 return return_value;
}

3.4 unimplemented_constructs.gs ファイル(_api_application_commandbars()_api_commandbars_item())内に作成された 2 つの関数を定義します。このステップでは、関数の元の呼び出しが機能することを確認します。

//This is straightforward based on the implementation of a CommandBar and the
// CommandBars collection above:
function _api_application_commandbars(CallingObject) {
 return GlobalCommandBars;
}
function _api_commandbars_item(CallingObject, index) {
 return CallingObject.getCommandBar(index);
}

未実装の言語構造

構成constructは、実行フローまたはデータ表示を制御するコード言語の要素です。たとえば、ループ、ラベル、イベント、goto などです。 VBA 構成のリストをご確認ください。

Macro Converter が変換できない構造体は、未実装の言語構造体と見なされます。

Macro Converter は、実装されていない言語構造が存在すると判断した場合、TODO コメントを挿入します。

次の VBA 構造はサポートされていません。

未実装の言語構造エラーを修正する

  1. サポートされていない言語構造にロジックが依存しないようにコードを更新します。
  2. エラーがある箇所の変換済みの Apps Script コードを開きます。エラーの検索をご覧ください。
  3. コードのロジックに基づいて、サポートされていない言語構造を必要としない方法でコードを更新します。
  4. サポートされていない言語構造を使用せずにコードを書き換える方法が見つからない場合は、このマクロを変換できません。

実装されていない言語構造のエラーの例

実装されていない言語構造の中で最も一般的なものとして、GoTo ステートメントがあります。一部の VBA GoTo ステートメントはループに置き換えることができます。以下に、GoTo ステートメントの代わりにループを使用する例を 2 つ示します。

例 1: GoToWhile Loop に置き換える

元の VBA コード
Sub Test()
 a = 0
 start: Debug.Print a
 While a < 100
   a = a + 1
   If a Mod 3 == 0
     Goto start
   End If
 Wend
End Sub
同等の Apps Script コード
function test() {
 var a = 0;
 start: do {
   console.log(a);
   while (a < 100) {
     a = a + 1;
     if (a % 3 == 0) {
       continue start;
     }
   }
   break start;
 } while (true);
}

例 2: GoTo を For ループに置き換える

元の VBA コード
Sub Test()
 a = 0
 For i = 1 to 100
   For j = 1 to 10
     a =a a + 1
     If i + j > 50
       GoTo endLoop
     End If
   Next j
 Next i
 endLoop: MsgBox a
End Sub
同等の Apps Script コード
function test() {
 var a = 0;
 endLoop: for (var i = 1; i <= 100; i++) {
    for  (var j = 0; j <=10; j++) {
      If (i + j > 50) {
        break endLoop;
      }
    }
 }
 Browser.msgBox(a);
}

   break start;
 } while (true);
}

一部サポートされている API

部分的にサポートされている API の場合、Apps Script でサポートされている入力パラメータもあれば、サポートされていない入力パラメータもあります。

たとえば、VBA API の legend_position は、Excel グラフの凡例を定義するために使用されます。次のような複数の型の入力値がサポートされています。

  • xlLegendPositionBottom: 凡例をグラフの下部に配置します。
  • xlLegendPositionCorner: 凡例をグラフの隅に配置します。
  • xlLegendPositionCustom: 凡例をグラフのカスタム位置に配置します。

Apps Script には、これらの値の一部のみをサポートする同等のコードがあります。次の値はサポートされていません。

  • xlLegendPositionCorner
  • xlLegendPositionCustom

変換されたコードで部分的にサポートされている API のサポートされていない値を報告するため、それらの値をチェックする検証条件が library.gs ファイルに追加されます。次に例を示します。

if (position == xlLegendPositionCorner ||
     position == xlLegendPositionCustom) {
   position = _handle_legend_position_error(position);
}

検証条件でサポートされていない値が見つかると、エラーハンドラ関数 _handle_<API_name>_errorunimplemented_constructs.gs ファイルに作成されます。

この関数はユーザーエラーをスローし、値をサポートされている値に置き換えません。例:

/**
* Throw error message for unsupported legend position.
* The VBA API Legend.Position which can take values xlLegendPositionTop,
* xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight,
* xlLegendPositionCorner, xlLegendPositionCustom. It is partially supported in
* Apps Scripts that supports only a subset of the values (does not support
* xlLegendPositionCorner and xlLegendPositionCustom).
* @param {string} position
*/
function _handle_legend_position_error(position) {
// Please comment the throw statement and return a supported position value
// instead.
// Values that are supported here are xlLegendPositionTop,
// xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight.
throw new Error(
   'Google Sheets does not support legend position: ' + position);
}

部分的にサポートされている API エラーを修正する

_handle_<API_name>_error 関数を定義して、サポートされていない値を、必要に応じて許容される回避策に置き換えます。

  1. エラーがある箇所の変換済みの Apps Script コードを開きます。エラーの検索をご覧ください。
  2. 関数の上にあるコメントを読み、サポートされている値とサポートされていない値を確認してください。
  3. サポートされていない値については、適切な置換として使用できるサポートされている値を決定します。
  4. 関数 _handle_<API_name>_error を更新して、サポートされている値を返すようにしてください。
  5. サポートされていない値を置き換える方法が見つからない場合は、このマクロを変換できません。

部分的にサポートされている API エラーの例

次の例は、上記の VBA API legend_position を拡張したものです。部分的にサポートされている API をご覧ください。

サポートされていない値 xlLegendPositionCustom を使用する元の VBA コードの例を次に示します。

Charts(1).Legend.Position = xlLegendPositionCustom

Macro Converter は、次の関数を unimplemented_constructs.gs ファイルに追加します。

/**
* Throw error message for unsupported legend position.
* The VBA API Legend.Position which can take values xlLegendPositionTop,
* xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight,
* xlLegendPositionCorner, xlLegendPositionCustom. It is partially supported in
* Apps Scripts that supports only a subset of the values (does not support
* xlLegendPositionCorner and xlLegendPositionCustom).
* @param {string} position
*/
function _handle_legend_position_error(position) {
// Please comment the throw statement and return a supported position value
// instead.
// Values that are supported here are xlLegendPositionTop,
// xlLegendPositionLeft, xlLegendPositionBottom, xlLegendPositionRight.
throw new Error(
   'Google Sheets does not support legend position: ' + position);
}

手作業が必要

手作業が必要とは、VBA API を Apps Script に変換できるものの、回避策が必要なことを意味します。

変換前に生成された互換性レポートでは、このタイプの API には「対応策(回避策あり)」というラベルが付きます。

ファイルを変換する前に VBA コード内でこの種の API を修正しなかった場合、Apps Script プロジェクトでの API は次のようになります。

/**
* Could not convert  API. Please add relevant code in the following
* function to implement it.
* This API has been used at the following locations in the VBA script.
*      : 
*
* You can use the following Apps Script APIs to convert it.
* Apps Script APIs : 
* Apps Script documentation links : 
*
* @param param1 {}
* @param param2 {}
* ...
* @return {}
*/
function _api_(param1, param2, ....) {
 ThrowException("API  not supported yet.");
}

手作業が必要なエラーを修正する

API を意図したとおりに動作させるための回避策を実装します。 1. エラーがある箇所の変換済みの Apps Script コードを開きます。エラーを探すをご覧ください。1. 回避策として使用できる API を確認するには、関数の上にあるコメントをお読みください。 1. 適切な回避策が見つからない場合は、コードから API を削除することを検討してください。 1. 回避策が見つからない場合、またはコードからこの API を削除できない場合、マクロがエラーをスローした場合、このマクロを変換することはできません。

手作業が必要なエラーの例

手動作業が必要なエラーをスローする API の例と、その修正方法は次のとおりです。

例 1: Autocorrect.Addreplacement

次の例では、VBA API Autocorrect.Addreplacement を変換できますが、回避策が必要です。マクロ コンバータにより、コードコメント内に関数を実装する方法が提案されます。

/**
* Could not convert autocorrect.addreplacement API. Please add relevant code in
* the following function to implement it.
* This API has been used at the following locations in the VBA script.
*     sheet1 : line 3
* You can use the following Apps Script APIs to convert it.
* Apps Script APIs : FindReplaceRequest , onEdit
* Apps Script documentation links :
* https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit
* https://developers.google.com/sheets/api/eap/reference/rest/v4/spreadsheets/request?hl=en#findreplacerequest

* Comments : AutoCorrect.AddReplacement was not converted, but there is an
* equivalent option you can implement manually. Use onEdit and FindReplaceRequest
* APIs instead, see https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit
* and https://developers.google.com/sheets/api/eap/reference/rest/v4/spreadsheets/request?hl=en#findreplacerequest.
* For more information on API manual implementation, see
* https://developers.google.com/apps-script/guides/macro-converter/fix-conversion-errors.

* @param {Object} CallingObject represents the parent object using which the API
* has been called.
* @param {string} What
* @param {string} Replacement
* @return {string}
*/

function _api_autocorrect_addreplacement(CallingObject, What, Replacement) {
  ThrowException('API autocorrect.addreplacement not supported yet.');

}

Autocorrect.Addreplacement API の実装を以下に示します。

var AUTO_CORRECTIONS = "AUTO_CORRECTIONS";
// Need to get the autocorrections set in previous sessions and use them.
var savedAutoCorrections = PropertiesService.getDocumentProperties().getProperty(AUTO_CORRECTIONS);
var autoCorrections = savedAutoCorrections ? JSON.parse(savedAutoCorrections) : {};
function onEdit(e) {
autoCorrect(e.range);
}
function autoCorrect(range) {
for (key in autoCorrections) {
// Replace each word that needs to be auto-corrected with their replacements.
range.createTextFinder(key)
.matchCase(true)
.matchEntireCell(false)
.matchFormulaText(false)
.useRegularExpression(false)
.replaceAllWith(autoCorrections[key]);
}
}
/**
* Could not convert autocorrect.addreplacement API. Please add relevant code in
* the following function to implement it.
* This API has been used at the following locations in the VBA script.
* sheet1 : line 3
*
* You can use the following Apps Script APIs to convert it.
* Apps Script APIs : createTextFinder , onEdit
* Apps Script documentation links : https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit ,
createTextFinder
* Comments : AutoCorrect.AddReplacement was not converted, but there is an
* equivalent option you can implement manually. Use onEdit and FindReplaceRequest
* APIs instead, see https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit
* and createTextFinder. For more information on API manual implementation, see
* https://developers.google.com/apps-script/guides/macro-converter/fix-conversion-errors.
*
* @param {Object} CallingObject represents the parent object using which the API has been called.
* @param {string} What
* @param {string} Replacement
*
* @return {string}
*/

function _api_autocorrect_addreplacement(CallingObject, What, Replacement) {
autoCorrections[What] = Replacement;
// Store the updated autoCorrections in the properties so that future executions use the correction.
PropertiesService.getDocumentProperties().setProperty(AUTO_CORRECTIONS, JSON.stringify(autoCorrections));
}

例 2: Workbook.open()

VBA API workbook.open() は、ファイルパスに基づいてローカル ファイルを開きます。

VBA コードで workbook.open() によって 2 つのファイルが開かれているとします。

  • ファイル 1: C:\Data\abc.xlsx
  • ファイル 2: C:\Data\xyz.xlsx

下記は、Macro Converter が、Workbook.open() を使用してファイル 1 を開くために使用されているすべての場所で Workbook.open() を Apps Script に置き換える方法を示しています。

var spreadSheetId =
   _handle_mso_excel_get_google_spreadsheet_id("C:\Data\abc.xlsx");
var spreadSheet = SpreadsheetApp.openById(spreadSheetId);
以下のエラーが、Apps Script プロジェクトの unimplemented_constructs.gs ファイルに追加されます。
/**
* Method to return the spreadsheet id manually.
*
* @param {string} FileName ID of the spreadsheet to be opened.
* @return {string} return the spreadsheet id.
*/
function _handle_mso_excel_get_google_spreadsheet_id(FileName) {
 // Upload the Excel files being opened by the API to Google Drive and convert
 // them to Google Sheets.
 // Determine the spreadsheet ID of the Google Sheets file created.
 // Implement this method to return the corresponding spreadsheet ID when given
 //the original file path as parameter.
 throw new Error('Please return the spreadsheet ID corresponding to filename: ' + FileName);
 return '';
}

上のサンプルのコメントにあるように、ターゲット ファイルを Google ドライブ上の Google スプレッドシート ファイルに変換する必要があります。

以下は、対応する Google スプレッドシート ID の太字部分です。

  • ファイル 1: C:\Data\abc.xlsxhttps://docs.google.com/spreadsheets/d/abc123Abc123Abc123abc になります
  • ファイル 2: C:\Data\abc.xlsxhttps://docs.google.com/spreadsheets/d/xyz456Xyz456xYz456xyZ になります

次に、次のように Apps Script 関数のコードを変更して、ID でファイルを開くことができます。

/**
* Method to return the spreadsheet id manually.
*
* @param {string} FileName ID of the spreadsheet to be opened.
* @return {string} return the spreadsheet id.
*/
function _handle_mso_excel_get_google_spreadsheet_id(FileName) {
 // Upload the Excel files being opened by the API to Google Drive and convert
 //them to Google Sheets.
 // Determine the spreadsheet ID of the Google Sheets file created.
 // Implement this method to return the corresponding spreadsheet ID when given
 //the original file path as parameter
 if (Filename.indexOf("abc.xlsx") >= 0) {
   return "abc123Abc123Abc123abc";
 } else if (Filename.indexOf("xyz.xlsx") >= 0) {
   return "xyz456Xyz456xYz456xyZ";
 }

意図的なエラー

変換後のコードには、元の VBA コードのエラー動作を模倣するために、意図的なエラーが追加されます。これらのエラーを修正する必要はありません。

意図的なエラーの例

VBA で配列の境界を超えて要素にアクセスしようとすると、コードによって例外がスローされます。Apps Script では、コードは未定義を返します。

予期しない結果を回避するため、Macro Converter は、配列の境界を超えて要素にアクセスしようとすると例外をスローする Apps Script コードを追加します。

この例を次のコードに示します。

元の VBA コード
Dim arr
arr = Array("apple", "orange")
MsgBox arr(5)
Will throw the following error:
Subscript out of range
変換済みの Apps Script コード(例外エラーが追加される前)
var arr;
arr = ["apple", "orange"];
Browser.msgBox(arr[5]);
Will return this value and not throw an error:
undefined
例外エラーをスローする Apps Script コードを追加
/**
* Extend the regular JS array to support VB style indexing with a get method.
* @returns{*} value at the index
*/
Array.prototype.get = function() {
 var curr_res = this;
 for (var i = 0; i < arguments.length; i++) {
   if (!Array.isArray(curr_res) || curr_res.length < arguments[i]) {
     throw new Error(‘Converted VBA Error (Intentional Error): Subscript out of range’);
   }
   curr_res = curr_res[arguments[i]];
 }
 return curr_res;
};
var arr;
arr  = ["apple", "orange"];
Browser.msgBox(arr.get(5));