Dodatek Macro Converter automatyzuje większość procesu konwersji, ale w przypadku niektórych interfejsów API i innych elementów może być konieczne wprowadzenie zmian, aby sfinalizować kod.
Z tego przewodnika dowiesz się, jakie pliki Apps Script (pliki GS) zostały dodane do Twojego projektu, jak interpretować różne typy błędów i jak je naprawiać.
Informacje o plikach Apps Script dodanych do projektu
Do projektu Apps Script dodawane są dodatkowe pliki GS, które pomagają:
- Zdefiniuj stałe i wartości VBA, które nie istnieją w Apps Script.
- Wdrażaj interfejsy API, które nie zostały przekonwertowane.
- Rozwiąż warianty.
Do projektu Apps Script zostaną dodane te pliki GS:
Library.gs
Unimplemented_constructs.gs
Variant_resolutions.gs
Library.gs
Zazwyczaj nie musisz niczego modyfikować w pliku library.gs
.
Plik library.gs
definiuje funkcje i stałe, które były używane w kodzie VBA, ale nie istnieją w Apps Script. Dzięki temu nowy kod Apps Script będzie bardziej przypominać kod VBA. Nie musisz też powtarzać definicji za każdym razem, gdy używasz funkcji lub stałych z pliku library.gs
.
Unimplemented_constructs.gs
Plik unimplemented_constructs.gs
zawiera konstrukcje lub interfejsy API, których nie udało się przekonwertować za pomocą narzędzia Macro Converter. Aby kod działał zgodnie z oczekiwaniami, prawdopodobnie musisz zmodyfikować ten plik.
Przykład: Window.Activate()
Poniżej znajdziesz przykład nieobsługiwanego interfejsu API o nazwie Window.Activate()
.
Dodatek Macro Converter tworzy nową funkcję Apps Script o podobnej nazwie i definiuje ją w pliku unimplemented_constructs.gs
. Funkcja VBA nie jest obsługiwana, więc nowa funkcja Apps Script zgłasza wyjątek.
Nowa funkcja jest dodawana do przekonwertowanego kodu Apps Script wszędzie tam, gdzie w kodzie VBA użyto oryginalnego interfejsu API.
Jeśli znajdziesz obejście, które pozwoli odtworzyć działanie oryginalnego interfejsu API, wystarczy, że zaktualizujesz definicję funkcji w pliku unimplemented_constructs.gs
. Gdy funkcja zostanie tam zdefiniowana, będzie obowiązywać wszędzie, gdzie pojawi się w projekcie Apps Script.
Oto przykład w kodzie:
Oryginalny kod VBA
Window.activate()
Przekonwertowany kod Apps Script dodany w linii
_api_window_activate();
Definicja funkcji została dodana do pliku 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
Plik variant_resolutions.gs
jest dodawany do projektu Apps Script, jeśli nie można określić typu obiektu. Może to wynikać z różnych przyczyn, np. interfejs API może mieć wiele typów zwracanych lub obiekt jest zadeklarowany jako wariant.
Konwerter makr dodaje do tego pliku nową funkcję o nazwie __handle_resolve_<api>()
, która zastępuje dany interfejs API i pomaga określić typ obiektu.
W niektórych przypadkach może być konieczne zaktualizowanie funkcji __handle_resolve_<api>()
, aby ręcznie zadeklarować typ obiektu. Zobacz Nieobsługiwany typ obiektu.
Przykład: name()
Wiele typów obiektów w VBA definiuje interfejs name()
API. Zwykle odpowiednikiem w Apps Script jest getName()
, ale nie w przypadku każdego typu obiektu. Może wystąpić kilka alternatywnych przypadków:
- Odpowiednik obiektu w API ma inną nazwę niż
getName()
. - Obiekt nie ma interfejsu Apps Script API, który umożliwia pobranie jego nazwy.
- Nie ma odpowiedniego obiektu Apps Script.
Gdy typ obiektu nie zostanie określony, Konwerter makr utworzy w pliku variant_resolutions.gs
nową funkcję o nazwie __handle_resolve_name
.
Oto przykład w kodzie:
Oryginalny kod VBA
a = Selection.name
W tym przypadku interfejs API name()
jest wywoływany w odniesieniu do bieżącego zaznaczenia. Wybrany element może być obiektem arkusza lub kształtu. Jeśli jest to obiekt arkusza, tłumaczenie to getName()
, ale jeśli jest to obiekt kształtu, w Apps Script nie ma odpowiednika.
Przekonwertowany kod Apps Script dodany w linii
a = __handle_resolve_name({}, getActiveSelection(), {});
Poniższa funkcja __handle_resolve_name()
jest dodawana do pliku variant_resolution.gs
, aby rozwiązać problem z różnymi typami obiektów. Funkcja sprawdza typ obiektu, a potem używa funkcji getName()
, jeśli jest ona obsługiwana, lub zgłasza błąd, jeśli nie jest.getName()
Definicja funkcji została dodana do pliku 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; }
Znajdowanie błędów
Jeśli w przekonwertowanym kodzie Apps Script wystąpi błąd, komunikat określi jego typ i lokalizację. Format komunikatu o błędzie zależy od używanego środowiska wykonawczego Apps Script.
Jeśli korzystasz z domyślnego środowiska wykonawczego V8, zobaczysz błąd podobny do tego:
_api_windows_active (unimplemented_constructs:2:3)
Oznacza to, że błąd znajduje się w pliku unimplemented_constructs.gs
w wierszu 2, znak 3.
Jeśli korzystasz z wycofanego środowiska wykonawczego Rhino, zobaczysz błąd podobny do tego:
unimplemented_constructs:2 (_api_windows_active)
Oznacza to, że błąd znajduje się w pliku unimplemented_constructs.gs
w wierszu 2.
Typy błędów
Większość błędów, które napotkasz, możesz naprawić w plikach unimplemented_constructs.gs
i variant_resolution.gs
opisanych powyżej.
Możliwe typy błędów:
- Niezaimplementowany interfejs API
- Niezaimplementowana konstrukcja języka
- Częściowo obsługiwany interfejs API
- Wymagana praca ręczna
- Celowy błąd
Niezaimplementowany interfejs API
Niezaimplementowany interfejs API to interfejs API, którego Macro Converter nie może przekonwertować z VBA na Apps Script i dla którego nie ma znanego obejścia.
Niezaimplementowane interfejsy API są zwykle dodawane jako puste funkcje – czasami z pustymi sygnaturami – do pliku unimplemented_constructs.gs
. Jeśli nie można określić typu obiektu, niezaimplementowany interfejs API może zostać dodany do pliku variant_resolution.gs
.
W raporcie zgodności wygenerowanym przed konwersją ten interfejs API jest oznaczony jako Wymaga dalszego zbadania.
Jeśli przed przekonwertowaniem pliku nie naprawisz tego typu interfejsu API w kodzie VBA, w projekcie Apps Script będzie on wyglądać tak:
/** * 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." ); }
Naprawianie błędów niezaimplementowanego interfejsu API
Zdefiniuj niewdrożony interfejs API za pomocą istniejących interfejsów Apps Script API lub bibliotek JS. W tym celu wykonaj następujące czynności:
- Otwórz przekonwertowany kod Apps Script w miejscu wystąpienia błędu. Zobacz Wyszukiwanie błędów.
- Nad funkcją przeczytaj dodany komentarz. W niektórych przypadkach komentarz zawiera sugestie dotyczące implementacji interfejsu API w Apps Script.
- Jeśli nie możesz zaimplementować interfejsu API w Apps Script, rozważ usunięcie go z kodu.
- Jeśli nie możesz znaleźć obejścia ani usunąć tego interfejsu API z kodu, a makro zwraca ten błąd, nie możesz go przekonwertować.
Przykłady niezaimplementowanych błędów interfejsu API
Oto przykłady scenariuszy, w których interfejs API nie został zaimplementowany, oraz sposoby ich naprawy:
- Brak odpowiednika w Apps Script:
wyświetla pośrednie obejście problemu z interfejsem API
Chart.Protect
, który nie istnieje w Apps Script. - Nieznany typ obiektu: pokazuje, jak obsługiwać typ obiektu, który jest zmienną, oraz jak zaimplementować nieobsługiwany typ obiektu, który można odtworzyć w Apps Script.
Przykład 1. Brak odpowiednika w Apps Script lub nieznany interfejs API
W tym przykładzie symbol Chart.Protect
nie został automatycznie przekonwertowany, ponieważ nie ma możliwości ochrony wykresu w Arkuszach 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.'); }
Przykładowa implementacja ochrony zakresu jest pokazana poniżej:
/** * 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(); } }
Przykład 2. Nieobsługiwany typ obiektu
Jeśli typ obiektu jest nieznany, do pliku variant_resolution.gs
dodawany jest błąd niezaimplementowanego interfejsu API. Poniższy przykład rozwija przedstawiony powyżej przykład interfejsu API VBA name()
. Zobacz variant_resolution.gs
.
Z tego przykładu dowiesz się:
- Jak interfejs API
name()
jest przekształcany w nową funkcję w plikuvariant_resolution.gs
- Nazwa nowej funkcji w przekonwertowanym kodzie.
- Jak utworzyć obejście dla
CommandBar
, nieobsługiwanego typu obiektu, w Apps Script
1. Ponieważ przekonwertowany kod nie może określić dokładnego typu obiektu, do którego odwołuje się wywołanie name()
, Konwerter makr tworzy nową funkcję o nazwie __handle_resolve_name
, jak pokazano poniżej.
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. Załóżmy, że kod VBA definiuje funkcję PrintName()
, która wywołuje interfejs name()
API. Kod VBA jest widoczny poniżej:
‘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. Załóżmy, że kod VBA wywołuje funkcję PrintName()
na typie obiektu CommandBar
. Kod VBA jest widoczny poniżej:
PrintName Application.CommandBars.item("Standard")
CommandBar
nie jest obsługiwany w Apps Script, dlatego 2 metody użyte w powyższym kodzie VBA również nie są obsługiwane.
Application.CommandBars()
: W VBA zwraca listę wszystkich obiektów.CommandBar
CommandBars.item()
: W VBA zwraca określony obiekt.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.'); }
Aby nowe funkcje działały, wykonaj te czynności:
3.1 Zdefiniuj nowy typ obiektu, który tworzy funkcje CommandBars
i nową kolekcję CommandBars
podobną do tej, która istnieje w VBA.
3.2 Dodaj metodę getName()
dla nowego typu obiektu.
Kroki 3.1 i 3.2 są pokazane w poniższym kodzie. Obiekty menu są tworzone jako nowy typ obiektu, który naśladuje działanie 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 Zmodyfikuj funkcję __handle_resolve_name
w pliku variant_resolution.gs
, aby obsługiwała nowy typ obiektu. Dodaj do funkcji sekcję, jak pokazano poniżej:
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 Zdefiniuj 2 funkcje utworzone w pliku unimplemented_constructs.gs
(_api_application_commandbars()
, _api_commandbars_item()
). Ten krok zapewnia prawidłowe działanie oryginalnych wywołań funkcji.
//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); }
Niezaimplementowane konstrukcje językowe
Konstrukcja to element języka kodu, który kontroluje przepływ wykonywania lub wyświetlanie danych. Na przykład pętle, etykiety, zdarzenia i instrukcje goto. Oto lista wszystkich konstrukcji VBA.
Konstrukcje, których konwerter makr nie może przekonwertować, są uznawane za niezrealizowane konstrukcje języka.
Jeśli konwerter makr wykryje niezaimplementowaną konstrukcję językową, wstawia komentarz TODO
.
Te konstrukcje VBA nie są obsługiwane:
- AddressOf
- Zgłoś
- DefType
- GoSub
- GoTo
- Implementuje
- Lset
- Otwarte
- RaiseEvent
- Nazwa
- Wznów
- Rset
- TypeOf
- Zajęcia
- Moduły zajęć
Rozwiązywanie błędów związanych z niezrealizowanymi konstrukcjami językowymi
- Zaktualizuj kod, aby logika nie opierała się na nieobsługiwanej konstrukcji językowej.
- Otwórz przekonwertowany kod Apps Script w miejscu wystąpienia błędu. Zobacz Wyszukiwanie błędów.
- Zaktualizuj kod zgodnie z jego logiką w taki sposób, aby nie wymagał nieobsługiwanej konstrukcji językowej.
- Jeśli nie możesz znaleźć sposobu na przepisanie kodu bez konstrukcji w nieobsługiwanym języku, nie możesz przekonwertować tego makra.
Przykłady błędów dotyczących niezaimplementowanych konstrukcji językowych
Jedną z najczęstszych niezaimplementowanych konstrukcji językowych jest instrukcja GoTo
.
Niektóre instrukcje VBA GoTo
możesz zastąpić pętlami. Poniżej znajdziesz 2 przykłady użycia pętli zamiast instrukcji GoTo
.
Przykład 1. Zastąp GoTo
tekstem While Loop
Oryginalny kod 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); }
Przykład 2. Zastąpienie instrukcji GoTo pętlą For Loop
Oryginalny kod VBASub 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); }
Częściowo obsługiwany interfejs API
W przypadku częściowo obsługiwanych interfejsów API niektóre parametry wejściowe są obsługiwane w Apps Script, a niektóre nie.
Na przykład interfejs VBA API legend_position
służy do definiowania legendy na wykresie w Excelu. Obsługuje wiele typów wartości wejściowych, w tym:
xlLegendPositionBottom
: umieszcza legendę u dołu wykresu.xlLegendPositionCorner
: umieszcza legendę w rogu wykresu.xlLegendPositionCustom
: umieszcza legendę w niestandardowych miejscach na wykresie.
Apps Script ma odpowiednik kodu, który obsługuje tylko niektóre z tych wartości. Nie są obsługiwane te wartości:
xlLegendPositionCorner
xlLegendPositionCustom
Aby oznaczyć nieobsługiwane wartości częściowo obsługiwanych interfejsów API w przekonwertowanym kodzie, do pliku library.gs
dodawany jest warunek sprawdzający, czy te wartości występują. Na przykład:
if (position == xlLegendPositionCorner || position == xlLegendPositionCustom) { position = _handle_legend_position_error(position); }
Jeśli warunek weryfikacji znajdzie jedną z nieobsługiwanych wartości, w pliku unimplemented_constructs.gs
zostanie utworzona funkcja obsługi błędów _handle_<API_name>_error
.
Funkcja zgłasza błąd użytkownika i nie zastępuje wartości obsługiwaną wartością. Na przykład:
/** * 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); }
Naprawianie błędów częściowo obsługiwanych interfejsów API
Zdefiniuj funkcję _handle_<API_name>_error
, aby zastąpić nieobsługiwane wartości akceptowalnym rozwiązaniem, które spełni Twoje potrzeby.
- Otwórz przekonwertowany kod Apps Script w miejscu wystąpienia błędu. Zobacz Wyszukiwanie błędów.
- Przeczytaj komentarz nad funkcją, aby dowiedzieć się, które wartości są obsługiwane, a które nie.
- W przypadku wartości nieobsługiwanych określ, które wartości obsługiwane mogą być odpowiednim zamiennikiem.
- Zaktualizuj funkcję
_handle_<API_name>_error
, aby zwracała obsługiwaną wartość. - Jeśli nie możesz znaleźć sposobu na zastąpienie nieobsługiwanej wartości, nie możesz przekonwertować tego makra.
Przykład błędu interfejsu API, który jest częściowo obsługiwany
Poniższy przykład rozwija wspomniany wyżej interfejs VBA API legend_position
.
Zobacz Częściowo obsługiwany interfejs API.
Poniżej znajdziesz przykład oryginalnego kodu VBA, który używa nieobsługiwanej wartości,xlLegendPositionCustom
.
Charts(1).Legend.Position = xlLegendPositionCustom
Konwerter makr dodaje do pliku unimplemented_constructs.gs
tę funkcję:
/** * 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); }
Wymagana praca ręczna
Wymaga pracy ręcznej oznacza, że interfejs VBA API można przekonwertować na Apps Script, ale wymaga to obejścia.
W raporcie zgodności wygenerowanym przed konwersją ten typ interfejsu API jest oznaczony jako Obsługiwany z obejściami.
Jeśli przed przekonwertowaniem pliku nie naprawisz tego typu interfejsu API w kodzie VBA, w projekcie Apps Script będzie on wyglądać tak:
/** * 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." ); }
Naprawianie błędów wymagających ręcznej pracy
Wprowadź obejście interfejsu API, aby działał zgodnie z przeznaczeniem. 1. Otwórz przekonwertowany kod Apps Script w miejscu wystąpienia błędu. Zobacz Znajdowanie błędów. 1. Przeczytaj komentarz nad funkcją, aby dowiedzieć się, których interfejsów API można użyć w przypadku obejścia problemu. 1. Jeśli nie możesz znaleźć odpowiedniego obejścia, rozważ usunięcie interfejsu API z kodu. 1. Jeśli nie możesz znaleźć obejścia lub usunąć tego interfejsu API z kodu, a makro powoduje błąd, nie możesz go przekonwertować.
Przykłady błędów „Wymagana praca ręczna”
Oto przykłady interfejsów API, które zgłaszają błędy wymagające ręcznego działania, oraz sposoby ich naprawy:
Implement a workaround for Autocorrect.Addreplacement
.Implement a workaround for workbook.open()
. Ten przykład pokazuje, jak otwierać pliki na Dysku Google za pomocą Apps Script.
Przykład 1: Autocorrect.Addreplacement
W poniższym przykładzie interfejs VBA API Autocorrect.Addreplacement
można przekonwertować, ale wymaga to obejścia. Konwerter makr podpowiada, jak wdrożyć funkcję w komentarzach do kodu.
/** * 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.'); }
Implementacja interfejsu Autocorrect.Addreplacement
API jest pokazana poniżej:
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)); }
Przykład 2: Workbook.open()
Interfejs VBA API workbook.open()
otwiera plik lokalny na podstawie ścieżki do pliku.
Załóżmy, że w kodzie VBA są otwierane 2 pliki:workbook.open()
- Plik 1:
C:\Data\abc.xlsx
- Plik 2:
C:\Data\xyz.xlsx
Poniżej pokazujemy, jak Macro Converter zastępuje Workbook.open()
językiem Apps Script wszędzie tam, gdzie Workbook.open()
jest używany do otwierania pliku 1:
var spreadSheetId = _handle_mso_excel_get_google_spreadsheet_id("C:\Data\abc.xlsx"); var spreadSheet = SpreadsheetApp.openById(spreadSheetId);
unimplemented_constructs.gs
w projekcie Apps Script dodano poniższy błąd:
/** * 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 '' ; }
Zgodnie z instrukcjami w komentarzach w przykładzie powyżej musisz przekonwertować pliki docelowe na pliki Arkuszy Google na Dysku Google.
Odpowiednie identyfikatory arkuszy kalkulacyjnych Google są poniżej wyróżnione pogrubieniem:
- Plik 1:
C:\Data\abc.xlsx
staje sięhttps://docs.google.com/spreadsheets/d/abc123Abc123Abc123abc
- Plik 2:
C:\Data\abc.xlsx
zmienia się whttps://docs.google.com/spreadsheets/d/xyz456Xyz456xYz456xyZ
Następnie zmień kod w funkcji Apps Script, aby otwierać pliki według identyfikatora, jak pokazano poniżej:
/** * 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"; }
Błąd celowy
Do przekonwertowanego kodu dodawane są celowe błędy, które mają naśladować zachowanie oryginalnego kodu VBA. Nie musisz ich modyfikować.
Przykład celowego błędu
Jeśli w VBA spróbujesz uzyskać dostęp do elementu znajdującego się poza zakresem tablicy, kod zgłosi wyjątek. W Apps Script kod zwraca wartość nieokreśloną.
Aby uniknąć nieoczekiwanych wyników, Konwerter makr dodaje kod Apps Script, który zgłasza wyjątek, jeśli spróbujesz uzyskać dostęp do elementów wykraczających poza granice tablicy.
Ten przykład pokazano w poniższym kodzie:
Oryginalny kod VBADim 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));
Powiązane artykuły
- Omówienie dodatku Macro Converter
- Sprawdzanie zgodności makr VBA
- Przenoszenie makr VBA do Apps Script
- Rozwiązywanie typowych problemów
- Obejrzyj samouczki dotyczące konwertera makr
- Lista zgodnych interfejsów API VBA