변환된 코드의 오류 수정

매크로 변환기 부가기능은 대부분의 변환 프로세스를 자동화하지만 코드를 완성하려면 일부 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 파일은 매크로 변환기로 변환할 수 없는 구성이나 API를 처리합니다. 코드가 의도한 대로 작동하도록 하려면 이 파일을 수정해야 할 수 있습니다.

예: Window.Activate()

다음은 지원되지 않는 Window.Activate() API의 예입니다. 매크로 변환기는 비슷한 이름의 새 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에 여러 반환 유형이 있거나 객체가 변형 자체로 선언된 것과 같은 여러 가지 이유로 발생할 수 있습니다.

매크로 변환기는 이 파일에 __handle_resolve_<api>()라는 새 함수를 추가합니다. 이 함수는 해당 API를 대체하고 객체 유형을 결정하는 데 도움이 됩니다.

경우에 따라 __handle_resolve_<api>() 함수를 업데이트하여 객체 유형을 수동으로 선언해야 할 수 있습니다. 지원되지 않는 객체 유형을 참고하세요.

예: name()

VBA의 여러 객체 유형은 name() API를 정의합니다. 일반적으로 Apps Script 상응 항목은 getName()이지만 모든 객체 유형에 해당하는 것은 아닙니다. 다음과 같은 여러 대안 사례가 발생할 수 있습니다.

  • 객체의 해당 API는 getName()과 다른 것으로 호출됩니다.
  • 객체에 이름을 가져오는 Apps Script API가 없습니다.
  • 이에 상응하는 Apps Script 객체가 없습니다.

객체 유형이 결정되지 않으면 매크로 변환기가 variant_resolutions.gs 파일에 __handle_resolve_name라는 새 함수를 만듭니다.

다음은 코드의 예입니다.

원래 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.gsvariant_resolution.gs 파일에서 발생하는 대부분의 오류를 수정할 수 있습니다.

발생할 수 있는 오류 유형은 다음과 같습니다.

구현되지 않은 API

구현되지 않은 API는 Macro Converter로 VBA에서 Apps Script로 변환할 수 없는 API이며 이 API에 알려진 해결 방법이 없습니다.

구현되지 않은 API는 일반적으로 unimplemented_constructs.gs 파일에 빈 함수(빈 서명이 포함된 경우도 있음)로 추가됩니다. 객체 유형을 확인할 수 없는 경우 구현되지 않은 API가 variant_resolution.gs 파일에 추가될 수 있습니다.

전환 전에 생성한 호환성 보고서에서 이 API는 추가 조사 필요로 라벨이 지정됩니다.

파일을 변환하기 전에 VBA 코드에서 이 유형의 API를 수정하지 않으면 Apps Script 프로젝트에 다음과 같이 표시됩니다.

/**
* 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_<API_name>(param1, param2, ....) {
  ThrowException("API  not supported yet.");
}

구현되지 않은 API 오류 수정

기존 Apps Script API 또는 JS 라이브러리로 구현되지 않은 API를 정의합니다. 힙 덤프를 분석하려면 다음 단계를 따르세요.

  1. 오류가 발생한 위치에서 변환된 Apps Script 코드를 엽니다. 오류 찾기를 참고하세요.
  2. 함수 위에서 추가된 주석을 읽습니다. 경우에 따라 주석에 Apps Script에서 API를 구현하는 방법이 제안됩니다.
  3. Apps Script에서 API를 구현하는 방법을 찾을 수 없는 경우 코드에서 API를 삭제하는 것이 좋습니다.
  4. 해결 방법을 찾을 수 없거나 코드에서 이 API를 삭제할 수 없어 매크로에서 이 오류가 발생하면 이 매크로를 변환할 수 없습니다.

구현되지 않은 API 오류의 예

다음은 구현되지 않은 API 시나리오의 예와 이를 해결하는 방법입니다.

  • 상응하는 Apps Script가 없음: Apps Script에 없는 API인 Chart.Protect에 대한 간접적인 해결 방법을 표시합니다.
  • 알 수 없는 객체 유형: 변수인 객체 유형을 처리하는 방법과 Apps Script에서 다시 만들 수 있는 지원되지 않는 객체 유형을 구현하는 방법을 보여줍니다.
예시 1: 상응하는 Apps Script가 없거나 알 수 없는 API

이 예에서는 Google Sheets에서 차트를 보호할 방법이 없으므로 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()가 호출되는 정확한 객체 유형을 확인할 수 없으므로 매크로 변환기는 아래와 같이 __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 코드가 객체 유형 CommandBar에서 PrintName() 함수를 호출한다고 가정해 보겠습니다. VBA 코드는 다음과 같습니다.

PrintName Application.CommandBars.item("Standard")
CommandBar는 Apps Script에서 지원되지 않으므로 위의 VBA 코드에서 사용된 두 메서드도 지원되지 않습니다.
  • Application.CommandBars(): VBA에서는 모든 CommandBar 객체 목록을 반환합니다.
  • CommandBars.item(): VBA에서 특정 CommandBar 객체를 반환합니다.
이 객체 유형은 Apps Script에서 지원되지 않으므로 변환된 코드는 정의해야 하는 `unimplemented_constructs.gs` 파일에 다음 함수를 만듭니다.
  • _api_application_commandbars()
  • _api_commandbars_item()
다음과 같이 변환된 코드에서 함수가 호출됩니다.
PrintName(_api_commandbars_item(_api_application_commandbars(), "Standard")))

Heres 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())를 정의합니다. 이 단계를 통해 함수의 원래 호출이 작동하는지 확인할 수 있습니다.

//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);
}

구현되지 않은 언어 구성

구문은 실행 흐름 또는 데이터 표시를 제어하는 코드 언어의 요소입니다. 예를 들어 루프, 라벨, 이벤트, 고토가 있습니다. 모든 VBA 구성의 목록을 참고하세요.

매크로 변환기에서 변환할 수 없는 구성은 구현되지 않은 언어 구성으로 간주됩니다.

매크로 변환기가 구현되지 않은 언어 구성이 있다고 판단하는 경우 TODO 주석을 삽입합니다.

다음 VBA 구성은 지원되지 않습니다.

구현되지 않은 언어 구성 오류 수정

  1. 로직이 지원되지 않는 언어 구성을 사용하지 않도록 코드를 업데이트합니다.
  2. 오류가 발생한 위치에서 변환된 Apps Script 코드를 엽니다. 오류 찾기를 참고하세요.
  3. 코드의 로직에 따라 지원되지 않는 언어 구성이 필요하지 않은 방식으로 업데이트합니다.
  4. 지원되지 않는 언어 구성 없이 코드를 다시 작성하는 방법을 찾을 수 없는 경우 이 매크로를 변환할 수 없습니다.

구현되지 않은 언어 구성 오류의 예

구현되지 않은 가장 일반적인 언어 구성 중 하나는 GoTo 문입니다. 일부 VBA GoTo 문을 루프로 바꿀 수 있습니다. 다음은 GoTo 문 대신 루프를 사용하는 두 가지 예입니다.

예 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 Loop로 대체

원래 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

매크로 변환기는 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 프로젝트에 다음과 같이 표시됩니다.

/**
* 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_<API_name>(param1, param2, ....) {
 ThrowException("API  not supported yet.");
}

수동 작업이 필요한 오류 수정

API가 의도한 대로 작동하도록 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

아래는 파일 1을 열 때 Workbook.open()를 사용하는 모든 위치에서 매크로 변환기가 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 Drive의 Google Sheets 파일로 변환해야 합니다.

해당 Google Sheets 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에서는 코드가 정의되지 않음을 반환합니다.

예상치 못한 결과를 방지하기 위해 매크로 변환기는 배열의 범위를 벗어난 요소에 액세스하려고 하면 예외를 발생시키는 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));