ส่วนเสริมตัวแปลงมาโครจะทำให้กระบวนการแปลงส่วนใหญ่ทำงานได้โดยอัตโนมัติ แต่คุณอาจต้องปรับ 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
แทน
ในรายงานความเข้ากันได้ที่คุณสร้า���ขึ้นก่อน 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 ที่มีอยู่ โดยทำตามขั้นตอนต่อไปนี้
- เปิดโค้ด 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
ตัวอย่างต่อไปนี้เป็นการต่อยอดจากตัวอย่าง API name()
ของ 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เนื่องจากมีการเรียก "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")
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เป็นองค์ประกอบของภาษาโค้ดที่ควบคุมขั้นตอนการดำเนินการหรือการแสดงข้อมูล ตัวอย่างเช่น ลูป ป้ายกำกับ เหตุการณ์ และ gotos นี่คือรายการโครงสร้าง VBA ทั้งหมด
โครงสร้างที่ตัวแปลงมาโครไม่สามารถแปลงได้จะถือว่าเป็นโครงสร้างภาษาที่ยังไม่ได้ใช้งาน
เมื่อตัวแปลงมาโครพิจารณาว่ามีโครงสร้างภาษาที่ยังไม่ได้นำมาใช้อยู่ ก็จะแทรกความคิดเห็น TODO
ระบบไม่รองรับโครงสร้าง VBA ต่อไปนี้
- AddressOf
- ประกาศ
- DefType
- GoSub
- GoTo
- การใช้งาน
- การตั้งค่า
- เปิด
- RaiseEvent
- ชื่อ
- เล่นต่อ
- Rset
- 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 Script ได้ แต่ต้องมีวิธีแก้ปัญหาเฉพาะหน้า
ในรายงานความเข้ากันได้ที่คุณสร้างขึ้นก่อนการแปลง 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 เพื่อให้ 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 โค้ดจะแสดงโค้ดที่ไม่ได้กำหนด
เพื่อหลีกเลี่ยงผลลัพธ์ที่ไม่คาดคิด ตัวแปลงมาโครจะเพิ่มโค้ด 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 ที่เข้ากันได้