/
paste.m
executable file
·243 lines (233 loc) · 9.42 KB
/
paste.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
% 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.
%
% This program was selected 'Pick of the Week' on March 7, 2014. :-)
%
% Author : Yvan Lengwiler
% Release: 1.51
% Date : 2014-03-19
%
% See also COPY, CLIPBOARD
% History:
% 2010-06-25 correction of a bug that occurred with multiple string
% cells on a single line.
% 2011-06-05 Simplified detection of line feeds.
% 2011-06-22 Removal of an unused variable.
% 2012-02-03 Tries to identify non-conventional decimal and thousand
% separators.
% 2013-03-19 Three optional arguments (dec, sep, and lf).
% 2014-02-21 Corrected a bug found by Jiro Doke. (Thanks, Jiro)
% 2014-03-19 Bug fix, thanks to Soren Preus.
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