How to insert a Chart in Excel through Matlab
Afficher commentaires plus anciens
I know there are many old posts about this topic, but none was able to help me, or outdated.
My project involves about 20 columns of Data, each 20.000 rows. All Calculations in Matlab are done and charts created.
But unfortunatly I need the whole evaluation in an Excel File, including several editable Charts.
Using xlswrite I created the Excel Files, now I struggle to create the Charts the way I like.
I tryed using this code, but got several errors and wasn't able to choose the X and Y Values of the Chart.
if true
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 "Error using
COM.Excel_Application/Range
Error: Object returned error code: 0x800A03EC"
end
I searched the web for hours how to use ActiveX to add Charts, but no suggestion worked for me.
So my question is, to make it clear:
- How to insert Charts in Excel using Matlab (general up to date ActiveX code structure)
- How to select own columns for the XValue and the YValues (Range)
- How to get acces to Chart Titles, Axes, Line appearance and Legend
Can anyone please help me out? Thank you a lot!
Kilian
By the way, I'm using latest Excel 2016, and Matlab R2017a. I need this for a project in an internship during college.
Réponses (1)
Not directly relevant to your question: I often see questions where people use invoke and get when dealing with COM. In most cases it's not needed; your code would work just as well (or as bad) with:
excel = actxserver('Excel.Application');
wb = excel.Workbooks.Open(somefile);
charts = wb.Charts;
chart = charts.Add;
chart.SetSourceData(excel.Range('Sheet1!$B$2:$B$16'));
and is easier to read and gives you tab completion.
Relevant to your question: I get no error and a chart with the above code, when testing against an excel file picked at random. This is using excel 2013 but I don't believe 2016 changed anything in that respect. Matlab is R2017a but that does not matter for your problem.
First thing to know is where the error is coming from, the range creation or setSourceData, so decouple that last line into:
rg = excel.Range('Sheet1!$B$2:$B$16');
chart.SetSourceData(rg);
and tell us which line causes the error. I would also recommend
excel.Visible = true;
after you've created the excel object, so you can see what is actually happening.
Finally, if you can attach you workbook (or a dummy one that causes the error) that would help.
16 commentaires
Kilian Weber
le 13 Juin 2017
Modifié(e) : Kilian Weber
le 13 Juin 2017
Guillaume
le 13 Juin 2017
Well, the second error is because the first error prevented the creation of the rg variable.That's normal.
The problem is thus with the creation of the range object. Instead of the rg = ... line, try:
sheet1 = wb.Worksheets.Item('Sheet1');
rg = sheet1.Range('$B$2:$B$16');
If that does not work, which line causes the error?
As said, if you can attach the workbook it would be easier to help you.
Kilian Weber
le 13 Juin 2017
Modifié(e) : Kilian Weber
le 13 Juin 2017
Guillaume
le 13 Juin 2017
Well, there's no sheet named 'Sheet1' in your workbook. It's no wonder you get an error when you define a range that refers to a sheet named Sheet1. Try replacing the name with 'Tabelle1', i.e.
chart.SetDataSource(excel.Range('Tabelle1!$B$2:$B$16'));
or, you could refer to the sheet by its index, i.e. to refer to the first sheet:
chart.SetDataSource(wb.Worksheets.Item(1).Range('$B$2:$B$16'));
my Excel now is getting crazy
If every time you try something, you start with:
excel = actxserver('Excel.Application')
and never ends with
excel.Quit
then it's no wonder. actxserver starts a new invisible instance of excel every time you call it. If you never close that instance (with Quit) then you'll end up with zillions instances of excel consuming memory and locking open files. In that case, kill all excel processes with task manager.
This is one of the reason I advised you to set the 'Visible' property to true immediately after the actxserver line. You'll see that new instance of excel and what it's doing.
Note that excel.Quit won't truly quit excel if you've opened a file and made some modification to it. Instead, it'll pop up a dialog asking whether you want to save the changes to the file. If excel is still invisible, the dialog will also be invisible and excel will stay in a state of limbo. To force quit an excel instance, discarding any change made to files:
excel.DisplayAlerts = false; %prevent the save modification dialog from popping up
excel.Quit; %quit excel discarding any unsaved changes
Kilian Weber
le 14 Juin 2017
Guillaume
le 14 Juin 2017
"In Range('$B$2:$B$16') I select the Y-Values and it automaticly takes the first column of the skript as the X-Values"
No, it doesn't. At the moment, your chart is a bar chart which does not even have x-values. You'd need a XY chart (scatter plot) for that. The bar chart uses labels for the x axis, which by default is 1 to number of points. That this matches your first column is a coincidence.
You can change the labels of your chart by iterating over the Series in the Chart's SeriesCollection and changing either their XValues or their Formula:
for sidx = 1 : chart.SeriesCollection.Count %iterate over the series
s = chart.SeriesCollection(sidx);
s.XValues = '=Tabelle1!$C$2:$C$37'; %for example
%or
s.Formula = "=Series(somename, xlabels, yrange)";
end
"Do you know a simple way to slesect the Y-Value-Data like this"
No. Other than letting excel autodetermine the range by selecting the whole column with Range('$B:$B'), I don't think there is a way. You either have to iterate over the rows and find the first empty row, or play around with Selection objects (let the selection object auto select the end of the range and query where that end is). Last option is the UsedRange property of the Worksheet, but that one, for some reason, is not always correct.
Kilian Weber
le 14 Juin 2017
"Did I misunderstand something?"
Well, yes, you set the XValues (and other properties of the Series) after you've set the SourceData of the chart. Otherwise, you're just editing the default series that the chart is created with and that are discarded as soon as you set the source data.
Unfortunately, you can't use '$C:$C' as a range as excel will include the header as part of the xdata. One possible way:
%%%%%general Code to insert a Chart in Excel using Matlab %%%%%
%%start Excel and open Workbook
excel = actxserver('Excel.Application');
wb = excel.Workbooks.Open('D:\Documents\Studium\Praxissemester\kleine Autoclave\Matlab\Test999.xlsx');
%%makes the created sheet visible
excel.Visible = true;
%%add Chart
chart = wb.Charts.Add;
chart.ChartType = 'xlXYScatterSmooth'
%%set source data
chart.SetSourceData(wb.Worksheets.Item(1).Range('$A:$A'));
series = chart.SeriesCollection(1);
yrange = regexp(series.Formula, '(?<==SERIES\([^,]*,[^,]*,)[^,]+', 'match', 'once');
series.XValues = regexprep(yrange, '\$A', '\$C');
%rest of your code
%WATCH OUT FOR CASE, Chart and chart are not the same!
%The line
Chart.HasLegend = true;
%creates a structure instead of updating the chart
It would be much easier if your xvalues were before the yvalues in your spreadsheet since you could specify the range in SetSourceData:
chart.SetSourceData(wb.Worksheets.Item(1).Range('$A:$A,$C:$C')
But if you want column C as the X values you do have to go through the series object.
Kilian Weber
le 14 Juin 2017
Modifié(e) : Kilian Weber
le 14 Juin 2017
Kilian Weber
le 14 Juin 2017
Guillaume
le 14 Juin 2017
If your x column is before the y columns then you can set the range with SetSourceData:
excel = actxserver('Excel.Application');
excel.Visible = true; %optional
wb = excel.Workbooks.Open('...')
chart1 = wb.Charts.Add;
chart1.ChartType = 'xlXYScatterSmooth';
chart1.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $H:$P'));
%...
chart2 = wb.Charts.Add([], chart1); %place after chart1
chart2.ChartType = 'xlXYScatterSmooth';
chart2.SetSourceData(wb.Worksheets.Item('Tabelle1').Range('$B:$B, $Q:$Q'));
%...
wb.SaveAs(...)
excel.Quit;
Kilian Weber
le 19 Juin 2017
Guillaume
le 19 Juin 2017
Yes, I did try the exact code above, and again today, received no error and got the correct graph.
So I'm not sure what is happening for you. The error tells you the range is not valid. Maybe try:
sheet = wb.Worksheets.Item('Tabelle1');
rg1 = sheet.Range('$B:$B');
rg2 = sheet.Range('$H:$P');
rg = excel.Union(rg1, rg2);
If it doesn't work which line is causing the error?
Kilian Weber
le 19 Juin 2017
Sorry, typo should hve been:
chart1.SetSourceData(rg);
Good news is that creating the range succeeded if you got this error.
Your code above works for me on the spreadsheet you posted a while ago. Your m file and new xlsx file are private. I can't access them
Kilian Weber
le 19 Juin 2017
Catégories
En savoir plus sur Use COM Objects in MATLAB dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!