📄 plotdata.m
字号:
function [hDataFig, hSpreadsheet] = plotdata(varargin)
% plotdata Displays raw data of figure plots in a separate spreadsheet figure
%
% Syntax:
% [hDataFig, hSpreadsheet] = plotdata
% [hDataFig, hSpreadsheet] = plotdata(hPlotFig)
% [hDataFig, hSpreadsheet] = plotdata(figureName, sheetName, xdata, ydata, xAxisName, yHeaders, ...)
%
% Description:
% PLOTDATA(hPlotFig) scans the supplied figure handle for any plot axes;
% for each plot axes found, a new spreadsheet is created with the plot
% data values (X & Y, not Z). The data is displayed in the color of the
% plot's original color. If the plot lines have a tag name or DisplayName
% property (also used by legend), these are used as data column headers.
% Note that all data vectors (xdata, ydata) must be the same length.
% If the plot or subplot(s) have titles, these are used as sheet names.
% Data stats may be turned on/off using the checkbox at the bottom.
% Data may be sorted, filtered, modified and exported to Excel -
% explore the many options available in the top toolbar!
% If the Excel plug-in is unavailable, tab-based Java tables are used.
%
% PLOTDATA() is equivalent to PLOTDATA(gcf), scanning the currently
% active figure.
%
% PLOTDATA(figureName, sheetName,xdata,ydata,xAxisName,yHeaders, ...)
% enables direct data display. Parameters #2-6 may be repeated: each set
% (5 parameters each) will create a separate spreadsheet.
%
% hDataFig = PLOTDATA(...) returns a handle to the data (spreadsheet)
% figure
%
% [hDataFig, hSpreadsheet] = PLOTDATA(...) also returns a handle to the
% spreadsheet object - either an Excel ActiveX, or a Java tabbed-pane.
%
% Examples:
% x=0:.01:10; ydata=[sin(x);cos(x)];
% hFig=figure; plot([x;x]',ydata');
% plotdata; % scan the current figure for raw data (2 data lines)
% plotdata(hFig); % scan the selected figure handle
% plotdata('title','sheet #1',1:3,magic(3),'X data',{'1','2','3'});
%
% Known issues/limitations:
% 1. Works best with Excel Web Component. This is available on any PC
% that has Excel installed, or can be downloaded for free from
% microsoft.com and used (read-only) even if Excel is not installed!
% 2. If the Excel plug-in is unavailable (e.g., on Linux), tab-based
% Java tables are used but these provide more limited functionality.
% When resizing java-based figure tables may become misplaced in their
% container: resize again by a very small amount to snap into place.
% 3. Requires all plot lines in an axis to have the same xdata.
% This limitation will be removed in a future version of PlotData.
% 4. Works on Matlab 7+. Might work on Matlab 6.5. Fails on Matlab 6.0
%
% Bugs and suggestions:
% Please send to Yair Altman (altmany at gmail dot com)
%
% Change log:
% 2007-06-23: Added hSpreadsheet return arg; used Java tables if Excel is unavailable
% 2007-06-20: First version posted on <a href="http://www.mathworks.com/matlabcentral/fileexchange/loadAuthor.do?objectType=author&mfx=1&objectId=1096533#">MathWorks File Exchange</a>
%
% See also:
% OfficeDoc (on <a href="http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=15192">MathWorks File Exchange</a>)
% Programmed by Yair M. Altman: altmany(at)gmail.com
% $Revision: 1.2 $ $Date: 2007/06/23 23:18:43 $
try
% Creates a new figure (or re-use existing one)
hFig = findall(0,'tag','PlotDataFig');
iconpath = [matlabroot, '/toolbox/matlab/icons/'];
if isempty(hFig)
% Prepare the figure
hFig = figure('tag','PlotDataFig', 'menuBar','none', 'toolBar','none', 'Name','Plot data', 'NumberTitle','off', 'handleVisibility','off', 'IntegerHandle','off', 'filename','', 'ResizeFcn',@figResizeFcn);
try
% Set the Window icon
jFig = get(hFig,'JavaFrame');
figIcon = javax.swing.ImageIcon([iconpath 'profiler.gif']);
jFig.setFigureIcon(figIcon);
catch
% never mind...
end
else
clf(hFig);
figure(hFig); % bring to front
end
% Fix the ActiveX tags, position etc.
acx = initSpreadsheet(hFig, varargin{:});
% Return the data figure handle, if requested
if nargout
hDataFig = hFig;
hSpreadsheet = acx;
end
catch
v = version;
if v(1)<='6'
err.message = lasterr; % no lasterror function...
else
err = lasterror;
end
try
err.message = regexprep(err.message,'Error using ==> [^\n]+\n','');
catch
try
% Another approach, used in Matlab 6 (where regexprep is unavailable)
startIdx = findstr(err.message,'Error using ==> ');
stopIdx = findstr(err.message,char(10));
for idx = length(startIdx) : -1 : 1
idx2 = min(find(stopIdx > startIdx(idx))); %#ok ML6
err.message(startIdx(idx):stopIdx(idx2)) = [];
end
catch
% never mind...
end
end
if isempty(findstr(mfilename,err.message))
% Indicate error origin, if not already stated within the error message
err.message = [mfilename ': ' err.message];
end
if v(1)<='6'
while err.message(end)==char(10)
err.message(end) = []; % strip excessive Matlab 6 newlines
end
error(err.message);
else
rethrow(err);
end
end
%% Initialize the displayed spreadsheet object
function acx = initSpreadsheet(hFig, varargin)
% Note: for help: http://msdn2.microsoft.com/en-us/library/microsoft.office.tools.excel.aspx
% Requires: C:\PROGRA~1\COMMON~1\MICROS~1\WEBCOM~1\##\OWC##.DLL (## = 9/10/11/...)
% Note2: see http://techsupt.winbatch.com/ts/T000001033005F9.html for list of all XLS consts
%set(hFig,'visible','on'); % for debugging...
% Set figure name
setFigureName(hFig, varargin{:});
% Create (or reset) the spreadsheet object
acx = createSpreadsheetObject(hFig);
% If successfully created
if ~isempty(acx)
if ~isjava(acx)
sheets = acx.Sheets;
end
% Set the data within the spreadsheet according to input type:
if nargin<2 | isempty(varargin) %#ok ML6 % No data - error
%error('Must supply data to display in table!');
varargin = {gcf};
end
if iscell(varargin) & ~isempty(varargin{1}) & ishandle(varargin{1}(1)) %#ok ML6 % figure handle
hSrcFig = varargin{1}(1);
% Place all axes in separate worksheets
ax = sort(findall(hSrcFig,'type','axes','visible','on'));
for axIdx = 1 : length(ax)
axTag = get(ax(axIdx),'tag');
if isempty(axTag) | isempty(strmatch(axTag,{'axLogo','legend'})) %#ok ML6
% Set this axis's data in the current worksheet
setWorksheetAxisData(acx,ax(axIdx),axIdx);
if ~isjava(acx)
% Freeze pane beneath the headers (figure needs to be visible)
set(hFig, 'visible','on');
freezePane(acx,'C2');
% Add a new worksheet for the next data set
invoke(sheets,'Add');
end
end
end
else
% Loop over all input args
numArgs = length(varargin);
sheetId = 1;
setIdx = 1 + (numArgs>0 & ~isempty(varargin{1}) & (ischar(varargin{1}(1)) | isstruct(varargin{1}(1)) | ishandle(varargin{1}(1)))); %#ok ML6
while setIdx <= numArgs
% Note: expected args format is: sheetName, xdata, ydata, xAxisName, yHeaders, ...
if ischar(varargin{setIdx})
sheetName = varargin{setIdx};
setIdx = setIdx + 1;
else
sheetName = sprintf('sheet%d',sheetId);
end
% data vals: {xdata, ydata}
data = varargin(setIdx:min(numArgs,setIdx+1));
setIdx = setIdx + length(data);
% headers: {xAxisName, yHeaders}
% Note: yHeaders may be a string or a cell array of strings
headers = varargin(setIdx:min(numArgs,setIdx+1));
%headers(~myCellfun(@ischar,headers)) = [];
if ~isempty(headers)
if ~ischar(headers{1})
headers = {};
elseif length(headers)>1 & ~ischar(headers{2}) & ~iscell(headers{2}) %#ok ML6
headers(2) = [];
end
end
setIdx = setIdx + length(headers);
% Set the data in the worksheet
setWorksheetData(acx, sheetName, data{:}, headers{:});
if ~isjava(acx)
% Freeze pane beneath the headers (figure needs to be visible)
set(hFig, 'visible','on');
freezePane(acx,'C2');
% Add a new worksheet for the next data set
invoke(sheets,'Add');
end
sheetId = sheetId + 1;
end
end
% If any data was entered, then the last worksheet is empty and unused, so delete it
if ~isjava(acx) & sheets.Count > 1 %#ok ML6
invoke(acx.ActiveSheet,'Delete');
end
else
% Do nothing - ActiveX not created so error msg was displayed
end % If ActiveX successfully created
%% Create spreadsheet object (or reset the existing one, if found)
function hActiveX = createSpreadsheetObject(hFig)
% If this figure was already open with the ActiveX, do not recreate it
%if ~isfield(handles,'hActiveX') | isempty(handles.hActiveX) | ~ishandle(handles.hActiveX) %#ok ML6
hActiveX = [];
hFigPos = getPixelPos(hFig);
% Try to select the latest possible ActiveX component
version = 15;
foundFlag = 0;
while ~foundFlag & (version > 9) %#ok ML6
try
verStr = num2str(version);
actxNameStr = ['OWC' verStr '.Spreadsheet.' verStr];
hActiveX = actxcontrol(actxNameStr, [0,0,hFigPos(3:4)], hFig); % hContainer 2nd output arg is invalid in ML6...
foundFlag = 1;
catch
version = version - 1;
end
end
% If not found, error
if foundFlag
% Set the control's position to be just inside the container's pixel position
try
set(hFig, 'userdata',hActiveX);
catch
set(hFig, 'userdata',hActiveX.Handle); % old ML6 format
end
%set(hContainer, 'tag','acxSpreadsheetContainer', 'units','normalized', 'position',[0,0,1,1], 'userdata',hActiveX); % forget ...'parent',hParent... - it creates a GUI overlap bacause of a Matlab bug... % hContainer is unavailable in ML6...
%uistack(findall(hFig,'tag','cbStats'),'top'); % doesn't work for an unknown reason
cbStats = uicontrol('style','checkbox', 'parent',hFig, 'value',1, 'string','Stats', 'units','pixels', 'pos',[210,1,45,15], 'tag','cbStats', 'callback',@cbStats_Callback); %#ok - cbStats unused
pause(0.1); %small delay to let the ActiveX time to render
% Remove all default worksheets (the ActiveX requires at least one remain visible)
sheets = hActiveX.Sheets;
if sheets.Count < 1 % should never happen
invoke(sheets,'Add');
else
while hActiveX.Sheets.Count > 1
invoke(hActiveX.ActiveSheet,'Delete');
end
end
% General properties
hActiveX.DisplayDesignTimeUI = 1;
% Clear the one visible worksheet
range = selectRange(hActiveX,'$1:$99999'); %=hActiveX.Range('$1:$99999');
invoke(range.EntireRow,'Select');
invoke(hActiveX.Selection,'ClearContents');
invoke(hActiveX.Selection,'ClearFormats');
else % Excel ActiveX plug-in not found
% TODO: handle error if excel ActiveX not found (maybe use uitable?)
%hMsg = uicontrol('style','text','string',{'Excel ActiveX','object not found'},'parent',hFig,'units','norm','position',[0,0,1,1],'FontSize',36,'Foreground','r','Background',get(hFig,'color'));
%hhMsg = handle(hMsg);
%%hhMsg.Position(4) = 0.5 + hhMsg.Extent(4)/2; % construct invalid in ML6...
%hhMsg.Position = [hhMsg.Position(1:3), 0.5 + hhMsg.Extent(4)/2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -