ส่วนเสริมตัวแปลงมาโครจะทำให้กระบวนการ 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 ที่ไม่ได้ใช้งาน
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 ที่มีอยู่ โดยทำตามขั้นตอนต่อไปนี้
- เปิดโค้ด 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
ตัวอย่างต่อไปนี้เป็นข้อมูลเพิ่มเติมเกี่ยวกับตัวอย่าง VBA name()
API ด้านบน โปรดดู variant_resolution.gs
ในตัวอย่างนี้ คุณจะได้เรียนรู้เกี่ยวกับ
- วิธีแปลง API ของ
name()
เป็นฟังก์ชันใหม่ในไฟล์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เนื่องจากมีการเรียก "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")
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); }
โครงสร้างทางภาษาที่ไม่มีการนำมาใช้
constructคือองค์ประกอบของภาษาโค้ดที่ควบคุมโฟลว์การดำเนินการหรือการแสดงข้อมูล เช่น การวนซ้ำ ป้ายกำกับ เหตุการณ์ และโกโต รายการโครงสร้าง VBA ทั้งหมดมีดังนี้
โครงสร้างที่ตัวแปลงมาโครแปลงไม่ได้ถือเป็นโครงสร้างภาษาที่ไม่มีการใช้งาน
เมื่อตัวแปลงมาโครพิจารณาว่ามีโครงสร้างภาษาที่ไม่มีการใช้งาน ระบบจะแทรกความคิดเห็นใน TODO
ไม่รองรับโครงสร้าง VBA ต่อไปนี้
- AddressOf
- ประกาศ
- DefType
- GoSub
- GoTo
- การใช้งาน
- Lset
- เปิด
- RaiseEvent
- ชื่อ
- เล่นต่อ
- รีเซ็ต
- TypeOf
- ชั้นเรียน
- โมดูลชั้นเรียน
แก้ไขข้อผิดพลาดเกี่ยวกับโครงสร้างภาษาที่ไม่มีการใช้งาน
- อัปเดตโค้ดเพื่อไม่ให้ตรรกะของคุณพึ่งพาโครงสร้างภาษาที่ไม่รองรับ
- เปิดโค้ด Apps Script ที่แปลงแล้วในตำแหน่งที่มีข้อผิดพลาด ดูค้นหาข้อผิดพลาด
- อัปเดตตามตรรกะของโค้ดโดยไม่ต้องสร้างภาษาที่ไม่สนับสนุน
- หากไม่พบวิธีเขียนโค้ดใหม่หากไม่มีโครงสร้างภาษาที่ไม่รองรับ คุณจะแปลงมาโครนี้ไม่ได้
ตัวอย่างข้อผิดพลาดในการสร้างภาษาที่ไม่มีการใช้งาน
หนึ่งในโครงสร้างภาษาที่ไม่ค่อยมีคนนำไปใช้มากที่สุดคือคำสั่ง 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
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 ที่รองรับบางส่วน ระบบจะรองรับพารามิเตอร์การอินพุตบางรายการใน 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
เพื่อแทนที่ค่าที่ไม่รองรับด้วยวิธีแก้ปัญหาที่ยอมรับได้สําหรับความต้องการของคุณ
- เปิดโค้ด 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 ได้ แต่ต้องมีวิธีแก้ปัญหาเบื้องต้น
ในรายงานความเข้ากันได้ที่คุณสร้างก่อนการแปลง API ประเภทนี้จะมีป้ายกำกับว่ารองรับวิธีแก้ปัญหาเฉพาะหน้า
ถ้าคุณไม่แก้ไข API ประเภทนี้ในโค้ด VBA ก่อนที่จะแปลงไฟล์ ลักษณะของ API ที่ปรากฏในโครงการ 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_ (param1, param2, ....) { ThrowException("API not supported yet."); }
แก้ไขข้อผิดพลาดที่จำเป็นสำหรับงานที่ต้องทำด้วยตนเอง
ใช้วิธีแก้ปัญหาเฉพาะหน้าเพื่อให้ 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.'); }
การใช้งาน 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
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 ที่เข้ากันได้