Thursday, November 21, 2019

Open Org Mode Links With Default Windows Application

I've been using Org Mode for several years.

One Org Mode quirk is that the links in Org files always open in the Emacs editor, by default.  Click a link to Emacs_reference_card_v25.pdf on your hard drive and you might end up with a buffer that starts with this content...

%PDF-1.5
%    
3 0 obj
<<
/Length 4340      
/Filter /FlateDecode
>>
stream

I finally figured out a way to tell Emacs to open such "external" links with the default Windows application.  The multi-part solution involves first specifying all such links with a Special Prefix.  I chose "file:".  It's lame, I know, but it's also how you'd prefix an address for your web browser to open a local file.

So, for the PDF above, the link would look like this:
file:C:\emacs-25.2_64\doc\Emacs_reference_card_v25.pdf

The second part of the solution is to figure out which application on Windows you'd like to use to open the file "properly."  Rather than specifying multiple programs, such as a PDF reader for PDF files, a spreadsheet program for XLS/ODS, a word processor for DOC/ODT, etc., I decided that the single Windows command START already knows how to open all the programs on my computer.

If you were to enter the following in a command prompt, the program associated with the PDF extension would open the target file (assuming the file exists).

START C:\emacs-25.2_64\doc\Emacs_reference_card_v25.pdf

But there's a slight complication.  If the link contains a space or other delimiting character, you'll need to surround the file path with quotes like this: "C:\Path With Spaces\My PDF.pdf".  Unfortunately, START interprets quoted content as the title specification. Therefore, invoking the following would merely open a command prompt window with the title C:\Path With Spaces\My PDF.pdf

START "C:\Path With Spaces\My PDF.pdf"

So to get START to work as intended, you'd want to invoke it thusly:

START "DUMMY_TITLE" "C:\Path With Spaces\My PDF.pdf"

So having figured out the proper way to open file links, we create a function to implement it:

(defun ludditegeek-open-ext (path-to-media)
 (shell-command (concat "start \"ludditegeek-open-ext\" " path-to-media)))

Note that I chose to use the function name as the text for the title.  No matter, if all goes well, START will close the command prompt after it carries out the command -- most likely you'll never see the window.  For debugging, you could include the /WAIT switch, in which case you'll see the window, and the application will be listed in Task Manager with the title included.

Another thing to note here is that strings are defined in Lisp as characters enclosed in double-quotes.  But the title also requires double-quotes!  So I used a backslash character to escape the double-quote characters that are used to define the title.

The third part of the solution is to employ org-add-link-type to define the "file" link:

(org-add-link-type "file" 'ludditegeek-open-ext)

I call it with eval-after-load.  Here, finally, is what you can put in your .emacs:

(eval-after-load "org"
  '(progn
     ;; Create links in Org thusly:
     ;; [[file:/path/to/ppt.pptx][name of ppt]]
     ;; [[file:"/path with spaces/to/pdf.pdf"][name of pdf]]
     ;; [[file:/path/to/video.mkv][name of video]]
     (defun ludditegeek-open-ext (path-to-media)
       ;; Use Windows start command to open default application.
       ;; Note that first parameter to START is the command prompt window's title,
       ;; necessary for links that are enclosed in "", such as links with spaces.
       (shell-command (concat "start \"ludditegeek-open-ext\" " path-to-media)))
     (org-add-link-type "file" 'ludditegeek-open-ext)
     ))

I hope you find this useful!

Thursday, October 17, 2019

Quickly Delete Many Excel Worksheets

In "Reverse the Order of Worksheets in an Excel Workbook" I show a VBA module that I wrote in order to reverse the order of several dozen worksheets in an Excel file.

Each tab contains a summary of data for a week.  After a few years, I had amassed over 100 worksheets.  So I decided I would split the workbook; each one would contain only one year's worth of data.  The workbook for 2018 would have only the 2018 worksheets; 2017 workbook, the 2017 worksheets; etc.

I copied the massive workbook to a 2018 workbook, from which I'd delete all but the 2018 worksheets.  Ditto for 2017, 2016, and, oh yes, 2019, as well.

Unfortunately I found this to be exceedingly tedious.  There didn't seem to be a way to delete multiple worksheets quickly and without many keystrokes and/or mouse clicks.  At best, I was able to select the six tabs that could be displayed at one time by clicking the left-most tab and shift-clicking the right-most tab.  Then I could right-click and delete the selected tabs.  But I'd have to do that about 20 times for each workbook!

So instead, I wrote the following VBA module to do it effortlessly.  Note that each worksheet is named with the date in YYYY-MM-DD format.  (So the worksheet for today would be named 2019-10-17. ) This module was used to delete all the 2019 worksheets.  Rather than write a nested loop to cycle through multiple years, I decided to change the year in the code manually.

  Sub DeleteNewWorksheets()
      ' 2019-03-24 TG  Created to clean up status records
      Dim Sheet As Worksheet
      Dim Book As Workbook
      Dim n As String
      Dim alerts As Boolean
      Dim i As Integer

      alerts = Application.DisplayAlerts
      Application.DisplayAlerts = False
      Set Book = ActiveWorkbook

      i = 0
      For Each Sheet In Book.Sheets
          n = Left(Sheet.Name, 4)
          If n = "2019" Then
              Debug.Print "Deleted " & Sheet.Name
              Sheet.Delete
              i = i + 1
          End If
      Next

      Application.DisplayAlerts = alerts
      MsgBox "Deleted " & i & " sheets.", vbInformation, "DeleteOldWorksheets Notification"
  End Sub


Saturday, June 15, 2019

Plunging Into Celsius

“What is that in Celsius?” asked my European coworker on the other end of an international conference call.  We had started the call by saying how cold it was in the Northeast, -21°F exactly, so I was already asking Google to convert it for me.

“About -30°C,” I replied, not missing a beat.

That’s when I asked myself, “Why do I still use the Fahrenheit temperature scale?”  I decided to switch the units on my favorite weather app and take the plunge to Celsius.

“Isn’t switching to Celsius hard for an old person like you?” you might ask.  Well, I know that water freezes at about 0°C and boils at about 100°C.  Also, I was already accustomed to using Celsius at work, so I knew that room temperature is about 25°C, at least for a warm room.  (I allow my house to stay much cooler in Winter.)

Given these three F-C equivalents, it’s easy to deduce temperatures that lie between 32°F (0°C) and 77°F (25°C) by using ratios.  For example, 12°C, a temperature that is halfway between 0°C and 25°C, is also halfway between 32°F and 77°F, and that’s 55°F.  Likewise, the “quarter points” are 6°C (44°F) and 18°C (66°F), a typical room temperature in Winter.

Below 0°C, I rely on the fact that for every one degree change in Celsius, there is a 1.8° change in Fahrenheit.  As well, for every 2°C change, we experience a 3.6°F change.  So -4°C would be about 7°F below 32°F, or 25°F.

On the upper end of the weather temperature scale, you might get a 35°C forecast, which is 10°C higher than room temperature, or 18°F above 77°F, or 95°F, which (unfortunately) my European coworkers experienced recently.

Have you guessed that I dislike warm weather?

I’m not sure I’ll bother using Celsius in cooking or baking.  First, if I change the units on the oven, my wife will be very upset.  But then I’d also have to convert all the recipes we’ve accumulated.  I don’t see any point in that.

So will you also switch the units in your weather app from Fahrenheit to Celsius?

Saturday, June 08, 2019

Pandora Music Streaming Tweak -- Change the Station Image

I've been a Pandora subscriber since 2006, and I have a couple of well-tweaked stations.  But one of my favorite stations was stuck with the ugly album art of the song that was used as the station seed.  I couldn't find a way to replace the image, and Pandora help had nothing to offer.  So here's how I changed the image:

  1. Log in to Pandora.
  2. Select the station from your collection.
  3. Click the icon to edit the station. (At this time, it looks like a pencil.)
  4. From here you can change the station Name, Description, and Thumb History, but most importantly, the "Seed" that the station evolved from, which is in the section called "Station Created From."
  5. (If there are multiple "seeds" in this section you can skip this step.)  Click "+ Add Variety" to add a new "seed" and choose a favorite song whose album cover you prefer.
  6. Delete the top-most "seed" to set the album cover from the next "seed" as the station image.
  7. You can continue this process until the "seed" that has your favorite album art occupies the top spot.
  8. At this point, you can add back the deleted "seeds" as described in step 5.  But for a mature station, you probably don't need to do this, especially if you've been diligent with the thumbs up button.