Category Archives: Tech

Licenc flame

10 éves VBA coder múlttal nem vagyok meggyőzhető az ellenkezőjéről). Ebből adódóan virtuális gépben futtatott Windowson dolgozom VBA-ban. A nagy asztali gépen ma reggel megszólalt az Excel 2010, hogy őt bizony nem aktiváltam még. Valóban, csak a notebookos verzió ment eddig keresztül a telefonos aktiváló tortúrán – megnéztem hát a termék dobozán, hogy hogyan tudok két gépes licencre upgradálni. A dobozon csak az van rajta, hogy a product key card verzió csak egy user egy gépes licencét biztosítja, viszont a hagyományos DVD terjesztés ad plusz egy gépnyi licencjogot. Nosza felhívtam az Office csomag viszonteladóját, hogy hogyan tudnám az egyik csomagot a másikra cserélni: az eredmény a SEHOGY. Vegyél még egy ugyanilyet, vagy vettél volna már eleve 2 licencest – mondja az MS. Na jó, de előre nem tudtam, hogy 3/4 év múlva lesz még egy gépem. Summa summarum, upgrade nincs, még egy 55000 HUF licenc és már használhatom is a második gépen a terméket. És most a flamethrower: Mac platform, 2011: Megveszem az operációs rendszert ugyanilyen digitálisan letölthető formában, 6500 HUF értékben, az összes gépemre. Megveszem az Apple által írt és terjesztett bármely alkalmazást egy összegben és használom a háztartás minden számítógépén. Megveszem a 3rd partyk által OS X-re írt, Apple által központilag terjesztett alkalmazást egy összegben és használom a háztartás minden számítógépén. *.fizetős platform: lehet überelni. ]]>

HyperDither

One Thing Well blogon találtam az előbb az ingyenes HyperDither alkalmazást, amely tetszőleges képet konvertál 1 bites változattá az Atkinson féle dithering algoritmust használva. Kamaszkoromban imádtam ezt a “régi újságpapír render” stílust – igaz anno 8 meg 16 biten a Floyd-Steinberg dithering volt a “menő” 🙂 Így néz ki a kép dithering előtt: before-1bit-ditherA fotó Gaba cimborám munkája, a 2008 novemberi Nerdületen készült. Így meg utána: after-1bit-dither Az Atkinson dithering algoritmus előnye, hogy finom szemcsés részleteket tart meg, ám a túl sötét / túl világos tónusú képrészletek bebuknak / kiégnek. Ez jól látszik a mintának választott fotón is: a sötét nadrágok finom részletei mind elvesztek a konverzió során. Ettől függetlenül nekem nagyon tetszik a végeredmény, ezért gondoltam, hogy felhívom rá a figyelmed. Szintén ezek a srácok csinálják a 2 USD-ba kerülő Percolator nevű fotó effektező iOS app-ot – érdemes vetni rá is egy pillantást.]]>

Hogy dolgozzam így hatékonyan, idióták?!

A probléma Amennyiben Excel 2007 feletti verziókban úgy akarsz conditional formattingot (=feltételes formázás) létrehozni, hogy az képlettel számolódik és a felhasznált képlet relatív hivatkozást tartalmaz, akkor a VBA engine hibásan az conditional formatting target range-ének első celláját használja fel _abszolút_ címzéssel a kért relatív címzés helyett.

A M$ féle “megoldás

Ne használj relatív címzést. Köszi. Az nem tudom feltűnt-e az ominózus WORKAROUND írójának, hogy a spreadsheet egyik legnagyobb előnye a relatív címzés használata.

Mindezek után a probléma közérthetőbben, példával

Képzeld el, hogy az a feladat, hogy 15000 cellát kell ugyanazzal a képlettel számoló feltételes formázással ellátnod (a 15000 cella még “öcsi”, bőven tudnak az userek ettől izmosabbat kérni). Nos, eddig ezt megtehetted úgy, hogy az összes cellára kiadtad a formázási utasítást, mostantól azonban szerintük ez úgy fasza, ha egyesével végigiteráltatod egy ciklussal minden egyes cellát és úgy “oldod meg” azt a problémát, amit az agyatlan codereik generáltak (ugyanis Excel 97-Excel 2007 között ez normálisan működött). Lehet találgatni, melyik mennyi időt vesz igénybe… Charles Simonyi agyoncsapná a codereiteket ezért, ha látná, hogy mit műveltek! Van fogalmatok ott Redmondban arról, hogy ezzel mekkora bajt okoztok a már kész VBA alkalmazásokban, amelyek használatánál a szerencsétlen döntéshozók a conditional formatting által vizualizált inputra támaszkodnak? Forr a vérem. Update: pont ez a feladat jött szembe ma az ügyfélnél, gondoltam mérek egyet: 6610 cellán futott le a kétféle conditional formattinggal ugyanaz az algoritmus – íme a futási eredmény hh:mm:ss bontásban, hogy a redmondi srácok is értsék, mekkora szart kavartak. Conditional formatting, range-re alkalmazva: cf-on-range Conditional formatting, ugyanarra a range-re cellánként iterálva: cf-on-iterated-cells ]]>

VBA turbo: findRangeRecursive()

postolta még 2004-ben az alábbi nagyszerű függvényt, melynek tech nyelven summázott dolga az, hogy egy tetszőleges forrásrange-ből filterezzen ki egy subRange-et a megadott matching pattern alapján:

Function findRange(findItem As Variant, searchRange As Range, Optional lookIn As Variant, Optional lookAt As Variant, Optional matchCase As Boolean) As Range
    Dim C As Range, firstAddress As String
    If IsMissing(lookIn) Then lookIn = xlValues 'xlFormulas
    If IsMissing(lookAt) Then lookAt = xlWhole ' xlPart
    If IsMissing(matchCase) Then matchCase = False
    With searchRange
        Set C = .Find( _
        What:=findItem, _
        lookIn:=lookIn, _
        lookAt:=lookAt, _
        SearchOrder:=xlByRows, _
        SearchDirection:=xlNext, _
        matchCase:=matchCase, _
        SearchFormat:=False)
        If Not C Is Nothing Then
            Set findRange = C
            firstAddress = C.Address
            Do
                Set findRange = Union(findRange, C)
                Set C = .FindNext(C)
            Loop While Not C Is Nothing And C.Address <> firstAddress
        End If
    End With
End Function
Ehhez kellett ma némi extra. A feladat az volt, hogy n darab párhuzamos range-ben kell egymás után keresni és a végén megtalált target range-et visszaadni. Magyarra fordítva ez kb. úgy fest egy példával illusztrálva, hogy “keressük meg azokat a sorokat egy táblában, ahol az A oszlopban 12 van, a B oszlopban 300, a C oszlopban meg mondjuk ‘kisMukk'”. A megoldást a FindRangeRecursive() függvény szolgáltatja, mindenki fogyassza igénye szerint:
Function findRangeRecursive(findItems As Variant, searchRanges As Variant, RC As Byte, Optional lookIn As Variant, Optional lookAt As Variant, Optional matchCase As Boolean) As Range
    Dim fii As Long, baseRange As Range, resultRange As Range
    Dim rOffset As Long, cOffset As Long
    If IsMissing(lookIn) Then lookIn = xlValues 'xlFormulas
    If IsMissing(lookAt) Then lookAt = xlWhole ' xlPart
    If IsMissing(matchCase) Then matchCase = False
    Set baseRange = searchRanges(LBound(searchRanges))
    For fii = LBound(findItems) To UBound(findItems)
        If fii < UBound(searchRanges) Then
            If RC = 1 Then rOffset = searchRanges(fii + 1).Row - baseRange.Row
            If RC = 2 Then cOffset = searchRanges(fii + 1).Column - baseRange.Column
        End If
        Set resultRange = findRange(findItem:=findItems(fii), searchRange:=baseRange, lookIn:=lookIn, lookAt:=lookAt, matchCase:=matchCase)
        If resultRange Is Nothing Then
            Set baseRange = Nothing
            Exit For
        Else
            Set baseRange = IIf(fii < UBound(searchRanges), resultRange.Offset(rOffset, cOffset), Nothing)
        End If
    Next fii
    Set findRangeRecursive = resultRange
End Function
]]>