VBA - tüübi mittevastavus (käitustõrge 13)

Mis on tüübi mittevastavuse viga?

VBA -koodi käivitamisel võib sageli ilmneda mittevastavuse viga. Viga peatab teie koodi täieliku töötamise ja märgib teate kasti abil, et see viga vajab lahendamist

Pange tähele, et kui te pole oma koodi enne kasutajatele levitamist täielikult testinud, on see veateade kasutajatele nähtav ja põhjustab teie Exceli rakenduse suhtes suure usalduse kaotuse. Kahjuks teevad kasutajad sageli rakendusega väga omapäraseid asju ja sageli on need asjad, mida teie kui arendaja pole kunagi kaalunud.

Tüübi mittevastavuse viga ilmneb seetõttu, et olete määratlenud muutuja, kasutades lauset Dim teatud tüübina, nt täisarv, kuupäev ja teie kood üritab määrata muutujale väärtust, mis pole vastuvõetav, nt tekstistring, mis on määratud täisarvumuutujale, nagu selles näites:

Siin on näide:

Klõpsake nuppu Silumine ja solvav koodirida on kollasega esile tõstetud. Vea hüpikaknas pole võimalust jätkata, kuna see on suur viga ja kood ei saa enam käituda.

Sel konkreetsel juhul on lahendus muuta Dim -lause muutujatüübiks, mis töötab selle väärtusega, mille määrate muutujale. Kood töötab, kui muudate muutuja tüübiks „String” ja tõenäoliselt soovite muuta ka muutuja nime.

Muutuja tüübi muutmiseks tuleb aga teie projekt lähtestada ja peate koodi uuesti algusest peale uuesti käivitama, mis võib pika protseduuri korral olla väga tüütu

Töölehe arvutamise põhjustatud viga mittevastavuses

Ülaltoodud näide on väga lihtne näide sellest, kuidas mittevastavuse viga saab tekitada ja sel juhul on see hõlpsasti parandatav

Kuid mittevastavuse vigade põhjus on tavaliselt sellest palju sügavam ega ole nii ilmne, kui proovite oma koodi siluda.

Oletame näiteks, et olete kirjutanud koodi töölehe teatud positsiooni väärtuse leidmiseks ja see sisaldab arvutusest sõltuvaid teisi töövihiku lahtreid (selles näites B1)

Tööleht näeb välja nagu see näide koos valemiga, mis võimaldab tekstistringist konkreetse märgi leida

Kasutaja seisukohast on lahter A1 vabas vormingus ja ta saab sisestada mis tahes väärtuse. Valem otsib aga märgi „B” esinemist ja sel juhul seda ei leita, nii et lahtril B1 on veaväärtus.

Allpool olev testkood tekitab mittevastavuse vea, kuna lahtrisse A1 on sisestatud vale väärtus

1234 Sub TestMismatch ()Dim MyNumber täisarvunaMyNumber = Sheets ("Sheet1"). Vahemik ("B1"). VäärtusEnd Sub

Lahtri B1 väärtus on tekitanud vea, kuna kasutaja on sisestanud lahtrisse A1 teksti, mis ei vasta oodatule ega sisalda märki „B”

Kood üritab määrata väärtuse muutujale „MinuNumber”, mis on määratud täisarvu ootama, ja nii kuvatakse mittevastavuse viga.

See on üks neist näidetest, kus teie koodi põhjalik kontrollimine ei anna vastust. Peate vaatama ka töölehelt, kust väärtus pärineb, et teada saada, miks see nii on.

Probleem on tegelikult töölehel ja valem B1 -s vajab muutmist, et veaväärtustega tegeleda. Seda saate teha, kasutades valemit „IFERROR”, et anda vaikeväärtus 0, kui otsingumärki ei leita

Seejärel saate lisada koodi, et kontrollida nullväärtust ja kuvada kasutajale hoiatusteade, et lahtri A1 väärtus on vale

12345678 Sub TestMismatch ()Dim MyNumber täisarvunaMyNumber = Sheets ("Sheet1"). Vahemik ("B1"). TekstKui MyNumber = 0 SiisMsgBox "Väärtus lahtris A1 on kehtetu", vbCriticalVälju subLõpp KuiEnd Sub

Võite kasutada ka arvutustabeli andmete valideerimist (rühm Andmetööriistad lindi vahekaardil Andmed), et peatada kasutaja tegemast kõike, mis talle meeldis, ja tekitada esmalt töölehe vigu. Lubage neil sisestada ainult väärtusi, mis ei põhjusta töölehe vigu.

Sisestatud sisendite kontrollimiseks võite töölehele muutmise põhjal kirjutada VBA -koodi.

Samuti kaitsege töölehte lukk ja parool, nii et kehtetuid andmeid ei saaks sisestada

Sisestatud lahtriväärtuste põhjustatud mittevastavuse viga

Ebakõla vead võivad teie koodis tekkida, kui tuua töölehelt normaalväärtused (mitte viga), kuid kui kasutaja on sisestanud ootamatu väärtuse, nt. tekstiväärtus, kui ootasite numbrit. Võimalik, et nad on otsustanud sisestada rea ​​numbrivahemikku, et panna lahtrisse märge, mis selgitab numbri kohta midagi. Lõppude lõpuks pole kasutajal aimugi, kuidas teie kood töötab ja et ta on lihtsalt oma märkme sisestades kogu asja välja visanud.

Allolev näite kood loob lihtsa massiivi nimega „MinuNumber”, mis on määratletud täisarvuväärtustega

Seejärel kordab kood lahtrite vahemikku A1 kuni A7, määrates lahtri väärtused massiivi, kasutades iga väärtuse indekseerimiseks muutujat „Coun”

Kui kood jõuab tekstiväärtuseni, põhjustab see mittevastavuse tõrke ja kõik peatub

Kui klõpsate vea hüpikaknas nupul „Silumine”, näete koodirida, mille probleem on kollasega esile tõstetud. Kui hõljutate kursorit koodi muutuja „Coun” mis tahes eksemplari kohal, näete koodi väärtuse korral väärtust „Coun”, mis antud juhul on 5

Töölehte vaadates näete, et 5th lahtris alla on teksti väärtus ja see on põhjustanud koodi ebaõnnestumise

Saate oma koodi muuta, seadistades tingimuse, mis kontrollib enne lahtri väärtuse massiivi lisamist kõigepealt numbrilist väärtust

12345678910111213 Sub TestMismatch ()Dim MyNumber (10) täisarvuna, Coun täisarvunaCoun = 1TehkeKui Coun = 11, siis VäljuIf IsNumeric (Sheets ("sheet1"). Lahtrid (Coun, 1). Value) SiisMyNumber (Coun) = Sheets ("sheet1"). Lahtrid (Coun, 1) .VäärtusMuiduMinuNumber (Coun) = 0Lõpp KuiCoun = Coun + 1LoopEnd Sub

Kood kasutab funktsiooni „IsNumeric”, et testida, kas väärtus on tegelikult number ja kui see on, siis sisestab selle massiivi. Kui see pole number, sisestab see nulli.

See tagab massiiviindeksi vastavuse arvutustabeli lahtrite ridade numbritega.

Samuti saate töölehele „Vead” lisada koodi, mis kopeerib algse veaväärtuse ja asukoha üksikasjad, et kasutaja saaks teie koodi käivitamisel näha, mida ta valesti tegi.

Arvutest kasutab massiivi väärtuse määramiseks lahtri täielikku koodi ja koodi. Võite väita, et see tuleks määrata muutujale, et mitte pidevalt sama koodi korrata, kuid probleem on selles, et peate muutuja määratlema kui „varianti”, mis pole parim.

Samuti on vaja töölehel andmete valideerimist ja töölehe parooliga kaitsmist. See takistab kasutajal ridade sisestamist ja ootamatute andmete sisestamist.

Funktsiooni või alamrutiini väljakutsumine parameetrite abil põhjustab sobimatuse tõrke

Funktsiooni kutsumisel edastate tavaliselt funktsioonile parameetrid, kasutades funktsiooni poolt juba määratud andmetüüpe. Funktsioon võib olla VBA -s juba määratletud või kasutaja loodud funktsioon, mille olete ise loonud. Alamrutiin võib mõnikord nõuda ka parameetreid

Kui te ei pea kinni parameetrite funktsioonile edastamise reeglitest, kuvatakse mittevastavuse tõrge

12345678 Alamkõnefunktsioon ()Dim Ret täisarvunaRet = MyFunction (3, "test")End SubFunktsioon MyFunction (N täisarvuna, T stringina) stringinaMinu funktsioon = T.Lõppfunktsioon

Siin on mitu võimalust mittevastavuse vea saamiseks

Tagastusmuutuja (Ret) on defineeritud täisarvuna, kuid funktsioon tagastab stringi. Kohe koodi käivitamisel ebaõnnestub see, kuna funktsioon tagastab stringi ja see ei saa minna täisarvuliseks muutujaks. Huvitav on see, et silumise käivitamine sellel koodil seda viga ei näita.

Kui panete jutumärgid esimese edastatava parameetri (3) ümber, tõlgendatakse seda stringina, mis ei vasta funktsiooni (täisarv) esimese parameetri määratlusele

Kui muudate funktsioonikõne teise parameetri numbriliseks väärtuseks, ebaõnnestub see mittevastavusega, kuna stringi teine ​​parameeter on määratletud stringina (tekst)

Viga mittevastavuses, mis on põhjustatud VBA teisendusfunktsioonide valesti kasutamisest

VBA -s saab kasutada mitmeid teisendusfunktsioone väärtuste teisendamiseks erinevat tüüpi andmetele. Näide on „CInt”, mis teisendab numbrit sisaldava stringi täisarvuväärtuseks.

Kui teisendatav string sisaldab mingeid tähemärke, kuvatakse mittevastavuse viga, isegi kui stringi esimene osa sisaldab numbrimärke ja ülejäänud on tähemärgid, nt. „123abc”

Vigade üldine ennetamine

Oleme ülaltoodud näidetes näinud mitmeid võimalusi oma koodi võimalike mittevastavuse vigade lahendamiseks, kuid on ka mitmeid muid viise, kuigi need ei pruugi olla parimad võimalused.

Määrake oma muutujad varianditüübiks

Varianditüüp on VBA vaikimisi muutuja tüüp. Kui te ei kasuta muutuja jaoks Dim -lauset ja hakkate seda lihtsalt oma koodis kasutama, antakse sellele automaatselt variandi tüüp.

Muutuja Variant aktsepteerib mis tahes tüüpi andmeid, olgu see siis täisarv, pikk täisarv, kahekordne täpsusarv, tõeväärtus või tekstiväärtus. See kõlab imelise ideena ja te imestate, miks kõik ei sea kõiki oma muutujaid lihtsalt variandiks.

Variandi andmetüübil on aga mitmeid negatiivseid külgi. Esiteks võtab see palju rohkem mälu kui muud andmetüübid. Kui määratlete variandina väga suure massiivi, neelab see VBA -koodi töötamise ajal tohutu hulga mälu ja võib kergesti põhjustada jõudlusprobleeme

Teiseks on selle toimivus üldiselt aeglasem kui teatud andmetüüpide kasutamisel. Näiteks kui teete keerukaid arvutusi ujuva kümnendkohaga, on arvutused tunduvalt aeglasemad, kui salvestate arvud variantidena, mitte kahekordsete täpsusarvudena

Variantitüübi kasutamist peetakse lohakaks programmeerimiseks, kui see pole absoluutselt vajalik.

Kasutage vigade käsitlemiseks käsku OnError

Käsu OnError saab lisada teie koodi, et tegeleda vigade püüdmisega, nii et kui tõrge juhtub, näeb kasutaja tavalise VBA vea hüpikakna asemel sisukat sõnumit

1234567 Alamvea lõks ()Dim MyNumber täisarvunaViga GoTo Err_HandlerMinuNumber = "test"Err_Handler:MsgBox "Ilmnes tõrge" & Err.Description & "End Sub

See hoiab tõhusalt ära tõrke peatamise teie koodi tõrgeteta toimimise ja võimaldab kasutajal veaolukorrast puhtalt taastuda.

Err_Handleri rutiin võib näidata vea kohta lisateavet ja selle kohta, kelle poole pöörduda.

Programmeerimise seisukohast on vigade käsitlemise rutiini kasutamisel üsna raske leida koodirida, millel viga on. Kui astute koodist läbi klahvi F8, niipea kui rikkuv koodirida käivitatakse, hüppab see veakäsitlusrežiimi ja te ei saa kontrollida, kus see valesti läheb.

Selle vältimiseks saate luua globaalse konstandi, mis on tõene või vale (Boolean) ja kasutada seda vigade käsitlemise rutiini sisse- või väljalülitamiseks, kasutades lauset „If”. Kui soovite viga testida, peate vaid määrama globaalse konstandi väärtuseks Väär ja veahaldur ei tööta enam.

1 Globaalne Const ErrHandling = Vale
1234567 Alamvea lõks ()Dim MyNumber täisarvunaKui ErrHandling = Tõene, siis tõrke korral Minge Err_HandlerMinuNumber = "test"Err_Handler:MsgBox "Ilmnes tõrge" & Err.Description & "End Sub

Selle üks probleem on see, et see võimaldab kasutajal veast taastuda, kuid ülejäänud kood alamrutiinis ei käivitu, mis võib rakenduses hiljem tohutult mõjutada

Kasutades varasemat lahtrite vahemiku läbimise näidet, jõuaks kood lahtrisse A5 ja tabaks sobimatu vea. Kasutaja näeks veateadet sisaldavat teadete kasti, kuid sellest vahemikust alates ei töödelda midagi.

Kasutage vigade kõrvaldamiseks käsku OnError

See kasutab käsku „On Error Resume Next”. Seda on väga ohtlik oma koodi lisada, kuna see hoiab ära hilisemate vigade kuvamise. Põhimõtteliselt tähendab see seda, et kui teie kood käivitub, kui koodireal ilmneb tõrge, liigub täitmine lihtsalt järgmisele saadaolevale reale ilma vearida täitmata ja jätkub tavapäraselt.

See võib lahendada võimaliku veaolukorra, kuid mõjutab siiski kõiki tulevasi koodi vigu. Seejärel võite arvata, et teie kood on veavaba, kuid tegelikult see pole nii ja teie koodi osad ei tee seda, mida teie arvates peaks tegema.

On olukordi, kus seda käsku on vaja kasutada, näiteks kui kustutate faili käsuga Kill (kui faili pole, ilmneb tõrge), kuid vigade püüdmine tuleb alati tagasi lülitada kohe pärast seda, kus võimalik viga võib ilmneda, kasutades järgmist:

1 Vea korral läks 0

Varasemas lahtrivahemikus loopimise näites, kasutades suvandit „On Error Resume Next”, võimaldaks see tsükkel jätkata, kuid tõrke põhjustanud lahtrit ei kanta massiivi ja selle konkreetse indeksi massiivielement omab nullväärtust.

Andmete teisendamine andmetüübiks, et need vastaksid deklaratsioonile

VBA -funktsioonide abil saate muuta sissetulevate andmete andmetüüpi nii, et see vastaks vastuvõtva muutuja andmetüübile.

Seda saate teha parameetrite edastamisel funktsioonidele. Näiteks kui teil on number, mida hoitakse stringimuutjas ja soovite selle funktsioonina numbrina edastada, saate kasutada CInt

Neid teisendusfunktsioone saab kasutada mitmeid, kuid siin on peamised.

CInt - teisendab stringi, millel on numbriline väärtus (alla + või - 32 768) täisarvuks. Pidage meeles, et see lühendab kümnendkohti

CLng - teisendab suure numbrilise väärtusega stringi pikaks täisarvuks. Kümnendkohad kärbitakse.

CDbl - teisendab ujuva kümnendkoha numbrit sisaldava stringi kahekordse täpsusega arvuks. Sisaldab komakohti

CDate - teisendab kuupäeva hoidva stringi kuupäevamuutujaks. Osaliselt sõltub Windowsi juhtpaneeli seadetest ja teie lokaadist, kuidas kuupäeva tõlgendatakse

CStr - teisendab numbrilise või kuupäeva väärtuse stringiks

Stringist numbriks või kuupäevaks teisendamisel ei tohi string sisaldada midagi muud peale numbrite või kuupäeva. Kui on olemas tähemärke, tekitab see mittevastavuse vea. Siin on näide, mis põhjustab mittevastavuse vea:

123 Alamkatse ()MsgBox CInt ("123abc")End Sub

Muutujate testimine teie koodis

Muutujat saate testida, et teada saada, milline andmetüüp see on, enne kui määrate selle teatud tüüpi muutujale.

Näiteks võite stringis kontrollida, kas see on numbriline, kasutades VBA funktsiooni „IsNumeric”

1 MsgBox IsNumeric ("123test")

See kood tagastab väärtuse Väär, sest kuigi string algab numbrimärkidega, sisaldab see ka teksti, nii et see ei läbi testi.

1 MsgBox IsNumeric ("123")

See kood tagastab tõese, kuna see on kõik numbrimärgid

VBA -s on mitmeid funktsioone erinevate andmetüüpide testimiseks, kuid need on peamised:

IsNumeric - kontrollib, kas avaldis on number või mitte

IsDate - testib, kas avaldis on kuupäev või mitte

IsNull - testib, kas avaldis on null või mitte. Nullväärtuse saab sisestada ainult variandi objekti, vastasel juhul kuvatakse tõrketeade „Invalid Use of Null”. Kui kasutate seda küsimuse esitamiseks, saadab sõnumikast tühiväärtuse, seega peab tagastamismuutuja olema variant. Pidage meeles, et iga nullväärtust kasutav arvutus tagastab alati nulli tulemuse.

IsArray - testib, kas avaldis kujutab endast massiivi või mitte

IsEmpty - testib, kas avaldis on tühi või mitte. Pange tähele, et tühi ei ole null. Muutuja on esmakordsel määratlemisel tühi, kuid see ei ole nullväärtus

Üllataval kombel pole IsText või IsString jaoks ühtegi funktsiooni, mis oleks tõesti kasulik

Objektid ja mittevastavuse vead

Kui kasutate selliseid objekte nagu vahemik või leht, kuvatakse mittevastavuse viga kompileerimise ajal, mitte käitusajal, mis hoiatab teid, et teie kood ei tööta

123456 Alamkatseulatus ()Dim MyRange As Range, I As LongMäära MyRange = Vahemik ("A1: A2")I = 10x = UseMyRange (I)End Sub
12 Funktsioon UseMyRange (R kui vahemik)Lõppfunktsioon

Sellel koodil on funktsioon nimega „UseMyRange” ja vahemiku objektina edastatud parameeter. Siiski edastatav parameeter on pikk täisarv, mis ei vasta andmetüübile.

VBA -koodi käivitamisel kompileeritakse see kohe ja näete seda veateadet:

Rikkuv parameeter tõstetakse esile sinise taustaga

Üldiselt, kui teete objekte kasutades VBA -koodis vigu, näete seda veateadet, mitte tüübi mittevastavuse teadet:

Te aitate arengu ala, jagades leht oma sõpradega

wave wave wave wave wave