MatLab: Iterating dynamically through Cells with Excel COM Add-In - excel

First of all thanks a lot, for very good answers that I have found here in other topics in the past.
Now to a new challenge:
I am currently working with the COM Add-In in Matlab, i.e. I am reading a Excel Workbook and extracting the Color Property:
excelapp = actxserver('Excel.Application'); %connect to excel
workbook = excelapp.Workbooks.Open('Solutions.xls');
worksheet = workbook.Sheets.Item(1);
ColorValue_Solutions=worksheet.Range('N2').Interior.Color;
Now, I want to do this for cells in the Range A1 up to J222, for which I would like to dynmaically loop through the Range property, letting the programm read each cell individually and then taking out the color proerty. For example:
Columns = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
for j = 1:length(Columns)
for i = 1:222
worksheet.(char( strcat('Range(''',Columns(j), num2str(i), ''')') )).Interior.Color
end
end
This, however, results in an error:
Undefined function or variable 'Range('A1')'.
I guess the problem is in the combination of interpreting a string with an included string, i.e. Range('A1').
Any help is much appreciated.

Some time ago I asked a similar question. Check it out, maybe you will find it helpful.
The following code should do what you want:
You can see how the Interior.Color property is extracted from every cell by first getting a Cell object, then accessing the Interior object of that Cell and finally getting the Color property of that Interior object. The Color property is a color integer defined by Microsoft (you can learn more here and here), I store that value in a matrix (M). In order to repeat this process through the specified range of cells, I use a nested loop, like you were doing already. Once the process is finished, I display the contents of M.
excelapp = actxserver('Excel.Application'); % Start Excel as ActiveX server.
workbook = excelapp.Workbooks.Open('Solutions.xls'); % Open Excel workbook.
worksheet = workbook.Sheets.Item(1); % Get the sheet object (sheet #1).
ncols = 10; % From column A to J.
nrows = 222; % From row 1 to 222.
M(nrows, ncols) = 0; % Preallocate matrix M.
for col = 1:ncols % Loop through every column.
for row = 1:nrows % Loop through every row.
cell = get(worksheet, 'Cells', row, col); % Get the cell object.
interior = cell.Interior; % Get the interior object.
colorint = get(interior, 'Color'); % Get the color integer property.
M(row, col) = colorint; % Store color integer in matrix M.
end
end
disp(M); % Display matrix M with the color integer information.
Remember to close the connection when you are finished. You can learn how to do it here and here.

Related

C++ Excel Automation : How to use SetFormula function for the cell elements whose row & column were unknown but will be given by the program later on?

I am working on the heritage codes which use C++ Excel Automation to output our analysis data in the excel spreadsheet. From the following article,
https://support.microsoft.com/en-us/topic/how-to-use-mfc-to-automate-excel-and-create-and-format-a-new-workbook-6f2450bc-ba35-a36a-df2f-c9dd53d7aef1
I knew we can use "range.SetFormula() function to calculate the formula results from some specific cells, for example:
range = sheet.GetRange(COleVariant("C2"), COleVariant("C6"));
range.SetFormula(COleVariant("=A2 & \" \" & B2"));
My question here is how can I use SetFormula function to point to some cell elements whose row & column are unknow but will be determined as the program runs. In specifically, I have a number of cell elements populated as my analysis runs. Different analysis will have different number of elements output to the excel spreadsheet. For example, if I have kw data, then the excel output will be populated in kw row 6 column and I also need to output some summary results based on these element underneath these populated elements. Something like this:
int kw = var_length; // the row changes depending on different analysis
DWORD numElements[2];
Range range;
range = sheet.GetRange(COleVariant(_T("A3")),COleVariant(_T("A3")));
numElements[0]= kw; //Number of rows in the range.
numElements[1]= 6; //Number of columns in the range.
saRet.Create(VT_R8, 2, numElements);
for(int iRow = 0;iRow < kw; iRow++)
{
for (iCol = 0; iCol < 6; iCol++)
{
index[0] = iRow;
index[1] = iCol;
saRet.PutElement(index, &somevalue);
}
}
range.SetValue2(COleVariant(saRet));
CString TStr;
TStr.Format(_T("A%d"), kw+2);
range = sheet.GetRange(COleVariant(TStr), COleVariant(TStr))
CString t1, t2;
t1.Format(_T("A%d"), kw/2);
t2.Format(_T("A%d"), kw);
range.SetFormula(COleVariant(L"=SUM(A&t1: A&t2)")); // Calculate the sum of second half of whole elements, Apparently, this didn't work, How can I fix this?
Here I want to sum the second half of whole elements but in the SetFormula function, I didn't know exactly row number for these element, eg, A25 - A50. The row number is dependent on the kw which is given as input from program. Different analysis, kw is different. I attempted to use TStr format to get the row number but it CAN NOT be used inside SetFormula function. Ideally I want to use formula for my summary data output so that if I change my populated the element values, the summary data output can change accordingly. I searched in your MSDN website but couldn't find any solution on how to resolve this.
Can someone help me with the issue?
Thanks in advance.

Average Excel Columns

I am trying to average out values within a column at a certain range. I tried listing out the range as a tuple then for looping to be able to get the cell value. I then created a variable for the average but get the error 'TypeError: 'float' object is not iterable.
range1 = ws["A2":"A6]
for cell in range1:
for x in cell:
average = sum(x.value)/len(x.value)
print(average)
Python and the Openpyxl API makes this kind of thing very easy.
rows = ws.iter_rows(min_row=2, max_row=6, max_col=1, values_only=True)
values = [row[0] for row in rows]
avg = sum(values) / len(values)
But you should probably check that the cells contain numbers, otherwise you'll see an exception.
Something like this will get you the mean of the cells.
import openpyxl as op
def main():
wb = op.load_workbook(filename='C:\\Users\\####\\Desktop\\SO nonsense\\Book1.xlsm')
range1 = wb['Sheet1']['A2:A6']
cellsum = 0
for i, cell in enumerate(range1, 1):
print(i)
cellsum += cell[0].value
print(cellsum / i)
main()

Background color for excel file with Pandas: problem with single column boundaries (for outliers)

I need to export an excel where the outliers of my dataset are highlighted in yellow. As you know, calculated with upper bound and lower bound.
I've managed to set up the function, I just can't get it to work in an iterated way so the bounds are for each column.
When I export the dataframe into an excel file, it colours the cells based on the outliers of only one variable. It doesn't work in iterated mode.
Here my code, where am I wrong?
Here I just calculate for each column the lower and the upper bound (except for Subject ID)
for col in dfm.columns.difference(['Sbj']):
Q1c = dfm[col].quantile(0.25)
Q3c = dfm[col].quantile(0.75)
IQRc = Q3 - Q1
lowc = Q1-1.5*IQR
uppc = Q3+1.5*IQR
I set the function to colour the single value based on the limit values (not iterated)
def color(v):
if v < lowc or v > uppc:
color = 'yellow'
return 'background-color: %s' % color
apply the function iteratively for each column
for col in dfm.columns.difference(['Sbj']):
df_colored = dfm.style.applymap(color)
It is obvious that something is wrong with the iteration.
Many thanks!!

How to un-select cells in Excel? Using Matlab to create a chart adds graph with value of makred area

Excel 2016 remembers the cells you "marked" (selected) last before closing the file and the same asrea will be marked at the next opening of the file.
The only way to not mark an area is an untouched file created by for example Matlab.
How to unmark all areas in Excel using Matlab?
In my program (code below) I access an existing Excel File using Matlab. The code creates a new chart with set range.
Unfortunately there are always created more graphs in the chart and selecet in range. To be more percise thge area slected in an matlab file will be added as a new graph. (when it's empty an empty graph will be added anyway)
here you can see the marked area:
which then after running the code will be added as a graph with exactly the range of the marked are:
original program with code and info for understanding the project:
Original goals:
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)
General problems:
untouched files work
at every other file additional graphs are added always
Code:
% Start Excel and open workbook
Excel = actxserver('Excel.Application');
WB = Excel.Workbooks.Open('C:\...\test.xlsx');
%the workbook
Excel.visible = 1;
% Add chart
Chart = invoke(WB.Charts,'Add');
% Get Sheet object
SheetObj = Excel.Worksheets.get('Item', 'Tabelle1'); % 'Tabelle1' is german Ecel equation for 'sheet1'
%% FORMATTING %%
% Name chart sheet
Chart.Name = 'TestChart';
% Set chart type
Chart.ChartType = 'xlXYScatterSmoothNoMarkers';
% 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;
%% Set source data range of chart, do X and Y data for each series
columns = 3:7; % set columns 3 to 7 as Y-Values
%%
colnames = {'xdata', 'my series 1', 'my series 2', 'my series 3','my series 4','my series 5','my series 6', 'my series 7', 'my series 8','my series 9'};
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 A as X-Value
%% Set column name
Srs.Name = colnames{col};
end
What the code does:
When it works, a new chart is created, that has column A as X-Value and column 3 to 7 as Y-Values with the colnames of the column.
When it doesn't work, it does the same things as it does, when it works but adds more graphs to chart. Tp be exact it adds every column of the file as Y-Value with no X-Value (so 1,2,3,4...), using the first row as their names.
Summary of the question
is there a way to unmark, unselect areas in Excel using Matlab code?
do you know where the problem comes from
any helpful solutions
I found myself a solution. Or more of a way around this problem.
So again: The problem is, that the preselected cells will automacly show in your chart even before you selected your own data and X- and Y-Values.
Solution:
clear the chart between the steps of automatic graph creation and selection of your own data
to do so you just nee to place this one-liner after SheetObj = Excel.Worksheets.get('Item', 'Tabelle1');:
%% Clear content
Chart.ChartArea.ClearContents;
so your chart will be empty before you select the data to fill it.
This worked for me... Hope it helps you, too.

Read out Excel cell with mixed text color using Matlab

I have troubles to read out the font information of an Excel cell containing text of mixed color with Matlab using ActiveX.
Take as an example an excel file with the string "GreenBlueRedBlack" in cell A1 with respective parts of the string in stated color.
MyExcel = actxserver('Excel.Application');
Workbook = MyExcel.Workbooks.Open('D:\data\Test.xlsx');
MySheet = MyExcel.ActiveWorkBook.Sheets.Item(1);
Text=get(MySheet.Range('A1').Characters,'Text');
Color=MySheet.Range('A1').Characters.Font.Color; % provides NaN
for m=1:size(Text,2) % read out letters seperately
Color(m)=MySheet.Range('A1').Characters(m,1).Font.Color;
end
The code of course provides NaN when indexing to the whole cell.
I am unable to find a way to correctly subindex and loop through each letter in the cell.
If I understood correctly Characters(x,y) should be fed with startpoint and length of the wanted subpart of the cell. But Characters(1,1) only returns NaN and Characters(2,1) as well as Characters(1,2) exceeds the matrix dimensions.
How does subindexing to a substring of a cell work?
Thank you.
I found a workaround, maybe somebody can benefit from it.
Add following Code into the Module1 of the Excel file.
Public Function getCellInfo(Row As Variant, Col As Variant, Sheet As Variant)
ActiveWorkbook.Sheets(Sheet).Activate
Text = Cells(Col)(Row).Text
TextLength = Len(Cells(Col)(Row))
Dim Color() As Variant
ReDim Color(TextLength)
For m = 0 To TextLength - 1
Color(m) = Cells(Col)(Row).Characters(m + 1, 1).Font.Color
Next
getCellInfo = Color
End Function
Then call the macro from Matlab using:
ColorVector=MyExcel.Run('getCellInfo',Sheet,Row,Col);
It's not very pretty though. If somebody knows a more elegant way without calling an excel macro that would be awesome.
Maybe too late, but this is the solution :
color = MySheet.Range('A1').get('Characters', start, length).Font.Color;

Resources