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

ส่วนเสริมตัวแปลงมาโครจะทำให้กระบวนการ Conversion ส่วนใหญ่เป็นไปโดยอัตโนมัติ แต่คุณอาจต้องปรับ 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 จะกำหนด API ของ name() โดยปกติแล้ว ค่าเทียบเท่าของ 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 แทน

ในรายงานความเข้ากันได้ที่คุณสร้างก่อนการแปลง 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 ตัวอย่างต่อไปนี้เป็นข้อมูลเพิ่มเติมเกี่ยวกับตัวอย่าง VBA name() API ด้านบน โปรดดู 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() ที่เรียกใช้ 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 Script ที่แปลงแล้วจะเรียกฟังก์ชัน `__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 Script ไม่รองรับออบเจ็กต์ประเภทนี้ โค้ดที่แปลงแล้วจะสร้างฟังก์ชันต่อไปนี้ในไฟล์ "unprocessored_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คือองค์ประกอบของภาษาโค้ดที่ควบคุมโฟลว์การดำเนินการหรือการแสดงข้อมูล เช่น การวนซ้ำ ป้ายกำกับ เหตุการณ์ และโกโต รายการโครงสร้าง 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 ได้ แต่ต้องมีวิธีแก้ปัญหาเบื้องต้น

ในรายงานความเข้ากันได้ที่คุณสร้างก่อนการแปลง 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 ทำงานตามที่ต้องการ 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.');

}

การใช้งาน 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()

VBA API workbook.open() จะเปิดไฟล์ในเครื่องตามเส้นทางของไฟล์

สมมติว่ามีไฟล์ 2 ไฟล์ที่เปิดโดย workbook.open() ในโค้ด 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 เพื่อแสดงข้อผิดพลาดเกี่ยวกับข้อยกเว้น
/**
* 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));