התוסף Macro Converter מבצע אוטומטית את רוב תהליך ההמרה, אבל יכול להיות שתצטרכו לבצע שינויים בכמה ממשקי API ובפריטים אחרים כדי להשלים את הקוד.
במדריך הזה מוסבר על קובצי Apps Script (קובצי GS) שנוספו לפרויקט, על סוגי השגיאות השונים ועל אופן תיקון השגיאות.
הסבר על קובצי Apps Script שנוספו לפרויקט
קבצים נוספים של Google Sheets מתווספים לפרויקט 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 שלא ניתן היה להמיר באמצעות Macro Converter. כנראה שתצטרכו לשנות את הקובץ הזה כדי שהקוד שלכם יפעל כמו שרציתם.
לדוגמה: Window.Activate()
הנה דוגמה ל-API לא נתמך בשם Window.Activate()
.
הכלי Macro Converter יוצר פונקציית Apps Script חדשה עם שם דומה ומגדיר אותה בקובץ unimplemented_constructs.gs
. הפונקציה החדשה של Apps Script זורקת חריגה כי אין תמיכה בפונקציית VBA.
הפונקציה החדשה מתווספת לקוד 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 יש כמה סוגי החזרה או שהאובייקט מוצהר כמשתנה בעצמו.
הכלי Macro Converter מוסיף לפונקציה הזו קובץ חדש בשם __handle_resolve_<api>()
שמחליף את ה-API הרלוונטי ועוזר לקבוע את סוג האובייקט.
במקרים מסוימים, יכול להיות שתצטרכו לעדכן את הפונקציה __handle_resolve_<api>()
כדי להצהיר באופן ידני על סוג האובייקט. מידע נוסף על סוגי אובייקטים שלא נתמכים
לדוגמה: name()
הרבה סוגי אובייקטים ב-VBA מגדירים name()
API. בדרך כלל, המקבילה ב-Apps Script היא getName()
, אבל לא לכל סוג אובייקט. יכולות להיות כמה אפשרויות:
- השם של ה-API המקביל לאובייקט שונה מ-
getName()
. - לאובייקט אין Apps Script API כדי לקבל את השם שלו.
- אין אובייקט מקביל ב-Apps Script.
אם סוג האובייקט לא נקבע, הכלי Macro Converter יוצר פונקציה חדשה בשם __handle_resolve_name
בקובץ variant_resolutions.gs
.
הנה דוגמה לקוד:
קוד VBA מקורי
a = Selection.name
במקרה הזה, ה-API name()
מופעל על הבחירה הנוכחית. הבחירה יכולה להיות אובייקט של גיליון או אובייקט של צורה. אם זה אובייקט Sheet, התרגום הוא getName()
, אבל אם זה אובייקט Shape, אין לו מקבילה ב-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
שמתוארים למעלה.
סוגי השגיאות שאתם עשויים להיתקל בהן כוללים:
Unimplemented API
ממשק API שלא הוטמע הוא ממשק API ש-Macro Converter לא יכול להמיר מ-VBA ל-Apps Script, ואין פתרון עקיף ידוע ל-API.
ממשקי API שלא הוטמעו מתווספים בדרך כלל כפונקציות ריקות – לפעמים עם חתימות ריקות – לקובץ unimplemented_constructs.gs
. אם לא ניתן לקבוע את סוג האובייקט, יכול להיות שה-API שלא הוטמע יתווסף לקובץ variant_resolution.gs
.
בדוח התאימות שיצרתם לפני ההמרה, ה-API הזה מסומן כנדרשת בדיקה נוספת.
אם לא תתקנו את סוג ה-API הזה בקוד ה-VBA לפני שתמירו את הקובץ, כך הוא יופיע בפרויקט 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 שלא הוטמע באמצעות ממשקי API קיימים של Apps Script או ספריות JS. לשם כך, בצע את הצעדים הבאים:
- פותחים את קוד Apps Script שהומר במיקום השגיאה. איך מוצאים שגיאות
- מעל הפונקציה, קוראים את התגובה שנוספה. במקרים מסוימים, ההערה מציעה איך להטמיע את ה-API ב-Apps Script.
- אם אתם לא מצליחים להטמיע את ה-API ב-Apps Script, כדאי להסיר אותו מהקוד.
- אם לא הצלחתם למצוא פתרון עקיף או להסיר את ה-API הזה מהקוד, והמאקרו מחזיר את השגיאה הזו, לא תוכלו להמיר את המאקרו.
דוגמאות לשגיאות API שלא הוטמעו
הנה דוגמאות לתרחישי API שלא הוטמעו ואיך לפתור אותם:
- אין מקבילה ב-Apps Script:
מוצג פתרון עקיף ל-
Chart.Protect
, API שלא קיים ב-Apps Script. - סוג אובייקט לא ידוע: במאמר הזה מוסבר איך לטפל בסוג אובייקט שהוא משתנה, ואיך להטמיע סוג אובייקט לא נתמך שאפשר ליצור מחדש ב-Apps Script.
דוגמה 1: אין API מקביל ב-Apps Script או שמדובר ב-API לא ידוע
בדוגמה הזו, הפונקציה Chart.Protect
לא הומרה אוטומטית כי אין דרך להגן על תרשים ב-Google Sheets.
/** * 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 של VBA name()
שמופיע למעלה. מידע נוסף מפורט ב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()
שקוראת ל-API name()
קוד ה-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
לא נתמך ב-Apps Script, ולכן גם שתי השיטות שבהן נעשה שימוש בקוד 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()
method לסוג האובייקט החדש.
שלבים 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 מגדירים את שתי הפונקציות שנוצרו בקובץ 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); }
מבני שפה שלא יושמו
מבנה הוא רכיב של שפת הקוד ששולט בזרימת הביצוע או בתצוגת הנתונים. לדוגמה, לולאות, תוויות, אירועים ופקודות מעבר. רשימת כל מבני ה-VBA
מבנים שהכלי להמרת פקודות מאקרו לא יכול להמיר נחשבים מבני שפה שלא הוטמעו.
אם הכלי לשינוי מאקרו מזהה מבנה שפה שלא יושם, הוא מוסיף הערה TODO
.
אין תמיכה במבני ה-VBA הבאים:
- AddressOf
- הצהרה
- DefType
- GoSub
- GoTo
- Implements
- Lset
- פתוח
- RaiseEvent
- שם
- המשך
- Rset
- TypeOf
- כיתה
- Class Modules
תיקון שגיאות של מבני שפה שלא יושמו
- מעדכנים את הקוד כך שהלוגיקה לא תסתמך על מבנה השפה שלא נתמך.
- פותחים את קוד Apps Script שהומר במיקום השגיאה. איך מוצאים שגיאות
- בהתאם ללוגיקה של הקוד, מעדכנים אותו כך שלא נדרשת מבנה שפה לא נתמך.
- אם לא הצלחתם למצוא דרך לשכתב את הקוד בלי מבנה השפה שלא נתמך, לא תוכלו להמיר את פקודת המאקרו הזו.
דוגמאות לשגיאות שקשורות למבני שפה שלא הוטמעו
אחת מהמבנים הנפוצים ביותר בשפה שלא מיושמים היא הצהרת GoTo
.
אפשר להחליף חלק מההצהרות של VBA GoTo
בלולאות. בהמשך מופיעות שתי דוגמאות לשימוש בלולאות במקום בהצהרות 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
הכלי Macro Converter מוסיף את הפונקציה הבאה לקובץ 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 כדי שהוא יפעל כמצופה. 1. פותחים את קוד Apps Script שהומר במיקום השגיאה. אפשר לעיין במאמר בנושא חיפוש שגיאות. 1. כדאי לקרוא את התגובה שמעל הפונקציה כדי להבין באילו ממשקי API אפשר להשתמש כדי לעקוף את הבעיה. 1. אם לא הצלחתם למצוא פתרון עקיף מתאים, כדאי להסיר את ה-API מהקוד. 1. אם לא הצלחתם למצוא פתרון עקיף או להסיר את ה-API הזה מהקוד, והמאקרו שלכם מחזיר שגיאה, לא תוכלו להמיר את המאקרו הזה.
דוגמאות לשגיאות שדורשות עבודה ידנית
ריכזנו כאן דוגמאות לממשקי API שמוציאים שגיאות שדורשות עבודה ידנית, והסבר איך לפתור אותן:
Implement a workaround for Autocorrect.Addreplacement
.-
Implement a workaround for workbook.open()
. בדוגמה הזו מוסבר איך לפתוח קבצים ב-Google Drive באמצעות 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()
פותח קובץ מקומי על סמך נתיב קובץ.
נניח שקוד ה-VBA פותח שני קבצים באמצעות workbook.open()
:
- קובץ 1:
C:\Data\abc.xlsx
- קובץ 2:
C:\Data\xyz.xlsx
בדוגמה הבאה אפשר לראות איך Macro Converter מחליף את 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 Sheets ב-Google Drive.
מספרי הגיליונות האלקטרוניים המתאימים ב-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.
כדי למנוע תוצאות לא צפויות, הכלי Macro Converter מוסיף קוד 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));
מאמרים קשורים
- סקירה כללית של התוסף Macro Converter
- קביעה אם פקודות מאקרו של VBA תואמות
- המרת פקודות מאקרו של VBA ל-Apps Script
- פתרון בעיות נפוצות
- צפייה במדריכים בנושא Macro Converter
- רשימת ממשקי VBA API תואמים