How to add data to existing XLSX file in MATLAB every time using a push button? - excel

I have a function which generates some variable, like score, right, wrong, unanswered. This function is called using a push button. The problem is how can I add/append these values generated by a function to an XLSX file every time? Or, how to create a MAT file so that it can be added? What may be a possible solution?

The challenge involved in appending to a xls file is knowing its last row, to avoid overwriting data with the xlswrite command. I'd suggest taking a look at this file exchange submission XLSAPPEND, as it takes care of this for you.

It sounds like you've got a GUI running and want to repeatedly output data to an Excel file. One option that may speed file output is to keep a COM server open for output while your GUI is active, instead of repeatedly opening and closing one for every call to xlswrite or xlsappend. Here's a sample script to illustrate how you could do this:
function excel_output_example
% Start COM server:
excel = actxserver('Excel.Application');
excelWorkbook = excel.Workbooks.Add(1);
excelSheet = excel.ActiveSheet;
fileName = 'example.xlsx';
rowIndex = 1; % Keeps track of the next row to output data to
% Create GUI:
hFigure = figure('Position', [100 100 120 70], ...
'DeleteFcn', #(~, ~) stop_excel(excelWorkbook, excel));
uicontrol(hFigure, 'Style', 'pushbutton', ...
'Position', [20 20 80 30 ], ...
'String', 'Add to Excel', ...
'Callback', #output_to_excel);
function output_to_excel(~, ~) % Adds a random value to the next row in column A
excelSheet.Range(sprintf('A%d', rowIndex)).Value = rand();
rowIndex = rowIndex+1;
end
function stop_excel(workbookObj, comObj) % Stops the COM server
workbookObj.SaveAs(fileName);
workbookObj.Close();
comObj.Quit();
comObj.delete();
end
end
This will open a small GUI window with a push button. Every time the button is pressed, a new random value will be added the the next available row in column A of the Excel file. When the GUI window is closed the Excel file is saved and the COM server stopped. For example, after pushing the button 5 times and closing the GUI you will get something like this in your Excel file:

Related

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

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

How to load specific CSV column to the left in EXCEL?

My CSV file:
Product Code,Product Description,Net Weight,POR Number,BBE Info (DD/MM/YY)
0001450,Californian Whole Almonds,22.68kg,POR17195,21/11/19
Excel file, when importing the CSV file.
Question
I'd like to place the POR Number column to the left of Product Code. But when I refresh the data, it goes back to it's original place.
How can I load the CSV file into excel and choose which column loads up where? Without adjusting the CSV structure.
Here is a desired output when I refresh the CSV data:
Read the file line by line and use split to split the columns and then output the data where you need.
Use application.OnTime to run the code every minute.
Make NextRun a global date variable
sub split_csv()
File = FreeFile()
Open "csv.csv" For Input As #File
i = 2
While Not EOF(File)
Line Input #File, csvLine
cols = split(csvLine, ",")
range("A" & i).value = cols(1) ' and so on...
i = i+1
Wend
NextRun = Now + timevalue("00:01:00")
Application.OnTime EarliestTime:=NextRun, Procedure:="split_csv", Schedule:=True
end sub
To stop the code from running you have to use Application.OnTime EarliestTime:=NextRun, Procedure:="split_csv", Schedule:=False, I'll advice you to add that to workbook_close or if you forget to turn off the function it will open the workbook again and keep going.
you can use the integrated feature Get & Transform (Excel 2016) or earlier Version with the MS Power Query Add-in.
Go to Data > New Query > From File > From CSV
Select your csv file. Click Import.
A preview of the csv data will be shown. Click Edit.
Go to Home > Transform > Use First Row As Headers
Move the column you want with drog & drap over the column header
you may remove some columns with right click on the column header
Give it a try. The UI is very intuitive and you don't have to write any code for most transforming tasks.

MATLAB: Save multiple tables in Excel using a while loop

I have the following while loop in which an image is read and analyzed, then the results are saved in a table, that is saved in an Excel worksheet. I initially did this code for one single image/table, then realized I need to develop it for n images.
I basically want the results to be saved in the same Excel worksheet without overwriting, ideally the tables are vertically separated by an empty row.
Here's my effort as for now:
while(1)
...
%code code code
...
message = sprintf('Do you want to save the results in an Excel
worksheet?');
reply = questdlg(message,'Run Program?','OK','Cancel', 'OK');
if strcmpi(reply, 'Cancel')
% User canceled so exit.
return;
end
% Table creation.
% code code code
% Saving table to Excel
T = table(Diameter,BandWidth,n1,n2,P1,P2,Damage,...
'RowNames',Band);
filename = 'Results.xlsx';
writetable(T, filename, 'Sheet',1, 'Range', 'A1','WriteRowNames',true);
% Create a while loop to save more experiments to the Excel worksheet.
promptMessage = sprintf('Do you want to process another photo?');
button = questdlg(promptMessage, 'Continue', 'Continue', 'Cancel',
'Continue');
if strcmpi(button, 'Cancel')
break;
end
end
If it can help you to get an idea, each table is a 6x8.
Prior to your while loop, declare a cell array to hold the table that you will eventually write to an excel file.
cellArrayOfTableToBeWritten = {};
Also prior to the loop, define a cell array that will serve as a blank row.
rowWidth = 8;
blankrow = repmat({''},1,rowWidth);
Where you currently write the table, instead add what you would have written to the cell array with a blank row at the bottom.
cellArrayOfTableToBeWritten = [cellArrayOfTableToBeWritten;
T.Properties.VariableNames;
table2cell(T);
blankrow];
Once your while loop is done, write the combined cell array to a file as an excel file.
xlswrite(filename, cellArrayOfTableToBeWritten);

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);

Creating EXCEL File with parfor command in MATLAB for parallel processing

I want to create excel file outside parfor loop (in the starting of the code) then updating excel file with each loop and finally storing excel file to specific location after loop is complete. But I am getting some errors. with following command :
matlabpool('open',2);
pwd='C:\Users\myPC\Desktop';
fName = fullfile(pwd, 'file.xls');
%# create Excel COM Server
Excel = actxserver('Excel.Application');
Excel.Visible = true;
%# create new XLS file
wb = Excel.Workbooks.Add();
wb.Sheets.Item(1).Activate();%line 10
offset = 0;
C1 = {'NAME', 'Max', 'Min','Average'};
%# calculate cell range to fit matrix (placed below previous one)
cellRange = xlcalcrange('A1', offset,0, size(C1,1),size(C1,2));
offset = offset + size(C1,1);
%# insert matrix in sheet
Excel.Range(cellRange).Select();
Excel.Selection.Value =C1;
parfor i=1:2
%some code , eg :
MAX =1
MIN =2
AVG=3
name='jpg'
row2 = { name MAX MIN AVG };
%# calculate cell range to fit matrix (placed below previous one)
cellRange = xlcalcrange('A1', offset,0, size(row2,1),size(row2,2));
offset = offset + size(row2,1);
Excel.Range(cellRange).Select(); %line32
Excel.Selection.Value =row2;
end
%# parsave XLS file
wb.SaveAs(fName,1);
wb.Close(false);
%# close Excel
Excel.Quit();
Excel.delete();
matlabpool('close');
Above code shows following error:
1. The variable Excel in a parfor cannot be classified.,
2. The PARFOR loop cannot run used due to the way variable 'offset' is used.,
3. The PARFOR loop cannot run used due to the way variable 'Excel' is used.,
4. Valid indices for 'Excel' are restricted in PARFOR loops.,
5. Call was rejected by callee.Error in line 10 (wb.Sheets.Item(1).Activate();).
Pls. help to use above code so that I can create excel file which updates inside PARFOR loop and EXCEL file get saved outside PARFOR loop
It is not safe to write to a file simultaneously from different threads. This is why MATLAB will automatically error when you try to do this sort of thing.
The answer to this problem will be one of the two:
Within the parfor loop, write your outputs to some sort of independent buffers, and then outside the parfor loop write the buffers to the file, serially. Or,
Don't use parfor. Use for instead.
See this: http://blogs.mathworks.com/loren/2009/10/02/using-parfor-loops-getting-up-and-running/ to learn more about the restrictions of the parfor command.

Resources