方法二<BR><BR>
<P>来自simwe liuxc0206 分享</P><PRE><FONT color=#ff0000>function eOut = table2excel(varargin)</FONT>
% TABLE2EXCEL is a special function is used to insert data to excell
% files.
% inputs :
% 1. argument should be either a filename or
% 2. argument is a struct of cell arrays or a string
%
% Example:
% xtable.Data = {'a','b','c'};
% xtable.Labels = {'label1','label2','label3'};
% xtable.SeparationStr = '%%%'; % Can be empty
% xtable.MergeWidth = 2;
% xtable.Group = 'Table 1';
% %For Initializing the excel you can use also
% % excel = TABLE2EXCEL('foo.xls','open'); this inserts no table.
% excel = TABLE2EXCEL('foo.xls',xtable); %if Fails it opens a new workbook
% %Then Insert another column to the same workbook
% TABLE2EXCEL(excel,xtable); %etc
% %Then Close it
% TABLE2EXCEL(excel,'close');
% In Excel you see following pattern
% Table is constructed from A to I Yo can Extend this range
% by changing eColEnd variable. The Excel is visible when you
% add some data this behavior can be made off by commented
% out the lines containing such command 'excel.Visible = 1'.
% A B C D E F G H I
% Separation 1 %%% %%% %%% %%% %%% %%% %%% %%% %%%
% Group 2 Table 1
% 3 label1 a a
% 4 label2 b b
% 5 label3 c c
%
% From B2 to I2 are merged. A2(the cell before group names) should be
% an char(187) for some reason.
% Author: Ibrahim ONARAN
% Date: 07 March 2004 Tuesday
% Time: 17:24
if nargin<1
error('Should be at least 1 argument');
end
% First, open an Excel Server.
excel = varargin{1};
if isa(excel,'COM.excel.application') %It is handle
eWB = excel.ActiveWorkbook;
if(~isempty(eWB)) %It has a active workbook
%Closes And Saves The Excel
if eWB.ReadOnly
eWB.Close;
Quit(excel);
delete(excel);
error('This File Is Already Open.');
end
if nargin > 1 & isstr(varargin{2}) & strfind(lower(varargin{2}),'cl')
%For Safely Close Excel Handles
% Now, save the workbook.
Save(eWB);
% To avoid saving the workbook and being prompted to do so
set(eWB, 'Saved', 1);
% Note: Make sure that you always close any workbooks that you add
% in Excel. This can prevent potential memory leaks.
Close(eWB);
% Quit Excel and delete the server.
Quit(excel);
delete(excel);
return
end
else %It is not opened before then open a fresh one
eWB = excel.Workbooks.Add;
% Default Name is Book 1 look if this name exist if so advanced the
% last digit by 1 to become Book2 etc
if isempty(eWB.Path)
new_excel_dir = excel.DefaultFilePath;
else
new_excel_dir = eWB.Path;
end
new_excel_dir = dir(new_excel_dir);
new_excel_dir = {new_excel_dir.name};
i = 1;
new_excel_name = 'Book%d.xls';
while(strmatch(sprintf(new_excel_name,i),new_excel_dir))
i = i + 1;
end
new_excel_name = sprintf(new_excel_name,i);
eWB.SaveAs(new_excel_name); %No File Name Given So Save it As it is
eWB.Saved = 1;
end
else
%recieved a filename to open
excel = actxserver('excel.application');
[dir_file,name_file,ext_file] = fileparts(varargin{1});
if isempty(dir_file)
dir_file = pwd;
end
if isempty(ext_file)
ext_file = '.xls';
end
filename = [dir_file '\' name_file ext_file];
try
eWB = excel.Workbooks.Open(filename);
if eWB.ReadOnly
eWB.Close;
Quit(excel);
delete(excel);
error('This File Is Already Open');
end
catch
if ishandle(excel)
eWB = excel.Workbooks.Add; %if file doesn't exist create a new file
eWB.SaveAs(filename);
eWB.Saved = 1;
else
rethrow(lasterror); %For handling eWB.ReadOnly Part
end
end
if nargin > 1 & isstr(varargin{2}) & strfind(lower(varargin{2}),'op')
eOut = excel;
return
end
end
% Get a handle to the active sheet.
eAS = excel.ActiveSheet;
% Get a handle to the active Workbook.
eAWB = excel.ActiveWorkbook;
eColEnd = 'I' - 'A' + 1;
%Font Name
fontName = 'Courier New';
CharPerRow = 8; %Depends on font size and column width
NoElementStr = '---';
char187 = char(187);
char160 = char(160);
if length(varargin) < 2
Fields = [];
else
Fields = varargin{2};
end
if(~isfield(Fields,'Labels'))
Labels = {'Label1';'Label2'};
else
Labels = Fields.Labels(:); %Make it Column
end
if(~isfield(Fields,'MergeWidth'))
MergeWidth = 2;
else
MergeWidth = Fields.MergeWidth;
end
if(~isfield(Fields,'Data'))
Data= {'Data 1';'Data 2'};
else
Data = Fields.Data(:); %First make it column and reshape
end
idt = length(Data);
ilb = length(Labels);
if(idt<ilb)
Labels(end-[0:(ilb-idt-1)]) = []; % No data Avaliable So No Label Required
else
Data = Data(1:floor(idt/ilb)*ilb);
Data = reshape(Data,ilb,floor(idt/ilb));
end
if(~isfield(Fields,'Group'))
Group = 'DEFAULT GROUP';
else
Group = Fields.Group;
end
Group = [char160 Group char160]; %This make group name unique
if(~isfield(Fields,'SeparationStr'))
SeparationStr = {'***'};
else
SeparationStr = Fields.SeparationStr;
end
if isfield(Fields,'SheetName')
SheetName = Fields.SheetName;
SheetName(find([SheetName == '\' | SheetName == '/'])) = '|';
SheetName(find(SheetName == ':' )) = ';';
if(SheetName(end)=='|')
SheetName(end) = [];
end
if(length(SheetName>31))
SheetName = [SheetName(1:13),'..',SheetName(end-15:end)];
end
% Try to find sheet with name SheetName
if ~strcmp(SheetName,eAS.Name)
try
i = 1;
while(1)
if strcmp(eAWB.Sheets.Item(i).Name,SheetName)
%Sheet found, Activate it
eAWB.Sheets.Item(i).Activate;
eAS = excel.ActiveSheet;
break;
end
i = i+1;
end
catch %Can not find the sheet=>Add new sheet and rename it.
eAWB.Sheets.Add;
eAS = excel.ActiveSheet;
eAS.Name = SheetName;
end
end
end
%eFG = Find Group
%eFE = Find Empty
%eR = Temporary Range
while ~isempty(Data)
%Try to Find Group
eR = eAS.UsedRange; %Used Range
eFG = eR.Find(Group); %Find Group
insert_new_table = 1;
if(~isempty(eFG)) %If find a group name
eFG = FindPrevious(eR,eFG); %Find Last Occurance Of Label
eR = getrange(eAS,1,eFG.Row+1,eColEnd,eFG.Row+1); %Find An Empty Space To Insert New Data
eFE = Find(eR,''); %Find An Empty Space To Insert New Data
if ~isempty(eFE) & (eFE.Column + MergeWidth < eColEnd+2)
%If Empty Space Found and Column Index does not Exceed Limits
insert_new_table = 0;
end
end
if insert_new_table
%Find An Empty Space To Insert Table
eR = eAS.UsedRange; %Used Range
nRow = eR.Rows.Count;
if nRow == 1
eR = getrange(eAS,1,1,1,1); %New WorkSheet
set(eR,'VerticalAlignment',2,'WrapText',1); % 2 Center
set(eR,'Value',char187,'HorizontalAlignment',3); % 3 Center
set(get(eR,'font'),'name',fontName,'bold',1); % Set Field Bold
eR = getrange(eAS,1,1,eColEnd,1); %New WorkSheet
else
eR = getrange(eAS,1,eR.Row+nRow-1,eColEnd,eR.Row+nRow-1); %Go To End of used range
end
%Insert Seperation String
if(~isempty(SeparationStr))
Insert(eR,3);
eR = getrange(eAS,1,eR.Row-1,1,eR.Row-1);
eR.Value = char187;
eR = getrange(eAS,2,eR.Row,eColEnd,eR.Row);
eR.Value = SeparationStr;
eR = getrange(eAS,1,eR.Row,eColEnd,eR.Row);
set(eR,'VerticalAlignment',2,'WrapText',1); % 2 Center
set(eR,'HorizontalAlignment',3); % 3 Center
set(get(eR,'font'),'name',fontName,'bold',1); % Set Field Bold
% If Separtion Inserted then advanced the row
eR = getrange(eAS,1,eR.Row+1,eColEnd,eR.Row+1);
end
%Insert Group Name
Insert(eR,3); %Inserts A Row
if(isempty(SeparationStr))
eR = getrange(eAS,1,eR.Row-1,1,eR.Row-1);
eR.Value = char187;
eR = getrange(eAS,2,eR.Row,eColEnd,eR.Row);
else
eR = getrange(eAS,2,eR.Row-1,eColEnd,eR.Row-1);
end
Merge(eR);
eR.Value = Group;
eR = getrange(eAS,1,eR.Row,eColEnd,eR.Row);
set(eR,'VerticalAlignment',2,'WrapText',1); % 2 Center
set(eR,'HorizontalAlignment',3); % 3 Center
set(get(eR,'font'),'name',fontName,'bold',1); % Set Field Bold
eFG = eR; %Store the group name for further usage
%Write Labels
%First Remove Labels With No Corresponding Data
k = 0;
for i=1:length(Labels)
if strcmp(Data{i-k,1},NoElementStr)
Data(i-k,:) = [];
Labels(i-k) = [];
k = k+1;
end
end
eR = getrange(eAS,1,eFG.Row+1,1,eFG.Row+length(Labels));
Insert(eR,3); %Inserts Rows
eR = getrange(eAS,1,eFG.Row+1,1,eFG.Row+length(Labels));
set(eR,'Value',Labels,'HorizontalAlignment',3); % 3 Center
%Store Empty Cell
eFE = getrange(eAS,2,eFG.Row+1,2,eFG.Row+1);
eR = getrange(eAS,2,eFG.Row+1,eColEnd,eFG.Row+length(Labels));
%When inserting new cells it copies the format of first upper cells
%to the inserted cells. But we don't want data to be bold.
eR.font.bold = 0;
if(eFE.Column+MergeWidth > eColEnd)
MergeWidth = eColEnd - eFE.Column; %Make Full Table Width
end
else
%This part handles the new inserted labels (always does this check even if labels are same)
%Find Old Labels
eR = eAS.UsedRange;
eRowEnd = eR.Rows.Count + eR.Row;
eR = getrange(eAS,1,eFG.Row+1,1,eRowEnd);
eF = eR.Find(char187); %Key Point, The Left Cell of a Group Name Should always Be char187
eR = getrange(eAS,1,eFG.Row+1,1,eF.Row-1);
oldLabels = eR.Value; %Be careful always when getting a value from excel
%It may not be a cell
if ~iscell(oldLabels) oldLabels = {oldLabels};end
%It may not be a cell str
for i = 1:length(oldLabels)
if isnumeric(oldLabels{i})
oldLabels{i} = num2str(oldLabels{i});
% elseif ~isstr(oldLabels{i})
% I don't know else ??? numeric,string,... ?
end
end
newLabels = oldLabels;
newData = repmat({NoElementStr},length(oldLabels),size(Data,2));
%Insert New Labels Reorder Data And Labels
for i = 1:length(Labels)
iLabelx = strmatch(Labels{i},oldLabels,'exact');
if(isempty(iLabelx)) % A New Label!
newLabels(end+1) = Labels(i);
newData(end+1,:) = Data(i,:);
%Insert New Line
iRow = eFG.Row+length(newLabels);
eINS = getrange(eAS,1,iRow,eColEnd,iRow);
Insert(eINS);
eRsource= getrange(eAS,2,iRow-1,eFE.Column-1,iRow-1);
eR = getrange(eAS,2,iRow,eFE.Column-1,iRow);
eRsource.Copy(eR);
eR.Value= NoElementStr;
eR = getrange(eAS,1,iRow,1,iRow);
eR.Value= newLabels{end};
else
newData(iLabelx,:) = Data(i,:);
end
end
Data = newData;
Labels = newLabels;
end
%Write Datas
for j = 1:size(Data,2)
k = j*MergeWidth + eFE.Column -1;
if eColEnd < k | isempty(Data)
break; %Break Loop And Insert New Table
end
%Control Old Labels
for i = 1:size(Data,1)
eR = getrange(eAS,k-MergeWidth+1,eFG.Row+i,k,eFG.Row+i);
Merge(eR);
set(eR,'Value',Data(i,1),'HorizontalAlignment',3); % 3 Center
end
Data(:,1) = [];
end
end
if nargout == 1 | isa(excel,'COM.excel.application');
%Don't Save Workbook since we will continue to use it
if(~excel.Visible)
set(excel, 'Visible', 1);
end
if nargout == 1
eOut = excel;
end
end
</PRE>
|