Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: VBA: excel suodatus ongelma

Sivun loppuun

saecci [09.06.2011 19:50:30]

#

Moro!
Olen yrittänyt tässä tehdä sellaista taulukkolaskuria komponenteille. Laskurissa pitää ensin valita Tyyppi jonka jälkeen jokin tyypin mukainen valmistaja ja sitten jokin malli valmistajalta. Kun valmistaja on valittu taulukossa näkyisi tietoja kyseisestä mallista esim jännite,virta,teho... näitä tietoja käytettäisiin sitten toisessa välilehdessä laskukaavoissa.
ELI sitten itse ongelmaan olen lähteny toteuttamaan tätä erittäin "purkka"-tyylillä eli olen tehny ison taulukon johon olen tehny pikasuodatuksen. Tälla tavallahan pystyn toteuttamaan tuon valinta prosessin (tyyppi,valmistaja,malli).
Sitten sen mallien tietojen kopioinnin toiseen välilehteen olen toteuttanut välisummalla, mutta minun olisi tarkoitus saada kopioitua myös tuon sen tyypin,valmistajan ja mallin nimet kyseiseen välilehteen.
Eli onko jotenki mahdollista kopioida suodatetusta taulukosta vain näkyviä soluja?
-tämä oli varmaan todella epäselvästi selitetty, mutta toivottavasti joku ymmärtää

neau33 [09.06.2011 20:48:02]

#

Moi saecci!

VBA:lla onnistuu monikin asia, elikä tutki ja mieti oheistä koodia...

'Taul1
Private Sub CommandButton1_Click()

    Dim alue As Range
    Dim solu, rivi, sarake
    Set alue = Sheets(1).UsedRange

    For Each solu In alue
        rivi = solu.Row
        sarake = solu.Column
        If Rows(rivi).Hidden = False Then
            Sheets(2).Cells(rivi, sarake).Value = solu.Value
        End If
    Next

End Sub

saecci [09.06.2011 21:16:59]

#

hmm... okei. Kiitos Nea! Ilmeisesti tuossa tehdään userformiin commandbutton, mutta pitää kyllä vähän tutkailla miten tuo toimii ja kuinka saan hyödynnettyä sitä. Ei ole tuota vba:ta aikaisemmin tullut pahemmin käytettyä :)

saecci [10.06.2011 09:55:17]

#

En nyt oikein ihan ymmärrä tuota koodia tai ainakaan en saa sitä toimimaan haluamallani tavalla. Nuo Dim alue... ovat kai pelkkiä muutujien määrittelyitä?
Mutta mikä kohta tuossa on se jossa määritellää se sarake jonka näkyviä ja piilotettuja soluja tarkastellaan? Kun eikö tuossa "Sheets(2).Cells(rivi, sarake).Value = solu.Value" määritetä se solu siellä toisessa välilehdessä johon halutaan kopioida.
Kun yritin suorittaa tätä koodia sillä tavalla miten sen itse ymmärsin ni se "kopioi" kyllä oikeaan soluun, mutta se vain pyöritti kaikki taulukon yhden rivin tiedot läpi nopeasti (tyyppi,valmistaja,malli,jännite,virta,teho..) jonka jälkeen solu oli taas tyhjä.
Haluasin, että se kopiosi suodatuksesta tyypin tiettyyn soluu, valmistajan omaansa ja niin edespäin.

neau33 [10.06.2011 11:34:21]

#

Moi taas saecci!

No selvennetään hieman elikä Range objektin avulla voidaan valita työkirjan talusta haluttu alue. Esimerkissä Range objektimuuttuja alue on alustettu ensin Dim lauseella ja sen jälkeen muuttujan arvo eli tässä tapauksesa taulun Sheets(1).UsedRange tarkoittaa aluetta joka muodostuu taulun viimeisen käytössä olevan rivin ja viimeisen käytössä olevan sarakkeen muodostamasta solualueesta. Sanotaan että taulussa on rivillä 129 missä tahansa sarakkeessa jokin tieto ja vaikkapa sarakkeessa J (sarake 10) millä tahansa rivillä jokin tieto niin taulun UsedRange on tällöin Range("A1:J129").
VBA-koodissa haluttu alue asetetaan Range-objektimuuttujan arvoksi Set lauseella.

Esim. Jos halutaan asettaa Range-objektimuuttujan arvoksi alue joka muodostuu yhden ainoan sarakkeen esim sarakkeen J ja taulun kaikkien kaytössä olevien rivien määrän muodostamasta solualueesta niin...

'alustetaan objektimuuttuja
Dim alue As Range

'alustetaan 3 Variant tyyppistä muuttujaa
Dim rivi, solu, rivit

'aseteaan muuttujan rivit arvoksi taulun Taul1
'viimeisen käytössä olevan rivin rivinumero
rivit = Taul1.Cells.SpecialCells(xlCellTypeLastCell).Row

'asetetaan objektimuuttujan alue arvoksi sarakkeen J
'ja muuttujan rivit arvon mukaan määräytyvä solualue
Set alue =  Taul1.Range("J1:J" & CStr(rivit))

'asetetaan muuttujan rivi arvoksi 0
rivi = 0

'käydään for each silmukassa läpi muutujan alue
'kaikki solut ensimmäisestä viimeisen...
For Each solu In alue
  'asetetaan muuttujan rivi arvoksi
  'kulloisenkin solun rivinumero
   rivi = solu.Row

   'tutkitaan If ehtolauseella onko
   'kulloisenkin solun rivi näkyvä vai ei
   'ja jos rivi ei ole piilossa niin...
   If Taul1.Rows(solu.Row).Hidden = False

     'kasvatetaan muuttujan rivi arvoa 1:llä
      rivi = rivi + 1

     'kopioidaan taulun Taul2 sarakkeen A
     'rivin rivi solun arvoksi muttujan solu arvo
     Taul2.Range("A" & CStr(rivi)).Value = Solu.Value
   End If
Next

Toivottavasti oheisen esimerkin avulla alkaa hieman valjeta. Kannattaa myös alkaa tutkimaan mitä kaikkea VBA-editorin ohjeista ja esimerkeistä löytyy (Suositus: mikäli ohjeita ei ole asennettu niin asenna)...

saecci [10.06.2011 13:42:13]

#

Kiitos taas! :)
Nyt minun on viellä vaan muokkailla tuota niin, että suodatus kopioituu vaikka soluun C11 eikä koko sarakkeelle C. Kun tuossahan se kopionti paikan rivinumero riippuu suodatuksen rivinumerosta. Yritin yhdistellä tätä koodia vähä tuohon ylempään millä pystyi määrittämään tarkalleen sen solun, mutta en viellä ihan saanut toimimaan. Mutta eiköhän tämä vielä tästä.

Arto [10.06.2011 15:18:17]

#

nii itte oon yhtä ainoota solua käsitelly komennolla cells(vaakarivi,pystyrivi)
esim; sheets("taulukko1").cells(2,2)=sheets("taulukko2").cells(2,5)

koipio tietoa taulukon 2 ruudusta 2E taulukon1 ruutuun 2B.

tällä alla olevalla koodin pätkällä oon kopioinu tiettoo toisaalle

dim a as single
a=0 'tällä määritetään miltä riviltä aloitetaan
do until sheet("taul1").cells(a,1)<>"" 'jos kohde solu on tyhjä ei tee mitään
a=a+1
sheets("taul2").cells(a,1)=sheets("taul1").cells­(a,1) 'muulloin kopio kohdesolun toisaalle
loop

saecci [10.06.2011 16:02:47]

#

Jooh, tuo toimisi muuten, muttä tässä kun on pikasuodatus niin rivi mistä kopioidaan voi vaihdella 2E:stä vaikka 1000E:hen riippuen kuinka paljon suodatettavassa taulussa on tavaraa ja minkä rivin tiedot suodattuu.
jos vaikka taulu olisi muotoa:

[tyyppi]    [valmistaja] [malli] [speksi1] [speksi2] [speksi3]
m,puhelin  nokia         n8        x          x         x
m.puhelin  nokia         e7        x          x         x
m.puhelin     htc        desire    x          x         x

ja jokin suodatuksen jälkeen näyttää tältä

[tyyppi]    [valmistaja] [malli] [speksi1] [speksi2] [speksi3]
m.puhelin     htc        desire      x         x         x

jolloin 2 ensimmäistä riviä häviävät ja "otsikon" jälkeinen rivi onkin 4.
En tiedä sitten pitäisikö tässä tehdä vba:lla jokin sellainen, että kopioi vain silloin kun näkyviä soluja on yksi. Visible = 1 tai jotain...

Arto [10.06.2011 16:21:59]

#

no nii toellaan.. unohtu tuo suodatus juttu.... ja sitte vielä pari riviä vois tuossa koodissa vaihtaa paikkaa...

saecci [13.06.2011 09:21:59]

#

ääh.. ei tää nyt oikee lähe :/
Sain myös tämmöisen mallikoodin, mutta en sitä ole viellä saanut toimimaan

Private Sub CommandButton1_Click()
  Dim Rng As Range

  If Taul2.FilterMode Then
        With Taul2.AutoFilter.Range
      Set Rng = .Offset(1, 1).Resize(.Rows.Count - 1, 1).SpecialCells(xlCellTypeVisible)
    End With
    Rng.Copy Taul1.Range("C11")
    MsgBox "Kopioitu", vbOKOnly Or vbInformation, "Information"
  Else
    MsgBox "Ei ole suodatettu", vbOKOnly Or vbInformation, "Information"
  End If
End Sub

tai kyllä tuo antaa nuo "Kopioitu" ja "Ei ole suodatettua" vastaukset, mutta en ole viellä saanut tuon kopioimaan oikeasti jotain.

Edit: no nyt sain tulostamaan ensimmäisen suodatuksen arvon eli tuon "tyypin" kun muutin "Set Rng = .Offset(1, 0)...", mutta en ole viellä keksinyt miten saan kopioitua muut kohdat.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta