Attribute VB_Name = "Module1" Private Function ViimeinenRivi() As Long 'Tässä funktiossa etsitään taulukossa käytetty viimeinen rivi. 'Rivillä 4 käytetään taulukkosivun UsedRange-ominaisuutta. 'Tämän rivin asetuslauseella saadaan TmpS-muuttujaan arvoksi $A$4:$E$220. 'Sitten etsitään silmukassa (rivit 5-7) viimeinen taalanmerkki merkkijonosta 'Tämän jälkeen osataan ottaa Mid-funktiolla viimeisen rivin numero ulos merkkijonosta. 1 Dim TmpS As String 2 Dim Lp As Long 3 Dim LPos As Long 4 TmpS = ActiveSheet.UsedRange.Address 5 For Lp = 1 To Len(TmpS) 6 If Mid(TmpS, Lp, 1) = "$" Then LPos = Lp 7 Next Lp 8 ViimeinenRivi = CLng(Mid(TmpS, LPos + 1, Len(TmpS) - LPos)) End Function Private Function ViimeinenRivi_SilmukkaLopusta() As Long 'Tällä funktiolla etsitään taulukkosivun viimeiseltä riviltä lähtien viimeinen täytetty rivi. 'Koodaaja voi varmasti miettiä tähän nopeampaa ja tehokkaampaa ratkaisua. 'Voi esimerkiksi ajatella, että siirtyy ensin taulukon keskikohdassa olevalle riville, ja tarkistaa sen ja jatkaa edelleen puolittamalla oikean paikan etsimistä. 'Koodaaja saattaa myös aloittaa hakemisen listan yläreunasta ja tehdä oletuksen, että jos taulukossa on kymmenen peräkkäistä tyhjää riviä niin lista on loppunut. 'Jos on mahdollista, että listassa on paljon peräkkäisiä tyhjiä rivejä, hakeminen listan alusta tai taulukon puolittaminen eivät ole varmoja tekniikoita löytää viimeinen rivi. 'Seuraava funktio aloittaa etsimisen taulukon viimeiseltä riviltä ja siirtyy rivi kerrallaan ylöspäin. ' 'Funktiossa ViimeinenRivi on esitelty kolme paikallista muuttujaa. 'Muuttujassa Rivi pidetään kirjaa silmukassa käsiteltävästä rivistä. 'Muuttujaan ViimRivi asetetaan silmukassa löydetty taulukon viimeinen rivi. 'Tämän muuttujan arvo asetetaan myös funktion tulokseksi. 'Muuttujaan R asetetaan solualue, joka annetaan CountA-funktiolle silmukan sisällä. 'Katso tarvittaessa lisätietoa Excelin työkirjan valmisfunktioiden käytöstä Excel-VBA -koodissa luvun 4 jaksosta Viittaus työkirjafunktioihin. 'Muuttujaan ViimRivi asetetaan oletusarvoksi nolla ja muuttujaan Rivi taulukossa olevien rivien kokonaismäärä. 'Silmukkaa (rivit 6-12) suoritetaan niin kauan kun ViimRivi-muuttujassa oleva arvo on nolla ja Rivi-muuttujassa oleva rivilaskuri on nollaa suurempi. 'Näistä ehdoista edellinen ei toteudu enää, kun silmukassa on löydetty rivi, joka ei ole tyhjä. 'Ehdoista jälkimmäinen ei toteudu enää, kun taulukon kaikki rivit on jo tarkistettu, ja seuraavaksi arvoksi tulisi nolla. 'Silmukointi lopetetaan siis joko silloin, kun viimeinen rivi on löydetty tai silloin, kun kaikki taulukkosivun rivit on tarkistettu. 'Huomaa, että ilman tarkistusta (Rivi > 0) koodi joutuisi suorituksenaikaiseen virheeseen, kun se suoritetaan tyhjälle taulukkosivulle (esimerkiksi solua A0 ei ole olemassa). 'Jos siis voi olettaa, että taulukossa on aina esimerkiksi otsikkorivi, tätä ehdon osaa ei välttämättä tarvitse kirjoittaa. 'Silmukan sisällä muuttujaan R (tietotyyppi on solualue eli Range) asetetaan kyseisen rivin mukaisesti solualue sarakkeiden A ja F välistä. 'Työkirjapuolen CountA-valmisfunktiolla saadaan selville solualueella olevien ei-tyhjien solujen kappalemäärä. 'Jos arvo on nollaa suurempi, tämän rivin arvo asetetaan ViimRivi-muuttujaan. 'Kun koodi jatkaa seuraavan kerran silmukan ehto-osaan, silmukan suorittaminen lopetetaan. 'Tällöin löydetty viimeinen rivi asetetaan funktion arvoksi. 1 Dim Rivi As Long 2 Dim ViimRivi As Long 3 Dim R As Range 4 ViimRivi = 0 5 Rivi = Application.Rows.Count 6 Do While (ViimRivi = 0) And (Rivi > 0) 7 Set R = Range("A" & Rivi & ":F" & Rivi) 8 If Application.WorksheetFunction.CountA(R) > 0 Then 9 ViimRivi = Rivi 10 End If 11 Rivi = Rivi - 1 12 Loop 13 ViimeinenRivi = ViimRivi End Function Private Sub MerkitseRivit(ByRef Rivit_MsgStr As String, _ ByRef Rivit_DelStr As String) 'Proseduurille MerkitseRivit on asetettu kaksi parametria. 'Parametreista kannattaa huomioida, että ne on määritelty ByRef -tyyppisiksi. 'Tämä tarkoittaa sitä, että kun aliohjelmaa kutsutaan, näiden parametrien arvo välitetään kutsuvan aliohjelman muuttujiin. 'Katso tarvittaessa lisätietoa luvun 3 jaksosta Funktiot ja proseduurit. 'Parametriin Rivit_MsgStr komennetaan merkkijono, joka kertoo käyttäjälle poistettavat rivit ja pyytää käyttäjältä varmistusta. 'Parametriin Rivit_DelStr asetetaan sellainen merkkijono, jolla poisto voidaan tehdä. 'Nämä kaksi parametria ovat molemmat tarpeelliset, koska poiston syntaksi on hieman erilainen kuin mitä käyttäjälle halutaan näyttää. 'Jos poistettavat rivit ovat vaikka 7 ja 8, niin muuttujan Rivit_MsgStr arvoksi saadaan "7, 8" ja muuttujan Rivit_DelStr arvoksi saadaan "7:7,8:8". 'Edellinen on kiva näyttää käyttäjälle, mutta kokonaisten rivien poistossa poistettava alue pitää merkitä jälkimmäisen syntaksin mukaisesti. 'Koska palautettavia arvoja on kaksi tässä ei ole käytetty funktiota. 'Koodissa käydään For-silmukassa läpi kaikki käsiteltävät rivit (koodirivit 7-13). 'Jos rivi on tyhjä, se palauttaa CountA-funktiolla (WorksheetFunction.CountA) arvon nolla (rivi 9). 'Tällöin rivi lisätään halutun syntaksin mukaisesti sekä muuttujaan Rivit_MsgStr että muuttujaan Rivit_DelStr. 'Kun silmukasta poistutaan, molemmissa merkkijonoissa on ylimääräinen pilkku lopussa. 'Jos poistettavat rivit ovat esimerkiksi 7 ja 8, niin silmukasta poistuttaessa muuttujassa Rivit_MsgStr on arvo "7, 8, " ja muuttujassa Rivit_DelStr on arvo "7:7,8:8,". 'Joten edellisestä poistetaan kaksi viimeistä merkkiä ja jäkimmäisestä yksi viimeinen merkki. Tämä tehdään merkkijonofunktiolla Mid. 'Katso tarvittaessa lisää tämän valmisfunktion käytöstä luvun 4 jaksosta Merkkijonofunktiot. 'Koska parametrit ovat ByRef -tyyppisiä, mitään erillistä asetusta tai vastausta ei aliohjelmassa ole tarpeen asettaa vaan parametrien muuttuneet arvot välitetään kutsuvalle aliohjelmalle automaattisesti. 1 Dim Alku As Long 2 Dim Loppu As Long 3 Dim Lp As Long 4 Dim R As Range 5 Alku = 5 6 Loppu = ViimeinenRivi 7 For Lp = Alku To Loppu 8 Set R = Range("A" & Lp & ":E" & Lp) 9 If Application.WorksheetFunction.CountA(R) = 0 Then 10 Rivit_MsgStr = Rivit_MsgStr & Lp & ", " 11 Rivit_DelStr = Rivit_DelStr & Lp & ":" & Lp & "," 12 End If 13 Next Lp 14 If Len(Rivit_MsgStr) >= 2 Then 15 Rivit_MsgStr = Mid(Rivit_MsgStr, 1, Len(Rivit_MsgStr) - 2) 16 End If 17 If Len(Rivit_DelStr) >= 1 Then 18 Rivit_DelStr = Mid(Rivit_DelStr, 1, Len(Rivit_DelStr) - 1) 19 End If End Sub Private Sub TeePoisto(ByVal Rivit_MsgStr As String, _ ByVal Rivit_DelStr As String) 'Proseduuri TeePoisto saa argumentteina poistettavan alueen kahdessa muodossa. 'Aivan kuten MerkitseRivit-aliohjelmassa, ensimmäistä (Rivit_MsgStr) käytetään käyttäjän ilmoitukseen ja jälkimmäistä (Rivit_DelStr) itse alueen poistamiseen. 'Aliohjelmassa tarkistetaan ensin, onko ylipäätään löydetty mitään poistettavaa (rivi 1). 'Tämä tunnistetaan siitä, että merkkijonomuuttujan Rivit_MsgStr arvo on tyhjä. 'Tarkistus voitaisiin tietenkin tehdä myös Rivit_DelStr-parametrin arvolla. 'Jos taulukossa on poistettavia rivejä, aliohjelma varmistaa käyttäjältä rivien poiston (rivi 4). 'Jos käyttäjä hyväksyy poiston, seuraavaksi tarvitaan Rivit_DelStr-muuttujan arvoa. 'Ehtolauseen tässä osassa komennetaan yksinkertaisesti kyseisten rivien poisto käyttämällä metodia Delete. 'Metodille on annettu taulukkoon poiston jälkeen jäävien solujen siirtosuunta. 'Tässä on pyydetty, että rivit siirretään ylöspäin. 'Parametri kannattaa välittää, koska oletusarvo ei ole kiinteä vaan Excel päättelee suunnan poistettavan alueen muodon mukaan. 'Tämä selviää parhaiten nauhoittamalla makro ja tutkimalla nauhoitettua koodia. 'Jos käyttäjä ei hyväksynyt poistoa, siirrytään ehdon Else-haaraan. 'Täällä käyttäjälle ilmoitetaan, että taulukkoon ei ole tehty mitään muutoksia. 1 If Rivit_MsgStr = "" Then 2 MsgBox "Ei mitään tehtävää." 3 Else 4 If MsgBox("Toiminto on poistamassa seuraavat rivit : " & _ Chr(10) & Rivit_MsgStr & Chr(10) & _ "Hyväksy poisto OK-painikeella", vbOKCancel) = vbOK Then 5 Range(Rivit_DelStr).Delete Shift:=xlUp 6 Else 7 MsgBox "Peruutit poiston. Mitään ei poistettu." 8 End If 9 End If End Sub Public Sub Main() 'Main-proseduurissa alustetaan muuttujat ja kutsutaan aliohjelmia. 'Muuttujalla RM merkitään muuttujaa, jolla käyttäjälle ilmoitetaan poistettavista riveistä. 'Muuttujaan RD merkitään poistettavien rivien alue valmiiksi siinä muodossa, kun ne poiston yhteydessä halutaan esittää. 'Aliohjelman Main muuttuja RM siis viittaa samaan muistipaikkaan kuin aliohjelman MerkitseRivit muuttuja Rivit_MsgBox, silloin kun kontrolli on aliohjelmassa MerkitseRivit. 'Vastaavasti, muuttujat RD ja Rivit_DelStr kuuluvat yhteen. 'Käytännössä muuttujia ei käytetä pääohjelmassa mitenkään. 'Muuttujat kierrätetään pääohjelman kautta, koska niitä ei haluttu alustaa moduulissa globaaleiksi. 'Yhtä hyvä tekninen ratkaisu olisi ollut määritellä muuttujat heti moduulin yläosassa yhteisiksi muuttujiksi kaikille moduulin aliohjelmille. 1 Dim RM As String 2 Dim RD As String 3 RM = "" 4 RD = "" 5 MerkitseRivit RM, RD 6 TeePoisto RM, RD End Sub