VBA - tipo neatitikimas (13 vykdymo laiko klaida)

Kas yra tipo neatitikimo klaida?

Vykdant VBA kodą dažnai gali atsirasti neatitikimo klaida. Klaida visiškai sustabdys jūsų kodo veikimą ir pažymės pranešimų laukelį, kad ši klaida turi būti išspręsta

Atminkite, kad jei iki galo neišbandėte savo kodo prieš platindami vartotojams, šis klaidos pranešimas bus matomas vartotojams ir labai sumažės pasitikėjimas „Excel“ programa. Deja, vartotojai dažnai daro labai ypatingus veiksmus su programa ir dažnai yra tai, ko jūs, kaip kūrėjas, niekada nepagalvojote.

Tipo neatitikimo klaida atsiranda dėl to, kad kintamąjį apibrėžėte naudodami Dim sakinį kaip tam tikrą tipą, pvz. sveikasis skaičius, data ir jūsų kodas bando priskirti kintamajam reikšmę, kuri yra nepriimtina, pvz. teksto eilutė, priskirta sveikam kintamajam, kaip šiame pavyzdyje:

Štai pavyzdys:

Spustelėkite Derinti ir pažeidžianti kodo eilutė bus paryškinta geltona spalva. Iššokančiajame klaidos lange nėra galimybės tęsti, nes tai yra didelė klaida ir nėra jokio būdo, kad kodas galėtų veikti toliau.

Šiuo konkrečiu atveju sprendimas yra pakeisti „Dim“ sakinį į kintamojo tipą, kuris atitinka tą vertę, kurią priskiriate kintamajam. Kodas veiks, jei pakeisite kintamojo tipą į „String“ ir tikriausiai norėtumėte pakeisti ir kintamojo pavadinimą.

Tačiau norint pakeisti kintamojo tipą, jūsų projektas turi būti iš naujo nustatytas, ir jūs turėsite iš naujo paleisti kodą iš naujo, o tai gali būti labai erzina, jei atliekama ilga procedūra

Neatitikimo klaida, kurią sukėlė darbalapio skaičiavimas

Aukščiau pateiktas pavyzdys yra labai paprastas, kaip gali būti padaryta neatitikimo klaida, ir šiuo atveju ji lengvai pašalinama

Tačiau neatitikimo klaidų priežastis paprastai yra kur kas gilesnė ir nėra tokia akivaizdi, kai bandote derinti kodą.

Pavyzdžiui, tarkime, kad parašėte kodą, kad gautumėte reikšmę tam tikroje darbalapio vietoje, ir jame yra skaičiavimu priklausančios kitos darbaknygės ląstelės (šiame pavyzdyje B1)

Skaičiuoklė atrodo kaip šis pavyzdys su formule, leidžiančia rasti tam tikrą simbolį teksto eilutėje

Vartotojo požiūriu, langelis A1 yra laisvo formato ir gali įvesti bet kokią norimą vertę. Tačiau formulėje ieškoma simbolio „B“, ir tokiu atveju jis nerandamas, todėl langelis B1 turi klaidos vertę.

Žemiau pateiktas bandymo kodas sukels neatitikimo klaidą, nes į langelį A1 įvesta neteisinga vertė

1234 Sub TestMismatch ()Dim MyNumber As IntegerMyNumber = Sheets ("Sheet1"). Diapazonas ("B1"). ReikšmėPabaiga Sub

B1 langelio reikšmė sukėlė klaidą, nes vartotojas įvedė tekstą į langelį A1, kuris neatitinka to, ko tikėtasi, ir jame nėra simbolio „B“

Kodas bando priskirti vertę kintamajam „Mano numeris“, kuris buvo nustatytas tikėtis sveikojo skaičiaus, todėl gausite neatitikimo klaidą.

Tai yra vienas iš šių pavyzdžių, kai kruopščiai patikrinus kodą nebus galima atsakyti. Taip pat turite pažvelgti į darbalapį, iš kurio gaunama vertė, kad sužinotumėte, kodėl taip atsitinka.

Problema iš tikrųjų yra darbalapyje, o B1 formulę reikia pakeisti, kad būtų pašalintos klaidų vertės. Tai galite padaryti naudodami formulę „IFERROR“, kad pateiktumėte numatytąją reikšmę 0, jei paieškos simbolis nerastas

Tada galite įtraukti kodą, kad patikrintumėte nulinę vertę ir parodytumėte vartotojui įspėjamąjį pranešimą, kad A1 langelio vertė yra netinkama

12345678 Sub TestMismatch ()Dim MyNumber As IntegerMyNumber = Sheets ("Sheet1"). Diapazonas ("B1"). TekstasJei MyNumber = 0 Tada„MsgBox“ „A1 langelio reikšmė yra netinkama“, „vbCritical“Išeiti iš SubPabaiga JeiPabaiga Sub

Taip pat galite naudoti skaičiuoklės duomenų patvirtinimą (duomenų įrankių grupė juostelės skirtuke „Duomenys“), kad sustabdytumėte vartotoją daryti viską, kas jam patinka, ir pirmiausia sukeltų darbalapio klaidų. Leiskite jiems įvesti tik tas vertes, kurios nesukels darbalapio klaidų.

Galite parašyti VBA kodą pagal darbalapio įvykį Keisti, kad patikrintumėte, kas buvo įvesta.

Taip pat užraktas ir slaptažodis apsaugo darbalapį, kad negalėtumėte įvesti netinkamų duomenų

Neatitikimo klaida, kurią sukelia įvestos ląstelių vertės

Jūsų kode gali atsirasti neatitikimų klaidų, įvedus normalias vertes iš darbalapio (ne klaida), bet kai vartotojas įvedė netikėtą reikšmę, pvz. teksto reikšmę, kai tikėjotės skaičiaus. Galbūt jie nusprendė įterpti eilutę į skaičių diapazoną, kad galėtų į langelį įrašyti pastabą, paaiškinančią ką nors apie skaičių. Galų gale, vartotojas neįsivaizduoja, kaip veikia jūsų kodas ir kad jis ką tik išmetė viską įvesdamas savo užrašą.

Žemiau pateiktas pavyzdinis kodas sukuria paprastą masyvą, pavadintą „Mano numeris“, apibrėžtą su sveikų skaičių reikšmėmis

Tada kodas kartojasi langelių diapazone nuo A1 iki A7, priskirdamas langelių reikšmes masyvui, naudodamas kintamąjį „Coun“, kad indeksuotų kiekvieną vertę

Kai kodas pasiekia teksto vertę, dėl to atsiranda neatitikimo klaida ir viskas sustoja

Spustelėję „Derinti“ klaidos iššokančiajame lange pamatysite kodo eilutę, kurioje problema pažymėta geltona spalva. Užvedę žymeklį ant bet kurio kintamojo „Coun“ egzemplioriaus kode, galėsite pamatyti „Coun“ reikšmę, jei kodas nepavyko, o šiuo atveju - 5

Žvelgdami į darbalapį pamatysite, kad 5tūkst langelio žemyn turi teksto reikšmę, todėl kodas nepavyko

Galite pakeisti kodą įvesdami sąlygą, kuri pirmiausia patikrina skaitinę reikšmę prieš pridėdama langelio reikšmę į masyvą

12345678910111213 Sub TestMismatch ()Dim MyNumber (10) kaip sveikasis skaičius, kaip sveikasis skaičiusCoun = 1DarykJei Coun = 11, tada išeikite DoJei IsNumeric (skaičiuoklės ("sheet1"). Ląstelės (Coun, 1). Value) TadaMyNumber (Coun) = Sheets ("sheet1"). Ląstelės (Coun, 1) .VertybėKitasMyNumber (Coun) = 0Pabaiga JeiCoun = Coun + 1KilpaPabaiga Sub

Kodas naudoja funkciją „IsNumeric“, kad patikrintų, ar vertė iš tikrųjų yra skaičius, o jei yra, tada įveda ją į masyvą. Jei tai nėra skaičius, jis įveda nulį.

Tai užtikrina, kad masyvo indeksas atitiktų skaičiuoklės langelių eilių numerius.

Taip pat galite pridėti kodą, kuris nukopijuoja pradinę klaidos vertę ir išsamią vietos informaciją į „Klaidų“ darbalapį, kad vartotojas galėtų pamatyti, ką padarė blogai, kai vykdomas jūsų kodas.

Skaitinis testas naudoja visą langelio kodą, taip pat kodą reikšmei priskirti. Galite teigti, kad tai turėtų būti priskirta kintamajam, kad nebūtų kartojamas tas pats kodas, tačiau problema ta, kad jums reikia apibrėžti kintamąjį kaip „variantą“, o tai nėra geriausias dalykas.

Taip pat reikia patvirtinti duomenis darbalapyje ir apsaugoti darbalapį slaptažodžiu. Tai neleis vartotojui įterpti eilučių ir įvesti netikėtų duomenų.

Neatitikimo klaida, atsiradusi iškviečiant funkciją ar papildomą tvarką naudojant parametrus

Kai iškviečiama funkcija, paprastai perduodate parametrus funkcijai, naudodami funkcijos jau apibrėžtus duomenų tipus. Funkcija gali būti ta, kuri jau apibrėžta VBA, arba tai gali būti vartotojo sukurta funkcija, kurią sukūrėte patys. Papildoma tvarka taip pat kartais gali pareikalauti parametrų

Jei nesilaikysite taisyklių, kaip parametrai perduodami funkcijai, gausite neatitikimo klaidą

12345678 Papildoma skambučio funkcija ()Dim Ret As IntegerRet = „MyFunction“ (3, „testas“)Pabaiga SubFunkcija MyFunction (N kaip sveikasis skaičius, T kaip eilutė) kaip eilutėMano funkcija = T.Pabaigos funkcija

Čia yra keletas galimybių gauti neatitikimo klaidą

Grąžinimo kintamasis (Ret) apibrėžiamas kaip sveikasis skaičius, tačiau funkcija grąžina eilutę. Kai tik paleisite kodą, jis nepavyks, nes funkcija grąžina eilutę ir tai negali patekti į sveiką skaičių kintamąjį. Įdomu tai, kad naudojant „Debug“ naudojant šį kodą ši klaida nepasireiškia.

Jei kabutes rašote aplink pirmąjį perduodamą parametrą (3), jis interpretuojamas kaip eilutė, neatitinkanti pirmojo funkcijos parametro apibrėžimo (sveikasis skaičius)

Jei antrąjį funkcijos iškvietimo parametrą paversite skaitine reikšme, jis nepavyks, nes neatitiks, nes antrasis eilutės parametras yra apibrėžtas kaip eilutė (tekstas)

Neatitikimo klaida, atsiradusi netinkamai naudojant konversijos funkcijas VBA

Yra keletas konversijos funkcijų, kurias galite naudoti VBA, norėdami konvertuoti vertes į įvairių tipų duomenis. Pavyzdys yra „CInt“, kuris eilutę, kurioje yra skaičius, paverčia sveiko skaičiaus verte.

Jei eilutėje, kurią reikia konvertuoti, yra bet koks alfa simbolis, gausite neatitikimo klaidą, net jei pirmoje eilutės dalyje yra skaitiniai simboliai, o likusi dalis yra raidžių, pvz. „123abc“

Bendra neatitikimų klaidų prevencija

Anksčiau pateiktuose pavyzdžiuose matėme kelis būdus, kaip pašalinti galimas kodo neatitikimo klaidas, tačiau yra ir kitų būdų, nors jie gali būti ne patys geriausi:

Apibrėžkite savo kintamuosius kaip Variant Type

Varianto tipas yra numatytasis kintamojo tipas VBA. Jei kintamajam nenaudojate „Dim“ sakinio ir tiesiog pradedate jį naudoti savo kode, tada jam automatiškai suteikiamas varianto tipas.

Kintamasis variantas priims bet kokio tipo duomenis, nesvarbu, ar tai sveikas skaičius, ar ilgas sveikasis skaičius, ar dvigubo tikslumo skaičius, loginė vertė ar teksto reikšmė. Tai skamba kaip nuostabi idėja, ir jums įdomu, kodėl visi nenustato visų kintamųjų variantų.

Tačiau duomenų tipo variantas turi keletą trūkumų. Pirma, tai užima daug daugiau atminties nei kiti duomenų tipai. Jei kaip variantą apibrėšite labai didelį masyvą, jis užims daug atminties, kai VBA kodas bus paleistas, ir gali lengvai sukelti našumo problemų

Antra, jos veikimas paprastai yra lėtesnis, nei naudojant konkrečius duomenų tipus. Pvz., Jei atliekate sudėtingus skaičiavimus naudodami slankiojo kablelio skaičius, skaičiavimai bus žymiai lėtesni, jei skaičius išsaugosite kaip variantus, o ne dvigubus tikslumo skaičius

Varianto tipo naudojimas laikomas aplaidžiu programavimu, nebent tai yra absoliučiai būtina.

Naudokite „OnError“ komandą klaidoms tvarkyti

„OnError“ komanda gali būti įtraukta į jūsų kodą, kad būtų pašalintas klaidų gaudymas, taigi, jei kada nors įvyks klaida, vartotojas pamatys prasmingą pranešimą, o ne įprastą iššokantį langą VBA

1234567 Sub ErrorTrap ()Dim MyNumber As IntegerDėl klaidos „GoTo Err_Handler“MyNumber = "testas"Err_Handler:„MsgBox“ įvyko klaida „& Err.Description &“Pabaiga Sub

Tai veiksmingai neleidžia klaidai sustabdyti sklandaus jūsų kodo veikimo ir leidžia vartotojui visiškai atsigauti po klaidos.

„Err_Handler“ rutina gali parodyti daugiau informacijos apie klaidą ir su kuo dėl jos susisiekti.

Programavimo požiūriu, kai naudojate klaidų tvarkymo procedūrą, gana sunku rasti kodo eilutę, kurioje klaida įjungta. Jei peržengiate kodą naudodami F8, kai tik paleidžiama pažeidžianti kodo eilutė, ji pereina prie klaidų tvarkymo tvarkos ir negalite patikrinti, kur klaida.

Išeitis yra nustatyti visuotinę konstantą, kuri yra teisinga arba klaidinga (loginė) ir naudoti ją, kad įjungtų arba išjungtų klaidų tvarkymo procedūrą naudojant teiginį „Jei“. Jei norite išbandyti klaidą, jums tereikia nustatyti visuotinę konstantą į False ir klaidų tvarkytojas nebeveiks.

1 Global Const ErrHandling = Netiesa
1234567 Sub ErrorTrap ()Dim MyNumber As IntegerJei „ErrHandling“ = tiesa, tada per klaidą „GoTo Err_Handler“MyNumber = "testas"Err_Handler:„MsgBox“ įvyko klaida „& Err.Description &“Pabaiga Sub

Vienintelė problema yra ta, kad tai leidžia vartotojui atsigauti po klaidos, tačiau likusi papildomo kodo dalis nėra paleista, o tai vėliau gali turėti milžiniškų padarinių programoje

Naudojant ankstesnį ciklų per įvairias langelius pavyzdį, kodas patektų į langelį A5 ir susidurtų su neatitinkančia klaida. Vartotojas pamatys pranešimų laukelį, kuriame pateikiama informacija apie klaidą, tačiau niekas nuo to langelio diapazone nebus apdorotas.

Norėdami pašalinti klaidas, naudokite komandą „OnError“

Tam naudojama komanda „On Error Resume Next“. Tai labai pavojinga įtraukti į savo kodą, nes tai neleidžia rodyti vėlesnių klaidų. Tai iš esmės reiškia, kad vykdant jūsų kodą, jei kodo eilutėje įvyksta klaida, vykdymas tiesiog perkeliamas į kitą turimą eilutę, nevykdant klaidos eilutės, ir tęsiamas kaip įprasta.

Tai gali išspręsti galimą klaidos situaciją, tačiau ji vis tiek paveiks kiekvieną būsimą kodo klaidą. Tada galite pagalvoti, kad jūsų kode nėra klaidų, bet iš tikrųjų taip nėra, o jūsų kodo dalys nedaro to, ką, jūsų manymu, turėtų daryti.

Yra situacijų, kai būtina naudoti šią komandą, pvz., Jei ištrinate failą naudodami komandą „Nužudyti“ (jei failo nėra, bus klaida), tačiau klaidų gaudymas visada turėtų būti perjungtas atgal iš karto po to, kai galima klaida gali atsirasti naudojant:

1 Klaida Goto 0

Ankstesniame ciklo ciklo ciklo pavyzdyje, naudojant „On Error Resume Next“, tai leistų ciklui tęsti, tačiau klaidą sukėlęs langelis nebūtų perkeltas į masyvą, o to konkretaus indekso masyvo elementas turėtų nulinę vertę.

Duomenų konvertavimas į duomenų tipą, kad atitiktų deklaraciją

Galite naudoti VBA funkcijas, kad pakeistumėte gaunamų duomenų duomenų tipą, kad jis atitiktų priimančio kintamojo duomenų tipą.

Tai galite padaryti perduodami parametrus funkcijoms. Pvz., Jei turite skaičių, kuris laikomas eilutės kintamajame ir norite jį perduoti kaip skaičių funkcijai, galite naudoti CInt

Galima naudoti daugybę šių konvertavimo funkcijų, tačiau čia yra pagrindinės:

CInt - konvertuoja eilutę, kurios skaitmeninė reikšmė (žemiau + arba - 32 768), į sveiką skaičių. Atminkite, kad tai sutrumpina visus dešimtainius taškus

CLng - paverčia eilutę, turinčią didelę skaitinę reikšmę, į ilgą sveikąjį skaičių. Dešimtainiai taškai sutrumpinami.

CDbl - paverčia eilutę, kurioje yra plūduriuojantis dešimtainis taškas, į dvigubą tikslumo skaičių. Apima dešimtainius taškus

CDate - paverčia eilutę, kurioje yra data, į datos kintamąjį. Iš dalies priklauso nuo nustatymų „Windows“ valdymo skydelyje ir jūsų lokalės, kaip interpretuojama data

CStr - paverčia skaitinę arba datos reikšmę į eilutę

Konvertuojant iš eilutės į skaičių ar datą, eilutėje negali būti nieko, išskyrus skaičius ar datą. Jei yra alfa simbolių, tai sukels neatitikimo klaidą. Štai pavyzdys, kuris sukels neatitikimo klaidą:

123 Antrasis testas ()„MsgBox CInt“ („123abc“)Pabaiga Sub

Kodo kintamųjų testavimas jūsų kode

Galite išbandyti kintamąjį, kad sužinotumėte, koks tai duomenų tipas, prieš priskirdami jį tam tikro tipo kintamajam.

Pvz., Galite patikrinti eilutę, kad pamatytumėte, ar ji yra skaitinė, naudodami funkciją „IsNumeric“ VBA

1 „MsgBox IsNumeric“ („123test“)

Šis kodas grąžins klaidingą, nes nors eilutė prasideda skaitiniais simboliais, joje taip pat yra teksto, todėl ji neišlaiko testo.

1 „MsgBox IsNumeric“ („123“)

Šis kodas grąžins „True“, nes tai visi skaitmeniniai simboliai

VBA yra daugybė funkcijų, skirtų įvairiems duomenų tipams tikrinti, tačiau tai yra pagrindinės:

IsNumeric - patikrina, ar išraiška yra skaičius, ar ne

IsDate - patikrina, ar išraiška yra data, ar ne

IsNull - patikrina, ar išraiška yra niekinė, ar ne. Nulinę vertę galima įterpti tik į varianto objektą, kitaip gausite klaidą „Neteisingas nulinio naudojimo naudojimas“. Pranešimų laukelyje pateikiama nulinė vertė, jei ją naudojate klausimui užduoti, todėl grąžinimo kintamasis turi būti variantas. Atminkite, kad bet koks skaičiavimas naudojant nulinę vertę visada grąžins nulinį rezultatą.

„IsArray“ - patikrina, ar išraiška reiškia masyvą, ar ne

IsEmpty - patikrina, ar išraiška tuščia, ar ne. Atminkite, kad tuščias nėra tas pats, kas nulis. Kintamasis tuščias, kai jis pirmą kartą apibrėžiamas, tačiau tai nėra nulinė vertė

Keista, bet nėra „IsText“ ar „IsString“ funkcijų, kurios būtų tikrai naudingos

Objektai ir neatitikimo klaidos

Jei naudojate tokius objektus kaip diapazonas ar lapas, neatitikimo klaidą gausite kompiliavimo metu, o ne vykdymo metu, o tai tinkamai įspės, kad jūsų kodas neveiks

123456 Antrasis bandymo diapazonas ()Dim MyRange As Range, I As LongNustatyti „MyRange = Range“ („A1: A2“)I = 10x = UseMyRange (I)Pabaiga Sub
12 Funkcijos naudojimas MyRange (R kaip diapazonas)Pabaigos funkcija

Šis kodas turi funkciją „UseMyRange“ ir parametrą, perduotą kaip diapazono objektą. Tačiau perduodamas parametras yra ilgas sveikasis skaičius, neatitinkantis duomenų tipo.

Kai paleisite VBA kodą, jis bus nedelsiant sukompiliuotas ir pamatysite šį klaidos pranešimą:

Pažeidžiantis parametras bus paryškintas mėlynu fonu

Paprastai, jei padarysite klaidų naudodami VBA kodą naudodami objektus, pamatysite šį klaidos pranešimą, o ne tipo neatitikimo pranešimą:

Padėsite svetainės plėtrą, dalintis puslapį su draugais

wave wave wave wave wave