התוסף של מאקרו המרה הופך את רוב תהליך ההמרה לאוטומטי, אבל יכול להיות שתצטרכו לבצע שינויים בחלק מממשקי ה-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()
. - לאובייקט אין API Apps Script כדי לקבל את השם שלו.
- אין אובייקט מקביל ב-Apps Script.
כשסוג האובייקט לא נקבע, הכלי להמרת מאקרו יוצר פונקציה חדשה שנקראת __handle_resolve_name
בקובץ variant_resolutions.gs
.
לפניכם דוגמה בקוד:
קוד VBA מקורי
a = Selection.name
במקרה הזה, ה-API name()
יופעל בבחירה הנוכחית. הבחירה יכולה להיות אובייקט Sheets או אובייקט צורה. אם מדובר באובייקט של Sheets, התרגום הוא 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 שאי אפשר להמיר מ-VBA ל-Apps Script, ואין פתרון עקיף ידוע ל-API.
בדרך כלל, ממשקי API לא מוטמעים מתווספים לקובץ unimplemented_constructs.gs
כפונקציות ריקות (לפעמים עם חתימות ריקות). אם לא ניתן היה לזהות את סוג האובייקט, יכול להיות שבמקום זאת יתווסף לקובץ variant_resolution.gs
את ה-API שלא הוטמע.
בדוח התאימות שיצרתם לפני ההמרה, ה-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_ (param1, param2, ....) { ThrowException("API not 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: אין 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()
API שלמעלה. variant_resolution.gs
בדוגמה הזו נלמד:
- איך ה-API של
name()
עובר המרה לפונקציה חדשה בקובץvariant_resolution.gs
. - איך הפונקציה החדשה נקראת בקוד שהומר.
- כיצד ליצור ב-Apps Script פתרון חלופי עבור
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מכיוון ש-'name() ' מופעל באובייקט שהוא משתנה, הקוד לאחר ההמרה לא יודע מהו סוג האובייקט בזמן ההמרה. קוד Apps הסקריפט שהומר יקרא לפונקציה `__handle_resolve_name`:
function PrintName(obj) { Logger.log(_handle_resolve_name(obj)); }
3. נניח שקוד ה-VBA מפעיל את הפונקציה PrintName()
בסוג האובייקט CommandBar
. קוד ה-VBA מוצג בהמשך:
PrintName Application.CommandBars.item("Standard")
CommandBar
, ולכן גם שתי השיטות (method) שנעשה בהן שימוש בקוד ה-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 מגדירים את שתי הפונקציות שנוצרו בקובץ 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
- שם
- המשך
- Rset
- TypeOf
- סיווג
- מודולים של כיתה
תיקון שגיאות במבנה שפה לא מוטמע
- מעדכנים את הקוד כך שהלוגיקה לא תסתמך על מבנה השפה שאינו נתמך.
- במיקום השגיאה, פותחים את קוד Apps Script שהומר. ראו איתור שגיאות.
- בהתאם ללוגיקה של הקוד, מעדכנים אותו באופן שלא דורש את מבנה השפה שאינו נתמך.
- אם אי אפשר לשכתב את הקוד ללא מבנה השפה שאינו נתמך, אי אפשר להמיר את המאקרו הזה.
דוגמאות לשגיאות במבנה שפה לא מיושם
אחד ממבני השפה הלא מיושמים הנפוצים ביותר הוא הצהרה GoTo
.
אפשר להחליף הצהרות GoTo
של VBA בלולאות. בהמשך מופיעות שתי דוגמאות
לשימוש בלולאות במקום בהצהרות 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 בלולאת עבור
קוד 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); }
אם תנאי התיקוף ימצא אחד מהערכים שלא נתמכים, נוצרת פונקציית
handler של שגיאות
_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_ (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 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()
פותח קובץ מקומי על סמך נתיב של קובץ.
נניח שיש שני קבצים שנפתחים על ידי 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 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, הקוד מחזיר קוד לא מוגדר.
כדי למנוע תוצאות לא צפויות, הכלי להמרת מאקרו מוסיף קוד של 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
- פתרון בעיות נפוצות
- צפייה במדריכים של הכלי להמרת מאקרו
- רשימה של ממשקי API תואמים של VBA