VBA - Tyyppivirhe (ajonaikainen virhe 13)

Mikä on tyyppivirhe?

VBA -koodin suorittamisessa voi usein ilmetä virheellisyysvirhe. Virhe estää koodisi toimimasta kokonaan ja ilmoittaa viestin ruudulla, että tämä virhe on selvitettävä

Huomaa, että jos et ole testannut koodiasi kokonaan ennen jakelua käyttäjille, tämä virheilmoitus näkyy käyttäjille ja aiheuttaa suuren luottamuksen menetyksen Excel -sovellukseesi. Valitettavasti käyttäjät tekevät sovellukselle usein hyvin erikoisia asioita ja ovat usein asioita, joita sinä kehittäjänä et koskaan ajatellut.

Tyypivirhevirhe ilmenee, koska olet määrittänyt muuttujan käyttämällä Dim -käskyä tietyntyyppiseksi, esim. kokonaisluku, päivämäärä ja koodisi yrittää määrittää muuttujalle arvon, joka ei ole hyväksyttävä, esim. tekstimerkkijono, joka on määritetty kokonaislukumuuttujalle kuten tässä esimerkissä:

Tässä on esimerkki:

Napsauta Virheenkorjaus ja rikkova koodirivi on korostettu keltaisella. Virhe-ponnahdusikkunassa ei ole vaihtoehtoa jatkaa, koska tämä on suuri virhe, eikä koodi voi toimia enää.

Tässä tapauksessa ratkaisu on muuttaa Dim -käsky muuttujatyypiksi, joka toimii muuttujalle määrittämäsi arvon kanssa. Koodi toimii, jos muutat muuttujan tyypiksi merkkijono, ja haluat todennäköisesti muuttaa myös muuttujan nimen.

Muuttujan tyypin muuttaminen edellyttää kuitenkin projektin nollaamista, ja sinun on suoritettava koodi uudelleen alusta alkaen, mikä voi olla erittäin ärsyttävää, jos kyseessä on pitkä menettely

Virhe laskentataulukon laskennassa

Yllä oleva esimerkki on hyvin yksinkertainen esimerkki siitä, miten yhteensopimattomuusvirhe voidaan tuottaa, ja tässä tapauksessa se on helppo korjata

Virheiden syy on kuitenkin yleensä paljon syvempi kuin tämä, eikä se ole niin ilmeistä, kun yrität korjata koodiasi.

Oletetaan esimerkiksi, että olet kirjoittanut koodin arvon noutamiseksi tietyssä laskentataulukon kohdassa ja se sisältää laskelmasta riippuvat muut työkirjan solut (B1 tässä esimerkissä)

Laskentataulukko näyttää tältä esimerkiltä ja sisältää kaavan tietyn merkin löytämiseksi merkkijonosta

Käyttäjän näkökulmasta solu A1 on vapaamuotoinen ja hän voi syöttää haluamansa arvon. Kaava etsii kuitenkin merkin "B" esiintymistä, ja tässä tapauksessa sitä ei löydy, joten solulla B1 on virhearvo.

Alla oleva testikoodi tuottaa virheen, koska soluun A1 on syötetty väärä arvo

1234 AlatestiMismatch ()Dim MyNumber kokonaislukunaOma numero = Sheets ("Sheet1"). Alue ("B1"). ArvoEnd Sub

Solun B1 arvo on aiheuttanut virheen, koska käyttäjä on syöttänyt soluun A1 tekstiä, joka ei vastaa odotettua eikä sisällä merkkiä "B"

Koodi yrittää määrittää arvon muuttujalle "MyNumber", joka on määritetty odottamaan kokonaislukua, joten saat virheellisyyden virheen.

Tämä on yksi näistä esimerkeistä, joissa koodin huolellinen tarkistaminen ei anna vastausta. Sinun on myös tarkasteltava laskentataulukkoa, josta arvo tulee, jotta voit selvittää, miksi näin tapahtuu.

Ongelma on itse asiassa laskentataulukossa, ja B1: n kaava on muutettava, jotta virhearvot käsitellään. Voit tehdä tämän käyttämällä IFERROR -kaavaa ja anna oletusarvo 0, jos hakumerkkiä ei löydy

Voit sitten sisällyttää koodin nolla -arvon tarkistamiseen ja varoitussanoman näyttämiseen käyttäjälle, että solun A1 arvo on virheellinen

12345678 AlatestiMismatch ()Dim MyNumber kokonaislukunaMyNumber = Sheets ("Sheet1"). Alue ("B1"). TekstiJos Oma numero = 0 SittenMsgBox "Arvo solussa A1 on virheellinen", vbCriticalLopeta SubLoppu JosEnd Sub

Voit myös käyttää laskentataulukon tietojen validointia (Data Tools -ryhmä valintanauhan Data -välilehdessä) estääksesi käyttäjän tekemästä mitä tahansa ja aiheuttavan laskentataulukon virheitä. Anna heidän syöttää vain arvoja, jotka eivät aiheuta laskentataulukon virheitä.

Voit kirjoittaa VBA -koodin laskentataulukon Muuta -tapahtuman perusteella tarkistaaksesi, mitä olet syöttänyt.

Lukitse ja salasana suojaa myös laskentataulukko, jotta virheellisiä tietoja ei voi syöttää

Virhe, joka johtuu syötetyistä soluarvoista

Virheitä koodissa voi aiheuttaa tuomalla normaaliarvot laskentataulukosta (ei virhe), mutta jos käyttäjä on antanut odottamattoman arvon, esim. tekstiarvo, kun odotit numeroa. He ovat saattaneet päättää lisätä rivin numeroalueelle, jotta he voivat laittaa soluun muistiinpanon, joka selittää jotain numerosta. Loppujen lopuksi käyttäjällä ei ole aavistustakaan siitä, miten koodisi toimii ja että he ovat vain heittäneet koko asian pois kirjoittamalla muistiinpanonsa.

Alla oleva esimerkkikoodi luo yksinkertaisen taulukon nimeltä "MyNumber", joka on määritetty kokonaislukuarvoilla

Koodi sitten iteroi solualueella A1 - A7, määrittäen soluarvot taulukkoon käyttäen indeksiä jokaisen arvon käyttämällä muuttujaa Coun

Kun koodi saavuttaa tekstiarvon, tästä aiheutuu yhteensopivuusvirhe ja kaikki pysähtyy

Napsauttamalla virheenkorjausikkunassa olevaa "Debug" -painiketta näet koodirivin, jossa ongelma on korostettu keltaisella. Kun viet kohdistimen koodin muuttujan Coun esiintymän päälle, näet Coun -arvon, jos koodi on epäonnistunut, mikä tässä tapauksessa on 5

Laskentataulukosta näet, että 5th solu alas on tekstiarvo ja tämä on aiheuttanut koodin epäonnistumisen

Voit muuttaa koodiasi asettamalla ehdon, joka tarkistaa numeerisen arvon ennen solun arvon lisäämistä taulukkoon

12345678910111213 AlatestiMismatch ()Dim MyNumber (10) kokonaislukuna, Coun kokonaislukunaCoun = 1TehdäJos Coun = 11, Lopeta DoJos IsNumeric (Sheets ("sheet1"). Solut (Coun, 1). Value) SittenMyNumber (Coun) = Sheets ("sheet1"). Solut (Coun, 1) .ArvoMuuOma numero (Coun) = 0Loppu JosCoun = Coun + 1SilmukkaEnd Sub

Koodi käyttää IsNumeric -funktiota testatakseen, onko arvo todella numero, ja jos on, se syöttää sen taulukkoon. Jos se ei ole luku, se syöttää arvon nolla.

Tämä varmistaa, että taulukkoindeksi pidetään laskentataulukon solurivin numeroiden mukaisesti.

Voit myös lisätä koodin, joka kopioi alkuperäisen virhearvon ja sijaintitiedot Virheet -laskentataulukkoon, jotta käyttäjä voi nähdä, mitä he ovat tehneet väärin, kun koodisi suoritetaan.

Numeerinen testi käyttää solun koko koodia sekä koodia arvon määrittämiseen taulukkoon. Voit väittää, että tämä pitäisi määrittää muuttujalle, jotta sama koodi ei toistu jatkuvasti, mutta ongelmana on, että sinun on määriteltävä muuttuja "Variantiksi", mikä ei ole paras asia.

Tarvitset myös laskentataulukon tietojen validoinnin ja laskentataulukon salasanasuojauksen. Tämä estää käyttäjää lisäämästä rivejä ja syöttämästä odottamattomia tietoja.

Virhe, joka aiheutuu toiminnon tai alirutiinin kutsumisesta parametrien avulla

Kun funktiota kutsutaan, välität yleensä parametrit funktiolle käyttämällä funktion jo määrittämiä tietotyyppejä. Toiminto voi olla sellainen, joka on jo määritetty VBA: ssa, tai se voi olla käyttäjän määrittämä toiminto, jonka olet itse rakentanut. Myös alirutiini voi joskus vaatia parametreja

Jos et noudata sääntöjä, joilla parametrit siirretään funktiolle, saat virheen

12345678 Sub CallFunction ()Dim Ret kokonaislukunaRet = Oma toiminto (3, "testi")End SubToiminto MyFunction (N kokonaislukuna, T merkkijonona) merkkijononaOma toiminto = T.Lopeta toiminto

Tässä on useita mahdollisuuksia saada virheellisyysvirhe

Palautusmuuttuja (Ret) määritellään kokonaislukuna, mutta funktio palauttaa merkkijonon. Heti kun suoritat koodin, se epäonnistuu, koska funktio palauttaa merkkijonon, eikä tämä voi mennä kokonaislukumuuttujaan. On mielenkiintoista, että virheenkorjauksen suorittaminen tällä koodilla ei poimi tätä virhettä.

Jos laitat lainausmerkit ensimmäisen välitettävän parametrin (3) ympärille, se tulkitaan merkkijonoksi, joka ei vastaa funktion (kokonaisluku) ensimmäisen parametrin määritelmää

Jos muutat funktiokutsun toisen parametrin numeeriseksi arvoksi, se epäonnistuu, koska se ei vastaa toisiaan, koska merkkijonon toinen parametri määritellään merkkijonoksi (teksti)

Väärinkäytösvirhe, joka aiheutuu VBA: n konversiotoimintojen käytöstä väärin

VBA: ssa on useita muuntotoimintoja, joiden avulla voit muuntaa arvot eri tyyppisiksi. Esimerkki on CInt, joka muuntaa numeron sisältävän merkkijonon kokonaislukuarvoksi.

Jos muunnettava merkkijono sisältää mitä tahansa alfa -merkkiä, saat täsmäytysvirheen, vaikka merkkijonon ensimmäinen osa sisältää numeerisia merkkejä ja loput ovat kirjaimia, esim. "123abc"

Yleinen yhteensopivuusvirheiden ehkäisy

Olemme nähneet yllä olevissa esimerkeissä useita tapoja käsitellä mahdollisia virheitä koodissasi, mutta on olemassa useita muita tapoja, vaikka ne eivät ehkä ole parhaita vaihtoehtoja:

Määritä muuttujasi muuttujatyypiksi

Varianttityyppi on VBA: n oletusmuuttujatyyppi. Jos et käytä Dim -lausetta muuttujalle ja alat käyttää sitä vain koodissasi, sille annetaan automaattisesti Variantin tyyppi.

Muuttujan muuttuja hyväksyy kaiken tyyppiset tiedot, olivatpa ne sitten kokonaislukuja, pitkiä kokonaislukuja, kaksinkertaisia ​​tarkkuuksia, totuusarvoa tai tekstiä. Tämä kuulostaa mahtavalta ajatukselta, ja ihmettelet, miksi kaikki eivät vain aseta kaikkia muuttujiaan variantiksi.

Muunnelman tietotyypillä on kuitenkin useita haittoja. Ensinnäkin se vie paljon enemmän muistia kuin muut tietotyypit. Jos määrität muunnelmana erittäin suuren ryhmän, se nielee valtavan määrän muistia, kun VBA -koodi on käynnissä, ja voi helposti aiheuttaa suorituskykyongelmia

Toiseksi sen suorituskyky on yleensä hitaampi kuin jos käytät tiettyjä tietotyyppejä. Jos esimerkiksi teet monimutkaisia ​​laskelmia käyttämällä liukuvia desimaalilukuja, laskelmat ovat huomattavasti hitaampia, jos tallennat luvut muunnelmina kaksinkertaisten tarkkuuslukujen sijaan

Muunnostyypin käyttöä pidetään huolimattomana ohjelmointina, ellei se ole ehdottoman välttämätöntä.

Käytä OnError -komentoa virheiden käsittelyyn

OnError-komento voidaan sisällyttää koodiin virheiden sieppauksen käsittelemiseksi, joten jos virhe ilmenee, käyttäjä näkee merkityksellisen viestin tavallisen VBA-virheen ponnahdusikkunan sijasta

1234567 Alavirheloukku ()Dim MyNumber kokonaislukunaVirhe GoTo Err_HandlerOma numero = "testi"Err_Handler:MsgBox "Virhe" & Err.Description & "on tapahtunut"End Sub

Tämä estää tehokkaasti virheen pysäyttämästä koodin sujuvaa toimintaa ja antaa käyttäjälle mahdollisuuden toipua virheellisestä tilanteesta.

Err_Handler -rutiini voisi näyttää lisätietoja virheestä ja siitä, keneen ottaa yhteyttä.

Ohjelmoinnin kannalta, kun käytät virheenkäsittelyrutiinia, on melko vaikeaa löytää koodirivi, jossa virhe on. Jos selaat koodia F8 -näppäimellä, heti kun rikkova koodirivi on suoritettu, se hyppää virheenkäsittelyrutiiniin etkä voi tarkistaa, missä se menee pieleen.

Yksi tapa kiertää tämä on määrittää globaali vakio, joka on tosi tai epätosi (Boolean), ja käyttää sitä virrankäsittelyrutiinin ottamiseen käyttöön tai poistamiseen käytöstä If -lausekkeen avulla. Kun haluat testata virhettä, sinun tarvitsee vain asettaa yleinen vakio arvoon False ja virheenkäsittelijä ei enää toimi.

1 Globaali Const ErrHandling = False
1234567 Alavirheloukku ()Dim MyNumber kokonaislukunaJos ErrHandling = Tosi sitten Virhe Siirry Err_HandlerOma numero = "testi"Err_Handler:MsgBox "Virhe" & Err.Description & "on tapahtunut"End Sub

Yksi ongelma tässä on se, että sen avulla käyttäjä voi toipua virheestä, mutta alikoodin muu koodi ei käynnisty, millä voi olla valtavia vaikutuksia myöhemmin sovelluksessa

Käyttämällä aikaisempaa esimerkkiä silmukan vaihtamisesta solualueen läpi koodi pääsisi soluun A5 ja osuisi virheelliseen virheeseen. Käyttäjä näkee viestiruudun, joka antaa tietoja virheestä, mutta mitään tästä solusta eteenpäin alueella ei käsitellä.

Käytä OnError -komentoa virheiden poistamiseen

Tämä käyttää 'On Error Resume Next' -komentoa. Tämä on erittäin vaarallista sisällyttää koodiin, koska se estää myöhempien virheiden näyttämisen. Tämä tarkoittaa pohjimmiltaan sitä, että koodisi suoritettaessa, jos virhe tapahtuu koodirivillä, suoritus siirtyy seuraavalle käytettävissä olevalle riville suorittamatta virheriviä ja jatkuu normaalisti.

Tämä saattaa selvittää mahdollisen virhetilanteen, mutta se vaikuttaa silti kaikkiin koodin tuleviin virheisiin. Saatat sitten ajatella, että koodisi on virheetön, mutta itse asiassa se ei ole, ja koodin osat eivät tee sitä, mitä luulet sen tekevän.

Joissakin tilanteissa on tarpeen käyttää tätä komentoa, kuten jos poistat tiedoston käyttämällä Kill -komentoa (jos tiedosto ei ole läsnä, tulee virhe), mutta virheen sieppaus on aina vaihdettava takaisin päälle heti sen jälkeen, kun mahdollinen virhe voi ilmetä käyttämällä:

1 Virhe Siirry 0

Aikaisemmassa esimerkissä silmukan kierrättämisestä solualueen läpi käyttämällä 'On Error Resume Next' -toimintoa tämä mahdollistaisi silmukan jatkumisen, mutta virheen aiheuttavaa solua ei siirretä taulukkoon eikä kyseisen indeksin taulukkoelementtiä olisi nolla -arvo.

Tietojen muuntaminen tietotyypiksi vastaamaan ilmoitusta

VBA -toimintojen avulla voit muuttaa saapuvan datan tietotyyppiä siten, että se vastaa vastaanottavan muuttujan tietotyyppiä.

Voit tehdä tämän, kun välität parametreja toiminnoille. Jos sinulla on esimerkiksi numero, joka on merkkijonomuuttujassa ja haluat siirtää sen numerona funktiolle, voit käyttää CInt

Näitä muuntotoimintoja voidaan käyttää useita, mutta tässä ovat tärkeimmät:

CInt - muuntaa merkkijonon, jolla on numeerinen arvo (alle + tai - 32 768), kokonaislukuarvoksi. Huomaa, että tämä katkaisee kaikki desimaalipisteet

CLng - Muuntaa merkkijonon, jolla on suuri numeerinen arvo, pitkäksi kokonaisluvuksi. Desimaalipisteet katkaistaan.

CDbl - Muuntaa kelluvan desimaaliluvun sisältävän merkkijonon kaksinkertaiseksi tarkkuudeksi. Sisältää desimaalipilkun

CDate - Muuttaa päivämäärän sisältävän merkkijonon päivämäärämuuttujaksi. Riippuu osittain Windowsin ohjauspaneelin asetuksista ja alueesta päivämäärän tulkinnasta

CStr - Muuntaa numero- tai päivämääräarvon merkkijonoksi

Kun muunnetaan merkkijonosta numeroksi tai päivämääräksi, merkkijono ei saa sisältää mitään muuta kuin numeroita tai päivämäärää. Jos alfa -merkkejä on läsnä, tämä aiheuttaa virheen. Tässä on esimerkki, joka tuottaa virheen:

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

Muuttujien testaaminen koodissasi

Voit testata muuttujaa selvittääksesi, mikä tietotyyppi se on, ennen kuin määrität sen tietyn tyyppiselle muuttujalle.

Voit esimerkiksi tarkistaa merkkijonon, onko se numeerinen käyttämällä VBA: n IsNumeric -funktiota

1 MsgBox IsNumeric ("123test")

Tämä koodi palauttaa epätosi, koska vaikka merkkijono alkaa numeerisilla merkeillä, se sisältää myös tekstiä, joten se epäonnistuu testissä.

1 MsgBox IsNumeric ("123")

Tämä koodi palauttaa arvon True, koska se sisältää kaikki numeeriset merkit

VBA: ssa on useita toimintoja eri tietotyyppien testaamiseen, mutta nämä ovat tärkeimmät:

IsNumeric - testaa, onko lauseke numero vai ei

IsDate - testaa, onko lauseke päivämäärä vai ei

IsNull - testaa, onko lauseke tyhjä vai ei. Nolla -arvo voidaan lisätä vain varianttiobjektiin, muuten saat virheilmoituksen "Invalid Use of Null". Viestiruutu palauttaa nolla -arvon, jos käytät sitä kysymyksen esittämiseen, joten palautusmuuttujan on oltava muunnelma. Muista, että kaikki nolla -arvoa käyttävät laskelmat palauttavat aina null -tuloksen.

IsArray - testaa, edustaakö lauseke matriisia vai ei

IsEmpty - testaa, onko lauseke tyhjä vai ei. Huomaa, että tyhjä ei ole sama kuin nolla. Muuttuja on tyhjä, kun se määritellään ensimmäisen kerran, mutta se ei ole nolla -arvo

Yllättävää kyllä, IsTextille tai IsStringille ei ole toimintoa, mikä olisi todella hyödyllistä

Objektit ja virheet

Jos käytät objekteja, kuten aluetta tai taulukkoa, saat täsmäytysvirheen käännös-, ei suoritusaikana, mikä varoittaa sinua siitä, että koodisi ei toimi

123456 Alatestialue ()Dim MyRange as Range, I As LongAseta MyRange = Range ("A1: A2")I = 10x = UseMyRange (I)End Sub
12 Toiminto UseMyRange (R As Range)Lopeta toiminto

Tällä koodilla on toiminto nimeltä UseMyRange ja parametri, joka välitetään alueobjektina. Kuitenkin parametri, jota välitetään, on pitkä kokonaisluku, joka ei vastaa tietotyyppiä.

Kun suoritat VBA -koodin, se kootaan välittömästi ja näet seuraavan virheilmoituksen:

Loukkaava parametri korostetaan sinisellä taustalla

Yleensä, jos teet virheitä VBA -koodissa objekteja käyttämällä, näet tämän virheilmoituksen eikä tyyppivirheviestiä:

Tulet auttaa kehittämään sivuston jakaminen sivu ystävillesi

wave wave wave wave wave