변환된 코드의 오류 수정

매크로 변환기 부가기능은 대부분의 변환 프로세스를 자동화하지만 코드를 완성하려면 일부 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 파일은 Apps Script에는 존재하지 않지만 VBA 코드에 사용된 함수와 상수를 정의합니다. 이렇게 하면 새 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 함수에서 예외가 발생합니다.

원본 API가 VBA 코드에서 사용된 모든 위치에서 변환된 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)

즉, 오류가 2행의 unimplemented_constructs.gs 파일에 있습니다.

오류 유형

위에 설명된 unimplemented_constructs.gsvariant_resolution.gs 파일에서 발생하는 대부분의 오류를 수정할 수 있습니다.

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

구현되지 않은 API

구현되지 않은 API는 매크로 변환기가 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_(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 없음: Apps Script에 존재하지 않는 API인 Chart.Protect에 대한 간접적인 해결 방법을 보여줍니다.
  • 알 수 없는 객체 유형: 변수인 객체 유형을 처리하는 방법과 지원되지 않는 객체 유형(예: Apps Script에서 다시 만들 수 있음)을 구현하는 방법을 보여줍니다.
예 1: 동등한 Apps Script 또는 알 수 없는 API가 없음

이 예시에서는 Chart.Protect가 자동으로 변환되지 않았습니다. Google Sheets에서는 차트를 보호할 수 있는 방법이 없기 때문입니다.

/**
* 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에서 지원되지 않으므로 변환된 코드는 사용자가 정의해야 하는 `unimplementationed_configurations.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())에서 생성된 두 함수를 정의합니다. 이 단계에서는 함수의 원래 호출이 작동하는지 확인합니다.

//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은 실행 흐름 또는 데이터 표시를 제어하는 코드 언어의 요소입니다. 루프, 라벨, 이벤트, gotos 등을 예로 들 수 있습니다. 전체 VBA 구성 목록을 확인하세요.

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

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

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

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

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

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

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

예시 1: GoTo을(를) While 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_(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()가 두 파일을 열고 있다고 가정해 보겠습니다.

  • 파일 1: C:\Data\abc.xlsx
  • 파일 2: C:\Data\xyz.xlsx

다음은 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 Drive의 Google Sheets 파일로 변환해야 합니다.

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

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