Add sparklines to excel with matlab - excel

With MATLAB I can start a COM server and programmatically write to an Excel workbook. However, I can't figure out a way to add sparklines (suggestions appreaciated):
% Open new workbook
excel = actxserver('excel.application');
excel.visible = 1;
wrkbook = excel.Workbooks.Add();
sheet = wrkbook.Sheets.Item(1);
% Write some data
sheet.Range('B1:Z1').Value = rand(1,25);
Here is the problem:
% Add column sparklines to 'A1', type 'xlSparkColumn' and DataSource: 'B1:Z1'
sheet.Range('A1').SparklineGroups.Add('xlSparkColumn','B1:Z1')
I get the following error:
Error using Interface.Microsoft_Excel_15.0_Object_Library.SparklineGroups/Add
Error: Object returned error code: 0x800A03EC
Close/cleanup
% Close without saving
wrkbook.Saved = 1;
wrkbook.Close
excel.Quit
delete(excel)
Reference to SparklineGroup Object (Excel). I am on win7 64bit, R2013a and Excel 2013.

Try:
xlSparkColumn = 2;
sheet.Range('A1').SparklineGroups.Add(xlSparkColumn,'B1:Z1')
In the future, if you want to figure out the corresponding value for a certain constant/enum, use the IL DASM tool as shown in these posts.
EDIT
Ok it turns out that the enumeration xlSparkColumn was not the real issue here, you could either specify it as a string argument or pass the underlying integer value for the enum.
The problem as you mentioned in the comments is that you had the R1C1 reference style set instead of the default A1 reference style, thus the range specified in your call was not valid in that format.
Either of these will work:
excel.ReferenceStyle = 'xlR1C1';
sheet.Range('A1').SparklineGroups.Add('xlSparkColumn','R1C2:R1C26')
excel.ReferenceStyle = 'xlA1';
sheet.Range('A2').SparklineGroups.Add('xlSparkColumn','B1:Z1')

Related

Using MATLAB to write String values into Excel spreadsheet via ActiveX protocol.. found a problem

I'm using MATLAB 2017a and have been using xlswrite in the past to perform this operation. The problem I ran into was with execution speed and I was looking for a better way. So, I decided to use actxserver and write data using get(obj) from MATLAB and Range.Value from ActiveX. Here's what the code looks like:
e = actxserver('Excel.Application);
eWorkbook = e.Workbooks.Add;
e.Visible = 1;
eSheets = e.ActiveWorkbook.Sheets;
eSheet1 = eSheets.get('Item',1);
eSheet1.Activate;
A = ["Str1";"Str2";"Str3";];
eActivesheetRange = get(e.Activesheet, 'Range', 'A1:A3');
eActivesheetRange.Value = A;
This inocuous bit of code does not execute, nor does it throw a warning or error message.. Nothin'. In my mind, the eActivesheetRange evaluates to: Range("A1:A3") on the ActiveX side. Interestingly, if I replace
A = ["Str1";"Str2";"Str3";];
with
A = char(["Str1";"Str2";"Str3";]);
then the program writes the A char array to each cell in the eActivesheetRange Range.
Is there a way to call cells() using the MATLAB Range.Value connection? Would cells().Value be able to solve this problem?
I don't think writing to Excel using ActiveX is able to handle string types properly. In this case, you can make it work by simply converting your string array into a cell array of character vectors using cellstr. Changing your last line of code to the following works for me (in R2016b):
eActivesheetRange.Value = cellstr(A);
Replacing the last two lines with the following also works:
e.Activesheet.Range('A1:A3').Value = cellstr(A);
The solution to this is of course, a for loop.
alphacolumn=char(97:117);
% iterate through data array
for i=1:21
str=string(alphacolumn(i))+2;
str2=string(alphacolumn(i))+202;
write1=char(str+":"+str2);
if ~isreal(tsc{i,1})
T = (tsc{i,1});
for j = 1:length(T)
rrange = xl.ActiveWorkbook.Activesheet.Range(char(string(alphacolumn(i)) + string(j+1)));
xlcompatiblestring1 = char(string(T(j,:,:)));
rrange.Value= xlcompatiblestring1;
end
else
tsci=tsc{i,1};
% write data to xl target file
%xlswrite(xlfilepath,tsci,write1);
xlActivesheetRange = get(xl.Activesheet,'Range',write1);
xlActivesheetRange.Value = tsci;
end
end

Error accessing Names in Excel using Interop

I am programming an application in C# (Visual Studio 2015) and I need to update an .xlsm file.
This file has many formulas, over 1200 names and vba code.
I am using the Interop library and I am able to update some cells and get the relative updated formulas but i have some problem with the Names defined in the Excel.
The program recognizes the names in the Names collection but doesnt let me access some of the names.
When I try to access the value of the cell using its name it produces an exception.
I dont understand why i can access some of the names and others no.
Besides, in the excel, I can see the Name in the combo but when I select it, the cursor doesn't position over the cell.
In my program I could avoid this problem accessing the cells using the reference instead of the Name, but the vba in the excel uses the names and if i open the file from my app it doesnt work.
I am using this code:
excelApplication = new Microsoft.Office.Interop.Excel.Application();
excelApplication.ScreenUpdating = true;
excelApplication.Visible = true;
excelApplication.DisplayAlerts = false;
excelWorkbook = excelApplication.Workbooks.Open(txtFicheroEntrada.Text);
wsDatos = excelWorkbook.Worksheets[1];
wsDatos.Select();
foreach(Microsoft.Office.Interop.Excel.Name v in excelWorkbook.Names)
{
string NombreVar = v.Name;
//here i found the name BobinadoAT correctly. It exists
if (NombreVar == "BobinadoAT" ){ Console.WriteLine(NombreVar); }
}
if (wsDatos.Range["BobinadoAT"] != null) //but here this produces an exception
{
string valorcelda = wsDatos.Range["BobinadoAT"].Value.ToString();
}
¿does anyone work with many excel Names?
¿Am I accessing the names incorrectly?

Sending commands across VBA

I am writing a script in VBA that creates a drawing in CorelDraw. I am having trouble centering the text. Here is the code that works properly in CorelDraw's Macro editor:
Dim s2 As Object
Dim Txt As Object
Dim test As String
Dim returntest As String
returntest = "Test~Test1234~Test56~Test789"
test = Replace(returntest, "~", Chr(13))
Set s2 = CorelApp.ActiveLayer.CreateArtisticText(-7.75, (1 - 0.5) / 2, test)
Set Txt = s2.Text
Txt.Story.Font = "Swis721 BT"
Txt.Story.Size = 20
Txt.Story.LineSpacing = 75
Txt.Story.Alignment = cdrCenterAlignment
s2.Fill.UniformColor.CMYKAssign 0, 0, 0, 100
s2.Outline.SetNoOutline
s2.CenterX = s1.CenterX
s2.CenterY = s1.CenterY
s1 is simply a rectangle that is already defined. The problem is with "cdrCenterAlignment". VBA does not recognize it as a valid argument because it is referencing something that exists only within CorelDraw. I get "cdrCenterAlignment variable not defined" or "type mismatch" if I call it a string. How, if even possible, can I send this command/argument to CorelDraw while still working in Excel?
I ran into similar problems sending the same drawing to AutoCAD but was able to work around it by sending things to the Command line.
In your VBA code you can define it yourself:
Const cdrCenterAlignment = 3
https://community.coreldraw.com/sdk/api/draw/19/e/cdrAlignment
Reference the CorelDRAW library (Tools > References) and the constants will be defined, and you can use actual CorelDRAW types and API and enjoy IntelliSense and auto-complete, instead of working against the Object interface and constantly referring to documentation for what members are available on what objects - and dealing with run-time error 438 whenever you make a typo, because late-bound code will happily compile and only be resolved at run-time.
Adding a reference to the CorelDRAW type library will allow you to write early-bound code that resolves at compile-time, exactly like the function calls you're making against the VBA or Excel type libraries, which are referenced by default in an Excel VBA project.

Write data to excel and change sheet name using ActiveX--Matlab

I need to export data to excel sheet with a specific name using Activex. Here is what I did: First i export the data to excel in first for loop and then modify the names of the sheet using second for loop. Can it be done even in one single for loop? I think there should be another better idea.
Note: The size of the data varies.
try
filename = fullfile(pwd,'example.xlsx');
for i=1:5
xlswrite(filename,[1 2;3 4]*i,i);
end
for i = 1:5
myExcel = actxserver('Excel.Application');
excelWorkBook = myExcel.Workbooks.Open(filename,0,false);
excelWorkBook.Worksheets.Item(i).Name = ['new_sheet_' num2str(i)];
excelWorkBook.Save;
excelWorkBook.Close;
myExcel.Quit;
end
catch
% Disp Error message.....
end
The xlswrite function also accepts a string as sheet parameter. So just replace your call by this one:
xlswrite(filename,[1 2;3 4]*i,['new_sheet_' num2str(i)]);
Fratyx's answer is the simplest to implement, but a bit of knowledge of the Excel Object Model goes a long way, so here's how to implement your solution with ActiveX in one loop:
e = actxserver('excel.application');
w = e.Application.Workbooks.Add();
numnewsheets = 4;
for i = 1:numnewsheets
w.Worksheets.Add([],w.Sheets.Item(w.Sheets.Count),1);
w.Worksheets.Item(i).Name = ['new_sheet_' num2str(i)];
w.Worksheets.Item(i).Cells.Range('A1:B2').Value = [1 2;3 4];
end
w.SaveAs(filename)
w.Close
e.Quit
e.delete
To calculate the range required for the size of your data, you will have to open file "xlswrite" and copy out the sub-function "calcrange".

Excel Graph to PowerPoint C++/CLI Exception from HRESULT: 0x800A03EC

I am trying to copy excel graphs and then pasting them into a PowerPoint using C++/CLI although I have run into difficulties when trying to use the Copy() method. Here is a simplified version of my code right now:
Worksheet = dynamic_cast<Excel::Worksheet^>(WS[3]);
chartObjects = dynamic_cast<Excel::ChartObjects^>(Worksheet->ChartObjects(paramMissing));
existingChartObject = dynamic_cast<Excel::ChartObject^>(chartObjects->Item(2));
existingChartObject->Copy();
shapeRange = Slide->Shapes->Paste();
but when I try this it give me an error of:
An unhandled exception of type 'System.NullReferenceException' occurred in Excel To PPT.exe
Additional information: Object reference not set to an instance of an object.
Now my Excel workbook has 6 graphs on each sheet starting on sheet 3. And if I copy all the graphs on sheet 3 and past them onto a slide like this.
Call this attempt one
for(count = 1, count <= 6; ++count){
Worksheet = dynamic_cast<Excel::Worksheet^>(WS[2]);
chartObjects = dynamic_cast<Excel::ChartObjects^>(Worksheet->ChartObjects(paramMissing));
existingChartObject = dynamic_cast<Excel::ChartObject^>(chartObjects->Item(count));
existingChartObject->Copy();
shapeRange = Slide->Shapes->Paste();
}
Then there is no exception thrown. Now if I were try to do the same thing but start at graph 2 instead of 1 I get the exception thrown. Like this:
Call this attempt two
for(count = 2, count <= 6; ++count){
Worksheet = dynamic_cast<Excel::Worksheet^>(WS[2]);
chartObjects = dynamic_cast<Excel::ChartObjects^>(Worksheet->ChartObjects(paramMissing));
existingChartObject = dynamic_cast<Excel::ChartObject^>(chartObjects->Item(count));
existingChartObject->Copy();
shapeRange = Slide->Shapes->Paste();
}
When I step through it and I hover over existingCharObject on the second attempt it is not empty and looks the exact same as in attempt 1.
Why would the second attempt throw an exception but the first wouldn't? I should be able to copy any excel ChartObject I want? It is forcing me to start at ChartObject 1 in the whole workbook and work my way up and not allowing me to randomly copy ChartObjects.
Let me know if there is more information you need. I did not want to past my whole project into this, this is the only part of the project that is giving me issues.

Resources