4

Given that I write to a workbook, I currently kill all Excel processes so that my code works when I call it in a loop.

xlswrite(path,values);
system('taskkill /F /IM EXCEL.EXE');

This makes me unable to run the code while I am working in another Excel file. How do I make it so that Matlab terminates only the Excel processes that itself created?

  • 2
    As of R2019a [writematrix](https://www.mathworks.com/help/matlab/ref/writematrix.html) or [writecell](https://www.mathworks.com/help/matlab/ref/writecell.html) are recommended functions for writing to excel files. – rahnema1 May 15 '19 at 10:15
  • @rahnema1 does these not have the same problem? I've been using the similarly named `writetable` for a long time and it believe it leaves a hidden Excel instance open if writing to xlsx... – Wolfie May 15 '19 at 10:36
  • 1
    @Wolfie Those functions have an option 'UseExcel' that should be set to `false`. – rahnema1 May 15 '19 at 11:05

2 Answers2

4

This was a "feature" introduced somewhere around R2015b to speed up multiple writes to Excel... not very user/memory friendly!

The xlswrite documentation links to this MathWorks Support Answer to manually write to Excel using actxserver, you can then manually delete the COM object referencing Excel.

You can actually edit xlswrite and see that it uses matlab.io.internal.getExcelInstance, which does the same thing and creates a COM interface with actxserver.

A cheeky option would be to copy xlswrite, add the Excel variable it creates as an output, and Quit and delete it afterwards, as shown below. I don't advocate breaking any of The MathWorks' copyright ownership of that function.

A less cheeky option would be to create a comparable function based on the answer I linked above, for writing data only it would look something like this:

function xlswriteClean( File, Data, Range )
% XLSWRITECELAN writes data like XLSWRITE, but deletes the Excel instance! 
%  XLSWRITECELAN (FILE,DATA,RANGE) writes the variable in
%  DATA to FILE, in the range specified by RANGE. 
%  RANGE is optional, defaults to "A1"
    % Obtain the full path name of the file
    % Could handle this more elegantly, i.e. 
    % this always assumes the current directory, but user might give a full path
    file = fullfile(pwd, File);
    % Open an ActiveX connection to Excel
    h = actxserver('excel.application');
    %Create a new work book (excel file)
    wb = h.WorkBooks.Add();
    % Select the appropriate range
    if nargin < 3
        Range = 'A1';
    end
    rng = h.Activesheet.get('Range', Range); 
    % Write the data to the range
    rng.value = Data; 
    % Save the file with the given file name, close Excel
    wb.SaveAs( File );  
    % Clean up - the point of this function
    wb.Close;
    h.Quit;
    h.delete;
end

You can customise basically everything within the new Excel workbook using the COM object h, so you could add any functionality which you use in xlswrite like sheet naming etc.

Wolfie
  • 27,562
  • 7
  • 28
  • 55
3

You can start the excel process by powershell and get its process id then use the process id to kill the process:

[~, pid] = system('powershell (Start-Process excel.exe -passthru).Id');
% Do your work
% ...
system(['powershell Stop-Process -Id ' pid])
rahnema1
  • 15,264
  • 3
  • 15
  • 27