Исправьте ошибки в преобразованном коде

Надстройка Macro Converter автоматизирует большую часть процесса преобразования, но вам может потребоваться внести изменения в некоторые API и другие элементы для завершения вашего кода.

Используйте это руководство, чтобы понять файлы Apps Script (файлы GS), добавленные в ваш проект, интерпретировать различные типы ошибок и научиться исправлять ошибки.

Понимание файлов Apps Script, добавленных в ваш проект

Дополнительные файлы GS добавляются в ваш проект Apps Script, чтобы помочь:

  • Определите константы и значения VBA, которых нет в Apps Script.
  • Внедряйте неконвертированные API.
  • Решите варианты.

В проект Apps Script добавляются следующие файлы GS:

  • 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()

Ниже приведен пример неподдерживаемого API под названием Window.Activate() . Конвертер макросов создает новую функцию Apps Script с аналогичным именем и определяет ее в файле unimplemented_constructs.gs . Поскольку функция VBA не поддерживается, новая функция Apps Script выдает исключение.

Новая функция добавляется в преобразованный код Apps Script везде, где в коде VBA использовался исходный API.

Если вы найдете обходной путь для воссоздания поведения исходного 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 определяют API name() . Обычно эквивалентом Apps Script является getName() , но не для каждого типа объекта. Может возникнуть несколько альтернативных случаев:

  • Эквивалентный API объекта называется иначе, чем getName() .
  • У объекта нет API Apps Script, чтобы получить его имя.
  • Эквивалентного объекта Apps Script не существует.

Если тип объекта не определен, конвертер макросов создает новую функцию с именем __handle_resolve_name в файле variant_resolutions.gs .

Вот пример в коде:

Исходный код VBA

a = Selection.name

В этом случае API name() вызывается для текущего выбора. Выделением может быть объект «Лист» или объект «Форма». Если это объект Sheet, то перевод будет getName() , но если это объект Shape, то в 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 вы используете.

Если вы используете среду выполнения 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 — это API, который конвертер макросов не может преобразовать из VBA в Apps Script, и для этого API не существует известного обходного пути.

Нереализованные API обычно добавляются как пустые функции (иногда с пустыми подписями) в файл unimplemented_constructs.gs . Если тип объекта определить не удалось, вместо этого нереализованный API можно добавить в файл variant_resolution.gs .

В отчете о совместимости, созданном вами перед преобразованием, этот API помечен как «Требует дополнительного исследования» .

Если вы не исправите этот тип API в своем коде VBA перед преобразованием файла, вот как он будет выглядеть в проекте 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

Определите нереализованный API с помощью существующих API-интерфейсов Apps Script или библиотек JS. Для этого выполните следующие действия:

  1. Откройте преобразованный код скрипта приложений в месте ошибки. См. раздел Поиск ошибок .
  2. Над функцией прочтите добавленный комментарий. В некоторых случаях в комментарии предлагается, как реализовать API в Apps Script.
  3. Если вы не можете найти способ реализовать API в Apps Script, рассмотрите возможность удаления его из своего кода.
  4. Если вы не можете найти обходной путь или удалить этот API из своего кода, а ваш макрос выдает эту ошибку, вы не сможете преобразовать этот макрос.

Примеры нереализованных ошибок API

Вот примеры нереализованных сценариев API и способы их исправления:

  • Эквивалента Apps Script нет : показывает косвенный обходной путь для Chart.Protect — API, которого нет в Apps Script.
  • Неизвестный тип объекта . Показывает, как обрабатывать тип объекта, являющийся переменной, и как реализовать неподдерживаемый тип объекта, который можно воссоздать в Apps Script.
Пример 1. Нет эквивалентного скрипта приложений или неизвестного 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: Неподдерживаемый тип объекта

Если тип объекта неизвестен, в файл variant_resolution.gs добавляется ошибка нереализованного API. Следующий пример расширяет приведенный выше пример API VBA name() . См. variant_resolution.gs .

В этом примере вы узнаете:

  1. Как API name() преобразуется в новую функцию в файле variant_resolution.gs .
  2. Как вызывается новая функция в преобразованном коде .
  3. Как создать обходной путь для CommandBar , неподдерживаемого типа объекта, в Apps Script .

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 определяет функцию PrintName() , которая вызывает API name() . Код 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 вызывает функцию PrintName() для типа объекта CommandBar . Код 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")))

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 и новую коллекцию CommandBars , аналогичную той, что существует в VBA.

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 Измените функцию __handle_resolve_name в файле 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;
   }
 }
 // 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. Откройте преобразованный код скрипта приложений в месте ошибки. См. раздел Поиск ошибок .
  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
Эквивалентный код сценария приложений
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
Эквивалентный код сценария приложений
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, а некоторые нет.

Например, legend_position API VBA используется для определения легенды на графике Excel. Он поддерживает несколько типов входных значений, в том числе:

  • xlLegendPositionBottom : помещает легенду внизу диаграммы.
  • xlLegendPositionCorner : помещает легенду в угол диаграммы.
  • xlLegendPositionCustom : помещает легенду в произвольные позиции на диаграмме.

Apps Script имеет эквивалентный код, который поддерживает только некоторые из этих значений. Следующие значения не поддерживаются:

  • xlLegendPositionCorner
  • xlLegendPositionCustom

Чтобы пометить неподдерживаемые значения частично поддерживаемых API в преобразованном коде, в файл library.gs добавляется условие проверки, которое проверяет эти значения. Например:

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

Если условие проверки обнаруживает одно из неподдерживаемых значений, в файле unimplemented_constructs.gs создается функция обработчика ошибок _handle_<API_name>_error .

Функция выдает ошибку пользователя и не заменяет значение поддерживаемым значением. Например:

/**
* 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. Откройте преобразованный код скрипта приложений в месте ошибки. См. раздел Поиск ошибок .
  2. Прочтите комментарий над функцией, чтобы понять, какие значения поддерживаются, а какие нет.
  3. Для неподдерживаемых значений определите, какие поддерживаемые значения могут служить подходящей заменой.
  4. Обновите функцию _handle_<API_name>_error , чтобы она вместо этого возвращала поддерживаемое значение.
  5. Если вы не можете найти способ заменить неподдерживаемое значение, вы не сможете преобразовать этот макрос.

Пример ошибки частично поддерживаемого API

Следующий пример расширяет упомянутую выше legend_position VBA API. См. Частично поддерживаемый API .

Ниже приведен пример исходного кода VBA, в котором используется неподдерживаемое значение xlLegendPositionCustom .

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

Нужна ручная работа

Необходимость ручной работы означает, что API VBA можно преобразовать в скрипт приложений, но для этого требуется обходной путь.

В отчете о совместимости, созданном перед преобразованием, этот тип API помечен как «Поддерживается с обходными путями» .

Если вы не исправите этот тип API в своем коде VBA перед преобразованием файла, вот как он будет выглядеть в проекте 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

В следующем примере API VBA 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.');

}

Реализация API Autocorrect.Addreplacement показана ниже:

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()

workbook.open() API VBA открывает локальный файл на основе пути к файлу.

Предположим, что в коде VBA с помощью workbook.open() открываются два файла:

  • Файл 1: C:\Data\abc.xlsx
  • Файл 2: C:\Data\xyz.xlsx

Ниже показано, как конвертер макросов заменяет Workbook.open() на Apps Script везде, где Workbook.open() используется для открытия файла 1:

var spreadSheetId =
   _handle_mso_excel_get_google_spreadsheet_id("C:\Data\abc.xlsx");
var spreadSheet = SpreadsheetApp.openById(spreadSheetId);
Приведенная ниже ошибка добавлена ​​в файл unimplemented_constructs.gs в проекте Apps Script:
/**
* 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 выделены жирным шрифтом ниже:

  • Файл № 1: C:\Data\abc.xlsx становится https://docs.google.com/spreadsheets/d/ abc123Abc123Abc123abc .
  • Файл №2: C:\Data\abc.xlsx становится https://docs.google.com/spreadsheets/d/ xyz456Xyz456xYz456xyZ

Затем измените код в функции Apps Script, чтобы открывать файлы по идентификатору, как показано ниже:

/**
* 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
Преобразованный код сценария приложений (до добавления ошибки исключения)
var arr;
arr = ["apple", "orange"];
Browser.msgBox(arr[5]);
Will return this value and not throw an error:
undefined
Добавлен код сценария приложений для выдачи ошибки исключения.
/**
* 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));