Code covered by the BSD License  

Highlights from
Straightforward COPY and PASTE functions

image thumbnail
from Straightforward COPY and PASTE functions by Yvan Lengwiler
Allows very simple manual exchange with other applications through the clipboard.

paste(dec,sep,lf)
% PASTE copies the content of the clipboard to a variable; creates a
% string, a cell array, or a numerical array, depending on content.
%
% Usage:
%   x = paste;
%   x = paste(dec,sep,lf);
%
% The program will try to create an array. For this to succeed, the
% material that is passed from the clipboard must be a tab delimited array,
% such as produced by Excel's copy command. If the content does not have
% this structure, the program simply returns a string. If the content is an
% array, x will be a numerical array if all its components qualify as
% numerical. If not, it will be a cell array.
%
% Optional arguments:
%   dec   Single character that indicates the decimal separator. Default is
%         the period ('.').
%   sep   Single character that indicates how horizontal neigbors of a
%         matrix or cell array are separated. Default is the tabulator code
%         (char 9).
%   lf    Single character that indicates how rows are separated.(lf stands
%         for line feed). Default is the line feed code (char 10).
%
% Examples:
%
% 1) If the clipboard contains 'George's job is to chop wood.', then
%    x = paste produces x = 'George's job is to chop wood.'
%
% 2) If the content of the clipboard is a simple text with multiple lines
%    (copied from Notepad or Word or similar), then x = paste produces a
%    cell array with one column and one row per line of the input so each
%    line of text will be separated in different cells. For example, if you
%    copy the follwing text from some other program,
%
%       Manche meinen lechts und rinks kann man nicht velwechsern.
%       Werch ein Illtum!
%
%    then, in Matlab, x = paste produces a 2x1 cell array with
%
%       x{1} = 'Manche meinen lechts und rinks kann man nicht velwechsern.'
%       x{2} = 'Werch ein Illtum!'
%
%    [Note: x = clipboard('copy') would produce just a string in this case,
%    not an array of stringcells, so choose the code that is most useful for
%    your purpose.]
%
% 3) However, if your text contains an equal number of tabs on each line,
%    for instance because you've copied something like this from Word,
%      1  ->  item 1
%      2  ->  item 2
%      3  ->  item 3
%    where -> denotes TABs, then x = paste produces a 3x2 cell array,
%      x = 
%         [1]    'item 1'
%         [2]    'item 2'
%         [3]    'item 3'
%
% 4) If the clipboard contains an array of cells, e.g.
%         1  2  3
%         4  5  6
%    for instance by copying these six cells from an Excel spreadsheet,
%    then x = paste makes a 2x3 array of doubles with the same content.
%    The same is true if there are NaN cells. So if the Excel excerpt was
%         1     2     3
%         4   #N/A    6
%    then x =
%         1     2     3
%         4   NaN     6
%
% 5) If the cell collection in the clipboard is
%         A  1.3  NaN
%    then x will not be a numerical array, but a 1x3 cell array, with
%     x = 
%        'A'    [1.3000]    [NaN]
%    so x{1} is a string, but x{2} and x{3} are doubles.
%
% 6) If the clipboard contains '1,2', then x=paste with no arguments will
%    be 12 (because Matlabs str2double('1,2') interprets this as the number
%    12). However, x=paste(',') will return 1.2
%
% 7) If the clipboard contains '1,2 & 100', then x=paste with no arguments
%    will return just the string '1,2 & 100'. x=paste(',','&'), on the
%    other hand, will return a numerical array [1.2, 100].
%
% Here is a practical example:
% ----------------------------
%   In Excel, select your data, say, a sample of observations organized in
%   a few columns. Place them into the clipboard with Ctrl-C.
%   Now switch to Matlab and say
%       x = paste;
%   This puts the data that you copied in Excel into a variable x in
%   Matlab's workspace.
%   Next, you can analyze the data. For instance, compute the principal
%   components (an analysis that is not readily available in Excel), and
%   push the result back into the clipboard,
%       [c,s] = princomp(x);
%       copy(s)
%   Now, back in Excel, you can paste the result into your spreadsheet with
%   Ctrl-V.
%   
%
% Author : Yvan Lengwiler
% Release: $1.05$
% Date   : $2013-03-19$
%
% See also COPY, CLIPBOARD

% History:
%    Version 1.01 (2010-06-25): correction of a bug that occurred with
%       multiple string cells on a single line.
%    Version 1.02 (2011-06-05): Simplified detection of line feeds.
%    Version 1.03 (2011-06-22): Removal of an unused variable.
%    Version 1.04 (2012-02-03): Tries to identify non-conventional decimal
%       and thousand separators.
%    Version 1.05 (2013-03-19): Three optional arguments (dec, sep, and
%       lf).

function x = paste(dec,sep,lf)
    
    % handle optional parameters
    if nargin < 3
        lf = char(10);  % default is line feed (char 10)
    end
    if nargin < 2
        sep = char(9);  % default is tabulator (char 9)
    end
    if nargin < 1
        dec = '.';      % default is a period '.'
    end
    
    % get the material from the clipboard
    p = clipboard('paste');
    
    % get out of here if nothing usable is in the clipboard
    % (Note: MLs 'clipboard' interface supports only text, not images or
    % the like.)
    if isempty(p)
        x = [];
        return;
    end
    
    % find linebreaks
    if p(end) ~= lf
        p = [p,lf];               % append linefeed if missing
    end
    posLF = find(ismember(p,lf)); % find linefeeds
    nLF   = numel(posLF);               % count linefeeds
    
    % break into separate lines; parse each line by tab
    lines  = cell(nLF,1);
    posTab = cell(nLF,1);
    numTab = zeros(nLF,1);
    last = 0;
    for i = 1:nLF
        lines{i}  = [p(last+1:posLF(i)-1),sep]; % append a tabulator
        last      = posLF(i);
        tabs      = ismember(lines{i},sep);     % find tabulators
        aux       = linspace(1,numel(lines{i}),numel(lines{i}));
        posTab{i} = aux(tabs);                  % positions of tabs
        numTab(i) = sum(tabs(:));               % count tabs in line
    end

    % is it an array (i.e. a rectangle of cells)?
    isArray = true;
    i = 1;
    while isArray && i <= nLF
        isArray = (numTab(i) == numTab(1));
        i = i+1;
    end
    
    if ~isArray
        % it's not an array, so just return the raw content of the clipboard
        x = p;
        % Note: A simple single or multi-line text with no tabs *does*
        % qualify as an array, so the program splits such content line-wise
        % into a one-column cell array.
    else
        % it is an array, so put it into a Matlab cell array
        isNum = true;   % will remain true if it is never switched off below
        x = cell(nLF,numTab(1));
        for i = 1:nLF
            last = 0;
            pos = posTab{i};
            for j = 1:numTab(1);
                x{i,j} = lines{i,1}(last+1:pos(j)-1);
                % try to make numerical cells if possible
                if ismember(x{i,j},{'NaN','#N/A'})
                    x{i,j} = NaN;
                else
                    aux = x{i,j};   % copy to work on
                    % deal with decimal and thousand separators
                    if dec ~= '.'
                        aux = strrep(aux,dec,'.');  % replace decimal
                                                    % separators with periods
                    else
                        if numel(strfind(aux,'''')) > 0
                            % remove apostrophes
                            aux = strrep(aux,'''','');
                            % if it is a number, it is formatted conventionally
                        else
                            % determine if decimal separator is comma and
                            % thousand separator is period
                            posComma  = strfind(aux,',');
                            posPeriod = strfind(aux,'.');
                            if numel(posComma == 1) && numel(posPeriod) > 0
                                if all(mod(posComma-posPeriod,4) == 0) && ...
                                        posComma > posPeriod(end)
                                    % this is potentially a non-conventionally
                                    % formatted number: remove periods first,
                                    % then replace comma with period
                                    aux = strrep(aux,'.','');
                                    aux = strrep(aux,',','.');
                                end
                            end
                        end
                    end
                    % determine if the cell is numerical
                    aux = str2double(aux);  % try to make a double
                    if isnan(aux)
                        % this cell is not numerical (turn off switch for
                        % later)
                        isNum = false;
                    else
                        % str2double has produced a ligit number
                        x{i,j} = aux;
                    end
                end
                last = pos(j);
            end
        end
        if isNum	% make a numerical array if possible
            x = cell2mat(x);
        end
    end
    
    % remove cell encapsulation if there is only one cell
    if numel(x) == 1
        try
            x = x{1};
        end
    end

Contact us