MultiPaste for Parsing Clipboard Paste Operations

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jackdunning
Posts: 126
Joined: 01 Aug 2016, 18:17
Contact:

MultiPaste for Parsing Clipboard Paste Operations

20 Sep 2019, 14:28

I know that many Clipboard-like scripts exist (and possibly one just like this), but I wrote MultiPaste.ahk to address the problem caused when copying a block of data which must go into discrete data fields.

The MultiPaste.ahk script discussion starts with the blog "Brute Force Data-Set Copy-and-Paste (AutoHotkey Clipboard Technique)."

Many Windows users will find this AutoHotkey script handy for copying data-sets and breaking them up into component parts for pasting into form fields. You can use the app to copy and parse portions of Web tables, groups of cells in a spreadsheet, single-line street addresses, and many other blocks of data—then insert those items into individual fields in another window.

Image

After selecting a section of a page (left-click, hold, and drag), activate the Hotkey combination CTRL+ALT+F to open a MsgBox window displaying the parsed components. The MsgBox remains always-on-top while you move to your input screen.

Next, in the destination window, select the target input field and press the Hotkey combination CTR:+ALT+WIN+W to activate the AutoHotkey Input command. You have five seconds to press one of the number keys (0-9). AutoHotkey inserts the text located next to the pressed number key in the MsgBox into the selected field. Or, merely press the recently added corresponding Hotkey ALT+1 through ALT+0 for direct paste.

This script parses text in the Windows Clipboard based upon the tab (`t) character, newlines (`r and `n), commas in single-line addresses, plus US and UK postal codes, for placement in the variable array listed in the MsgBox. This script works in a wide variety of situations—although some Web formatting may limit its results.

September 19, 2019, Added temporary Hotkeys (ALT+1 through ALT+0) which directly paste the corresponding items in the MsgBox. Hotkeys deactivate after closing the "Multi Paste" MsgBox window.

Code: Select all

^!F::         ; Hotkey combination CTRL+ALT+F
  OldClipboard := ClipboardAll
  Clipboard = ;clears the Clipboard
  SendInput, ^c
  ClipWait 0 ; pause for Clipboard data
  If ErrorLevel
  {
    MsgBox, Error message for non-selection
  }

; Replace all new paragraph marks with tabs for parsing
  Clipboard := StrReplace(Clipboard, "`r`n" , "`t")
; Just in case the data-set includes a stray `r or`n 
  Clipboard := StrReplace(Clipboard, "`r" , "`t") 
  Clipboard := StrReplace(Clipboard, "`n" , "`t") 

; For single-line addresses replace commas
  Clipboard := StrReplace(Clipboard, "`, " , "`t")

;  To parse US zip codes
  Clipboard := RegExReplace(Clipboard, "\s(\d\d\d\d\d)", "`t$1")

;  To parse UK postal codes
  Clipboard := RegExReplace(Clipboard, "\s([A-Za-z][A-Za-z]?\d\w?)", "`t$1")

; Designed to removes excess tabs, replaced this loop with the one-line RegEx
; which follows. Loop doesn't work if a space appears between tabs—the 
; RegEx does.

;  Loop 
;  {
;   Clipboard := StrReplace(Clipboard, "`t`t" , "`t")
;    If ! InStr(Clipboard, "`t`t")
;      Break
;  }

Clipboard := RegExReplace(Clipboard, "`t\s*`t" , "`t")

; Sparse data-set
  Transaction := StrSplit(Clipboard , "`t", , MaxParts := -1) ; [v1.1.28} 

; Display MsgBox always-on-top (4096) for pasting into target fields 
; Word-wrapped using line continuation techniques
  MsgBox, 4096,Multi Paste , % "[1] " . Transaction[1] . "`r" 
     . "[2] " . Transaction[2] . "`r" 
     . "[3] " . Transaction[3] . "`r" 
     . "[4] " . Transaction[4] . "`r" 
     . "[5] " . Transaction[5] . "`r" 
     . "[6] " . Transaction[6] . "`r" 
     . "[7] " . Transaction[7] . "`r" 
     . "[8] " . Transaction[8] . "`r" 
     . "[9] " . Transaction[9] . "`r" 
     . "[0] " . Transaction[10]
  Clipboard := OldClipboard
Return

^!#w::
  Input, SingleKey, L2 T5, ,1,2,3,4,5,6,7,8,9,0
; Special action for date fields
  If SingleKey = 0
     SingleKey := 10

; Check for date format to parse
If (Transaction[SingleKey] ~= "\d\d?[/\-.]\d\d?[/\-.]\d\d(\d\d)?")
{
  If InStr(Transaction[SingleKey],"/")
    date := StrSplit(Transaction[SingleKey],"/")
  If InStr(Transaction[SingleKey],"-")
    date := StrSplit(Transaction[SingleKey],"-")
  If InStr(Transaction[SingleKey],".")
    date := StrSplit(Transaction[SingleKey],".")

  SendInput, % date[1]
  SendInput, /
  SendInput, % date[2]
  SendInput, /
  SendInput, % date[3]

; msgbox, % date[1] date[2] date[3]
; For date field tabbing use the following:
; SendInput, % date[1] . "`t" . date[2] . "`t" . date[3]
}
Else If SingleKey != ""
  SendInput, % Transaction[SingleKey]
Return

#IfWinExist Multi Paste
  !1::SendInput, % Transaction[1]
  !2::SendInput, % Transaction[2]
  !3::SendInput, % Transaction[3]
  !4::SendInput, % Transaction[4]
  !5::SendInput, % Transaction[5]
  !6::SendInput, % Transaction[6]
  !7::SendInput, % Transaction[7]
  !8::SendInput, % Transaction[8]
  !9::SendInput, % Transaction[9]
  !0::SendInput, % Transaction[10]
#IfWinExist
User avatar
tidbit
Posts: 1273
Joined: 29 Sep 2013, 17:15
Location: USA

Re: MultiPaste for Parsing Clipboard Paste Operations

21 Sep 2019, 17:52

small nitpick:
instead of all the: clipboard:=replace(clipboard, ...) lines
1) save the clipboard to a variable
2) then work on that variable
3) then when you work is done, set that variable to the clipboard.
... infact you don't even need step 3. just pass it to Transaction := StrSplit(newVar, ...)

that way you don't brutalize the clipboard with a bunch of calls, setting and getting. And anyone with a clipboard manager won't instantly get 15 new entries for a single action of your script.
rawr. fear me.
*poke*
Is it December 21, 2012 yet?
User avatar
jackdunning
Posts: 126
Joined: 01 Aug 2016, 18:17
Contact:

Re: MultiPaste for Parsing Clipboard Paste Operations

22 Sep 2019, 00:56

tidbit wrote:
21 Sep 2019, 17:52
small nitpick:
instead of all the: clipboard:=replace(clipboard, ...) lines
1) save the clipboard to a variable
2) then work on that variable
3) then when you work is done, set that variable to the clipboard.
... infact you don't even need step 3. just pass it to Transaction := StrSplit(newVar, ...)

that way you don't brutalize the clipboard with a bunch of calls, setting and getting. And anyone with a clipboard manager won't instantly get 15 new entries for a single action of your script.
Good idea!

See the new version using a variable below.
Last edited by jackdunning on 26 Sep 2019, 10:19, edited 1 time in total.
PotatoHut
Posts: 1
Joined: 25 Sep 2019, 21:58

Re: MultiPaste for Parsing Clipboard Paste Operations

26 Sep 2019, 02:39

how would you paste all the values of that parsed array without having to spam up clipboard managers and still using paste? the reason I wouldn't use SendInput is because I could be copying from an Excel spreadsheet and there could be an extremely long paragraph in one of them and sending that in a form field could take ages relatively.

this is what I have that works, but I don't know if this is the best way to do it, and I don't know how to drop large blocks of text almost instantly without the use of a clipboard

Code: Select all

F1::
    Clipboard := "" ; empty clipboard 
    Send ^c 
    Clipwait 
    Sleep -1
    str := clipboard 
    return

F2::
    for k, v in strSplit(str, A_Tab, "`r`n") ; parse saved variable 
	{
		Send ^a ; select all in field to be replaced 
		Clipboard := "" ; empty clipboard 
		Clipboard := v ; set parsed text to clipboard
		Clipwait
		Send ^v
		send {Tab} ; next field
		sleep 25 ; need sleep (somewhere?) because of reliability issues when pasting so fast
	}
User avatar
jackdunning
Posts: 126
Joined: 01 Aug 2016, 18:17
Contact:

Re: MultiPaste for Parsing Clipboard Paste Operations

26 Sep 2019, 09:50

If you paste to an Edit control, I've found that Control, EditPaste works well for long text. It gives you speed that you can't get from the clipboard and Send command. However, you must paste to an Edit field.

I discuss the command in the Chapter 13.1.7 "Control, EditPaste for Speed" of my book Jack's Motley Assortment of AutoHotkey Tips.

Here is the script using a variable (ClipboardCopy) to avoid spamming up the clipboard:

Code: Select all

^!F::         ; Hotkey combination CTRL+ALT+F
  OldClipboard := ClipboardAll
  Clipboard = ;clears the Clipboard
  SendInput, ^c
  ClipWait 0 ; pause for Clipboard data
  If ErrorLevel
  {
    MsgBox, Error message for non-selection
  }

  ClipboardCopy := Clipboard
; Replace all new paragraph marks with tabs for parsing
  ClipboardCopy := StrReplace(ClipboardCopy, "`r`n" , "`t")
; Just in case the data-set includes a stray `r or`n 
  ClipboardCopy := StrReplace(ClipboardCopy, "`r" , "`t") 
  ClipboardCopy := StrReplace(ClipboardCopy, "`n" , "`t") 

; For single-line addresses replace commas
  ClipboardCopy := StrReplace(ClipboardCopy, "`, " , "`t")

;  To parse US zip codes
  ClipboardCopy := RegExReplace(ClipboardCopy, "\s(\d\d\d\d\d)", "`t$1")

;  To parse UK postal codes
  ClipboardCopy := RegExReplace(ClipboardCopy, "\s([A-Za-z][A-Za-z]?\d\w?)", "`t$1")

; Designed to removes excess tabs, replaced this loop with the one-line RegEx
; which follows. Loop doesn't work if a space appears between tabs—the 
; RegEx does.

;  Loop 
;  {
;   ClipboardCopy := StrReplace(ClipboardCopy, "`t`t" , "`t")
;    If ! InStr(Clipboard, "`t`t")
;      Break
;  }

ClipboardCopy := RegExReplace(ClipboardCopy, "`t\s*`t" , "`t")

; Sparse data-set
  Transaction := StrSplit(ClipboardCopy , "`t", , MaxParts := -1) ; [v1.1.28} 

; Display MsgBox always-on-top (4096) for pasting into target fields 
; Word-wrapped using line continuation techniques
  MsgBox, 4096,Multi Paste , % "[1] " . Transaction[1] . "`r" 
     . "[2] " . Transaction[2] . "`r" 
     . "[3] " . Transaction[3] . "`r" 
     . "[4] " . Transaction[4] . "`r" 
     . "[5] " . Transaction[5] . "`r" 
     . "[6] " . Transaction[6] . "`r" 
     . "[7] " . Transaction[7] . "`r" 
     . "[8] " . Transaction[8] . "`r" 
     . "[9] " . Transaction[9] . "`r" 
     . "[0] " . Transaction[10]
  Clipboard := OldClipboard
Return

^!#w::
  Input, SingleKey, L2 T5, ,1,2,3,4,5,6,7,8,9,0
; Special action for date fields
  If SingleKey = 0
     SingleKey := 10

; Check for date format to parse
If (Transaction[SingleKey] ~= "\d\d?[/\-.]\d\d?[/\-.]\d\d(\d\d)?")
{
  If InStr(Transaction[SingleKey],"/")
    date := StrSplit(Transaction[SingleKey],"/")
  If InStr(Transaction[SingleKey],"-")
    date := StrSplit(Transaction[SingleKey],"-")
  If InStr(Transaction[SingleKey],".")
    date := StrSplit(Transaction[SingleKey],".")

  SendInput, % date[1]
  SendInput, /
  SendInput, % date[2]
  SendInput, /
  SendInput, % date[3]

; msgbox, % date[1] date[2] date[3]
; For date field tabbing use the following:
; SendInput, % date[1] . "`t" . date[2] . "`t" . date[3]
}
Else If SingleKey != ""
  SendInput, % Transaction[SingleKey]
Return

#If WinExist("Multi Paste")
  !1::SendInput, % Transaction[1]
  !2::SendInput, % Transaction[2]
  !3::SendInput, % Transaction[3]
  !4::SendInput, % Transaction[4]
  !5::SendInput, % Transaction[5]
  !6::SendInput, % Transaction[6]
  !7::SendInput, % Transaction[7]
  !8::SendInput, % Transaction[8]
  !9::SendInput, % Transaction[9]
  !0::SendInput, % Transaction[10]
#If
It does not attempt to use the Control, EditPaste command but I'm sure you could put in a condition which identified long blocks of text or Edit fields before the paste operation.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 149 guests