📜 "Useful Snippets 2018"

February 19, 2019  An archive of useful snippets from 2018 (no longer required on main code page).


Selenium Within Autohotkey using COM

Joe Glines has done a great job of documenting how to use Selenium within Authotkey. The basic logic is that you first install Seleniumbasic - A COM library to use Selenium with Excel in the Visual Basic Editor or within a visual basic script (VBS). Autohotkey allows you to directly call COM objects using a few simple commands. Consequently, it’s quite trivial to implement Selenium using Autohotkey.

#SingleInstance, Force

driver := ComObjCreate("Selenium.ChromeDriver")

However, for most of my projects I ended up actually just using subprocesses in Python. I found this to be a more logical way to harness the power of Autohotkey and Selenium in a single program. While I commend the efforts of the Seleniumbasic developer, Florent; it’s not as well documented or feature rich as the default Selenium. Here’s a simple example of an AHK subprocess in Python (that takes command line arguments).

import subprocess
subprocess.run(f"C:\\Code\\selenium_ahk\\calendar_pick.exe {daterc[0]} {daterc[1]}")

Autocomplete in Autohotkey GUI Applications

I found this really neat little script called CbAutoComplete which enables Autocomplete in a Combobox for Autohotkey. See the image below for an example!

To use it in a script is quite trivial. First, you need to download the script from: https://github.com/Pulover/CbAutoComplete/blob/master/CbAutoComplete.ahk. Then, you need to load the script at the top of your AHK application. Next, within your combobox, you need to make a subprocess call to the autocomplete function. And, that’s it - you will now have autocomplete in your combobox!

;; Include autohotkeyscript
#Include %A_ScriptDir%\CbAutoComplete.ahk

;; some GUI component with the autocomplete subroutine
Gui, 2:Add, ComboBox,x60 w180 h200 vOutVar gAutoComplete, %list_of_items%


;; Subroutine for Autocomplete functionality


To be honest, although I barely use hotstrings, I find the concept and possible automation quite tantalizing. The idea that I could simply replace a static typed word with dynamic contents, like a date or email, just has such obvious face value.

Here’s a simple one for just insertng the current time and date.

FormatTime, CurrentDateTime,, yyyy-MM-dd HH:mm
SendInput %CurrentDateTime%

Bash / Utilities

Batch Renaming 1 - X

If you have a bunch of files with some extension, and you want to rename them all to a new extension, this will do the trick.

ls | cat -n | while read n f; do mv "$f" "$n.extension"; done X

ImageMagick: Joining images side by side

Imagine you have a bunch of figures you’d like to join, either side by side or stacked…

montage [0-5].png -tile 5x1 -geometry +0+0 out.png
# Horitzontal
 convert +append *.png out.png
# vertical
 convert -append *.png out.png

Count number of pages in a PDF

pdfinfo "${PDFFILE}" | grep Pages | sed 's/[^0-9]*//'

VBA and Powershell

Generate Pictures with Captions VBA {#generate-pictures-with-captions-vba

For each rent inspection I need to take 100-150 photos, I think can rename the photos based on each room. Finally, I want to load all of these into a word document, with the filename as the caption. This VB script will automatically generate a document containing all the images in a directory, and then have a caption for each image with the filename.

Sub PicWithCaption()
    Dim file
    Dim path As String
    path = "C:\pathto\images"
    file = Dir(path & "*.jpg")

    CaptionLabels.Add Name:="Filename"
    Do While file <> ""
        With Selection
            .EndKey Unit:=wdStory
            .InlineShapes.AddPicture FileName:=path & file, _
            LinkToFile:=False, SaveWithDocument:=True
            .InsertAfter vbCrLf & vbCrLf
            .Collapse 0
            .MoveLeft Unit:=wdCharacter, Count:=1
            .Style = "Caption"
            .Text = path & file
        End With
        file = Dir()
    Selection.EndKey Unit:=wdStory
End Sub

Remove User Account Login Data Windows

This is honestly one of the oddest problems. I doubt anyone will ever use it. However, sometimes you wnat to remove hidden user data associated with accounts that have synced on a Windows Enterprise server on a computer. The following command, if run as administator, will remove all hidden user data.

REG ADD "HKLM\System\CurrentControlSet\Services\CSC\Parameters" /v FormatDatabase /t REG_DWORD /d 1 /f * Cleaning Computers

Remove Password VBA

The code below is taken directly from this Stack Overflow question. In short, it provides a cheeky method of removing passwords associated with an excel document.

You can try this direct VBA approach which doesn’t require HEX editing. It will work for any files (*.xls, *.xlsm, *.xlam …).

Thankyou Đức Thanh Nguyễn!

Option Explicit


Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (Destination As Long, Source As Long, ByVal Length As Long)

Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Long, _
        ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long

Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long

Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, _
        ByVal lpProcName As String) As Long

Private Declare Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As Long, _
        ByVal pTemplateName As Long, ByVal hWndParent As Long, _
        ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer

Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As Long
Dim Flag As Boolean

Private Function GetPtr(ByVal Value As Long) As Long
    GetPtr = Value
End Function

Public Sub RecoverBytes()
    If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub

Public Function Hook() As Boolean
    Dim TmpBytes(0 To 5) As Byte
    Dim p As Long
    Dim OriginProtect As Long

    Hook = False

    pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")

    If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then

        MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
        If TmpBytes(0) <> &H68 Then

            MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6

            p = GetPtr(AddressOf MyDialogBoxParam)

            HookBytes(0) = &H68
            MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
            HookBytes(5) = &HC3

            MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
            Flag = True
            Hook = True
        End If
    End If
End Function

Private Function MyDialogBoxParam(ByVal hInstance As Long, _
        ByVal pTemplateName As Long, ByVal hWndParent As Long, _
        ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
    If pTemplateName = 4070 Then
        MyDialogBoxParam = 1
        MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
                           hWndParent, lpDialogFunc, dwInitParam)
    End If
End Function

Sub unprotected()
    If Hook Then
        MsgBox "VBA Project is unprotected!", vbInformation, "*****"
    End If
End Sub

Emacs Lisp

Bibtex lookup current clipboard entry

(global-set-key (kbd "C-c C-m")
                (lambda ()
                  (crossref-lookup (current-kill 0))))

Dired sort directory by number

(setq dired-listing-switches "-laGh1v --group-directories-first")

Selective File Loading lisp

Handy way to load files selectively, but without errors if they don’t exist.

(if (file-readable-p "~/.spacemacs.d/modes-config.el") (load "~/.spacemacs.d/modes-config.el"))
(if (file-readable-p "~/.spacemacs.d/org-config.el") (load "~/.spacemacs.d/org-config.el"))
(if (file-readable-p "~/.spacemacs.d/keybinds.el") (load "~/.spacemacs.d/keybinds.el"))

Better Backwards Delete Emacs

I found by default Emacs was deleting way too much content on a and found this handy gem on stack from aborn.

(defun aborn/backward-kill-word ()
  "Customize/Smart backward-kill-word."
  (let* ((cp (point))
         (backword-char (if (bobp)
                            ""           ;; cursor in begin of buffer
                          (buffer-substring cp (- cp 1)))))
    (if (equal (length backword-char) (string-width backword-char))
            (setq backword (buffer-substring (point) (progn (forward-word -1) (point)))))
          (setq ab/debug backword)
            (when (and backword          ;; when backword contains space
                       (s-contains? " " backword))
              (setq space-pos (ignore-errors (search-backward " ")))))
            (let* ((pos (ignore-errors (search-backward-regexp "\n")))
                   (substr (when pos (buffer-substring pos cp))))
              (when (or (and substr (s-blank? (s-trim substr)))
                        (s-contains? "\n" backword))
                (setq end pos))))
          (if end
              (kill-region cp end)
            (if space-pos
                (kill-region cp space-pos)
              (backward-kill-word 1))))
      (kill-region cp (- cp 1)))         ;; word is non-english word

(global-set-key  [C-backspace] 'aborn/backward-kill-word)

Fix Rmarkdown Code Blocks Breaking from Fill command

Rmarkdown requires R src code blocks do not break or split over multiple lines. In order to prevent Emacs markdown mode from breaking R src blocks, add this to your config

;; Fix inline codeblocks being split in markdown mode in Rmarkdown documents when filling
(with-eval-after-load 'markdown-mode
  (add-hook 'fill-nobreak-predicate

Open Current File or Directory in System Viewer

(defun open-directory-in-system-viewer ()
  (when-system gnu/linux
    (if default-directory
        (browse-url-of-file (expand-file-name default-directory))
      (error "No `default-directory' to open")))
  (when-system windows-nt
    (if default-directory
        (w32explore (expand-file-name default-directory))
      (error "No `default-directory' to open"))))

Enable Meta Shift Y to yank pop forwards

In Emacs, shift Y will paste current command, but consecutive Meta Ys will go through the almost infinite clipboard. You can undo if you go to far, but I find M-Y to be far more intuitive.

;; ‘M-y’ (‘yank-pop’) cycles backwards through the ‘kill-ring’.
;; Here’s a way to cycle in the reverse direction with ‘M-Y’ (Meta-Shift-Y):
(defun yank-pop-forwards (arg)
  (interactive "p")
  (yank-pop (- arg)))
(global-set-key "\M-Y" 'yank-pop-forwards) ; M-Y (Meta-Shift-Y)