Az „Excel” fórum célja, hogy keretet adjon az Excel felhasználók széles táborának tapasztalataik megosztására, és lehetőséget a segítséget kérőknek. Az alábbi összefoglaló azért készült, hogy segítse a helyes kérdésfeltevést.
– Írd le szabatosan a problémát. Úgy fogalmazz, hogy ne csak te magad, de a szakértő is megértse, mire szeretnél választ kapni.
– Írd le, hogy milyen verziójú Excellel dolgozol. (Vagy ha nem – ill. nem csak – Excel, akkor micsoda?)
– Írd le, hogy milyen úton indultál el, és hol akadtál el rajta.
– A kérdés megértése szempontjából sokat segíthet, ha feltölteszt egy képet, amin látszik, hogy mit szeretnél, vagy illusztrálja azt.
– Még jobb, ha feltöltesz egy minta munkafüzetet valahová (pl. data.hu). Feltöltés előtt távolítsd el belőle a nem publikus adatokat.
– Ha a feladat jellege olyan, célszerű az "előtte" és "utána" állapotokat bemutatni. (Miből kellene csinálni mit?)
– Ha VBA kódon kell javítani, másold be a releváns kódrészt. Rövid kód mehet hozzászólásba, hosszú kód inkább ide: http://pastebin.com/
– Ha valami nem úgy működik, ahogy kellene, add meg a rendellenes viselkedés jellemzőit, a hibaüzenetet, és a hibát okozó programsort.
Van az A oszlopodban egy halom keresztnév, mellettük a B és C oszlopokban összegek. A feladat, hogy a sorban, ahol a Vilhelmina név szerepel, a D oszlopba a B és C szorzata kerüljön. Többezer sor van.
Sub szoroz() Dim sor As Integer
For sor = 2 To Range("A65536").End(xlUp).Row If Cells(sor, 1) = "Vilhelmina" Then Cells(sor, 4) = Cells(sor, 2) * Cells(sor, 3) Exit For End If Next End Sub
A feltétel az If-es sor. Tudjuk, hogy csak 1 Vilhelmina van, ezért a művelet elvégzése után nem nézetjük tovább a rengeteg további nevet, hanem kilépünk a ciklusból. Ebben az esetben Exit Sub is lehetett volna a kilépés.
Nincs mit. Arra figyelj, hogy ebben a makróban a Target tartomány jelöli a megváltozott cellákat. Egyszerre ugyanis nem csak egy, hanem több cella is megváltozhat, pl. értékek törlésekor, másolás-beillesztéskor, stb. Nagyon kifinomult szűréseket is lehet csinálni arra nézve, hogy milyen Target esetén fusson le a makró, és mikor ne. Én most azt a feltételt adtam meg, hogy a megváltozott tartomány egyoszlopos legyen, és ez az egy oszlop az első (A) oszlop legyen. Nem tudom, hogy a céljaidnak mi a legmegfelelőbb.
már csak azt kellene tudnom, hogy mit változtassak ha a pl: E oszlopba szeretnék írni és ennek hatására a 15-ik oszlopba kellene hogy beírja az időpontot
Igazándiból, ebből számomra nem látszik, hogy mitől lassult le, de, ha vannak a munkalapon képletek, ennek folyamatos újraszámoltatása okozhatott lassulást.
Ebből kiindulva az újraszámolás ki/be kapcsolása segíthetett.
Private Sub Worksheet_Change(ByVal Target As Range) Dim c As Range If (Target.Columns.Count = 1) And (Target.Column = 1) Then For Each c In Target.Offset(, 2) If c = "" Then c = Now Next End If End Sub
egy excel táblában azt szeretném, hogy pl: az A oszlop egyik cellájába adatbevitelkor, az ugyanabban a sorban lévő C oszlopba írja be a bevitel dátumát, idejét és ez frissítéskor ne változzon meg.
Eljutottam odáig hogy ide célszerú VB-t használni.
A következő már majdnem jó:
Private Sub Worksheet_SelectionChange(ByVal Target As Range) Const LNG_OSZLOP As Long = 3 Dim lngSor As Long lngSor = ActiveCell.Row - 1 If Cells(lngSor, LNG_OSZLOP) = "" Then Cells(lngSor, LNG_OSZLOP) = Now() End If End Sub
csak itt az a probléma, hogy akárhova írok a táblázatba, beteszi a dátumot/időt, holott csak az A oszlop azonos sorába íráskor kellene hogy működjön.
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(Target, Range("B12:B65000")) Is Nothing Then Target.Value = Date Cancel = True End If
If Not Intersect(Target, Range("Q12:AC65000, G12:G65000, K12:K65000")) Is Nothing Then Target.Value = "IGEN" Cancel = True End If
End Sub
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(Target, Range("K12:K65000")) Is Nothing Then Target.Value = "NEM" Cancel = True End If
If Not Intersect(Target, Range("G12:G65000")) Is Nothing Then Selection.ClearContents Cancel = True End If
End Sub
EDDIG ezek futottak vánszorogva. Aztán a tegnapi hóka-móka (amit ajánlottál) után, már rendesen futnak.
Aztán ezek mellett vannak még ezek: Sub Gomb9_Kattintás() Range("A12:AD65000").Select Selection.Sort Key1:=Range("A12"), Order1:=xlAscending, Header:=xlGuess, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ DataOption1:=xlSortNormal Range("A12").Select
Ez(ek) a fejlécgomb(ok) sorba rendezik az adott oszlop alapján az egész táblát. Ez is kínkeserves volt. Ez elé, illetve mögé nem írtam semmit, de már ez is normálisan fut.
Az Application.EnableEvents = false volt a ludas, ezt ki kell venni, illetve a kattintások közötti feldolgozási rész eljére tenni (a végén pedig visszakapcsolni). Egyébként még be lehet illeszteni a képernyő frissítések ki/be kapcsolását is, ez is lassíthat.
Application.ScreenUpdating = False 'kikapcsolás
Application.ScreenUpdating = True 'bekapcsolás
Mondjuk, a leghatékonyabban úgy tudnánk segíteni, ha mutatnál kódot (kódrészletet) ami lassan fut.
1. Beírtam a kérdéses makró elejére és végére, amit ajánlottál. 2. Erre gyorsan (nem vacakolva) beírt egyet, de utána a dupla klikk, illetve maga a makró nem működött. 3. Mentettem, bezártam 4. Újra megnyitottam, a dupla klikk és a makró ugyanúgy nem működött. 5. Töröltem az általad leírtakat a makró elejéről-végéről, majd ment/bezár 6. Megnyitottam újra, és tökéletesen működik, semmi tökölés, villámgyorsan ír be, de az eredeti állapothoz képest (elvileg) nem változott semmi.
Érdemes lehet szemügyre venni magukat a makrókat is. Általában lehet a meglévőnél hatékonyabb algoritmust találni. Tipikus hiba, amikor ciklusban sorra Select-áljuk a cellákat. Semmi értelme, viszont hálából 10-szeres lassulást okoz.
Ha sok a képlet a munkalapon, esetleg érdemes kikapcsolni a képletek újraszámolást, mert minden változáskor ez lefut. Aztán még meg lehet próbálni az események futását is kikapcsolni a makró futásának idején, hátha ez is lassít valamit:
Application.EnableEvents = False ' ne fussanak az események Application.Calculation = xlCalculationManual 'ne számolja újra a képleteket
Ne felejtsd el a nakró végén ezeket visszakacsolni:
Application.EnableEvents = True ' fussanak az események Application.Calculation = xlCalculationAutomatic 'mehet a képletek újraszámolása
Ezen a ponton már érdemes foglalkozni az algoritmusok hatékonyságával. Például egy rendezésnél, aminek a lépésszáma az elemszámmal közel négyzetesen nő, bizony előfordulhat ez. Tehát érdemes körülnézni a rendezési algoritmusok elméletében.
Azért nem, mert egy "üres" lapot tölt ki a felhasználó adatokkal. Ebben az "üres" lapban vannak adatbevitelt könnyítő makrók, valamint sorba rendező makrók amiknek természetesen az egész lapon kellene működniük.
De, ha bármilyen okból több ezer sort vizsgálnánk (mert szükséges), akkor természetes ez a lassulás?
Jó a kérdésed, őszintén szólva, most kipróbáltam, szóval, ha az adott oszlop 65536. sorában van valami adat, akkor is az ettől felfelé az első értéket képviselő sort adja eredményül, vagyis, ebben az esetben nem ad jó eredményt...
Jó, hogy felvetetted, használat előtt ezentúl már ezt is vizsgálni fogom pl. így:
If Range("A" & Rows.Count) = "" Then MsgBox "Az 'A' oszlop utolsó sora: " & Range("A" & Rows.Count).End(xlUp).Row Else: MsgBox "Az 'A' oszlop utolsó sora: " & Rows.Count End If
Köszönöm, így már teljesen világos. Ha én írtam volna ezt a Basicet, lenne valami egyszerűbb megoldás, amit megérteni is egyszerűbb lenne, mondjuk Last néven. :-) Jut eszembe, ez a megoldás akkor is működik, ha a 65536. sorban is van adat? Mert a lenti kísérletem nem erre utal.
Rows.Count = a munkalap utolsó sorának száma (Excel2003 esetében ez 65536)
End(xlUp).Row = az utolsó sorhoz képest felfelé az első értéket képviselő sor
Range("A" & Rows.Count).End(xlUp).Row = az "A" oszlopban az utolsó értéket képviselő sor, és mindegy, hogy előtte vannak üres sorok is vagyis nem folytonos a kitöltés.
Hát igen, nehéz egy mondatban összefoglalni, de pontosan arról van szó, amit leírtál. Talán azt lehetne mondani, hogy az aktuális összefüggő adattartomány adott irányba eső végére ugrik, ha pedig éppen a végén vagy, akkor a következő, adott irányba eső összefüggő adattartomány közelebbi végére.
A teljességhez hozzátartozik, hogy makróban az End művelet az aktív cellát nem viszi sehová, nincs is semmi köze az aktív cellához. Csak átdefiniálja a tartományt, amelyre a tényleges művelet majdan vonatkozni fog. Ez a sor
Range("C122")
önmagában semmi, csak egy tartománydefiníció. Ehhez adódnak hozzá módosítók, mint pl. az End, Offset, Resize, stb.
Range("C122").End(xlUp)
A Range("C122") -höz képest megkeresi a következő adattartomány-határt, és ez lesz a módosult tartománydefiníció. Módosítókat halmozni is lehet, pl
tudom macerás, nem automata, de megoldás, miszerint, ha pl a böngészőben az éppen olvasott weblapot mentés másként címmel lementitek, akkor az excel simán meg tudja nyitni, mindent lehet vele csinálni.
hogy kevesebbet kelljen mentegetni, itt akár 500 hozzászólás is lehet egy filécske.
vagy van pl. winhtrack nevű oldalletöltögető progi, ami az egész, összes hozzászólást lementi, persze be kell állítani, hogy ne keressen túl távoli linkek után, tehát ne töltsön az igényeidnek mélyebb fastruktúrát.
ilyesmi oldal letöltögető természetesen elég sok féle van, ki melyikre esküszik.
a lényeg, hogy a bármimódon lementett html, vagy mht, vagy bármi webformátumot az excel simán kezeli.
Ez kicsit zavaros. Ha üres cellán állok, felugrik a fölötte levő legalsó adatra. Ha nem üres a cella, de felette üresek vannak, akkor felugrik a "luk" feletti legalsó adatra. Ha viszont folytonosak az adatok, akkor átugorja a felette levőket, és a folyamatos adattartomány legfelső nem üres cellájára ugrik. Ha nincs a cella fölött adat, akkor meg az oszlop tetejére.