VBA - Neshoda typov (chyba spustenia 13)

Čo je chyba nezhody typu?

Pri spustení kódu VBA sa často môže vyskytnúť chyba nesúladu. Chyba spôsobí, že sa váš kód úplne nespustí, a nahlási to prostredníctvom okna so správou, ktoré je potrebné vyriešiť

Upozorňujeme, že ak ste svoj kód pred distribúciou používateľom úplne nevyskúšali, toto chybové hlásenie bude pre používateľov viditeľné a spôsobí veľkú stratu dôvery vo vašu aplikáciu Excel. Používatelia bohužiaľ často robia aplikácii veľmi zvláštne veci a často sú to veci, o ktorých ste ako vývojár nikdy neuvažovali.

Vyskytla sa chyba nesúladu typu, pretože ste definovali premennú pomocou príkazu Dim ako určitý typ, napr. celé číslo, dátum a váš kód sa pokúša priradiť premennej hodnotu, ktorá nie je prijateľná, napr. textový reťazec priradený celočíselnej premennej ako v tomto prípade:

Tu je príklad:

Kliknite na Debug a problematický riadok kódu bude zvýraznený žltou farbou. Vo vyskakovacom okne s chybou nie je možné pokračovať, pretože ide o závažnú chybu a neexistuje spôsob, akým by kód mohol ďalej pokračovať.

V tomto konkrétnom prípade je riešením zmeniť príkaz Dim na typ premennej, ktorý pracuje s hodnotou, ktorú premennej priraďujete. Kód bude fungovať, ak zmeníte typ premennej na „String“ a pravdepodobne budete chcieť zmeniť aj názov premennej.

Zmena typu premennej však bude vyžadovať reset vášho projektu a budete musieť kód spustiť znova od začiatku, čo môže byť veľmi nepríjemné, ak ide o dlhý postup.

Chyba nesúladu spôsobená výpočtom pracovného hárka

Vyššie uvedený príklad je veľmi jednoduchým spôsobom, ako možno vytvoriť chybu nesúladu, a v tomto prípade je možné ho ľahko opraviť.

Príčina chýb nesúladu je však zvyčajne oveľa hlbšia a nie je taká zrejmá, keď sa pokúšate ladiť kód.

Predpokladajme napríklad, že ste napísali kód na vyzdvihnutie hodnoty na určitom mieste v hárku a obsahuje ďalšie bunky závislé od výpočtu v zošite (v tomto prípade B1)

Pracovný list vyzerá ako v tomto prípade so vzorcom na nájdenie konkrétneho znaku v reťazci textu

Z užívateľského hľadiska je bunka A1 voľného formátu a môže zadať ľubovoľnú hodnotu. Vzorec však hľadá výskyt znaku „B“ a v tomto prípade ho nenašiel, takže bunka B1 má chybovú hodnotu.

Testovací kód uvedený nižšie spôsobí chybu nesúladu, pretože do bunky A1 bola zadaná nesprávna hodnota

1234 Nesúlad čiastkových skúšok ()Dim MyNumber as IntegerMyNumber = Sheets ("Sheet1"). Range ("B1"). ValueKoniec pod

Hodnota v bunke B1 spôsobila chybu, pretože používateľ zadal do bunky A1 text, ktorý nevyhovuje tomu, čo sa očakávalo, a neobsahuje znak „B“.

Kód sa pokúša priradiť hodnotu premennej „Moje číslo“, ktorá bola definovaná tak, aby očakávala celé číslo, a tak sa zobrazí chyba nesúladu.

Toto je jeden z týchto príkladov, kde starostlivá kontrola kódu neposkytne odpoveď. Musíte sa tiež pozrieť na pracovný list, odkiaľ pochádza hodnota, aby ste zistili, prečo sa to deje.

Problém je v skutočnosti v pracovnom hárku a vzorec v B1 je potrebné zmeniť, aby bolo možné spracovať chybové hodnoty. Môžete to urobiť tak, že pomocou vzorca „IFERROR“ zadáte predvolenú hodnotu 0, ak sa nenájde hľadaný znak.

Potom môžete začleniť kód na kontrolu nulovej hodnoty a na zobrazenie varovného hlásenia používateľovi, že hodnota v bunke A1 je neplatná

12345678 Nesúlad čiastkových skúšok ()Dim MyNumber as IntegerMyNumber = Sheets ("Sheet1"). Range ("B1"). TextAk je moje číslo = 0, potomMsgBox „Hodnota v bunke A1 je neplatná“, vbCriticalUkončiť subKoniec AkKoniec pod

Môžete tiež použiť validáciu údajov (skupina Nástroje údajov na karte Údaje na páse s nástrojmi) v tabuľke, aby ste zabránili tomu, aby používateľ robil, čo sa mu páčilo, a v prvom rade spôsoboval chyby v hárku. Umožnite im iba zadať hodnoty, ktoré nespôsobia chyby v pracovnom hárku.

Môžete napísať kód VBA na základe udalosti Zmeniť v pracovnom hárku a skontrolovať, čo bolo zadané.

Pracovný list tiež chráni zámok a heslo, aby nebolo možné zadávať neplatné údaje

Chyba nesúladu spôsobená zadanými hodnotami bunky

Chyby nesúladu môžu byť spôsobené vo vašom kóde zavedením normálnych hodnôt z pracovného hárka (bez chyby), ale tam, kde používateľ zadal neočakávanú hodnotu, napr. textová hodnota, keď ste očakávali číslo. Možno sa rozhodli vložiť riadok do rozsahu čísel, aby mohli do bunky vložiť poznámku vysvetľujúcu niečo o čísle. Užívateľ koniec koncov netuší, ako váš kód funguje a že celú vec práve vyhodil z kiltera zadaním svojej poznámky.

Nasledujúci príklad kódu vytvára jednoduché pole s názvom „Moje číslo“ definované celočíselnými hodnotami

Kód potom iteruje v rozsahu buniek od A1 do A7, pričom priradí hodnoty buniek do poľa pomocou premennej „Coun“ na indexovanie každej hodnoty.

Keď kód dosiahne textovú hodnotu, spôsobí to chybu nesúladu a všetko sa zastaví

Kliknutím na položku „Ladiť“ v kontextovom okne s chybou sa zobrazí riadok kódu, v ktorom je problém zvýraznený žltou farbou. Keď umiestnite kurzor na ľubovoľný prípad premennej „Coun“ v kóde, uvidíte hodnotu „Coun“ v prípade zlyhania kódu, čo je v tomto prípade 5.

Pri pohľade na pracovný hárok uvidíte, že 5th bunka nadol má textovú hodnotu a to spôsobilo zlyhanie kódu

Kód môžete zmeniť tak, že zadáte podmienku, ktorá najskôr skontroluje číselnú hodnotu pred pridaním hodnoty bunky do poľa

12345678910111213 Nesúlad čiastkových skúšok ()Dim MyNumber (10) As Integer, Coun As IntegerPočítadlo = 1UrobAk je Coun = 11, potom Exit DoAk je číselné (hárky („sheet1“). Bunky (počítadlo, 1). Hodnota) PotomMyNumber (Coun) = Sheets ("sheet1"). Cells (Coun, 1). ValueInakMoje číslo (počítadlo) = 0Koniec AkPočítadlo = počítadlo + 1SlučkaKoniec pod

Kód pomocou funkcie „IsNumeric“ testuje, či je hodnota skutočne číslom, a ak je, zadá ju do poľa. Ak to nie je číslo, zadá hodnotu nula.

Tým sa zabezpečí, že index poľa bude v tabuľke v súlade s číslami riadkov buniek.

Do pracovného hárka „Chyby“ môžete tiež pridať kód, ktorý skopíruje pôvodnú hodnotu chyby a podrobnosti o mieste, aby používateľ pri spustení kódu videl, čo urobil zle.

Numerický test používa na priradenie hodnoty do poľa celý kód bunky a kód. Môžete namietať, že by to malo byť priradené k premennej, aby sa neopakoval rovnaký kód, ale problém je v tom, že by ste premennú museli definovať ako „variant“, čo nie je najlepšie urobiť.

Potrebujete tiež overenie údajov v pracovnom hárku a pracovný hárok chrániť heslom. Užívateľ tak nebude môcť vkladať riadky a zadávať neočakávané údaje.

Chyba nesúladu spôsobená volaním funkcie alebo čiastkovej rutiny pomocou parametrov

Keď sa zavolá funkcia, zvyčajne jej odovzdáte parametre pomocou dátových typov, ktoré už funkcia definovala. Funkcia môže byť funkcia už definovaná vo VBA alebo to môže byť funkcia definovaná používateľom, ktorú ste sami vytvorili. Drobná rutina môže tiež niekedy vyžadovať parametre

Ak nedodržíte konvencie o spôsobe odovzdávania parametrov do funkcie, zobrazí sa chyba nesúladu

12345678 Sub CallFunction ()Dim Ret ako celé čísloRet = MyFunction (3, "test")Koniec podFunkcia MyFunction (N ako celé číslo, T ako reťazec) ako reťazecMoja funkcia = TKoncová funkcia

Existuje niekoľko možností, ako získať chybu nesúladu

Návratová premenná (Ret) je definovaná ako celé číslo, ale funkcia vracia reťazec. Hneď ako spustíte kód, zlyhá, pretože funkcia vracia reťazec, ktorý nemôže ísť do celočíselnej premennej. Je zaujímavé, že spustenie ladenia v tomto kóde túto chybu nezachytí.

Ak umiestnite úvodzovky okolo prvého prechádzajúceho parametra (3), bude sa interpretovať ako reťazec, ktorý sa nezhoduje s definíciou prvého parametra vo funkcii (celé číslo)

Ak urobíte z druhého parametra volania funkcie číselnú hodnotu, zlyhá to s nesúladom, pretože druhý parameter v reťazci je definovaný ako reťazec (text)

Chyba nesúladu spôsobená nesprávnym použitím funkcií prevodu vo VBA

Existuje niekoľko funkcií prevodu, ktoré môžete vo VBA použiť na prevod hodnôt na rôzne typy údajov. Príkladom je „CInt“, ktorý prevádza reťazec obsahujúci číslo na celočíselnú hodnotu.

Ak reťazec, ktorý sa má previesť, obsahuje akékoľvek alfa znaky, zobrazí sa chyba nesúladu, aj keď prvá časť reťazca obsahuje číselné znaky a zvyšok sú alfa znaky, napr. „123abc“

Všeobecná prevencia chýb nesúladu

V príkladoch vyššie sme videli niekoľko spôsobov, ako sa vysporiadať s potenciálnymi chybami nesúladu vo vašom kóde, ale existuje niekoľko ďalších spôsobov, aj keď to nemusia byť najlepšie možnosti:

Definujte svoje premenné ako typ varianty

Variantný typ je predvoleným typom premennej vo VBA. Ak pre premennú nepoužívate príkaz Dim a jednoducho ho začnete používať vo svojom kóde, bude mu automaticky daný typ Variantu.

Premenná typu Variant bude akceptovať akýkoľvek typ údajov, či už ide o celé číslo, dlhé celé číslo, číslo s dvojnásobnou presnosťou, logickú hodnotu alebo textovú hodnotu. To znie ako úžasný nápad a čudujete sa, prečo každý nenastaví všetky svoje premenné na variant.

Variantný typ údajov má však niekoľko tienistých stránok. Po prvé, zaberá oveľa viac pamäte ako iné typy údajov. Ak ako variant definujete veľmi veľké pole, pri spustenom kóde VBA pohltí obrovské množstvo pamäte a môže ľahko spôsobiť problémy s výkonom.

Za druhé, výkon je vo všeobecnosti pomalší, ako keby ste používali konkrétne typy údajov. Ak napríklad robíte komplexné výpočty pomocou čísel s plávajúcou desatinnou čiarkou, výpočty budú výrazne pomalšie, ak čísla uložíte ako varianty, nie ako čísla s dvojnásobnou presnosťou.

Použitie variantného typu sa považuje za odfláknuté programovanie, pokiaľ to nie je nevyhnutné.

Na zvládnutie chýb použite príkaz OnError

Príkaz OnError môže byť zahrnutý do vášho kódu na riešenie zachytávania chýb, takže ak sa vyskytne chyba, používateľ namiesto štandardného vyskakovacieho okna s chybami VBA uvidí zmysluplnú správu

1234567 Sub ErrorTrap ()Dim MyNumber as IntegerPri chybe GoTo Err_HandlerMyNumber = "test"Err_Handler:MsgBox "Chyba" & Err.Popis & "došlo"Koniec pod

To efektívne zabráni tomu, aby chyba zastavila plynulý chod vášho kódu, a umožňuje užívateľovi bezproblémové zotavenie sa z chybovej situácie.

Rutina Err_Handler môže zobraziť ďalšie informácie o chybe a koho na ňu kontaktovať.

Z hľadiska programovania je pri použití rutiny spracovania chýb dosť ťažké nájsť riadok kódu, na ktorom sa chyba nachádza. Ak prechádzate kódom pomocou klávesu F8, hneď ako sa spustí problematický riadok kódu, skočí na rutinu spracovania chýb a nemôžete skontrolovať, kde sa deje chyba.

Možným riešením je nastaviť globálnu konštantu, ktorá je pravdivá alebo nepravdivá (logická hodnota), a pomocou nej zapnúť alebo vypnúť rutinu spracovania chýb pomocou príkazu „If“. Ak chcete chybu otestovať, stačí, ak nastavíte globálnu konštantu na hodnotu False a obsluha chýb už nebude fungovať.

1 Global Const ErrHandling = False
1234567 Sub ErrorTrap ()Dim MyNumber as IntegerAk ErrHandling = True, potom pri chybe GoTo Err_HandlerMyNumber = "test"Err_Handler:MsgBox "Chyba" & Err.Popis & "došlo"Koniec pod

Jediným problémom je, že to umožňuje užívateľovi zotaviť sa z chyby, ale zvyšok kódu v rámci podradenej rutiny sa nespustí, čo môže mať neskôr v aplikácii obrovské dôsledky.

Použitím predchádzajúceho príkladu cyklovania cez rozsah buniek by sa kód dostal do bunky A5 a narazil na nesúladnú chybu. Používateľovi sa zobrazí okno so správou s informáciami o chybe, ale nič od tejto bunky ďalej v rozsahu sa nespracuje.

Na potlačenie chýb použite príkaz OnError

Používa sa na to príkaz „Pri chybe Pokračovať ďalej“. Zahrnutie do kódu je veľmi nebezpečné, pretože zabraňuje zobrazeniu následných chýb. To v podstate znamená, že keď sa váš kód vykonáva, ak sa v riadku kódu vyskytne chyba, vykonanie sa jednoducho presunie na nasledujúci dostupný riadok bez vykonania chybového riadka a bude pokračovať ako obvykle.

To môže vyriešiť potenciálnu chybovú situáciu, ale bude to mať vplyv na každú budúcu chybu v kóde. Potom si môžete myslieť, že váš kód neobsahuje chyby, ale v skutočnosti to tak nie je a časti vášho kódu nerobia to, čo by podľa vás robiť malo.

Existujú situácie, keď je potrebné použiť tento príkaz, napríklad keď odstraňujete súbor pomocou príkazu „Zabiť“ (ak súbor neexistuje, vyskytne sa chyba), ale odchyt chýb by sa mal vždy prepnúť späť ihneď po tom, kde by sa mohla vyskytnúť potenciálna chyba, pomocou:

1 Pri chybe Choďte na 0

V predchádzajúcom príklade opakovania cyklu buniek pomocou „On Error Resume Next“ by to umožnilo pokračovať v slučke, ale bunka spôsobujúca chybu by nebola prenesená do poľa a prvok poľa pre tento konkrétny index bude mať nulovú hodnotu.

Konvertovanie údajov na typ údajov tak, aby zodpovedali deklarácii

Funkcie VBA môžete použiť na zmenu dátového typu prichádzajúcich údajov tak, aby zodpovedal dátovému typu prijímajúcej premennej.

Môžete to urobiť pri odovzdávaní parametrov funkciám. Ak napríklad máte číslo, ktoré je uložené v reťazcovej premennej, a chcete ho preniesť ako číslo do funkcie, môžete použiť CInt

Existuje niekoľko týchto funkcií prevodu, ktoré je možné použiť, ale tu sú hlavné:

CInt - prevádza reťazec, ktorý má číselnú hodnotu (pod + alebo - 32 768), na celočíselnú hodnotu. Uvedomte si, že sa tým skrátia všetky desatinné miesta

CLng - Konvertuje reťazec, ktorý má veľkú číselnú hodnotu, na dlhé celé číslo. Desatinné miesta sú skrátené.

CDbl - Konvertuje reťazec obsahujúci číslo s desatinnou čiarkou na číslo s dvojnásobnou presnosťou. Zahŕňa desatinné miesta

CDate - Konvertuje reťazec, ktorý obsahuje dátum, na premennú dátumu. Čiastočne to závisí od nastavení v ovládacom paneli systému Windows a vášho miestneho nastavenia od toho, ako sa interpretuje dátum

CStr - Konvertuje číselnú alebo dátumovú hodnotu na reťazec

Pri prevode z reťazca na číslo alebo dátum nesmie reťazec obsahovať nič iné ako čísla alebo dátum. Ak sú prítomné alfa znaky, spôsobí to chybu nesúladu. Tu je príklad, ktorý spôsobí chybu nesúladu:

123 Vedľajší test ()MsgBox CInt ("123abc")Koniec pod

Testovanie premenných vo vašom kóde

Premennú môžete otestovať a zistiť, o aký dátový typ ide, predtým, ako ju priradíte k premennej konkrétneho typu.

Pomocou funkcie „IsNumeric“ vo VBA môžete napríklad skontrolovať, či je reťazec číselný.

1 MsgBox je číselný („123test“)

Tento kód vráti hodnotu False, pretože hoci reťazec začína číselnými znakmi, obsahuje tiež text, takže v teste zlyhá.

1 MsgBox je číselný („123“)

Tento kód vráti hodnotu True, pretože obsahuje iba číselné znaky

Vo VBA existuje množstvo funkcií na testovanie rôznych typov údajov, ale toto sú hlavné:

IsNumeric - testuje, či je výraz číslo alebo nie

IsDate - testuje, či je výraz dátum alebo nie

IsNull - testuje, či je výraz nulový alebo nie. Nulovú hodnotu je možné vložiť iba do variantného objektu, inak sa zobrazí chyba „Neplatné použitie hodnoty Null“. Okno so správou vráti hodnotu null, ak ho používate na položenie otázky, takže návratová premenná musí byť variantom. Majte na pamäti, že akýkoľvek výpočet s hodnotou null vždy vráti výsledok null.

IsArray - testuje, či výraz predstavuje pole alebo nie

IsEmpty - testuje, či je výraz prázdny alebo nie. Všimnite si, že prázdne nie je to isté ako null. Premenná je pri prvom definovaní prázdna, ale nie je to nulová hodnota

Prekvapivo neexistuje žiadna funkcia pre IsText alebo IsString, ktorá by bola skutočne užitočná

Objekty a chyby nesúladu

Ak používate objekty, ako napríklad rozsah alebo hárok, zobrazí sa chyba nesúladu v čase kompilácie, nie v čase spustenia, čo vás varuje, že váš kód nebude fungovať.

123456 Rozsah čiastkového testu ()Dim MyRange As Range, I As LongNastaviť rozsah MyRange = rozsah ("A1: A2")Ja = 10x = UseMyRange (I)Koniec pod
12 Funkcia UseMyRange (R As Range)Koncová funkcia

Tento kód má funkciu nazvanú „UseMyRange“ a parameter je prenášaný ako objekt rozsahu. Parameter, ktorý sa prenáša, je však dlhé celé číslo, ktoré sa nezhoduje s typom údajov.

Keď spustíte kód VBA, okamžite sa skompiluje a zobrazí sa vám toto chybové hlásenie:

Urážlivý parameter bude zvýraznený modrým pozadím

Vo všeobecnosti, ak robíte chyby v kóde VBA pomocou objektov, zobrazí sa namiesto chybového hlásenia o nesúlade typu toto chybové hlásenie:

Vám pomôže rozvoju miesta, zdieľať stránku s priateľmi

wave wave wave wave wave