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ä: