Excel Regex: vastaa merkkijonoja säännöllisillä lausekkeilla

  • Jaa Tämä
Michael Brown

Tässä opetusohjelmassa tarkastelemme perusteellisesti, miten regexiä käytetään merkkijonojen täsmäyttämiseen Excelissä.

Kun haluat löytää tietyn arvon solualueelta, käytät MATCH- tai XMATCH-toimintoa. Kun etsit tiettyä merkkijonoa solusta, FIND- ja SEARCH-toiminnot ovat käteviä. Ja mistä tiedät, sisältääkö solu tietoa, joka vastaa tiettyä mallia? Ilmeisesti käyttämällä säännöllisiä lausekkeita. Mutta Excel ei kuitenkaan tue regexejä! Ei hätää, me pakotamme sen siihen :)

    Excel VBA Regex -funktio merkkijonojen vastaamiseksi

    Kuten otsikosta käy melko selvästi ilmi, säännöllisiä lausekkeita käyttääkseen Excelissä sinun on luotava oma funktio. Onneksi Excelin VBA:ssa on sisäänrakennettu RegExp objektin, jota voit käyttää koodissasi alla esitetyllä tavalla:

    Public Function RegExpMatch(input_range As Range, pattern As String , Optional match_case As Boolean = True ) As Variant Dim arRes() As Variant 'array tulosten tallentamiseen Dim iInputCurRow, iInputCurCol, cntInputRows, cntInputCols As Long 'lähdealueen nykyisen rivin indeksi, lähdealueen nykyisen sarakkeen indeksi, rivien lukumäärä, sarakkeiden lukumäärä On Error GoTo ErrHandlRegExpMatch = arRes Set regex = CreateObject ( "VBScript.RegExp" ) regex.pattern = pattern regex.Global = True regex.MultiLine = True If True = match_case Then regex.ignorecase = False Else regex.ignorecase = True End If cntInputRows = input_range.Rows.Count cntInputCols = input_range.Columns.Count ReDim arRes(1 To cntInputRows, 1 To cntInputCols) For iInputCurRow = 1 To cntInputRows ForiInputCurCol = 1 To cntInputCols arRes(iInputCurRow, iInputCurCol) = regex.Test(input_range.Cells(iInputCurRow, iInputCurCol).Value) Next Next RegExpMatch = arRes Exit Function ErrHandl: RegExpMatch = CVErr(xlErrValue) End Function

    Liitä koodi VBA-editoriin, ja uusi koodisi on RegExpMatch toiminto on valmis käytettäväksi. Jos sinulla ei ole kovin paljon kokemusta VBA:sta, tästä oppaasta voi olla apua: VBA-koodin lisääminen Exceliin.

    Huomautus. Kun olet lisännyt koodin, muista tallentaa tiedosto tiedostona nimellä makrotoiminnoilla varustettu työkirja (.xlsm).

    RegExpMatch-syntaksi

    The RegExpMatch funktio tarkistaa, vastaako jokin lähdejonon osa säännöllistä lauseketta. Tuloksena on boolen arvo: TRUE, jos vähintään yksi vastaavuus löytyy, muuten FALSE.

    Mukautetussa funktiossamme on kolme argumenttia - kaksi ensimmäistä ovat pakollisia ja viimeinen on valinnainen:

    RegExpMatch(text, pattern, [match_case])

    Missä:

    • Teksti (pakollinen) - yksi tai useampi merkkijono, josta haetaan. Voidaan antaa solu- tai alueviitteenä.
    • Kuvio (pakollinen) - Säännöllinen lauseke, jota halutaan verrata. Kun kuvio sijoitetaan suoraan kaavaan, se on suljettava kaksinkertaisiin lainausmerkkeihin.
    • Match_case (valinnainen) - määrittelee vastaavuustyypin. Jos TRUE tai jätetään pois (oletus), täsmäytys tehdään isojen ja pienten kirjainten perusteella; jos FALSE - isojen ja pienten kirjainten perusteella.

    Toiminto toimii kaikissa Excel 365-, Excel 2021-, Excel 2019-, Excel 2016-, Excel 2013- ja Excel 2010 -versioissa.

    3 asiaa, jotka sinun tulisi tietää RegExpMatchista

    Ennen kuin siirrymme käytännön laskelmiin, ota huomioon seuraavat seikat, jotka selventävät joitakin teknisiä seikkoja:

    1. Toiminto voi käsitellä yksittäinen solu tai soluväli Jälkimmäisessä tapauksessa tulokset palautetaan viereisiin soluihin dynaamisen joukon tai vuotoalueen muodossa, kuten tässä esimerkissä on esitetty.
    2. Oletusarvoisesti toiminto on case-sensitive Jos haluat jättää huomiotta tekstin isot ja pienet kirjaimet, aseta match_case argumentin arvoksi FALSE. VBA Regexp -rajoitusten vuoksi isojen ja pienten kirjainten erittelemätöntä mallia (?i) ei tueta.
    3. Jos kelvollista kuviota ei löydy, funktio palauttaa FALSE; jos kuvio on virheellinen , tapahtuu #VALUE! -virhe.

    Alla on muutama regex-otteluesimerkki, jotka on luotu esittelytarkoituksiin. Emme voi taata, että mallimme toimivat moitteettomasti laajemmalla syötetiedon valikoimalla todellisissa työarkkeissasi. Ennen kuin otat ne käyttöön tuotannossa, muista testata ja mukauttaa esimerkkimalliamme tarpeidesi mukaan.

    Miten regexiä käytetään merkkijonojen sovittamiseen Excelissä?

    Kun kaikilla merkkijonoilla, joita haluat verrata, on sama kuvio, säännölliset lausekkeet ovat ihanteellinen ratkaisu.

    Oletetaan, että sinulla on solualue (A5:A9), joka sisältää erilaisia tietoja tietyistä tuotteista. Haluat tietää, mitkä solut sisältävät SKU-tunnuksia. Oletetaan, että jokainen SKU-tunnus koostuu kahdesta isosta kirjaimesta, yhdysmerkistä ja kolmesta numerosta, ja voit verrata niitä käyttämällä seuraavaa lauseketta.

    Kuvio : \b[A-Z]{2}-\d{3}\b

    Jossa [A-Z]{2} tarkoittaa kahta isoa kirjainta A:sta Z:hen ja \d{3} kolmea numeroa 0-9. \b-merkki tarkoittaa sanan rajaa, mikä tarkoittaa, että SKU on erillinen sana eikä osa suurempaa merkkijonoa, kuten 23-MAR-2022.

    Kun kaava on luotu, voimme siirtyä kaavan kirjoittamiseen. Periaatteessa mukautetun funktion käyttäminen ei eroa natiivista funktiosta. Heti kun aloitat kaavan kirjoittamisen, funktion nimi ilmestyy Excelin AutoComplete-ominaisuuden ehdottamaan luetteloon. Dynaamisessa kaavarivillä varustetussa Excelissä (Microsoft 365 ja Excel 2021) ja perinteisessä Excelissä (2019 ja vanhemmat versiot) on kuitenkin muutamia vivahteita.

    Täsmää merkkijono yhdessä solussa

    Jos haluat löytää merkkijonon yksittäisessä solussa, viittaat kyseiseen soluun ensimmäisessä argumentissa. Toisen argumentin on tarkoitus sisältää säännöllinen lauseke.

    =RegExpMatch(A5, "\b[A-Z]{2}-\d{3}\b")

    Kuvio voidaan myös säilyttää ennalta määritetyssä solussa, joka on lukittu absoluuttisella viittauksella ($A$2):

    =RegExpMatch(A5, $A$2)

    Kun olet syöttänyt kaavan ensimmäiseen soluun, voit vetää sen alas kaikille muille riveille.

    Tämä menetelmä toimii erinomaisesti kaikki Excel-versiot .

    Täsmää merkkijonoja useissa soluissa kerralla

    Jos haluat yhdistää useita merkkijonoja yhdellä kaavalla, sisällytä ensimmäiseen argumenttiin viittaus alueeseen:

    =RegExpMatch(A5:A9, "\b[A-Z]{2}-\d{3}\b")

    Osoitteessa Excel 365 ja Excel 2021 jotka tukevat dynaamisia matriiseja, se toimii näin: kirjoitat kaavan ensimmäiseen soluun, painat Enter-näppäintä, ja kaava leviää automaattisesti alla oleviin soluihin.

    Osoitteessa Excel 2019 ja aiemmissa versioissa se toimii vain perinteisenä CSE-määrityskaavana, joka syötetään solualueelle ja täydennetään painamalla Ctrl + Shift + Enter -näppäimiä yhdessä.

    Regex vastaamaan numeroa

    Jos haluat löytää minkä tahansa yksittäisen numeron välillä 0-9, käytä näppäintä \d Lisää tehtävästäsi riippuen sopiva kvantifikaattori tai luo monimutkaisempi kuvio.

    Regex, joka vastaa mitä tahansa numeroa

    Jos haluat löytää minkä tahansa pituisen luvun, laita +-kvantifikaattori heti /d-merkin jälkeen, mikä tarkoittaa, että etsitään numeroita, jotka sisältävät 1 tai useampia numeroita.

    Kuvio : \d+

    =RegExpMatch(A5:A9, "\d+")

    Regex vastaamaan tietyn pituista numeroa

    Jos tavoitteenasi on löytää tietyn määrän numeroita sisältäviä numeerisia arvoja, käytä \d-merkkiä yhdessä sopivan kvantifioijan kanssa.

    Jos haluat esimerkiksi täsmälleen 7 numeroa sisältäviä laskunumeroita, käytä \d{7}. Muista kuitenkin, että se vastaa 7 numeroa missä tahansa merkkijonossa, mukaan lukien 10-numeroinen tai 100-numeroinen numero. Jos et etsi tätä, laita molemmille puolille sananraja \b.

    Kuvio : \b\d{7}\b

    =RegExpMatch(A5:A9, "\b\d{7}\b")

    Regex vastaamaan puhelinnumeroita

    Koska puhelinnumerot voidaan kirjoittaa eri muodoissa, niiden täsmäyttäminen vaatii monimutkaisemman säännöllisen lausekkeen.

    Alla olevassa tietokokonaisuudessa etsitään 10-numeroisia numeroita, joiden kahdessa ensimmäisessä ryhmässä on 3 numeroa ja viimeisessä ryhmässä 4 numeroa. Ryhmät voidaan erottaa toisistaan pisteellä, väliviivalla tai välilyönnillä. Ensimmäinen ryhmä voidaan sulkea sulkuihin tai olla sulkematta.

    Kuvio: (\(\d{3}\)

    Kun tämä säännöllinen lauseke puretaan, saadaan seuraavaa:

    • Ensimmäinen osa (\(\(\d{3}\))
    • Osa [-\.\s]? tarkoittaa 0 tai 1 merkin esiintymistä hakasulkeissa: väliviiva, piste tai välilyönti.
    • Seuraavaksi on vielä yksi kolmen numeron ryhmä d{3}, jota seuraa yhdysmerkki, piste tai välilyönti [\-\.\s]?, joka esiintyy 0 tai 1 kertaa.
    • Viimeistä neljän numeron ryhmää \d{4} seuraa sanarajoitus \b, joka tekee selväksi, että puhelinnumero ei voi olla osa suurempaa numeroa.

    Kun alkuperäinen merkkijono on A5:ssä ja säännöllinen lauseke A2:ssa, kaava on seuraavanlainen:

    =RegExpMatch(A5, $A$2)

    ... ja toimii täsmälleen odotusten mukaisesti:

    Huomautuksia:

    • Kansainvälisiä koodeja ei tarkisteta, joten niitä voi olla tai olla olematta.
    • Säännöllisissä lausekkeissa \s tarkoittaa mitä tahansa välilyönti-merkkiä, kuten välilyöntiä, tabulaattoria, rivinvaihtoa tai uutta riviä. Jos haluat sallia vain välilyönnit, käytä [-\. ] eikä [-\.\s].
    • Regex EI vastaa merkkiä

      Jos haluat etsiä merkkijonoja, jotka EIVÄT sisällä tiettyä merkkiä, voit käyttää negaatioluokkia [^ ], jotka vastaavat kaikkea, mitä EI ole suluissa. Esimerkiksi:

      • [^13] vastaa mitä tahansa yksittäistä merkkiä, joka ei ole 1 tai 3.
      • [^1-3] vastaa mitä tahansa yksittäistä merkkiä, joka ei ole 1, 2 tai 3 (eli mitä tahansa numeroa 1-3).

      Oletetaan, että haluat löytää puhelinnumeroiden luettelosta ne, joissa ei ole maakoodia. Kun muistat, että kaikki kansainväliset koodit sisältävät +-merkin, voit käyttää merkkiluokkaa [^\\+] löytääksesi merkkijonoja, jotka eivät sisällä plus-merkkiä. On tärkeää huomata, että yllä oleva lauseke vastaa mitä tahansa yksittäistä merkkiä, joka ei ole +. Koska puhelinnumero voi olla missä tahansa merkkijonossa, eivälttämättä aivan alussa, *-kvantifikaattori lisätään tarkistamaan jokainen seuraava merkki. Alku- ^- ja loppu $-ankkurit varmistavat, että koko merkkijono käsitellään. Tuloksena saamme alla olevan säännöllisen lausekkeen, joka sanoo "älä vastaa +-merkkiä missään merkkijonon kohdassa".

      Kuvio : ^[^\+]*$

      =RegExpMatch(A5, "^[^\\+]*$"))

      Regex, joka EI vastaa merkkijonoa

      Vaikka ei ole olemassa erityistä säännöllistä lausekesyntaksia, jolla ei soviteta tiettyä merkkijonoa, voit jäljitellä tätä käyttäytymistä käyttämällä negatiivista lookaheadia.

      Oletetaan, että haluat löytää merkkijonoja, jotka eivät sisällä sana "sitruunat". Tämä säännöllinen lauseke toimii hienosti:

      Kuvio : ^(((?!sitruunat).)*$

      On selvää, että tässä tarvitaan selitystä. Negatiivinen lookahead (?!sitruuna) katsoo oikealle, ettei edessä ole sanaa "sitruuna". Jos sanaa "sitruuna" ei ole, piste sopii mihin tahansa merkkiin paitsi rivinvaihtoon. Yllä oleva lauseke suorittaa vain yhden tarkistuksen, ja *-kvantifikaattori toistaa sen nolla tai useampia kertoja ^:llä ankkuroidun merkkijonon alusta ^:llä ankkuroidun merkkijonon loppuun.$.

      Jotta tekstin isot ja pienet kirjaimet jätettäisiin huomiotta, asetamme 3. argumentin arvoksi FALSE, jolloin funktio ei huomioi isoja ja pieniä kirjaimia:

      =RegExpMatch(A5, $A$2, FALSE)

      Vinkkejä ja huomautuksia:

      • Yllä oleva regex toimii vain yksirivinen Milti-rivisten merkkijonojen tapauksessa ^- ja $-merkit täsmäävät jokaisen rivin alkuun ja loppuun syötetyn merkkijonon alun ja lopun sijasta, joten regex etsii vain ensimmäiseltä riviltä.
      • Vastaamaan merkkijonoja, jotka älä käynnistä tietyn tekstin kanssa , käytä säännöllistä lauseketta, kuten ^(?!sitruunat).*$.
      • Vastaamaan merkkijonoja, jotka eivät lopu tietyn tekstin kanssa , sisällytä loppuosan merkkijonoankkuri hakukuvioon: ^(((?!sitruunat$).)*$

      Case insensitive matching

      Klassisissa säännöllisissä lausekkeissa on erityinen kuvio isojen ja pienten kirjainten erittelemätöntä täsmäytystä varten (?i), jota VBA RegExp ei tue. Tämän rajoituksen poistamiseksi mukautettu funktiomme hyväksyy kolmannen valinnaisen argumentin nimeltä match_case Jos haluat tehdä isoja ja pieniä kirjaimia erittelemättömän täsmäytyksen, aseta sen arvoksi FALSE.

      Oletetaan, että haluat tunnistaa päivämäärät, kuten 1-Mar-22 tai 01-MAR-2022. Jotta voit vastata dd-mmm-yyyyyy ja d-mmm-yy formaatteja, käytämme seuraavaa säännöllistä lauseketta.

      Kuvio : \b\d{1,2}-(Jan

      Lausekkeemme etsii 1 tai 2 numeron ryhmää, jota seuraa yhdysmerkki, jota seuraa mikä tahansa kuukauden lyhenne erotettuna

      Miksi et käyttäisi yksinkertaisempaa mallia, kuten \d{1,2}-[A-Za-z]{3}-\d{2,4}\b? Jotta vältyttäisiin vääriltä positiivisilta osumilta, kuten 01-ABC-2020.

      Syötä kuvio kohtaan A2, niin saat seuraavan kaavan:

      =RegExpMatch(A5, $A$2, FALSE)

      Regex, joka vastaa kelvollisia sähköpostiosoitteita

      Kuten yleisesti tiedetään, sähköpostiosoite koostuu neljästä osasta: käyttäjänimi, @-symboli, verkkotunnus (sähköpostipalvelin) ja ylätason verkkotunnus (kuten .com, .edu, .org jne.). Tarkistaaksemme sähköpostiosoitteen oikeellisuuden, meidän on toistettava yllä oleva rakenne säännöllisillä lausekkeilla.

      Kuvio : \b[\w\.\-]+@[A-Za-z0-9]+[A-Za-z0-9\.\-]*[A-Za-z0-9]+\.[A-Za-z]{2,24}\b

      Jotta ymmärtäisit paremmin, mistä tässä on kyse, tarkastellaan tarkemmin kutakin osaa:

      • Käyttäjätunnus voi sisältää kirjaimia, numeroita, alleviivauksia, pisteitä ja väliviivoja. Kun pidetään mielessä, että \w sopii mihin tahansa kirjaimeen, numeroon tai alleviivaukseen, saadaan seuraava regex: [\w\.\-]+
      • Verkkotunnus voi sisältää isoja ja pieniä kirjaimia, numeroita, väliviivoja (mutta ei ensimmäisessä eikä viimeisessä kohdassa) ja pisteitä (jos kyseessä on aliverkkotunnus). Koska alleviivaukset eivät ole sallittuja, käytämme \w:n sijasta kolmea eri merkistöä: [A-Za-z0-9]+[A-Za-z0-9\.\-]*[A-Za-z0-9]+ [A-Za-z0-9]+.
      • Ylätason verkkotunnus koostuu pisteestä, jota seuraavat isot ja pienet kirjaimet. Se voi sisältää 2-24 kirjainta (pisin tällä hetkellä käytössä oleva TLD): \.[A-Za-z]{2,24}

      Huomautus. Mallissa oletetaan, että verkkotunnus sisältää vähintään 2 aakkosnumeerista merkkiä.

      Kun alkuperäinen teksti on A5:ssä ja kuvio A5:ssä, kaava on seuraavanlainen:

      =RegExpMatch(A5, $A$2)

      Voit myös käyttää sähköpostin validointiin yksinkertaisempaa säännöllistä lauseketta, jossa on joko pienet tai isot kirjaimet:

      Kuvio : \b[\w\.\-]+@[a-z0-9]+[a-z0-9\.\-]*[a-z0-9]+\.[a-z]{2,24}\b

      Tee kaavasta kuitenkin isojen ja pienten kirjainten suhteen erittelemätön:

      =RegExpMatch(A5, $A$2, FALSE)

      Excelin IF-kaava ottelun regexin kanssa

      Koska sisäänrakennetut ja mukautetut funktiot sopivat hyvin yhteen, mikään ei estä sinua käyttämästä niitä yhdessä yhdessä kaavassa.

      Jos haluat palauttaa tai laskea jotain, jos säännöllinen lauseke täsmää, ja jotain muuta, jos se ei täsmää, upota mukautettu RegExpMatch-funktio IF:n loogiseen tekstiin:

      IF(RegExpMatch(...), [value_if_true], [value_if_false])

      Jos esimerkiksi merkkijono A5 sisältää kelvollisen sähköpostiosoitteen, voit palauttaa "Kyllä", muuten "Ei".

      =IF(RegExpMatch(A5, $A$2,), "Kyllä", "Ei")

      Laske, jos regex on sovitettu

      Koska natiivit Excel-funktiot eivät tue säännöllisiä lausekkeita, regexiä ei voi laittaa suoraan COUNTIS- tai COUNTIFS-funktioon. Onneksi voit jäljitellä tätä toimintoa mukautetun funktiomme avulla.

      Oletetaan, että olet käyttänyt regexiä puhelinnumeroiden etsimiseen ja tulostanut tulokset sarakkeeseen B. Saadaksesi selville, kuinka monta solua sisältää puhelinnumeroita, sinun tarvitsee vain laskea TRUE-arvot kohdissa B5:B9. Tämä voidaan tehdä helposti käyttämällä tavallista COUNTIF-kaavaa:

      =COUNTIF(B5:B9, TRUE)

      Etkö halua ylimääräisiä sarakkeita laskentataulukkoon? Ei hätää. Kun muistat, että mukautettu funktiomme voi käsitellä useita soluja kerrallaan ja että Excelin SUM voi laskea yhteen arvot matriisissa, toimi näin:

      • Anna RegExpMatchille alueellinen viite, jotta se palauttaa TRUE- ja FALSE-arvojen joukon.
      • Käytä kaksoisnegaatiota (--) pakottaaksesi loogiset arvot ykkösiksi ja nolliksi.
      • Pyydä SUM-funktiota laskemaan yhteen tuloksena syntyvän matriisin 1:t ja 0:t.

      =SUM(--RegExpMatch(A5:A9, $A$2))

      Regex-sovitus Ultimate Suite -ohjelmalla

      Ultimate Suite -ohjelmistomme käyttäjät voivat hyödyntää neljää tehokasta Regex-funktiota lisäämättä VBA-koodia työkirjoihinsa, sillä ne on integroitu sujuvasti Exceliin lisäosan asennuksen aikana. Mukautettuja funktioitamme käsitellään tavallisella .NET RegEx -moottorilla ja ne tukevat täydellisiä klassisia säännöllisiä lausekkeita.

      Miten käyttää mukautettua RegexMatch-funktiota

      Olettaen, että sinulla on asennettuna Ultimate Suite -ohjelman uusin versio (2021.4 tai uudempi), voit luoda Regex Match -kaavan kahdessa yksinkertaisessa vaiheessa:

      1. On Ablebits Data välilehdellä, kohdassa Teksti ryhmää, klikkaa Regex-työkalut .

    • On Regex-työkalut ruudussa, toimi seuraavasti:
      • Valitse lähdejonot.
      • Syötä kuvio.
      • Valitse Ottelu vaihtoehto.
      • Jos haluat, että tulokset ovat kaavoja, eivät arvoja, valitse valintaruutu Lisää kaavana valintaruutu.
      • Napsauta Ottelu nappi.

      Hetkeä myöhemmin AblebitsRegexMatch toiminto lisätään uuteen sarakkeeseen tietojen oikealle puolelle.

      Alla olevassa kuvakaappauksessa funktio tarkistaa, sisältävätkö sarakkeessa A olevat merkkijonot 7-numeroisia numeroita vai eivät.

      Vinkkejä:

      • Toiminto voi olla lisätty suoraan soluun standardin Lisää toiminto valintaikkunassa, jossa se on luokiteltu kohtaan AblebitsUDFs .
      • Oletusarvoisesti säännöllinen lauseke lisätään kaavaan, mutta voit pitää sen myös erillisessä solussa. Käytä tällöin vain soluviitettä 2. argumenttina.
      • Oletusarvoisesti toiminto on case-sensitive Käytä (?i)-mallia, jos haluat käyttää isoja ja pieniä kirjaimia erittelemätöntä täsmäytystä.

      Lisätietoja on kohdassa AblebitsRegexMatch-funktio.

      Näin teet säännöllisen lausekkeen täsmäytyksen Excelissä. Kiitän sinua lukemisesta ja odotan innolla, että tapaamme sinut blogissamme ensi viikolla!

      Saatavilla olevat lataukset

      Excel Regex Match -esimerkkejä (.xlsm-tiedosto)

      Ultimate Suite 14 päivän täysin toimiva versio (.exe-tiedosto)

    Michael Brown on omistautunut teknologian harrastaja, jolla on intohimo yksinkertaistaa monimutkaisia ​​prosesseja ohjelmistotyökalujen avulla. Yli vuosikymmenen kokemuksella teknologia-alalta hän on hionut taitojaan Microsoft Excelissä ja Outlookissa sekä Google Sheetsissä ja Docsissa. Michaelin blogi on omistettu jakamaan tietojaan ja asiantuntemustaan ​​muiden kanssa, ja se tarjoaa helposti seurattavia vinkkejä ja opetusohjelmia tuottavuuden ja tehokkuuden parantamiseksi. Olitpa kokenut ammattilainen tai aloittelija, Michaelin blogi tarjoaa arvokkaita oivalluksia ja käytännön neuvoja, joiden avulla saat kaiken irti näistä tärkeistä ohjelmistotyökaluista.