แก้ไขข้อผิดพลาดในโค้ดที่แปลงแล้ว

ส่วนเสริมตัวแปลงมาโครจะทำให้กระบวนการแปลงส่วนใหญ่ทำงานได้โดยอัตโนมัติ แต่คุณอาจต้องปรับ API บางรายการและรายการอื่นๆ เพื่อให้โค้ดของคุณสม����ร��์

ใช้คู่มือนี้เพื่อทำความเข้าใจไฟล์ Apps Script (ไฟล์ GS) ที่เพิ่มลงในโครงการ ตีความข้อผิดพลาดประเภทต่างๆ และดูวิธีแก้ไขข้อผิดพลาด

ทำความเข้าใจไฟล์ Apps Script ที่เพิ่มลงในโปรเจ็กต์ของคุณ

ระบบจะเพิ่มไฟล์ GS เพิ่มเติมลงในโปรเจ็กต์ Apps Script ของคุณเพื่อช่วยในการดำเนินการต่อไปนี้

  • กำหนดค่าคงที่และค่า VBA ที่ไม่มีใน Apps Script
  • ใช้ 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()

ต่อไปนี้เป็นตัวอย่างของ API ที่ไม่รองรับชื่อ Window.Activate() ตัวแปลงมาโครจะสร้างฟังก์ชันของ Apps Script ใหม่ที่มีชื่อคล้ายกันและระบุไว้ในไฟล์ unimplemented_constructs.gs เนื่องจากไม่รองรับฟังก์ชัน VBA ฟังก์ชันใหม่ของ Apps Script จึงจะมีข้อยกเว้น

ระบบจะเพิ่มฟังก์ชันใหม่ในโค้ด Apps Script ที่แปลงแล้วในทุกที่ที่ใช้ API เดิมในโค้ด VBA

หากคุณพบวิธีแก้ปัญหาเบื้องต้นเพื่อสร้างลักษณะการทำงานของ 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 ที่เทียบเท่า

เมื่อไม่มีการระบุประเภทออบเจ็กต์ ตัวแปลงมาโครจะสร้างฟังก์ชันใหม่ชื่อ __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 ที่ไม่ได้ใช้งานคือ API ที่ตัวแปลงมาโครไม่สามารถแปลงจาก VBA เป็น Apps Script และไม่มีวิธีแก้ปัญหาที่ทราบแล้วสำหรับ API

โดยปกติแล้ว API ที่ไม่ได้ใช้จะเพิ่มเป็นฟังก์ชันที่ว่างเปล่าลงในไฟล์ unimplemented_constructs.gs ซึ่งบางครั้งอาจมีลายเซ็นเปล่า หากระบุประเภทออบเจ็กต์ไม่ได้ ระบบอาจเพิ่ม API ที่ยังไม่ได้ใช้ลงในไฟล์ variant_resolution.gs แทน

ในรายงานความเข้ากันได้ที่คุณสร้า���ขึ้นก่อน Conversion API นี้จะมีป้ายกำกับเป็นต้องตรวจสอบเพิ่มเติม

หากคุณไม่แก้ไข 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 ที่ไม่ได้ใช้งาน

กำหนด API ที่ยังไม่ได้นำมาใช้ด้วย Apps Script API หรือไลบรารี JS ที่มีอยู่ โดยทำตามขั้นตอนต่อไปนี้

  1. เปิดโค้ด Apps Script ที่แปลงแล้วในตำแหน่งที่เกิดข้อผิดพลาด ดูหัวข้อหาข้อผิดพลาด
  2. อ่านความคิดเห็นที่เพิ่มไว้เหนือฟังก์ชัน ในบางกรณี ความคิดเห็นจะแนะนำวิธีใช้ API ใน Apps Script
  3. หากไม่พบวิธีนำ API ไปใช้ใน Apps Script ให้ลองนำ API ดังกล่าวออกจากโค้ด
  4. หากคุณไม่พบวิธีแก้ปัญหาหรือนำ API นี้ออกจากโค้ดของคุณ และมาโครของคุณแสดงข้อผิดพลาดนี้ คุณจะไม่สามารถแปลงมาโครนี้ได้

ตัวอย่างข้อผิดพลาดของ API ที่ไม่ได้ใช้งาน

ต่อไปนี้คือตัวอย่างสถานการณ์ API ที่ยังไม่ได้ใช้และวิธีแก้ไข

ตัวอย่างที่ 1: ไม่มี Apps Script ที่เทียบเท่าหรือ API ที่ไม่รู้จัก

ในตัวอย่างนี้ Chart.Protect ไม่ได้แปลงโดยอัตโนมัติ เนื่องจากไม่มีวิธีปกป้องแผนภูมิใน Google ชีต

/**
* 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 ตัวอย่างต่อไปนี้เป็นการต่อยอดจากตัวอย่าง API name() ของ VBA ด้านบน โปรดดู variant_resolution.gs

ในตัวอย่างนี้ คุณจะได้เรียนรู้เกี่ยวกับสิ่งต่อไปนี้

  1. วิธีที่ name() API แปลงเป็นฟังก์ชันใหม่ในไฟล์ 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() ที่เรียกใช้ name() API โค้ด 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()" ในออบเจ็กต์ที่เป็นตัวแปร โค้ดที่แปลงจึงไม่ทราบประเภทออบเจ็กต์ ณ เวลาที่เกิด Conversion โค้ด Apps สคริปต์ที่แปลงแล้วจะเรียกฟังก์ชัน "__handle_resolve_name" ดังนี้
function PrintName(obj) {
  Logger.log(_handle_resolve_name(obj));
}

3. สมมติว่าโค้ด VBA ของคุณเรียกใช้ฟังก์ชัน PrintName() ในประเภทออบเจ็กต์ CommandBar โค้ด VBA แสดงอยู่ด้านล่างนี้

PrintName Application.CommandBars.item("Standard")
Apps Script ไม่รองรับ CommandBar ดังนั้นระบบจะไม่รองรับ 2 วิธีที่ใช้ในโค้ด VBA ด้านบนด้วย
  • Application.CommandBars(): ใน VBA ระบบจะแสดงรายการออบเจ็กต์ CommandBar ทั้งหมด
  • CommandBars.item(): ใน VBA ระบบจะแสดงออบเจ็กต์ CommandBar ที่เจาะจง
เนื่องจากสคริปต์ Apps ไม่รองรับออบเจ็กต์ประเภทนี้ โค้ดที่แปลงแล้วจะสร้างฟังก์ชันต่อไปนี้ในไฟล์ `undisableed_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 กำหนดฟังก์ชัน 2 รายการที่สร้างขึ้นในไฟล์ 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 บางส่วนด้วยการวนซ้ำได้ ด้านล่างนี้คือ 2 ตัวอย่างของการใช้ลูปแทนคำสั่ง 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>_error ในไฟล์ 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 ที่รองรับบางส่วน

กำหนดฟังก์ชัน _handle_<API_name>_error เพื่อแทนที่ค่าที่ไม่รองรับด้วยวิธีแก้ปัญหาเบื้องต้นที่ยอมรับได้ตามความต้องการของคุณ

  1. เปิดโค้ด Apps Script ที่แปลงแล้วในตำแหน่งที่เกิดข้อผิดพลาด ดูหัวข้อหาข้อผิดพลาด
  2. อ่านความคิดเห็นด้านบนฟังก์ชันเพื่อทำความเข้าใจว่าค่าใดรองรับและไม่รองรับ
  3. สำหรับค่าที่ไม่รองรับ ให้ระบุค่าที่รองรับซึ่งทำหน้าที่เป็นค่าทดแทนที่เหมาะสมได้
  4. อัปเดตฟังก์ชัน _handle_<API_name>_error เพื่อแสดงค่าที่รองรับแทน
  5. หากไม่พบวิ���ีแทนที่ค่าที่ไม่รองรับ คุณจะ��ปลง���������ค���������ไ��่���ด้

ตัวอย่างข้อผิดพลาดของ API ที่รองรับบางส่วน

ตัวอย่างต่อไปนี้เป็นการต่อยอดใน VBA API legend_position ที่กล่าวไว้ข้างต้น ดู 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);
}

งานที่ต้องดำเนินการด้วยตนเอง

การทำงานด้วยตนเองหมายความว่า VBA API แปลงเป็น Apps Script ได้ แต่ต้องมีวิธีแก้ปัญหาเฉพาะหน้า

ในรายงานความเข้ากันได้ที่คุณสร้างขึ้นก่อนการแปลง API ประเภทนี้จะมีป้ายกำกับเป็นรองรับด้วยวิธีแก้ปัญหาชั่วคราว

หากคุณไม่แก้ไข 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() จะเปิดไฟล์ในเค��ื่องตามเส้นทางไฟล์

สมมติว่า workbook.open() เปิดไฟล์ 2 ไฟล์ในโค้ด VBA

  • ไฟล์ 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
โค้ด 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));