Archive for the 'Tech' Category

Page 2 of 6

VBA turbo: findRangeRecursive()

Aaron Blood, az ozgrid.com Excel coder site fórumán 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

HOWTO: Disable Office 2010 online help

Halálba idegesített már, hogy ott az offline help db-je a VBA motornak, ez meg minden egyes F1-re igyekszik az MSOffice online help site-ról tölteni. Természetesen körülnéztem az egész helpet, hogy hol lehet az offline helpet elsődleges prioritásúvá tenni, de sehol semmi. Végül kitúrtam, hogy hol lehet az egész online help hozzáférést tokkal-vonóval letiltani - itt van (nem volt egyértelmű rátalálni):

File/Options/Trust Center/Trust Center Settings.../Privacy Options/Connect to Office.com for updated content when I'm connected to the Internet.

VBA binary ops WTF

Update: megkövetem a szidott codereket, természetesen helyes az eredmény. Ebből is látszik, hogy nem kellene éjjel fosni a kódot. Megyek, beáztatom a kenderkötelet.

Szerintük így korrekt:

?&H0100& and &H00FF&
 0

Sok minden hiányossággal számoltam már a VBA-val kapcsolatban, de arra még sose mertem gondolni, hogy egy binary and csak 8 bitig fog menni...

VBA Color hiszti

Okos, offsetelős color kezelést kell csinálnom Excelben (az Excel és az "okos" color kezelés két külön fogalom, de ettől most tekintsünk el).

Elsőnek csinálunk egy Long típusú color adatot épeszű RGB-re felbontó függvényt:

Sub color2RGB(myColor As Long, RGBComponents() As Byte)
    RGBComponents(0) = (myColor And &HFF0000) \ &H10000
    RGBComponents(1) = (myColor And &HFF00&) \ &H100
    RGBComponents(2) = (myColor And &HFF&)
End Sub

A fenti függvény debilnek látszó részeihez némi magyarázat:

  • Azon hexa számok végén lakik &, akik max. 16 biten elférnek, de én 32 bitre szeretném őket erőltetni (=force 32 bit). A 16 bitnél hosszabb számok mögé is pakolhatsz &-t, de azt még az IDE legyilkolja.
  • A \ egy spéci osztás, ami az osztás eredményének egész részét adja vissza (=int(a/b))

Ezek után írjunk egy color offsetelőt, ami egy Long colort tud offsetelni:

Function offsetColor(myColor As Long, Optional R As Integer = 0, Optional G As Integer = 0, Optional B As Integer = 0) As Long
    Dim RGBComponents(2) As Byte
 
    Call color2RGB(myColor, RGBComponents())
 
    R = (R + RGBComponents(0)) Mod &HFF
    If R < 0 Then R = 0
 
    G = (G + RGBComponents(0)) Mod &HFF
    If G < 0 Then G = 0
 
    B = (B + RGBComponents(0)) Mod &HFF
    If B < 0 Then B = 0
 
    offsetColor = RGB(R, G, B)
End Function

Meg is volnánk, próbáljuk ki:

?Hex(offsetColor(myColor:=0, R:=1, G:=2, B:=3))
30201

A bolygón minden más programozási nyelven azt várnád, hogy 0x010203 lesz az eredmény - ehelyett a "drágaszág" RGB() függvény az R és a B értékeit láthatóan megcserélve tárolja. Nice.
Biztosra akartam menni, hogy nem én vagyok az idióta és megnéztem az Excel VBA helpet - íme a gyári példa:

MyObject.Color = RGB(255, 0, 0)    ' Set the Color property of MyObject to Red.

Értem én, hogy annak a Long-nak a struktúrája az engine belső magánügye, de könyörgöm, fiúk, ott Redmondban, mi a francért kell ezt másképp csinálni, mint az egész világ? Persze lehet, hogy az egész csak byte-sorrend kérdése, de már akar a franc belegondolni.

iOS video stream: Plex vs Air Video

Reggel 3 körül felébresztett a cica. Egy fél órát forgolódtam, aztán kiültem a nappaliba tutorial videot nézni az iPad-en, hátha az elringat. Ebből aztán végül felébredés lett - nézzük, mi tágította ki a pupillámat.

Emlékeztem rá, hogy a Plex iOS klienst a napokban update-elték tvájszemézingesre, gondoltam ez pont jó alkalom egy tesztre, így el is indítottam a Mac-en a Plex Media Servert, majd az iPad kliensben kiválasztottam egy H.264 file-t és megnyomtam a Play gombot. Döbbenten néztem az elém táruló látványt:

iOS-stream-Plex

Stream leállít, beállítások ellenőriz: local WiFi módban automatán áll a streaming quality beállítás, nosza felnyomom a maximum 8 Mbps/1080p verzióra, hátha az javít - hiába, a kép ugyanaz a blokkos, nézhetetlen szemét. A WiFi kapcsolatnak semmi baja, a videofile 960x600px natív H.264, nem értem.

Már épp feladni készülök a fotelben nézős, közben bealvós projectet, mikor eszembe jut, hogy még a Plex for iOS előtti időkből van nekem egy Air Video iOS kliensem. Minden remény nélkül adok neki is egy esélyt: Plex Media Server lelő, Air Video Server indít, Air Video kliens indít. A különbség döbbenetes:

iOS-stream-AirVideo

A körülmények teljesen azonosak voltak, sőt: míg az Air Video csuklóból tette a dolgát, a Plexnek adtam még egy esélyt az újrakonfigurált streaming quality settinggel - hiába.

Summa summarum: használj Air Videot legalább addig, amíg a házikedvenc Plex ki nem növi ezt a betegségét.

Excel VBA comment autosize

Jól eldugták, de most már megvan és nem eresztem:

myCell.Comment.Shape.TextFrame.AutoSize = True

Mac workflow: memory dump, avagy mentsük ami menthető

Még kómásan ugyan, de felkeltem már 6 körül dolgozni, tudván, hogy a munkanapnak nálam ma délben vége szakad, feladat pedig van bőven. Első körben egy viszonylag hosszabb elemzés megírását akartam befejezni, amit egy zárt phpBB forumba kell postolnom.

Az első hibát ott követtem el, hogy a pár mondatnál hosszabb anyagot nem egy text editorban kezdtem el legyártani, hanem a fórummotor saját comment textboxában.
Kész lett a bejegyzés, nyomtam egy Preview-t ami legenerálta a bejegyzést végleges formájában, átolvastam, majd miután találtam benne pár apró elírást, egy rutinmozdulattal rányomtam a browser tab close gombjára, hogy folytathassam a szerkesztést. Igen ám, csak a WordPress-hez szokott agyam gondolkodott így a korai órán, dacára a fél liter tejeskávénak: a phpBB ugyanis a WordPress-szel ellentétben a Preview-t ugyanabba a tab-ba generálta le, plusz nem készített róla Draft mentést, így én egy elegáns mozdulattal becsuktam bő fél órányi munkámat.

Mivel ez nem egy post commentje volt, hanem effektív munka, amelyre több kollégám számít, muszáj volt újraírni, de legalábbis előtúrni valahogy. Ilyenkor jön a képbe a lusta coder egyetlen fegyvere, az agya.

Nagy eséllyel az épp bezárt ablak tartalma ott lapul valahol a RAM-ban, így már csak egy memdumpot végző alkalmazás és egy keresni tudó jóféle hex editor kell ahhoz, hogy kikotorjam a postot, ahelyett, hogy újragépelem.

A memdump elvégzéséhez a Mac Memory Reader nevű binárist használtam - egyértelmű kis célszerszám, sokat nem kérdez, csak dumpol és sanyi.
A szöveget fds cimborám által is nagyra tartott Hex Fiend segített előkeresni.

Ettől tovább nem is kell ragozni a történetet. Ha esett meg már veled hasonló baj, szedd most le a Mac Memory Readert, telepítsd fel, hogy amikor legközelebb ér ilyen baleset, minél kevésbé koszold be a dumpolandó memóriát.

Synology NAS scp HOWTO

A Synology NAS-ok firmware-ében sajna a mai napig nincs jó kis scp - segítsünk ezen az alábbi, nem túl ravasz módon:

mkdir /volume1/tmp/scp_patch
cd /volume1/tmp/scp_patch
ipkg download openssh
tar -xvzf openssh*.ipk
tar -xvzf data.tar.gz
cp opt/bin/openssh-scp /bin/scp
cd /
rm -rf /volume1/tmp/scp_patch

A művelethez az ipkg csomagkezelőnek már fent kell lennie - ipkg HOWTO-t már írtak tőlem okosabbak ide.

Mac workflow: a supporter fegyvere az embeddelő userek ellen

A probléma

A gonosz user küld nekünk egy hibaüzenet screenshotot, jó esetben csak egy, rosszabb esetben több, általában Office dokumentumban egymásba ágyazva (jött már olyan, hogy a szép fejléces (!) PowerPointba ágyazott debug screenshot csini Word dokumentumba gyógyítva, szép veretes picture frame-mel). Megkapom, ránézek és máris nem kell lemennem evezni, hogy 150-re szökjön a pulzus:

user-embeddelt-hibauzenete

A megoldás

Azért jó ideje már nem szökik. Egyfelől van nekem szép \screenshot fedőnevű TextExpander shortcutom, ami ilyet csinál azonnal a válaszmailbe:

Képernyőfotók küldése Windows alatt a legegyszerűbb módon
 
1. Tegyük aktívvá a fotózandó ablakot (egyszerűen rá kell csak kattintani).
2. Nyomjuk meg az Alt+Print Screen billentyűkombinációt — a fotó az aktív ablakról a vágólapra kerül.
3. Indítsuk el a levelező programunkat, kezdjünk el egy új levelet.
4. Kattintsunk a levél törzsébe, és oda illesszük be a vágólap tartalmát a Control+V billentyűkombinációval.
5. Címezzük meg a levelet és küldjük el!

Másrészt nem lennék címzetes shareware junkie lovag, ha ne tartanék erre fent egy appot. Az app neve File Juicer. A kis 13 EUR-ba kerülő shareware alkalmazás az univerzális kicsomagoló - rengetegszer behozta már az árát nekem. Számos formátumot képes atomjaira szedni, továbbá nagy segítség tud lenni, ha memóriakártyáról kell visszahozni törölt adatot.

A File Juicer kis ronda ikonnal rendelkezik, valamint az UI sem egy díjnyertes csődör:

file-juicer-UI

Az ablak bal oldalán található drop target boxba, vagy az alkalmazás dokkon levő ikonjára kell dobnod a gonosz felhasználó által küldött dokumentumot, amit az app szétszed, ahogy illik:

file-juicer-result

A File Juicer természetesen AppleScriptelhető, így semeddig nem tart egy Service-t gyártani hozzá, ami jobb clickre indítja a konverziót. Minden embeddelő userellenséggel találkozó Mac OS X usernek kötelező fegyver ez a kis gyöngyszem.

Update: Józsi párhuzamos postja a témában erre.

Space a /etc/fstab-ban

Fél órája szívok egy mount definícióval. Próbáltam az alábbi két módszert, hiába:

//vmware-host/Shared\ Folders/plannr /plannr smbfs binary 0 0
"//vmware-host/Shared Folders/plannr" /plannr smbfs binary 0 0

A kézivezérlésű mount simán mountol bármelyikkel. Kis RTFM után megjött a megoldás, gyorsan rögzítem is ide, okulásul, mert *nix alatt így megy a móka (incl. OS X ugye):

//vmware-host/Shared\040Folders/plannr /plannr smbfs binary 0 0

FYI: a \040 a Space (32-es ASCII kód) oktálisan, az kell a drága szentemnek.