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: