תוסף Macro Converter ל-Google Workspace מבצע אוטומטית את רוב תהליך ההמרה, אבל יכול להיות שתצטרכו לבצע התאמות בחלק מממשקי ה-API ובפריטים אחרים כדי להשלים את הקוד.
המדריך הזה יעזור לכם להבין את קובצי Apps Script (קובצי GS) שנוספו לפרויקט, לפרש את סוגי השגיאות השונים וללמוד איך לתקן שגיאות.
הסבר על קובצי Apps Script שנוספו לפרויקט
קבצים נוספים של GS מתווספים לפרויקט Apps Script כדי לעזור לכם:
- הגדרת קבועים וערכים של VBA שלא קיימים ב-Apps Script.
- הטמעה של ממשקי API שלא הומרו.
- פתרון וריאציות.
הקבצים הבאים של GS מתווספים לפרויקט Apps Script:
Library.gsUnimplemented_constructs.gsVariant_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. מכיוון שהפונקציה של 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. בדרך כלל, המקבילה ב-Apps Script היא getName, אבל לא לכל סוג אובייקט. יכולים להיות כמה מקרים חלופיים:
- השיטה המקבילה של האובייקט נקראת בשם שונה מ-
getName. - לאובייקט אין API של Apps Script שאפשר להשתמש בו כדי לקבל את השם שלו.
- אין אובייקט מקביל ב-Apps Script.
אם סוג האובייקט לא נקבע, הכלי Macro Converter יוצר פונקציה חדשה בשם __handle_resolve_name בקובץ variant_resolutions.gs.
הנה דוגמה לקוד:
קוד VBA מקורי
a = Selection.name
במקרה הזה, ה-method name נקראת בבחירה הנוכחית. הבחירה יכולה להיות אובייקט Sheet או אובייקט Shape. אם זה אובייקט 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 שלא ניתן להמיר מ-VBA ל-Apps Script באמצעות Macro Converter, ואין פתרון עקיף ידוע לממשק ה-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 שלא הוטמע באמצעות ממשקי Apps Script API קיימים או ספריות 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. בדוגמה הבאה מוצגת הרחבה של הדוגמה לשיטת VBA name. מידע נוסף מפורט בvariant_resolution.gs.
בדוגמה הזו נסביר:
- איך השיטה
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:
‘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:
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 מופיעה במאמר Statements (הצהרות) (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 Subfunction 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 Subfunction 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 יש קוד מקביל שתומך רק בחלק מהערכים האלה. הערכים הבאים לא נתמכים:
xlLegendPositionCornerxlLegendPositionCustom
כדי לסמן ערכים לא נתמכים של ממשקי 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 כדי שהוא יפעל כמצופה. 1. פותחים את קוד Apps Script שהומר במיקום של השגיאה. איך מוצאים שגיאות 1. כדאי לקרוא את התגובה שמעל הפונקציה כדי להבין באילו ממשקי API אפשר להשתמש כדי למצוא פתרון עקיף. 1. אם לא מצאתם פתרון עקיף מתאים, כדאי להסיר את ה-API מהקוד. 1. אם לא הצלחתם למצוא פתרון עקיף או להסיר את ה-API הזה מהקוד, והמאקרו שלכם מחזיר שגיאה, לא תוכלו להמיר את המאקרו הזה.
דוגמאות לשגיאות שדורשות עבודה ידנית
ריכזנו כאן דוגמאות לממשקי API שמופיעות בהם שגיאות שדורשות עבודה ידנית, והסבר איך לפתור אותן:
דוגמה 1: Autocorrect.Addreplacement
בדוגמה הבאה, אפשר להמיר את VBA API Autocorrect.Addreplacement, אבל צריך לעקוף את הבעיה. הכלי להמרת פקודות מאקרו מציע איך להטמיע את הפונקציה בהערות הקוד.
/** * Could not convert autocorrect.addreplacement API. Please add relevant code in * the following function to implement it. * This API has been used at the following locations in the VBA script. * sheet1 : line 3 * You can use the following Apps Script APIs to convert it. * Apps Script APIs : FindReplaceRequest , onEdit * Apps Script documentation links : * https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit * https://developers.google.com/sheets/api/eap/reference/rest/v4/spreadsheets/request?hl=en#findreplacerequest * Comments : AutoCorrect.AddReplacement was not converted, but there is an * equivalent option you can implement manually. Use onEdit and FindReplaceRequest * APIs instead, see https://developers.google.com/apps-script/reference/script/spreadsheet-trigger-builder#onedit * and https://developers.google.com/sheets/api/eap/reference/rest/v4/spreadsheets/request?hl=en#findreplacerequest. * For more information on API manual implementation, see * https://developers.google.com/apps-script/guides/macro-converter/fix-conversion-errors. * @param {Object} CallingObject represents the parent object using which the API * has been called. * @param {string} What * @param {string} Replacement * @return {string} */ function _api_autocorrect_addreplacement(CallingObject, What, Replacement) { ThrowException('API autocorrect.addreplacement not supported yet.'); }
בדוגמה הבאה מוצגת ההטמעה של 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 פותח קובץ מקומי על סמך נתיב.
נניח שקוד ה-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 '' ; }
כמו שמוסבר בהערות בדוגמה הקודמת, צריך להמיר את קובצי היעד לקובצי Sheets ב-Drive.
המזהים המתאימים של גיליונות אלקטרוניים של Google מודגשים ברשימה הבאה:
- קובץ מספר 1:
C:\Data\abc.xlsxהופך ל-https://docs.google.com/spreadsheets/d/abc123Abc123Abc123abc - קובץ מספר 2:
C:\Data\xyz.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 rangevar 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
- רשימה של ממשקי API תואמים של VBA