Error while choosing range for Excel chart using matlab - excel

I have an Excel file with to sheets. First about 30 columns and 20.000 rows. 2nd about 10 columns and 2 rows. Each with a header.
No, there are less than 66.000 rows in the file I work with and I use .xlsx files, so it's not that problem. this might be related but didn't help for me
The goals for the script were:
Automaticly creating a Chart in an already Existing .xlsx file using Matlab
Easy way to choose Range, X- and Y-Values (by sheet and column) freely
applicable to all sizes on .xlsx files. (up to 20.000 rows and 50 columns and several sheets)
In this Code range is set to the following: X -> column B , Y -> column H - P , the sheet is 'sheet1' called 'Tabelle1'
%%%%% general Code to insert a Chart in Excel using Matlab %%%%%
%% start Excel and open Workbook
excel = actxserver('Excel.Application');
wb = excel.Workbooks.Open('C:\...\Test.xlsx');
%% makes the created sheet visible
excel.Visible = true;
%% add 1. Chart
chart1 = wb.Charts.Add;
%% set source data
chart1.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $H:$P')); % 'Tabelle1' is the german equal to sheet1, my excel is german
%% Name chart sheet
chart1.Name = '1. TestChart';
%% Set chart title, see https://msdn.microsoft.com/en-us/library/office/ff196832.aspx
chart1.HasTitle = true;
chart1.ChartTitle.Text = 'Test Title';
%% Set chart types, see https://msdn.microsoft.com/en-us/library/office/ff837417.aspx
chart1.ChartType = 'xlXYScatterSmoothNoMarkers';
%% Set chart legend, see https://msdn.microsoft.com/en-us/library/office/ff821884.aspx
chart1.HasLegend = true;
%% Set Axes Titles
chart1.Axes(1).HasTitle = true;
chart1.Axes(1).AxisTitle.Text = 'Time [s]'; % XAxes
chart1.Axes(2).HasTitle = true;
chart1.Axes(2).AxisTitle.Text = 'Temperature[°C]'; %YAxes
%% add 2nd chart
chart2 = wb.Charts.Add([], chart1); %place after chart1
chart2.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $Q:$Q'));
% ... same procedure as above
%% use to quit all open Excel processes
% excel.Quit;
this Error occurs:
Error using Interface.000208D8_0000_0000_C000_000000000046/Range
Error: Object returned error code: 0x800A03EC
Error in CodeTestmy (line 13)
chart1.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $H:$P'));
I'm pretty sure, that this code works just fine and I can't explain the error.
Can you please help me to find out, were the error comes from to finaly solve the problem.
Here are the download Links (Google Drive) to the .m script and .xlsx file used
Thanks
Kilian Weber

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:

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

Excel MathType Equation from matlab

Is it possible to insert a mathType equation from matlab into the excel spreadsheet?
I am going to create an excel file through matlab and create a pdf report. My report includes some formula and I want to create them with excel MathType equation. Is there any access to MathType equation from activeX in matlab?
This would require creating a MathType equation, then adding it as an object to the Excel file through ActiveX. I haven't found any way to call MathType from MATLAB, let alone move the resulting object to the file.
One alternative is to plot your formula in a MATLAB figure, then capture and insert the figure as an image into your Excel file through ActiveX. Here's an example for plotting the formula:
hFigure = figure('Position', [100 100 300 200], 'Color', 'w'); % Create white figure
hAxes = axes(hFigure, 'Position', [0 0 1 1], 'Visible', 'off'); % Create invisible axes
text(hAxes, 0.5, 0.5, '$$y = \sum_{i=1}^N a_i*x_i$$', ... % Create equation text
'Interpreter', 'latex', ...
'FontSize', 30, ...
'HorizontalAlignment', 'center');
And the resulting figure:
Now you can print this figure to the clipboard and insert it into an Excel worksheet with ActiveX:
excel = actxserver('Excel.Application'); % Create server object
excelWorkbook = excel.Workbooks.Add(1); % Add a workbook
excelSheet = excel.ActiveSheet; % Get the active sheet
dpi = get(groot, 'ScreenPixelsPerInch'); % Get screen dpi
print(hFigure, sprintf('-r%d', dpi), ... % Print the figure at the screen resolution
'-clipboard', '-dbitmap'); % to the clipboard as a bitmap
excelSheet.Range('B2').PasteSpecial(); % Paste from clipboard (top left corner
% of image will be in the cell 'B2')
excelWorkbook.SaveAs('formula.xlsx'); % Save workbook to a file
excelWorkbook.Close(); % Close workbook
excel.Quit(); % Quit server
excel.delete(); % Delete server object
And here's how it looks in the Excel file:

Using Matlab to create Excel charts with X and Y values from range

I have about 20 columns of data, each ~20,000 rows. All calculations are done in Matlab, and then charts are created.
Unfortunately, I need the whole output to be in an Excel File, including several editable charts. Using xlswrite I created the Excel file, now I am struggling to create the charts the way I want.
I tried using this code, but got several errors and wasn't able to choose the X and Y Values of the chart.
Excel = actxserver('Excel.Application');
WB = Excel.workbooks.Open('D:\...\Test.xlsx');
Charts = WB.Charts;
Chart = invoke(Charts,'Add');
invoke(Chart, 'SetSourceData', Excel.Range('Sheet1!$B$2:$B$16')); %% here an error occurs
The error:
Error using COM.Excel_Application/Range. Object returned error code: 0x800A03EC"
I have not been able to find any solutions for adding charts through the ActiveX object in Matlab. Any posts I have found on this topic were outdated or unhelpful.
Summary, my question is:
How can I insert charts in Excel using Matlab (using a general, up to date ActiveX code structure).
How can I select the columns for the XValue and the YValues (Range)
How can I get access to chart titles, axes, line appearance and legend
I'm using Excel 2016 and Matlab R2017a.
Edit:
during this week I developed a own solution, that still doesn't work perfectly but is close to what I want. Could you have a look on this code too please:
Important is only chart1. I wanted to set the XValue to column B and the YValues to column H - P of the sheet1 (Tabelle1).
%%%%% general Code to insert a Chart in Excel using Matlab %%%%%
%% start Excel and open Workbook
excel = actxserver('Excel.Application');
wb = excel.Workbooks.Open('C:\...\Test.xlsx');
%% makes the created sheet visible
excel.Visible = true;
%% add 1. Chart
chart1 = wb.Charts.Add;
%% set source data
chart1.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $H:$P')); % 'Tabelle1' is the german equal to sheet1, my excel is german
%% Name chart sheet
chart1.Name = '1. TestChart';
%% Set chart title, see https://msdn.microsoft.com/en-us/library/office/ff196832.aspx
chart1.HasTitle = true;
chart1.ChartTitle.Text = 'Test Title';
%% Set chart types, see https://msdn.microsoft.com/en-us/library/office/ff837417.aspx
chart1.ChartType = 'xlXYScatterSmoothNoMarkers';
%% Set chart legend, see https://msdn.microsoft.com/en-us/library/office/ff821884.aspx
chart1.HasLegend = true;
%% Set Axes Titles
chart1.Axes(1).HasTitle = true;
chart1.Axes(1).AxisTitle.Text = 'Time [s]'; % XAxes
chart1.Axes(2).HasTitle = true;
chart1.Axes(2).AxisTitle.Text = 'Temperature[°C]'; %YAxes
%% add 2nd chart
chart2 = wb.Charts.Add([], chart1); %place after chart1
chart2.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $Q:$Q'));
% ... same procedure as above
%% use to quit all open Excel processes
% excel.Quit;
another Error occurs:
Error using Interface.000208D8_0000_0000_C000_000000000046/Range
Error: Object returned error code: 0x800A03EC
Error in CodeTestmy (line 13)
chart1.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $H:$P'));
for now this question is nearly answered. For further bug related answers have a look at a related question
As I suggested in the comments, a better documented method for doing this would be to use VBA. As it happens, the VBA documentation can actually be used to take most of the guesswork out of interacting with the COM object directly from Matlab, as the syntax is similar.
Here is some updated Matlab code which achieves your three points. I have included links to the MSDN documentation where appropriate:
% Start Excel and open workbook
Excel = actxserver('Excel.Application');
WB = Excel.Workbooks.Open('C:\...\test.xlsx');
% Show the workbook
Excel.visible = 1;
% Add chart
Chart = invoke(WB.Charts,'Add');
% Get Sheet object
SheetObj = Excel.Worksheets.get('Item', 'Sheet1');
% Name chart sheet
Chart.Name = 'TestChart';
% Set source data range of chart
% X and Y data can also be set to Matlab arrays, by Srs.Values and Srs.XValues, ensuring equal length
% Y data
Srs = Chart.SeriesCollection.Add(SheetObj.Range('B2:B16'));
% X data, could be a Matlab array of correct length
Srs.XValues = SheetObj.Range('A2:A16');
% Series name
Srs.Name = 'Test Series';
% For chart types, see https://msdn.microsoft.com/en-us/library/office/ff837417.aspx
Chart.ChartType = 'xlXYScatterSmooth';
% Set chart title, see https://msdn.microsoft.com/en-us/library/office/ff196832.aspx
Chart.HasTitle = true;
Chart.ChartTitle.Text = 'Test Title';
% Set chart legend, see https://msdn.microsoft.com/en-us/library/office/ff821884.aspx
Chart.HasLegend = true;
Your error:
You were encountering an error because you were trying to access the Range object of the Excel application. This doesn't exist! All Range objects belong to a Sheet object, which is what I retrieve first in the above code.
Creating many series:
You say you have many columns of data, here is a way to include them through a loop. It also finds the last used row in each column.
% ... CREATE WORKBOOK / CHART AS BEFORE ...
%
Chart.Name = 'TestChart';
% Set source data range of chart, do X and Y data for each series
columns = 2:4;
colnames = {'xdata', 'my series 1', 'my series 2', 'my series 3'};
for col = columns
% Get Excel column *letter* from column *number*
colchar = strrep([char(96+floor((col-1)/26)) char(97+rem(col-1,26))],char(96),'');
% Last row of data, see https://msdn.microsoft.com/en-us/library/office/ff839539.aspx
% Data must be contiguous (no gaps / blank cells)
lastrow = num2str(SheetObj.Range([colchar, '2']).End('xlDown').Row);
% Y data, creating range strings by concatenation of column character and row number
Srs = Chart.SeriesCollection.Add(SheetObj.Range([colchar, '2:', colchar, lastrow]));
% X data, same approach is used for last row, but only column = 1 = "A"
Srs.XValues = SheetObj.Range(['A2:A', lastrow]);
% Set column name, to use the first row do
% Srs.Name = SheetObj.Range([colchar, '1']);
Srs.Name = colnames{col};
end
Chart.ChartType = 'xlXYScatterSmooth';
%
% ... TITLE / LEGEND AS BEFORE ...
Output chart sheet and input "Sheet1":
Edit:
In the above, I loop over the column numbers to populate the y data. If you know the column letter then you can just loop over colchar instead of creating it.
% There are shortcuts to creating a cell array of consecutive letters,
% Like columnletters = cellstr(('H':'J')');
for colchar = {'H', 'I', 'J'};
% ... same as the above for loop, but don't need to get colchar from col
lastrow = num2str(SheetObj.Range([colchar, '2']).End('xlDown').Row);
Srs = Chart.SeriesCollection.Add(SheetObj.Range([colchar, '2:', colchar, lastrow]));
Srs.XValues = SheetObj.Range(['A2:A', lastrow]);
Srs.Name = SheetObj.Range([colchar, '1']);
end

Matlab - ActiveX Move Excel Sheet

Which is the command to move an excel sheet after another from one book to other?. Commented lines failed.
X = actxserver('Excel.Application');
XW0 = X.Workbooks.Open('t0.xlsx');
XW2 = X.Workbooks.Open('t2.xlsx');
XW2.Worksheets.Item(1).Name = 't2';
% XW2.Worksheets.Item(1).Move('after',XW0.Sheets(1));
XW0.Save
XW0.Close(false)
XW2.Save
XW2.Close(false)
X.Quit
I was able to get Sheet t2 to move from t2.xlsx to after Sheet 1 in t0.xlsx by replacing your commented-out line with this:
XW2.Worksheets.Item(1).Move([], XW0.WorkSheets.Item(1));
Note the empty matrix for the first argument, which is where the Before option goes (see here).

Resources