Saturday, May 27, 2023

A Novel Way to Gain Followers

I heard the news today that, “Neuralink, the neurotech startup co-founded by Elon Musk, announced Thursday it has received approval from the Food and Drug Administration to conduct its first in-human clinical study.”1

This technology is meant to “help patients with severe paralysis control external technologies using only neural signals. … patients with severe degenerative diseases like ALS could eventually regain their ability to communicate ... by … typing with their minds.”

All I could think was, “He must be desperate to get new followers on Twitter!”


1https://news.yahoo.com/elon-musk-brain-implant-company-134631197.html

Saturday, May 20, 2023

Interview with YouChat 2023-04-01

On April 1, 2023, Luddite Geek chatted with the AI bot at You.Com. Here's what transpired:

Hey there! How can I be of assistance?

> Hello, please tell me what you think of the term "Luddite"

As an AI language model, I do not have personal opinions or beliefs. However, I can provide information on the term "Luddite". The term "Luddite" refers to a person who is opposed to technological change and automation, particularly in the workplace. The term comes from the Luddite movement in 19th-century England, which was a social movement of textile workers who opposed the use of machinery that threatened their jobs. Today, the term is sometimes used more broadly to refer to anyone who is resistant to new technologies or social changes. Some people see the term as pejorative, while others identify with it as a rejection of the rapid pace of technological change in modern society.

> Please tell me what you think of the term "Geek"

As an AI language model, I do not have personal opinions or beliefs. However, I can provide information on the term "geek". The term "geek" originally referred to someone who was socially awkward or obsessed with a particular hobby or interest, particularly those related to technology or pop culture. Over time, the term has evolved and taken on more positive connotations, with many people identifying as geeks or using the term to express pride in their hobbies or interests. Some people use the term in a derogatory way to mock people for being too obsessed with something, but overall it is generally considered to be a more neutral or even positive term today.

> What would the term "Luddite Geek" connotate?

The term "Luddite Geek" could potentially connote someone who is interested in technology but also has reservations about the potentially negative effects of technology or the pace of technological change. It may suggest someone who is interested in technological topics but also values the importance of human connection and physical experience. Alternatively, the term could be used ironically to suggest someone who is interested in technology but rejects modern or advanced technology in favor of more primitive or outdated technologies. However, the specific connotations or interpretations of the term may vary depending on the context in which it is used.

> Tell me what you think of the blog Ramblings of a Luddite Geek at https://ludditegeek.blogspot.com. Do you think it conveys the thoughts of a "Luddite Geek"?

As an AI language model, I cannot browse the internet, so I am unable to provide a specific opinion on a particular blog. However, based on the term "Luddite Geek", a blog with this title may suggest that the author has an interest in technology but may also have reservations about the potential negative effects of technology or the rapid pace of technological change. The blog may explore topics related to technology and its impact on society, while also exploring more traditional, non-technological ways of experiencing the world. Whether or not this particular blog conveys the thoughts of a "Luddite Geek" would depend on the content of the blog and how the author frames their ideas and opinions.

Saturday, March 25, 2023

Nearly Wasted Lotion

Here's what I found at the bottom of a bottle of lotion -- the pump tube ends about an inch from the bottom!  I have enough to last for another two weeks!

Monday, March 06, 2023

New Life For an Old Scanner

Here’s the scenario:

You buy new a computer for the first time in 10 years.

Then you hook up your scanner to scan a document and find that the new OS doesn’t recognize the scanner.

You go in search of a driver for the scanner that can be installed on the new computer. But alas, nothing can be found.

This is the pitfall of replacing a 32-bit operating system (OS) with a 64-bit OS – you might not find 64-bit drivers for all your peripherals.

It happened to me. But luckily I found a post by a MVP1 who recommended VueScan2.

VueScan is compatible with my Cano Lide 20 and runs under Windows 10. It can be downloaded, installed, and run for free; however the resulting scans include a watermark. But for less than the cost of a new scanner, you can buy a license for VueScan that removes the watermark and gives you access to one year of updates.

I’m not averse to paying for a new scanner. But I hate the idea of discarding a perfectly good piece of hardware just because I lack the software to operate it.

There is second option, aside from buying a new scanner. You can create a Virtual Machine (VM) that emulates the 32-bit OS and install the scanner driver on that. It’s more complicated, but it might be the preferred option if you have peripherals other than just a scanner to preserve. We do this at work so that we can keep using old lab hardware. The only drawback is that you might need a second license for the OS that runs on the VM.


1 https://answers.microsoft.com/en-us/windows/forum/all/scanner-driver-for-canon-lide-20

2 http://www.hamrick.com/

Friday, March 03, 2023

Fear Our Autonomous Future

We’re supposed to have faith in self-driving cars. Yet we can’t seem to prevent two trains from colliding.

This is a reference to the March 1 head-on train crash in Greece. According to the BBC and The Guardian, “The passenger train and the freight train were travelling in opposite directions but ended up on the same track”1 and “The two trains are thought to have travelled along the same track for 2-3km before they met head-on.”2

Maybe the problem with trains is that they’re confined to a limited number of paths (tracks), which increases the chances of a crash. The reason we have so few airplane collisions is only because of how improbable it is that two planes would occupy the same space during most of their flights.


1 https://www.bbc.com/news/world-europe-64813367

2 https://www.theguardian.com/world/2023/mar/01/greece-train-crash-deaths-injuries-larissa-collision-derailment

Friday, December 23, 2022

CLCL Customization for Emacs

Way back in 2017 I wrote an introduction to CLCL1, the clipboard manager that I prefer.  That post described how to add the supplementary Edit tool.  Today I’ll describe how to make CLCL work with Emacs.

By default, CLCL is set up to “listen” to the keystrokes Ctrl-x and Ctrl-c for pushing a selection to its stack of clipboard items, and Ctrl-v for popping the latest item into the focused application.  But Emacs’ standard keystrokes are Ctrl-w for “cutting,” Alt-w for “copying,” and Ctrl-y for “pasting.”  The terms “cutting,” “copying,” and “pasting” are in quotations because Emacs uses “killing” for “cutting” and “yanking” for “pasting.”2   And the keystrokes are described in Emacs-speak as C-w and C-y respectively.  The Emacs function “kill-ring-save” is like copy; it’s bound to M-w on my system.3

Anyway, to get a CLCL item yanked into the Emacs buffer, I add the Ctrl-y keystroke to CLCL.  You can do this on the Key tab of the Options dialog while Emacs is open.  Here's how.

Click the Add... button and scroll the Present Window List until you find a row whose title matches the text in the title bar of your Emacs application.  For me, that’s “GNU Emacs 25.2.1: *scratch*”, which is shown highlighted below.  Select that line and then click the down arrow button (or just double-click the line) to transfer the settings into the edit portion of the dialog box.


The Emacs title bar may include the name of the buffer.  In my example, that’s “*scratch*.”  But since the buffer name will vary, we need to replace it with the asterisk wildcard.

Click in the textbox below Copy and press Ctrl-w.4  Likewise, click in the textbox below Paste and click Ctrl-y.  The dialog should look similar to the one below.  Note that CLCL shows uppercase versions of W and Y in the Copy and Paste boxes; if you had pressed Ctrl-Shift-W it would display Ctrl + Shift + W instead.  OK your way out.


Now when you choose an item from CLCL while visiting a buffer in Emacs, it will be yanked into the buffer as expected.

Do you have a CLCL tip that you’d like to share?  Please let me know.  Add a comment below or email me.


1 https://ludditegeek.blogspot.com/2017/11/introduction-to-clcl-tools.html

2 And to further confuse the issue, Emacs maintains it own “clipboard” which is called the “kill ring.”  Somehow, Emacs on Windows will yank from the Windows clipboard or yank from its kill ring depending on which was modified last.

3 Please see https://www.emacswiki.org/emacs/CopyAndPaste for more details.

4 Actually, configuring Copy not not be necessary.  Emacs on Windows seems to kill to the Windows clipboard, and CLCL adds each new clipboard item to its stack.

Friday, December 09, 2022

Get Path to Current LibreOffice Spreadsheet

There are two comments related to the previous post:
  1. The blood draw wasn’t scheduled for the next morning. It was for the following morning! What a dummy I am!
  2. The code that I use in LibreOffice Calc to return the Current Working Directory can be found below. I call it with this worksheet function as an argument: CELL("FILENAME",$A$1).  Please note that the module in which this resides has the following statement at the top: Option VBASupport 1

Function LG_GetPath(s As String) As String

' 2019-02-26 LG  Created, mostly to derive Current Working Directory
	Dim sTemp As String
	Dim i As Long, j As Long
	' MsgBox "Contents of s: " & s
	If IsNull(s) Then
    	LG_GetPath = "ERROR"
    Else
    	sTemp = CStr(s)
    	i = InStr(s, "///") + 3
    	j = InStrRev(s, "/")
    	j = j - i
    	If j > 0 Then
    		sTemp = Mid(s, i, j) & "/"
    		LG_GetPath = sTemp
    	Else
    		LG_GetPath = "ERROR"
    	EndIf
    EndIf	
End Function ' LG_GetPath

Wednesday, December 07, 2022

High Blood Pressure vs. Computer Use -- Correlation?

Tonight I prepared for a 7:20AM fasting blood draw. Here’s how.

I have an outstanding balance with the lab, so I decide to pay it online and add a record to my database of paid medical balances.

I fire up my brand new laptop and navigate to the lab’s patient portal to accesse my account.

But before I pay any medical bill, I always verify that the balance does not exceed the Patient Responsibility as determined on the Insurance Provider’s Explanation of Benefits (EOB). So I also go to the insurance company website. While at the login prompt, I open my password manager to get the password for the site.

Unfortunately, the site rejects the username / password combination. The password had been created in 2018, so it must have expired.

At this point I could just reset the password. But then I would need to update both my work computer and the old computer. So I decide to start up my old, slow laptop and check the password manager on that computer. But the password manager offers the same old password for that site.

That’s not a problem. All I have to do is open Chrome, in which I save nearly all my passwords. But Chrome is running extremely slowly; seconds turn into minutes, so I take a break to feed the animals.

After I feed the animals, Chrome finally is loaded, and I find the new password in its password manager. I write that down on the invoice and transfer it over to the new computer via “SneakerNet.”

And this is where things spiraled into high blood pressure territory. The insurance company decided it was time to do maintenance on its website; it refused to display the login page any more!

I decide to call the insurance company, which is open after hours and also a few time zones behind me. Hold times are long. “Of course they are,” I told myself. “No one can log into the website!”

Finally, an agent picks up. “Hi, I just wanted to verify a Patient Responsibility – I can’t get into the website to do it.” The agent says, “I’m sorry but I can’t get that for you -- our computers are down. But they’ll be back up tomorrow morning.” “Oh, you too, huh?”

So then I decide that I’d just pay the darn balance. I’d rather pay online and download a receipt for my records than pay in person and get a paper receipt.

I switch tabs back to the lab’s invoice of my previous blood draw, the one I need to pay. But the information is gone – too much time had elapsed! So I’m required to re-enter the account details. I do that, and I’m able to transact the payment easily.

Next, I want to enter a record of the transaction in my database. I have a flat file database implemented in spreadsheet form with LibreOffice’s Calc. A brand new installation of LibreOffice, it loads quickly. Unfortunately the links to all my receipts and EOBs are showing up as #NAME. Now what?

It takes a while, but I figure out that I use =CELL(“FILENAME”, $A$1) to obtain the spreadsheet’s full path and file name. And then I use a home made function LG_GetPath() to strip away the spreadsheet’s file name and extension, returning a string that contains just the drive letter and directory. It’s this string (CWD) that prefaces all the links to the receipts and EOBs.

I go back to the old computer, open the Macro Editor, export the module, email it to myself (in case I can’t get it through the home network) and enter it into the LibreOffice installation on my new computer.

Finally I’m able to enter a record of the bill payment, the last step of my procedure for paying medical bills.

How long did this take? I recall that I finished feeding the cats at about 6:30PM and that I was able to finish my supper at 7:30Pm (thereby reducing the 12 hour fast to eleven-and-change). Given that it took me at least 15 minutes to eat, the process took nearly 45 minutes.

But from the way my heart was beating and the arteries throbbing in my neck, I’d say the time that was wasted was secondary to the increase in blood pressure.

And now, exactly eleven hours before tomorrow morning’s fasting blood draw, I’m quaffing the dregs of a Murphy’s Irish Stout.

We do not need medication to control blood pressure; we need new lives.

Friday, December 02, 2022

Add Command Prompt Here to Explorer Without Mucking About With the Registry

Windows 10 computers are missing the “Open Command Prompt Here” on the shortcut menu.

You can find a registry change online that will bring it back. But that “fix” involves changing the Permissions / Ownership of that part of the registry, so I declined to try it.

Instead I came up with a solution that uses the SendTo feature to call a batch file that calls CMD with the /K switch. To use it, create a batch file in your SendTo directory called OpenCMD.cmd. Add the content below, between the “BEGIN--------” and “END--------” tokens, and save it. Then Right-Click any file, choose SendTo OpenCMD.cmd, and a command prompt will be opened in the directory in which that file resides (if the path is on a local hard drive or mapped drive).

The SendTo directory can be found under your user profile; the <UN> in the path below is your user name:

C:\Users\<UN>\AppData\Roaming\Microsoft\Windows\SendTo

You can also enter the following in the explorer address bar to navigate to SendTo: shell:SendTo

Here’s the batch file source code. Please note that most of the lines are either comments (which start with REM) or debugging statements (which start with Echo). In fact the only lines that are necessary are the ones between the labels :OpenCMD and :END.  And please don't include the “BEGIN--------” and “END--------” tokens

Begin--------

REM OpenCMD.cmd (c) 2022 Luddite Geek

REM Opens the command prompt in the directory of the given path

REM

REM 2022-11-04 LG Created.

GOTO OpenCMD

GOTO BEGIN

cmd /?

:BEGIN

@echo off

Echo %0 %1

Echo DRIVE: %~d0

Echo PATH: %~p0

Echo NAME: %~n0

Echo EXT: %~x0

Echo.

Echo Drive and Path of parameter 1: %~dp1

pause


:OpenCMD

%~d1

cd %~dp1

CMD /D /K CLS

:END

End--------

Tuesday, October 04, 2022

Born to Social Distance

Long before the COVID-19 pandemic, I was getting ready to practice social isolation. I’ve always had an aversion to crowded spaces, and I became practiced in how avoid touching door knobs and handles. This guided me in my prescient preparations.

1. Haircuts. I’ve been cutting my own hair for a few years. I’ve always disliked anyone pampering me, so visiting a barbershop or hair salon every month was uncomfortable. Besides, you’re also expected to make small talk with the groomer. And you either have to call to make an appointment, or you have to sit and wait – both of which are intolerable. Buying the electric shaver and trim kit was a great decision. And it paid for itself within eight months.

2. Paper products. Besides being socially awkward (some might say autistic) I am a cheapskate. I refuse to pay more for something than I need to. So when I buy toilet paper, I wait for the 9- or 12-pack of mega rolls to go on sale and then I buy one. It just so happened that right before all the toilet paper disappeared from the stores in my neighborhood, I bought a “12 pack = 48 rolls”. My wife and I had to conserve TP, but this bulk supply lasted more than eight weeks, and we never actually ran out. Nevertheless, I decided to see what it would be like to have no toilet paper. I found that paper towels felt just fine “down there.” Of course I was careful to not flush the wipe. The other paper product Armageddon that I survived was the other TP shortage: Tissue Paper. No tissues? No matter – I had decided to go cold turkey months ago. I switched to using cotton handkerchiefs. I did this more to lower my footprint than anything else. And napkins? Don’t make me laugh – they’re for slobs and sissies.

3. Shopping. I never go shopping. I go “buying.” I decide that I need something, so I go and buy it. I shop online whenever I can because I can convert credit card rewards into gift certificates that can be redeemed online. The only Brick and Mortar stores I bother with are the supermarket, drug store and Walmart. Occasionally I go to a local hardware store if I’m not sure what I need. Fortunately, all four of these types of stores were designated essential, so I almost didn’t have to change my routine of running errands. The one change I did have to make was to eliminate the weekly trips to the library.

4. Masks. Last year my breathing got progressively more difficult. So I decided that I would use the best possible mask while scooping the dusty litterboxes. In late November (or early December) I bought a two-pack of 3M N95 particulate filter masks. This N95 mask is fantastic. It’s also effective protection against airborne viruses like coronavirus. Cheap surgical masks and homemade masks that the CDC mandates only cut down on the amount of virus you emit; they don’t protect you well from others. Masks are tricky, though, and there’s a special protocol for donning them and removing them. And they’re not meant to be reused. So I use my N95 mask only at home during dusty projects. If I were to wear it out in public, I’d be afraid of getting it contaminated with the virus. So when I go out in public, I wear a cheap surgical mask, which I don’t mind throwing away if I need to.

5. Dentists, etc. All those routine checkups we’re supposed to get have been put on hold indefinitely. That includes the semi-annual dental checkup. I haven’t been to the dentist in a few years, and even when I went annually, there was no need for any work except for a cleaning. Colonoscopies, apparently, are another sham. Eye exams, on the other hand, I would try to maintain.

Tuesday, August 23, 2022

Trash Talk

 The capacity of my kitchen garbage can is 3.2 gallons, but I usually buy ordinary 4-gallon trash bags for it.  And I resent having to buy them; I used to use the free plastic grocery bags before they were banned.

It takes me a few days to fill it, too.

Yet when I go shopping for them, I find mostly 13-gallon bags.  There are bags from Glad and Hefty along with the store brand.  You can choose bags with drawstring closure, wire twist or hand tie.  The boxes have various quantities.

But that’s not all.  Now garbage bags can be found in a variety of scents, such as Lavender, Fresh, Hawaiian, Ocean, Vanilla, Lemon, Cherry Blossom, Mountain Air, Eucalyptus & Peppermint and more.  Sometimes you can even find unscented bags if you have the patience to look long enough.

What are people throwing away that they need a 13-gallon bag?  It would take me a couple of weeks to fill a garbage with that much capacity.  At full capacity it would be difficult to lift.  And even with a cover, the stink would be horrendous, regardless of what scent the bag is.

And why do we need scented bags?  When new, their smell is off-putting.  When full, they do nothing to alter the smell of what’s in the bag.

So let’s have only unscented bags.  It will leave more room on store shelves for other size bags or other products.  If people want to make their garbage scented, they can spray their favorite room freshener into it.

Thursday, July 21, 2022

Count Selected Items in Outlook

The modern Outlook status bar no longer shows the number of selected items. So some folks suggest that you select items and simply press Enter in order to trick Outlook into thinking you want to open all of them. And if you have more than four items selected, Outlook supposedly will pop up a warning that opening X number of items could take a long time.

But what happens if you accidentally agree to open them, or if the instance of Outlook doesn’t warn you, as in my case? Then you’ve wasted time opening emails and failed to get your answer.

No, it’s never a good idea to rely on an operation’s side effect; it could be eliminated in the next version!

What I do instead is surprisingly simple.  I just call the Count property of Selection.  This returns the number of selected items. I call the property with a message box that’s wrapped in a subroutine, which I link to a button on the Actions Menu.

This is all you need:

Sub CountItems()

MsgBox ActiveExplorer.Selection.Count & " items are selected", vbOKOnly, "CountItems() Message"

End Sub


It would be nice if there were an easy way to add a link to this on my shortcut menu.

Monday, July 04, 2022

Simple Washing Machine Improvement

A medium load of laundry had been taking over an hour to finish.  When I watched the tub fill with cold water, it looked like effluence from a down spout during a gentle summer rain shower.

I knew the machine had filters for the water, and I suspected they needed to be cleaned, but I wasn't sure where they were.  It turns out that the filters were easily accessible; all I had to do was shut off the water and unscrew the hoses at the machine.  Then just pull out the filters with a pair of needle nosed pliers.

When I did this, I saw that the cold water filter was extremely clogged with metal bits.  I get a lot of this kind of debris from my well water; it gets trapped in the faucet aerators, too.

I submerged the filter in a small cup of vinegar, shaking it vigorously, until it looked mostly clear.

The next load of laundry went so much more quickly.  An added benefit was that the solid dark clothes no longer were left mottled with a sludge of gray lint.

Have you ever cleaned your washing machine's water intake filters?  Do an Internet search to see just how easy it is!


Sunday, May 15, 2022

Losing Faith in America

I’m losing faith in our institutions.

First example is how the Federal Reserve thinks it can get inflation under control by raising interest rates.  If prices are higher now than they were one year ago, it’s mostly because they were so low before.  Recall that low demand in 2020 caused prices to fall sharply.  (In fact crude oil prices were actually negative1 in April 2020.)  Now we’re seeing low supply as a backlash from that effect.  Thus prices climb as demand returns to normal.  The higher interest rates may placate Wall Street investors, but it hurts anyone who needs to replace an automobile or relocate.

Second there’s Justice Samuel Alito’s draft proposal to eliminate the right to an abortion2.  In it he claims that the decision was “egregiously wrong from the start.”  So even the Supreme Court of today has no faith in the Supreme Court of five decades ago.  Sure, personal opinions change.  But law is built on precedent, isn’t it?

Third, and most troubling of all, is how the Federal Court in April struck down the CDC’s public transportation mask mandate3.  The person who brought the suit before the court has anxiety and complained that exceptions to the mandate did not apply to her.  In fact the mandate provides for a variety of exclusions that the plaintiff could claim, including “to catch [one’s] breath after ‘feeling winded’”.  The court decision is a blatant attack on science.

It won’t be long before we round up all scientists and engineers and burn them at the stake.


1 https://www.marketwatch.com/story/oil-prices-went-negative-a-year-ago-heres-what-traders-have-learned-since-11618863839

2 https://www.politico.com/news/2022/05/02/supreme-court-abortion-draft-opinion-00029473

https://storage.courtlistener.com/recap/gov.uscourts.flmd.391798/gov.uscourts.flmd.391798.53.0_1.pdf

Sunday, April 03, 2022

Excel -- Copy Only Visible Cells

Here's the scenario...

You've put considerable effort into eliminating "outlier" rows from a data table.  Now, you want to put a static copy into another worksheet or document.  So, just copy and paste, right?

Wrong.

When you invoke copy, Excel will put the entire range onto the clipboard, including any hidden rows.  So when you paste, all the outliers will be present as if you did nothing to remove them!

It shouldn’t do this, of course.  Or it’s totally unintuitive / lazy design.  But fortunately, "modern" Excel,1 provides a series of steps we can take to ensure only the visible cells get copied to the clipboard.

Here's what you do....

After you’ve selected the range that you’re interested in, choose Find & Select from the Home ribbon menu, then Go To Special, and Visible cells only.  OK your way out.  

Here’s a link to the page that offers Microsoft’s solution:

https://support.microsoft.com/en-us/office/copy-visible-cells-only-6e3a1f01-2884-4332-b262-8b814412847e

BTW, if you use LibreOffice Calc, you’ll need an extension to enable this behavior.  Here’s a link that describes the extension and how it functions, although it has mixed reviews:

https://extensions.libreoffice.org/en/extensions/show/copy-only-visible-cells


1 Version 2007 and later.

Saturday, July 10, 2021

Air Conditioning

I used to get head colds and sinus infections in Winter.  But now, thanks to modern air conditioning, I can  suffer from them in Summer, too.

Saturday, April 25, 2020

Measure Your Laundry Detergent

The cap on a bottle of liquid laundry detergent doubles as a measuring cup.

Most brands instruct the consumer to "fill to line 1 for medium loads." Line 1 on this cap is about 1cm from the bottom, as shown in the photo below.

As well, when you put the cap back on the bottle, the cap and bottle are designed so that any residual detergent that remains in the cup drains back into the bottle.

I thought everyone knew that until the day I saw my wife pouring the detergent directly into the washing machine. Not only do you waste money using more detergent than you need to, the excess detergent produces lots of suds that muck up your drain pipe.

If you want to reduce your ecological footprint, this is one way to do it.

Thursday, January 23, 2020

View Internet Header of an Email Message in Modern Outlook Client

One should always examine the Internet Header of a suspicious email.  Yet, when Microsoft upgraded Outlook, this has become more difficult than just right-clicking and choosing View Header.  Instead, you'll first have to open the message (a cringe-worthy action), and then navigate to File and Properties as described here.

I can never remember the procedure.  Besides, I want to see the header before I open the message!

So I wrote a macro that displays the beginning of the header in a message box.  Then it offers the choice of whether to copy the header content to the clipboard, which would allow for pasting into a new message to the IT department (for example).

Then I added a button to Quick Launch and bound it to the macro.  The upshot is that I can select the message in my Inbox list of messages, press the button, and see the header!

Here's the code, which I couldn't have completed without the help of the Slipstick code sample.  Please be careful of unintended wrapping of code, particularly for the value of PR_TRANSPORT_MESSAGE_HEADERS constant!

Sub HeaderReview()
' Copy Message Header contents of selected Mail Item to the Windows Clipboard.
' See: https://www.slipstick.com/developer/code-samples/outlooks-internet-headers/
' 2020-01-23 LG  Created from CopyToClipboard dated 12/13/04

Dim objCB As New DataObject ' Clipboard object
Dim ol As New Outlook.Application
Dim oe As Outlook.Explorer
Dim mi As Outlook.MailItem
Dim strMH As String ' Mail Header

Set oe = ol.ActiveExplorer

If oe.CurrentFolder.DefaultItemType = olMailItem Then
    Const PR_TRANSPORT_MESSAGE_HEADERS = "http://schemas.microsoft.com/mapi/proptag/0x007D001E"
    Dim olkPA As Outlook.PropertyAccessor
    Dim i As Integer
    Set mi = oe.Selection.Item(1)
    Set olkPA = mi.PropertyAccessor
    strMH = olkPA.GetProperty(PR_TRANSPORT_MESSAGE_HEADERS)
    Debug.Print strMH
    i = MsgBox(strMH, vbYesNo, "Copy Message Header to Clipboard?")
    Select Case i
        Case vbYes
            objCB.SetText strMH
            objCB.PutInClipboard
    End Select
Else
    MsgBox "Sorry, HeaderReview() supports only Mail items at this time.", _
    , "HeaderReview() Help"
    
End If

End Sub

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