MATLAB: How to paste fig Into excel, then save and close excel file? - excel

I generated an excel file in MATLAB and successfully saved and closed it using this:
invoke(Workbook,'Save')
invoke(Excel,'Quit');
delete(Excel);
clear Excel;
But then when I add a figure to that excel file using PlotInExcel, I can't save and close the file using that same code again. Here is PlotInExcel:
function PlotInExcel
x= {1:10};
a= cell2mat(x);
y= {1:10};
b= cell2mat(y);
%............plotting......................
plot(a,b);
xlabel('X Values');
ylabel('Y Values');
print -dmeta; %.................Copying to clipboard
FILE = 'C:DATA.xlsx';
Range='OL14';
%.............excel COM object...........................................
Excel = actxserver ('Excel.Application');
Excel.Visible = 1;
if ~exist(FILE,'file')
ExcelWorkbook=Excel.Workbooks.Add;
ExcelWorkbook.SaveAs(FILE);
ExcelWorkbook.Close(false);
end
invoke(Excel.Workbooks,'Open',FILE); %Open the file
ActiveSheet = Excel.ActiveSheet;
ActiveSheetRange = get(ActiveSheet,'Range',Range);
ActiveSheetRange.Select;
ActiveSheetRange.PasteSpecial; %.................Pasting the figure to the selected location
%-----------------------------------end of function"PlotInExcel----------
How do I get MatLab to save this file now and exit? The aforementioned code at top doesn't work now. Is there someway to add code to the function? or can/should I Save/Close the file outside the function back in my script?

With enough bashing around, I was finally able to answer my own question. I'm posting the resolution here in the event anyone else has this problem. I removed the lines at the beginning because they just produced a test figure. The function below assumes you have your own figure you want to paste into an excel spreadsheet. BTW, you must have your figure saved to the clipboard before running this function.
function PlotInExcel
FILE = 'C:\DATA.xlsx'; %identify the name and location of your excel spreadsheet
Range='R1'; %select where you want your figure pasted in the speadsheet (cell ID)
%.............excel COM object............................................................................
Excel = actxserver ('Excel.Application');
Excel.Visible = 1;
if ~exist(FILE,'file')
ExcelWorkbook=Excel.Workbooks.Add;
ExcelWorkbook.SaveAs(FILE);
ExcelWorkbook.Close(false);
end
invoke(Excel.Workbooks,'Open',FILE); %Open the file
ActiveSheet = Excel.ActiveSheet;
ActiveSheetRange = get(ActiveSheet,'Range',Range);
ActiveSheetRange.Select;
ActiveSheetRange.PasteSpecial; %.................Pasting the figure to the selected location
Excel.ActiveWorkbook.Save % Now save the workbook
if eq(Excel.ActiveWorkbook.Saved,1)
Excel.ActiveWorkbook.Close;
else
Excel.ActiveWorkbook.Save;
end
invoke(Excel, 'Quit'); % Quit Excel
delete(Excel); % End process
end

Related

Excel - Allow editing from MATLAB while sheet still open

I'm trying to create an add-in for Excel with Matlab, where the end goal is to import data and graphs.
I've managed to paste the current figure in Matlab to Excel using the code below:
function xlsPasteToCOPY(filename,sheetname,width, height,varargin)
%Paste current figure to selected Excel sheet and cell
%
%
% xlsPasteTo(filename,sheetname,width, height,range)
%Example:
%xlsPasteTo('File.xls','Sheet1',200, 200,'A1')
% this will paset into A1 at Sheet1 at File.xls the current figure with
% width and height of 200
%
% tal.shir#hotmail.com
options = varargin;
range = varargin{1};
[fpath,file,ext] = fileparts(char(filename));
if isempty(fpath)
fpath = pwd;
end
Excel = actxserver('Excel.Application');
set(Excel,'Visible',0);
Workbook = invoke(Excel.Workbooks, 'open', [fpath filesep file ext]);
Workbook.ChangeFileAccess(2);
sheet = get(Excel.Worksheets, 'Item',sheetname);
invoke(sheet,'Activate');
ExAct = Excel.Activesheet;
ExActRange = get(ExAct,'Range',range);
ExActRange.Select;
pos=get(gcf,'Position');
set(gcf,'Position',[ pos(1:2) width height])
print -dmeta
invoke(Excel.Selection,'PasteSpecial');
invoke(Workbook, 'Save');
invoke(Excel, 'Quit');
delete(Excel);
However this only works when the said Excel sheet is closed. I need a way to allow editing while it's still open. Is this possible?
It works perfectly while the Excel-sheet is closed. But when kept open, I receive this error message:

Close an Excel file was opened in Matlab

My code needs to open an Excel file (with formulas) to search for a given value and close this file, will do some calculations and will write the answer in this file.
I can not get Matlab to close the file before it writes the response and this error appears:
Error using xlswrite (line 226)
The file C: \Temp\Data_Home.xlsx is not writable. It might be locked by another process.
File_123 = 'C: \Temp\Data_Home.xlsx';
xlObj = actxserver('Excel.Application'); %Start Excel
wsObj = xlObj.Workbooks.Open(File_123); %Open workbook
Sheet = wsObj.Sheets.Item(3); %Assume we're using the first sheet
Use Quit and delete as mentioned in the example in the documentation of actxserver.
Quit(xlObj);
delete(xlObj);

Working with Excel sheets in MATLAB

I need to import some Excel files in MATLAB and work on them. My problem is that each Excel file has 15 sheets and I don't know how to "number" each sheet so that I can make a loop or something similar (because I need to find the average on a certain column on each sheet).
I have already tried importing the data and building a loop but MATLAB registers the sheets as chars.
Use xlsinfo to get the sheet names, then use xlsread in a loop.
[status,sheets,xlFormat] = xlsfinfo(filename);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(filename,sheets{sheetindex});
data{sheetindex}=num; %keep for example the numeric data to process it later outside the loop.
end
I 've just remembered that i posted this question almost 2 years ago, and since I figured it out, I thought that posting the answer could prove useful to someone in the future.
So to recap; I needed to import a single column from 4 excel files, with each file containing 15 worksheets. The columns were of variable lengths. I figured out two ways to do this. The first one is by using the xlsread function with the following syntax.
for count_p = 1:2
a = sprintf('control_group_%d.xls',count_p);
[status,sheets,xlFormat] = xlsfinfo(a);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(a,sheets{sheetindex},'','basic');
data{sheetindex}=num;
FifthCol{count_p,sheetindex} = (data{sheetindex}(:,5));
end
end
for count_p = 3:4
a = sprintf('exercise_group_%d.xls',(count_p-2));
[status,sheets,xlFormat] = xlsfinfo(a);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(a,sheets{sheetindex},'','basic');
data{sheetindex}=num;
FifthCol{count_p,sheetindex} = (data{sheetindex}(:,5));
end
end
The files where obviously named control_group_1, control_group_2 etc. I used the 'basic' input in xlsread, because I only needed the raw data from the files, and it proved to be much faster than using the full functionality of the function.
The second way to import the data, and the one that i ended up using, is building your own activeX server and running a single excelapplication on it. Xlsread "opens" and "closes" an activeX server each time it's called so it's rather time consuming (using the 'basic' input does not though). The code i used is the following.
Folder=cd(pwd); %getting the working directory
d = dir('*.xls'); %finding the xls files
N_File=numel(d); % Number of files
hexcel = actxserver ('Excel.Application'); %starting the activeX server
%and running an Excel
%Application on it
hexcel.DisplayAlerts = true;
for index = 1:N_File %Looping through the workbooks(xls files)
Wrkbk = hexcel.Workbooks.Open(fullfile(pwd, d(index).name)); %VBA
%functions
WorkName = Wrkbk.Name; %getting the workbook name %&commands
display(WorkName)
Sheets=Wrkbk.Sheets; %sheets handle
ShCo(index)=Wrkbk.Sheets.Count; %counting them for use in the next loop
for j = 1:ShCo(index) %looping through each sheet
itemm = hexcel.Sheets.Item(sprintf('sheet%d',j)); %VBA commands
itemm.Activate;
robj = itemm.Columns.End(4); %getting the column i needed
numrows = robj.row; %counting to the end of the column
dat_range = ['E1:E' num2str(numrows)]; %data range
rngObj = hexcel.Range(dat_range);
xldat{index, j} = cell2mat(rngObj.Value); %getting the data in a cell
end;
end
%invoke(hexcel);
Quit(hexcel);
delete(hexcel);

Matlab Actxserver :How could I terminate process opened by actxserver in matlab

I want to open and close an Excel file in MATLAB.
I have tried the code below, but it failed on closing process with actxserver
h.WorkBooks.Item(wbkname).Close;
here is my code for this issue, how can I terminate the excel file?
.Quit
.delete
I also tried to close excel file via VBA sub-module, but it gives me an error message:
fullFileName = [pwd '\KOSPI200_1월.xlsm'];
excel = actxserver('Excel.Application');
file = excel.Workbooks.Open(fullFileName);
excel.Run('jongho_bot_initial');
excel.Run('jongho_bot_loop',2);
Here is an example that creates a new spreadsheet, write some values, save the file and exit. The Excel process is cleanly terminated at the end.
% create Excel COM server
excel = actxserver('Excel.Application');
excel.Visible = true; % make the window visible
% create new workbook
wb = excel.Workbooks.Add();
% get "Sheet1" and activate it
sheet = wb.Sheets.Item(1);
sheet.Activate();
% select a 5x5 range, and fill it with some numeric values
sheet.Range('A1:E5').Value = num2cell(magic(5));
% save spreadsheet file
excel.DisplayAlerts = false; % overwrite file without prompts
wb.SaveAs(fullfile(pwd(),'myfile.xlsx'));
% close spreadsheet
wb.Close(false);
% quit Excel
excel.Quit();
% delete handles and clear variables
delete(excel);
clear sheet wb excel
You might additionally want to set certain properties appropriately, if you want the automation to be performed in the background with no user interaction:
excel.Visible = false; % invisible Excel window
excel.ScreenUpdating = false; % turn off screen update to run faster
excel.Interactive = false; % non-interactive mode, with no keyboard/mouse
excel.DisplayAlerts = false; % no prompts or alert messages
excel.UserControl = false; % object freed when reference count reaches zero

How to modify xlsread to get a step-by-step updated flag from loading process

I have installed Matlab r2010a on my computer
I need use the function xlsread to load data from one just one *.xls or *.xlsx file. that's not a big challenge, the problem is How to modify xlsread.m to get a flag (integer) that gives the percentage of the loading process?
Thanks a lot.
so far i made this:
put a step variable to count until half then call xlsread that take a little time and after load process, the counter in 49.5% count to the end.
Not the best, but this is what I have
file = 'example.xls';
h = waitbar(0, ['Loading data from ' file], ...
'Name', 'Loading',...
'CreateCancelBtn',...
'setappdata(gcbf, ''canceling'', 1)');
steps = 200;
for step = 1 : steps
%# Check for Cancel button press
if getappdata(h, 'canceling')
okCancel = 1;
break
end
pause(0.01); %# Delay time for wait bar progres
if step == steps/2
[data, txt] = xlsread(file);
end
%# Process status report
waitbar(step/steps, h, sprintf(['Loading data from file... %3.2f%%'], step*100/steps));
end
set(h, 'CloseRequestFcn', 'closereq')
close(h)
XLSREAD function allows you to specify ranges of cells to read. Therefore you could read your data in batches (say read the first 50 rows of the table, then the next 50, and so on), each time "incrementing" the progress bar.
Note that this will be slower than reading the whole table at one, because the function has to make a connection to Excel COM then tear it down each time it is called (see this post for an explanation and a possible solution).
EDIT:
Here is a quick example:
%# path to excel file to read
fname = fullfile(pwd,'test.xls');
%# get number of rows/columns in table
Excel = actxserver('Excel.Application'); %# open Excel COM Server
wb = Excel.Workbooks.Open(fname, 0, true); %# open XLS file for reading
sheet = Excel.Worksheets.get('item',1); %# activate first sheet
numRows = sheet.Range('A1').End('xlDown').Row;
numCols = sheet.Range('A1').End('xlToRight').Column;
wb.Close(false); %# close XLS file
Excel.Quit(); %# cleanup
Excel.delete();
clear Excel wb sheet;
%# read rows in steps, and show progress-bar
numSteps = 20;
idx = fix(linspace(0,numRows,numSteps+1));
num = cell(numSteps,1);
h = waitbar(0, 'Reading excel file');
for i=1:numSteps
%# update progress-bar
waitbar(i / numSteps);
%# range of cells to read
cellRange = sprintf('%c%d:%c%d', ...
'A', idx(i)+1, char('A'+numCols-1), idx(i+1));
num{i} = xlsread(fname, 1, cellRange);
end
close(h)
%# merge all cells into a matrix
num = cell2mat(num);
This assumes the Excel file contains a table of numeric data. Feel free to adapt to your own file.

Resources