📄 plotdata.m
字号:
nanIdx(nanIdx==0) = []; %#ok mlint
[data{nanIdx}] = deal(single(zeros(1,0)));
% Set the data into the relevant worksheet cell range
%acx.Range([nn2an(2+numStats,lineIdx+2) ':' nn2an(R+1+numStats,lineIdx+2)]).Select;
selection = selectRange(acx,[nn2an(2+numStats,lineIdx+2) ':' nn2an(R+1+numStats,lineIdx+2)]);
selection.Value = data;
set(selection.Font,'Color',color(lineIdx));
% Fix stats formulae in case of non-finite numeric values (Inf, NaN, ...)
numericIdx = myCellfun(@isnumeric, data);
if all(numericIdx)
[data{cellfun('isempty', data)}] = deal(0); % empty cells are ok => set to 0=finite
isf = myCellfun(@isfinite, data);
if ~all(isf)
ed = diff(isf);
ed(find(ed==1)+1) = -2; % start position of finite-data spans
edg = find(ed<0);
if ~isempty(edg)
if (ed(edg(1))==-1), edg = [1,edg]; end; %#ok mlint
if (ed(edg(end))==-2), edg(end+1) = length(data); end %#ok mlint
edg = edg + 1 + length(statNames);
%rcPos = arrayfun(@(n)([n2a(lineIdx+2) num2str(n)]),edg,'uniformoutput',0); % annonymous funcs invalid in ML6
rcPos = {};
for arrayIdx = length(edg) : -1 : 1
rcPos{arrayIdx} = [n2a(lineIdx+2) num2str(edg(arrayIdx))]; %#ok mlint
end
spansStr = '';
for idx = 1 : 2 : length(edg)
if ~isempty(spansStr), spansStr(end+1)=','; end %#ok mlint
spansStr = [spansStr, rcPos{idx} ':' rcPos{idx+1}]; %#ok mlint
end
setWorksheetStats(acx, C, statNames, lineIdx+2, spansStr);
end
end
end
end
else
error('X (%d) and Y (%d) lengths mismatch in "%s"', R, size(ydata{1},1), titleStr);
end
else
disp(['No Y data in "' titleStr '"']);
end
% Set focus on top-left (A1) cell
%acx.Range('A1').Select;
selectRange(acx,'A1');
%% Prepare java data table
function [tablePeer table] = prepareJTable(columnNames,colWidth,hContainer,data)
persistent jideTableUtils
% Prepare the data table
numCols = length(columnNames);
if nargin < 4
%data = mat2cell(magic(numCols),ones(1,numCols),ones(1,numCols));
%data = [data;data;data];
%for rowIdx = 1 : size(data,1)
% data{rowIdx,1} = java.lang.Boolean(mod(rowIdx,2)); % checkbox = boolean
% data{rowIdx,2} = int16(data{rowIdx,2}); % ID = int16
% data{rowIdx,3} = 0.5 + data{rowIdx,3}; % double
% data{rowIdx,4} = ['yes' num2str(data{rowIdx,3})]; % string
%end
data = mat2cell(zeros(0,numCols),ones(1,0),ones(1,numCols));
else
data = cell2mat(data);
data = mat2cell(data,ones(1,size(data,1)),ones(1,size(data,2)));
end
%tablePeer = uitable(hFig, 'NumRows',0, 'Data',data, 'ColumnNames',colNames);
%table = JTable(2,numCols);
%table = JTable({},colNames);
data_model = javax.swing.table.DefaultTableModel;
data_model.setColumnCount(numCols);
tablePeer = com.mathworks.hg.peer.UitablePeer(data_model);
tablePeer.setData(data);
table = tablePeer.getTable();
% Auto-resize columns
try
% Try JIDE features - see http://www.jidesoft.com/products/JIDE_Grids_Developer_Guide.pdf
if isempty(jideTableUtils)
com.mathworks.mwswing.MJUtilities.initJIDE;
jideTableUtils = eval('com.jidesoft.grid.TableUtils;'); % prevent JIDE alert by run-time (not load-time) evaluation
end
jideTableUtils.autoResizeAllColumns(table);
catch
% JIDE is probably unavailable - never mind...
end
% Fix for JTable focus bug : see http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4709394
% Taken from: http://xtargets.com/snippets/posts/show/37
table.putClientProperty('terminateEditOnFocusLost', java.lang.Boolean.TRUE);
% We want to use sorter, not data model...
% unfortunately, UitablePeer expects DefaultTableModel (not TableSorter) so we need a modified UitablePeer class
% however, UitablePeer is a Matlab class, so instead let's use a modified TableSorter and attach it to the Model
% Note: TableSorter is available for download at http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=14225
if ~isempty(which('TableSorter'))
sorter = TableSorter(data_model);
table.setModel(sorter);
tablePeer.setTableModel(sorter);
sorter.setTableHeader(table.getTableHeader());
table.getTableHeader.setToolTipText('<html> <b>Click</b> to sort up; <b>Shift-click</b> to sort down<br> <b>Ctrl-click</b> (or <b>Ctrl-Shift-click</b>) to sort secondary <br> <b>Click again</b> to change sort direction<br> <b>Click a third time</b> to return to unsorted view<br> <b>Right-click</b> to select entire column</html>');
end
% Some more administrative stuff...
tablePeer.setUIContainer(hContainer);
tablePeer.setColumnNames(columnNames);
pause(.1); % pause a bit otherwise the next line might run before all headers were set
tablePeer.setColumnWidth(colWidth);
% hide grid-lines
table.setGridColor(java.awt.Color.white);
%% General worksheet stats, which are good for all input source types
function setWorksheetStats(acx, numCols, statNames, colNum, spanStr)
% Stats column and data area
numStats = length(statNames);
endRow = num2str(1+numStats);
%acx.Range(['A2:A' endRow]).Value = statNames;
range = selectRange(acx,['A2:A' endRow]);
range.Value = statNames;
col = acx.Columns(1);
invoke(col,'AutoFit'); % auto fit entire table (BEFORE any data is inserted!)
startCol = 'B';
endCol = n2a(numCols+1);
if nargin>3
startCol = n2a(colNum);
endCol = startCol;
end
if nargin<5
spanStr = ['b' num2str(2+numStats) ':b65536'];
end
% Repeat for all requested stats (one beneath the other)
for statIdx = 1 : numStats
rowStr = num2str(1+statIdx);
%acx.Range([startCol rowStr ':' endCol rowStr]).Formula = ['=' statNames{statIdx} '(' spanStr ')'];
range = selectRange(acx,[startCol rowStr ':' endCol rowStr]);
range.Formula = ['=' statNames{statIdx} '(' spanStr ')'];
end
% Solid border line beneath bottom stat line
%acx.Range([startCol endRow ':' endCol endRow]).Border.Item(4).Weight = 3;
range = selectRange(acx,[startCol endRow ':' endCol endRow]);
set(invoke(range.Border,'Item',4),'Weight',3);
% Silver color for all stats
%acx.Range([startCol '2:' endCol endRow]).Font.Color = hex2dec('C0C0C0'); % silver
range = selectRange(acx,[startCol '2:' endCol endRow]);
set(range.Font,'Color',hex2dec('C0C0C0')); % silver
%% Convert RC format to 'A1' format
function cr = nn2an(r,c)
cr = [n2a(c), num2str(r)];
%% Convert col # format to 'A','B','C' format
% Thanks Brett Shoelson, via CSSM
function colStr = n2a(c)
t = [floor((c-1)/26)+64, rem(c-1,26)+65];
if (t(1)<65), t(1) = []; end
colStr = char(t);
%% Set figure name
function setFigureName(hFig, varargin)
% If valid source plot figure handle, dataStruct or a simple name
if nargin>1 & iscell(varargin) & ~isempty(varargin{1}) %#ok ML6
if ishandle(varargin{1}(1)) % figure handle
hSrcFig = varargin{1}(1);
set(hFig,'Name', get(hSrcFig,'Name'));
elseif ischar(varargin{1}) % figure name
set(hFig,'Name', varargin{1});
else
%error(['Very odd input to plotdata: ' char(varargin{1})]);
end
else
% Do nothing - error message will be presented shortly after
end
%% Executes on button press in cbStats.
function cbStats_Callback(varargin) %#ok
% Hint: get(hObject,'Value') returns toggle state of cbStats
newValue = get(gcbo,'Value');
% Loop over all worksheets
hActiveX = get(gcbf, 'UserData');
if isnumeric(hActiveX)
hActiveX = activex(hActiveX); % old ML6 format
end
sheets = hActiveX.Sheets;
for sheetIdx = 1 : sheets.Count
thisSheet = invoke(sheets,'Item',sheetIdx);
% Show/hide Column A (stats headers)
%thisSheet.Range('A:A').EntireColumn.Hidden = ~newValue;
range = selectRange(thisSheet,'A:A');
set(range.EntireColumn,'Hidden',~newValue);
% Show/hide rows #2-N (stats data)
range = selectRange(thisSheet,'A2');
lastCell = invoke(range,'End','xlDown');
numStats = min(50,lastCell.Row);
%statRows = thisSheet.Range(['$2:$' num2str(numStats)]).EntireRow;
range = selectRange(thisSheet,['$2:$' num2str(numStats)]);
statRows = range.EntireRow;
statRows.Hidden = ~newValue;
invoke(statRows,'Select'); % displays the rows when unhiding (setting Hidden=0 is not enough...)
% If stats were unhidden, then display column A (otherwise you'd need to scroll left...)
if newValue
%thisSheet.Range('A1').Select;
selectRange(thisSheet,'A1');
else
%thisSheet.Range('B1').Select;
selectRange(thisSheet,'B1');
end
end
%% Cellfun replacement for old Matlab versions
function results = myCellfun(func, data)
v = version;
if str2double(v(1:3)) >= 7.1
results = cellfun(func, data); %#ok ML6
else
results = [];
for cellIdx = length(data) : -1 : 1
x = data{cellIdx};
results(cellIdx) = feval(func,x); %#ok mlint
end
results(results==0) = [];
end
%% Figure resize callback function (needed for ML6, where the ActiveX container is not available to have its units set to 'normalized')
function figResizeFcn(varargin)
try
hFig = gcbf;
hFigPos = getPixelPos(hFig);
newPos = [0,0,hFigPos(3:4)];
hActiveX = get(hFig, 'UserData');
if isjava(hActiveX)
% Compute the new table & ScrollPane sizes
ud = get(hActiveX,'userdata');
newSizeTp = hActiveX.getSize;
newWidth = newSizeTp.getWidth() - 10;
newHeight = newSizeTp.getHeight() - 17 * (hActiveX.getTabRunCount()+1);
newSize = java.awt.Dimension(newWidth, newHeight);
% Loop over all tabs and modify the displayed table & viewport
matlabVersion = str2double(regexprep(version,'^(\d+\.\d+).*','$1'));
for tabIdx = 1 : length(ud.tables)
try
ud.tables(tabIdx).getTable.setPreferredScrollableViewportSize(newSize);
catch
ud.tables(tabIdx).setPreferredScrollableViewportSize(newSize);
end
ud.tables(tabIdx).revalidate;
ud.scroll(tabIdx).setPreferredSize(newSize);
if matlabVersion >= 7.2
ud.scroll(tabIdx).setSize(newSize);
end
end
% Modify the table column widths
%updateTablesWidth(ud.tables,hActiveX);
% TODO: Fix problem when scrolling right/left and tabs overlap/de-overlap causing less/more available height
% Note: drawnow or repaint() don't seem to work...
%start(timer('TimerFcn',@figResizeFcn,'StartDelay',.5));
% Set the focus, to force an immediate repaint
pause(0.05);
hActiveX.requestFocus;
drawnow;
elseif ~isempty(hActiveX)
if isnumeric(hActiveX)
hActiveX = activex(hActiveX); % old ML6 format
end
move(hActiveX,newPos); % hActiveX is more readable, but invalid in ML6...
end
catch
% never mind...
end
%% Matlab6 replacement for the unsupported ActiveX Range interface (failed attempt...)
function rangeObj = selectRange(app,rangeStr)
rangeObj = invoke(app,'Range',rangeStr); %Range() is unsupported on ML6...
%rangeStr = invoke(app,'ConvertFormula',rangeStr,1,-4150,1); % fails! ConvertFormula() & Goto() only available on XLS server - not ActiveX...
%invoke(app,'Goto',rangeStr);
%rangeObj = app.Selection;
invoke(rangeObj,'Select');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -