Using Julia's clipboard() function with numerical data in columns

When copying to clipboard numeric columnar data similar to (but in larger sizes):

675.7  2962
636.6  2961
565.9  2964
517.5  2956

from a Win10 text editor to the REPL via Julia’s clipboard() function, the following string is produced:

julia> str = clipboard()
"675.7  2962\r\n636.6  2961\r\n565.9  2964\r\n517.5  2956"

Do we need to use Regex to parse this into a matrix of floats or there is a simpler way?

The code below parses it to a column vector but then this would require counting the number of columns/rows to reshape it, which is not practical.

julia> parse.(Float64, split(str))
8-element Vector{Float64}:
  675.7
 2962.0
  636.6
 2961.0
  565.9
 2964.0
  517.5
 2956.0

A vector of strings can be also be obtained with:

julia> split(str, "\r\n")
4-element Vector{SubString{String}}:
 "675.7  2962"
 "636.6  2961"
 "565.9  2964"
 "517.5  2956"

This last form seems easier to attack.

1 Like

Use xlcopy from ActuaryUtilities.jl. It should work in that case, I think (though not 100% sure).

2 Likes

Here is my simple approach. You say it’s not practical, but it works for me. Thanks for introducing the function clipboard to me.

function cbtomatrix(clipboard::AbstractString)
       rowsep = "\r\n"
       # add +1 if there is no row separator at the end (see example)
       nrows = length(findall(rowsep, clipboard)) + 1
       data = parse.(Float64, split(clipboard))
       return reshape(data, nrows, :)
end
1 Like

@zweiglimmergneis, brilliant.
With your function it becomes totally convenient :slight_smile:
NB: we need to add +1 to nrows:
nrows = length(findall(rowsep, clipboard)) + 1

Yes, the clipboard may or may not have a row separator at the end.

This one is nice too and accepts both comma-separated and spaces-separated clipboard data:

function clip2m()
    str = split(clipboard(), "\r\n")
    str = replace.(str, "," => " ")
    nr, nc = length(str),  length(split(str[1]))
    [parse(Float64,split(str[i])[j]) for i in 1:nr, j in 1:nc]
end

# copy columnar data (comma- or space-separated) to clipboard then run:
julia> clip2m()
4×2 Matrix{Float64}:
 675.7  2962.0
 636.6  2961.0
 565.9  2964.0
 517.5  2956.0

You can use the DelimitedFiles standard library to read the data into a matrix:

julia> using DelimitedFiles

julia> readdlm(IOBuffer(str))
4×2 Matrix{Float64}:
 675.7  2962.0
 636.6  2961.0
 565.9  2964.0
 517.5  2956.0
4 Likes

@stevengj, thanks for this method.
Is it possible to instruct readdlm to accept both space delimited and comma separated data?

NB: edited clip2m() function above to accept both of these inputs.

If they are different inputs, just use the delim parameter to specify the delimiter. If you have a single input that uses both comma and space separators (or you don’t know whether it is using commas or spaces), no; you’d have to preprocess the input with replace(inputstring, ','=>' ') or similar AFAIK.

1 Like

After revising this problem, @stevengj’s solution using DelimitedFiles seems to be the most robust:

clip2m() = readdlm(IOBuffer(replace(clipboard(), ','=>' ')))

It is already added to my startup.jl

1 Like

@pdeffebach has since created a dedicated package for this:

until you introduce locales into the clipboard

1,000 10
2,000 20

Yes, but that can be trivially handled at the source (jEdit, Excel, etc.). The great usefulness of this is to quickly and easily get the data into a Julia matrix for further processing, plotting, etc. In particular when working on 2 machines with a remote desktop connection, where the clipboard communicates across.

ClipData.jl allows passing all the same keyword arguments as CSV.read, so you should have lots of customization for odd formatting.