ส่วนเสริมตัวแปลงมาโครจะทํากระบวนการแปลงส่วนใหญ่โดยอัตโนมัติ แต่คุณอาจต้องปรับ 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 ที่ไม่ได้ใช้งาน
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_<API_name>(param1, param2, ....) { ThrowException("APInot supported yet." ); }
แก้ไขข้อผิดพลาดเกี่ยวกับ API ที่ไม่ได้ติดตั้งใช้งาน
กำหนด API ที่ยังไม่ได้นำมาใช้ด้วย Apps Script API หรือไลบรารี JS ที่มีอยู่ โดยทำตามขั้นตอนต่อไปนี้
- เปิดโค้ด Apps Script ที่แปลงแล้ว ณ ตำแหน่งที่เกิดข้อผิดพลาด ดูหัวข้อค้นหาข้อผิดพลาด
- อ่านความคิดเห็นที่เพิ่มไว้เหนือฟังก์ชัน ในบางกรณี ความคิดเห็นจะแนะนำวิธีใช้ API ใน Apps Script
- หากไม่พบวิธีใช้ API ใน Apps Script ให้ลองนำ API ออกจากโค้ด
- หากไม่พบวิธีแก้ปัญหาหรือนํา API นี้ออกจากโค้ดและมาโครแสดงข้อผิดพลาดนี้ คุณจะแปลงมาโครนี้ไม่ได้
ตัวอย่างข้อผิดพลาดของ API ที่ไม่ได้ติดตั้งใช้งาน
ต่อไปนี้คือตัวอย่างสถานการณ์ API ที่ไม่ได้ติดตั้งใช้งานและวิธีแก้ไข
- ไม่มี Apps Script ที่เทียบเท่า:
แสดงวิธีแก้ปัญหาทางอ้อมสำหรับ
Chart.Protect
ซึ่งเป็น API ที่ไม่มีใน Apps Script - ประเภทออบเจ็กต์ที่ไม่รู้จัก: แสดงวิธีจัดการประเภทออบเจ็กต์ที่เป็นตัวแปร และวิธีใช้ประเภทออบเจ็กต์ที่ไม่รองรับซึ่งสร้างใหม่ได้ใน Apps Script
ตัวอย่างที่ 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
ตัวอย่างต่อไปนี้ขยายความจากตัวอย่าง name()
API ของ VBA ด้านบน โปรดดู variant_resolution.gs
ในตัวอย่างนี้ คุณจะได้เรียนรู้สิ่งต่อไปนี้
- วิธีแปลง
name()
API เป็นฟังก์ชันใหม่ในไฟล์variant_resolution.gs
- วิธีเรียกใช้ฟังก์ชันใหม่ในโค้ดที่แปลงแล้ว
- วิธีสร้างวิธีแก้ปัญหาสำหรับ
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
function PrintName(obj) { Logger.log(_handle_resolve_name(obj)); }
3. สมมติว่าโค้ด VBA ของคุณเรียกใช้ฟังก์ชัน PrintName()
ในประเภทออบเจ็กต์ CommandBar
โค้ด VBA แสดงอยู่ด้านล่าง
PrintName Application.CommandBars.item("Standard")
CommandBar
และด้วยเหตุนี้ ระบบจึงไม่รองรับเมธอด 2 รายการที่ใช้ในโค้ด VBA ด้านบน
Application.CommandBars()
: ใน VBA คำสั่งนี้จะแสดงรายการออบเจ็กต์CommandBar
ทั้งหมดCommandBars.item()
: ใน VBA ระบบจะแสดงออบเจ็กต์CommandBar
ที่เจาะจง
_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); }
โครงสร้างภาษาที่ไม่ได้ใช้งาน
คอนสตรัคต์คือองค์ประกอบของภาษาโค้ดที่ควบคุมขั้นตอนการดำเนินการหรือการแสดงข้อมูล เช่น ลูป ป้ายกำกับ เหตุการณ์ และ gotos รายการคอนสตรัคต์ VBA ทั้งหมดมีดังนี้
โครงสร้างที่เครื่องมือแปลงมาโครแปลงไม่ได้จะถือว่าไม่ได้ใช้งาน โครงสร้างภาษา
เมื่อตัวแปลงมาโครพิจารณาว่ามีโครงสร้างภาษาที่ไม่ได้ใช้งานอยู่ ก็จะแทรกความคิดเห็น TODO
โครงสร้าง VBA ต่อไปนี้ไม่รองรับ
- AddressOf
- ประกาศ
- DefType
- GoSub
- GoTo
- ใช้งาน
- Lset
- เปิด
- RaiseEvent
- ชื่อ
- เล่นต่อ
- Rset
- TypeOf
- ชั้นเรียน
- โมดูลชั้นเรียน
แก้ไขข้อผิดพลาดเกี่ยวกับโครงสร้างภาษาที่ไม่ได้ติดตั้งใช้งาน
- อัปเดตโค้ดเพื่อไม่ให้ตรรกะของคุณใช้คอนสตรัคต์ภาษาที่ไม่รองรับ
- เปิดโค้ด Apps Script ที่แปลงแล้วในตำแหน่งที่เกิดข้อผิดพลาด ดูค้นหาข้อผิดพลาด
- และอัปเดตโค้ดในลักษณะที่ไม่จำเป็นต้องใช้โครงสร้างภาษาที่ไม่รองรับ ทั้งนี้ขึ้นอยู่กับตรรกะของโค้ด
- หากไม่พบวิธีเขียนโค้ดใหม่โดยไม่ใช้คอนสตรัคต์ภาษาที่ไม่รองรับ คุณจะแปลงมาโครนี้ไม่ได้
ตัวอย่างข้อผิดพลาดเกี่ยวกับโครงสร้างภาษาที่ไม่ได้ติดตั้งใช้งาน
หนึ่งในโครงสร้างภาษาที่นิยมใช้กันมากที่สุดคือคำสั่ง GoTo
คุณแทนที่คำสั่ง GoTo
ของ VBA บางรายการด้วยลูปได้ ด้านล่างนี้คือตัวอย่าง 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
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
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 ที่รองรับเพียงบางส่วน แอปสคริปต์จะรองรับพารามิเตอร์อินพุตบางรายการ แต่บางรายการไม่รองรับ
เช่น 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
เพื่อแทนที่ค่าที่ไม่รองรับด้วยวิธีแก้ปัญหาที่ยอมรับได้สำหรับความต้องการของคุณ
- เปิดโค้ด Apps Script ที่แปลงแล้วในตำแหน่งที่เกิดข้อผิดพลาด ดูหัวข้อค้นหาข้อผิดพลาด
- อ่านความคิดเห็นด้านบนฟังก์ชันเพื่อให้ทราบว่าระบบรองรับค่าใดบ้างและไม่รองรับค่าใด
- สําหรับค่าที่ไม่รองรับ ให้พิจารณาว่าค่าที่รองรับใดสามารถทำหน้าที่แทนที่ได้อย่างเหมาะสม
- อัปเดตฟังก์ชัน
_handle_<API_name>_error
ให้แสดงผลค่าที่รองรับแทน - หากไม่พบวิธีแทนที่ค่าที่ไม่รองรับ คุณจะแปลงมาโครนี้ไม่ได้
ตัวอย่างข้อผิดพลาดของ 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 ก่อนแปลงไฟล์ ลักษณะที่ปรากฏในโปรเจ็กต์ Apps Script จะเป็นดังนี้
/** * Could not convertAPI. Please add relevant code in the following * function to implement it. * This API has been used at the following locations in the VBA script. *: * * You can use the following Apps Script APIs to convert it. * Apps Script APIs :* Apps Script documentation links : * * @param param1 { } * @param param2 {} * ... * @return {} */ function _api_<API_name>(param1, param2, ....) { ThrowException("APInot supported yet." ); }
แก้ไขข้อผิดพลาดที่จำเป็นต้องดำเนินการด้วยตนเอง
ใช้วิธีแก้ปัญหาสำหรับ API เพื่อให้ API ทํางานตามที่ตั้งใจไว้ 1. เปิดโค้ด Apps Script ที่แปลงแล้ว ณ ตำแหน่งที่เกิดข้อผิดพลาด ดูหัวข้อค้นหาข้อผิดพลาด 1. อ่านความคิดเห็นเหนือฟังก์ชันเพื่อดูว่า API ใดบ้างที่ใช้แก้ปัญหาได้ 1. หากไม่พบวิธีแก้ปัญหาที่เหมาะสม ให้ลองนำ API ออกจากโค้ด 1. หากไม่พบวิธีแก้ปัญหาหรือนํา API นี้ออกจากโค้ดและมาโครแสดงข้อผิดพลาด คุณจะแปลงมาโครนี้ไม่ได้
ตัวอย่างข้อผิดพลาดที่ต้องใช้การดำเนินการด้วยตนเอง
ตัวอย่าง API ที่แสดงข้อผิดพลาดที่ต้องดำเนินการด้วยตนเองและวิธีแก้ไข
Implement a workaround for Autocorrect.Addreplacement
Implement a workaround for workbook.open()
ตัวอย่างนี้แสดงวิธีเปิดไฟล์ใน Google ไดรฟ์ด้วย Apps Script
ตัวอย่างที่ 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 โค้ดจะแสดงผลเป็น "undefined"
เครื่องมือแปลงมาโครจะเพิ่มโค้ด 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));
บทความที่เกี่ยวข้อง
- ภาพรวมของส่วนเสริมตัวแปลงมาโคร
- ตรวจสอบว่ามาโคร VBA เข้ากันได้หรือไม่
- แปลงมาโคร VBA เป็น Apps Script
- จัดการปัญหาที่พบได้ทั่วไป
- ดูบทแนะนำเกี่ยวกับตัวแปลงมาโคร
- รายการ VBA API ที่ใช้งานร่วมกันได้