Close an Excel file was opened in Matlab - excel

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

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 add data to existing XLSX file in MATLAB every time using a push button?

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:

Creating a new Excel File in pywin32

I'm writing a program that, summarized, takes a notepad file and saves it as a excel file.
Right now my program opens up a blank excel file I have created, just "Book1.xls":
xlApp = Dispatch("Excel.Application")
xlApp.Visible=0
xlWb = xlApp.Workbooks.Open(file_path+"/Book1.xls")
workBook = xlApp.ActiveWorkbook
sheet = xlApp.ActiveSheet
and it uses Book1.xls to write into and format as is required, then saves it as another file name using
workBook.SaveAs(new_file_path+'/UpdatedSheet.xls')
I want to know how to simply create a new excel file to write to, then save as a file. Without the need of having Book1.xls already created in a specific directory.
You can create a new workbook using the Add method of the Workbooks object:
>>> import win32com.client as win32
>>> excel = win32.Dispatch("Excel.Application")
>>> workbook = excel.Workbooks.Add()
>>> workbook.SaveAs(new_file_path+'/UpdatedSheet.xls')

How to add more than 3 sheets to an excel workbook from within MATLAB

How do I add more sheets to an excel workbook from within matlab?
I set up the workbook like so (based on code I got from someone else's post in this forum):
%# create Excel COM Server
Excel = actxserver('Excel.Application');
Excel.Visible = true;
%# create new XLS file
wb = Excel.Workbooks.Add();
wsheet=1;
wb.Sheets.Item(wsheet).Activate();
That's fine. Then later on inside the loop I open a new sheet after so many loops:
...
if loop==sheetlimit,
wsheet=wsheet+1;
wb.Sheets.Item(wsheet).Activate();
end
This works up to sheet 3. But when wsheet=4 I get this error message:
??? Invoke Error, Dispatch Exception: Invalid index.
Error in ==> filename at 97
wb.Sheets.Item(wsheet).Activate();
Appreciate any help. Thanks.
I don't know Matlab but I would be surprised if wb.Sheets.Item(wsheet).Activate(); is actually adding any new worksheets. Most likely it is selecting / activating each worksheet in your wb workbook and your default Excel template has three worksheets. Hence why it errors when it gets to more than three.
Something like this might add a new Excel worksheet:
wb.sheets.Add();
Aargh - comment formatting completely messed up - I'll re-enter it as an new answer
Yes wb.sheets.Add(); will work. You can query the available methods of an interface like this:
methods(wb.sheets)
which gives:
Methods for class Interface.000208D7_0000_0000_C000_000000000046:
Add FillAcrossSheets PrintOut addproperty events loadobj set
Copy Item PrintPreview delete get release
Delete Move Select deleteproperty invoke saveobj

How do I make an Excel VBA Function that works when I reopen the document?

OK, I've just written a very simple VBA script that goes off and grabs the file size of a file found at a specified location (edit update code from dscarr):
Public Function FileSize(path As String) As Variant
On Error GoTo Err_FileSize:
Dim retVal As Variant
Dim filesys As Object
Dim file As Object
retVal = ""
Set filesys = CreateObject("Scripting.FileSystemObject")
Set file = filesys.GetFile(path)
retVal = file.Size
Exit_FileSize: On Error Resume Next
FileSize = retVal
Exit Function
Err_FileSize: retVal = "Error: " & Err.Description
Resume Exit_FileSize
End Function
If I import this into a new workbook, save the document as a "Excel Macro-Enabled Workbook" alongside an empty file called readme.txt and then put "./readme.txt" in A1 and "=FileSize(A1)" in A2, A2 evaluates properly to the file size of readme.txt, 0 bytes. Great. If I then save the document, close and reopen it, I'm warned that macros are disabled. If I enable them, the content of A2 has changed to #VALUE! and nothing I do will make the function work again. Has anyone seen this before, can anyone point out the mistake that I'm making here?
edit: the issue seems to be caused by me using relative paths. I can't explain why it works for a new workbook, but not once saved and reopened, but using absolute paths solves the problem, which as dscarr identified, was a "File Not Found" issue.
I duplicated your code in an Excel 2007 Macro Enabled workbook and found that it worked just fine with the following caveats
It does not automatically update the value (e.g. run the FileSize function) when you open the workbook. This can be compensated for by adding some code to the Worrkbook_Open event handler that calculates the workbook.
I get the #VALUE error when it cannot find the file that is specified. Indeed, when the file is missing or incorrectly named the line "Set file = filesys.GetFile(path)" throws the error number 53 "File Not Found". In this case the return value is never set because the line of code that sets it is never called. You could try setting a default value of "File Not Found" before actually attempting to retrieve the file size.
In Excel 2010, Go File->Options->Trust Center->Macro Settings and make sure the Enable option button has been selected.

Resources