I have an Excel File which I like to use to fill my parameter. The Excel file is an output so I don't want to change something on the formation of the file.
For my first parameter I want to import all values of the certain row in the Excel file. For example all values for all years of row 3. I already created a parameter as army with the years as dimension but doesn't know how to get the values in the best way. Maybe someone can help me.
Assume number of years equal to 30 and you have an array p[] with years as dimension:
for( int i = 0 ; i < 30 ; i++)
{
p[i] = excelFile.getCellNumericValue(1, 3, i + 3);
i++;
}
Related
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.
I know how to read in multiple Excel files, but am struggling to conduct the same analysis on all of those files. The analysis requires I average some values in different columns, then print those average values to a separate Excel sheet. I can do this with one Excel file, but have trouble figuring out how to print each average value in a different row in the output Excel file. Here is the code I have that works for one file (reads it, averages values in column 4, then prints to a separate Excel file):
data = xlsread('test_1.xlsx');
average_values_1 = data(:,4);
a = [average_values_1];
data_cells = num2cell(a);
column_header ={'Average Value 1'};
row_header(1,1) ={'File 1'}
output = [{' '} column_header; row_header data_cells];
xlswrite('Test Averages.xls', output);
How might I do this over and over again while printing values from each file in the output file as its own table? I suspect a nested loop is in my future.
Thanks in advance.
Here is working example of what you possibly want to do with xlswrite[1]:
filename = 'testdata.xlsx'; % Filename to save average values in
for k = 1:10 % Looping for 10 iterations
sheet = 2; % Selecting sheet2
Avg = randi([1 10],1,1); % Generating a random average each time the loop is run
xlRange = char(64+k); % 65 is the ASCII value of A
xlswrite(filename,Avg,sheet,xlRange); % Writing the excel file
end
This code gives the following output [2] :
Fig.1: Values are saved in a single row of excel file
If you want to get the output in a single column then use this xlRange = ['A',num2str(k)]; instead. It'll give you the following output [2] :
Fig.2: Values are saved in a single column of excel file
[1]: Read the documentation of xlswrite for more details.
[2]: Output values may vary since random integers are generated.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Counting values by day/hour with timeseries in MATLAB
This is an elementary question, but I cannot find it:
I have a 3000x25 character array:
2000-01-01T00:01:01+00:00
2000-01-01T00:01:02+00:00
2000-01-01T00:01:03+00:00
2000-01-01T00:01:04+00:00
These are obviously times. I want to reformat the array to be a 3000x1 array. How can I redefine each row to be one entry in an array?
(Again, this is simple, I'm sorry)
Other than converting to serial date numbers as other have shown, I think you simply wanted to convert to cell array of strings:
A = cellstr(c)
where c is the 3000x25 matrix of characters.
You need to specify a format for the array and feed it to datenum, like this:
>> d = datenum(c,'YYYY-MM-DDTHH:mm:ss')
d =
1.0e+005 *
7.3487
7.3487
7.3487
7.3487
The times are now stored as datenums, i.e. as floating point numbers representing the number of days elapsed since the start of the Matlab epoch. If you want to convert these to numbers representing the fraction of the day elapsed, you can do
>> t = d - fix(d);
and if you want the number of seconds since midnight, you can do
>> t = 86400 * (d - fix(d));
t =
61.0000
62.0000
63.0000
64.0000
I have a very rough workaround for 10 statements using a combination of 2 cells, as follows
Cell 1 (O2)
=IF(C2="TW2-OUT",VLOOKUP($D2,Players,8,FALSE)+VLOOKUP($D2,Players,9,FALSE),IF(C2="TW2-IN",IF($D2="","",VLOOKUP($D2,Players,10,FALSE)),IF(C2="Playing",IF($D2="","",VLOOKUP($D2,Players,8,FALSE)+VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE)),IF(C2="IN1OUT2",VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE),IF(C2="TW1-OUT",IF($D2="","",VLOOKUP($D2,Players,8,FALSE)),IF(C2="TW1-IN",IF($D2="","",VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE)),IF(C2="TW3-OUT",VLOOKUP($D2,Players,8,FALSE)+VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE),0)))))))+P2
Cell 2 (P2)
=IF(C2="TW3-IN",IF($D2="","",VLOOKUP($D2,Players,11,FALSE)),IF(C2="IN2OUT3",VLOOKUP($D2,Players,10,FALSE),IF(C2="IN1OUT3",VLOOKUP($D2,Players,9,FALSE)+VLOOKUP($D2,Players,10,FALSE),0)))
Is there a better way of doing this. I have read via a Google search about using a table approach with an array to achieve the same effect. However, in my case the status of a player determines the score of a player and this complicates things for me. Here are the 10 possible statuses (if statements) broken down as follows with how scored are calculated:
TransferStatuses Cols
Playing 8+9+10+11
TW1-IN 9+10
TW1-OUT 8
TW2-IN 10+11
TW2-OUT 8+9
TW3-IN 11
TW3-OUT 8+9+10
IN1OUT2 9
IN1OUT3 9+10
IN2OUT3 10
8 = ColK (Transfer Window 0)
9 = ColL(Transfer Window 1)
10 = ColM (Transfer Window 2)
11 = ColN(Transfer Window 3)
The 'score' array will be along the lines as follows:
=VLOOKUP(C2,$S$2:$T$11,2,FALSE)
The problem is that I don't know how to put it all together to make it work, i.e. I have to extend my formula to 300 cells but I don't know how to implement it so that the array calculates the scores correctly for each player?
Can someone help?
If I understand you correctly I would approach it like this:
Set up a matrix of binary values that specify, for each status, which columns should be added up. Use OFFSET and MATCH to look up the status for each data row and return the array/range of binary values, and SUMPRODUCT to sum it all up. See screenshot:
I have a 6x7 matrix(A) and some operation I'm doing on it for k=1:50 (number of loops).
I know that in order to write a single matrix in an excel file I need:
xlswrite('Filename.xls', A, 'A1')
How is it possible to write the information after each loop, in that way that each loop starts at position A1+((k-1)*6+1) in Excel and I have all results of Matrix(A) listed one after each other.
Thank you!
When using the XLSWRITE function, you can avoid having to compute Excel cell ranges each time, by specifying both sheet number and range, where range only gives the first cell to start at.
It is especially useful if the matrix changes size each iteration; we simply take the last cell used and shift it by the number of rows of the matrix.
Example:
offset = 1;
for i=1:5
%# generate different size matrices each loop
A = ones(randi(4),randi(4)).*i;
%# insert matrix in Excel inside the 1st sheet, starting at cell specifed
xlswrite('filename.xls', A, 1, sprintf('A%d',offset));
%# increment offset
offset = offset + size(A,1);
end
this creates an Excel file with the following content:
1 1
1 1
1 1
2 2 2 2
3 3
3 3
4
4
4
4
5 5 5
5 5 5
5 5 5
5 5 5
Note that a connection is made to Excel then closed each time XLSWRITE is called. This has a significant overhead.
A better approach would be to open Excel once, and reuse the same session to write all of your data, then close it once we are done. However, you will have to call the Office Interop functions yourself.
Since the trick I mentioned above won't work now, I will be using the "Calculate Excel Range" function to compute the cell ranges (there are many other implementations of FEX).
Here is the code (reusing some code from a previous answer):
%# output file name
fName = fullfile(pwd, 'file.xls');
%# create Excel COM Server
Excel = actxserver('Excel.Application');
Excel.Visible = true;
%# delete existing file
if exist(fName, 'file'), delete(fName); end
%# create new XLS file
wb = Excel.Workbooks.Add();
wb.Sheets.Item(1).Activate();
%# iterations
offset = 0;
for i=1:50
%# generate different size matrices each loop
A = ones(randi(4),randi(4)).*i;
%# calculate cell range to fit matrix (placed below previous one)
cellRange = xlcalcrange('A1', offset,0, size(A,1),size(A,2));
offset = offset + size(A,1);
%# insert matrix in sheet
Excel.Range(cellRange).Select();
Excel.Selection.Value = num2cell(A);
end
%# save XLS file
wb.SaveAs(fName,1);
wb.Close(false);
%# close Excel
Excel.Quit();
Excel.delete();
In fact, I ran both version with 50 iterations, and compared timings with TIC/TOC:
Elapsed time is 68.965848 seconds. %# calling XLSWRITE
Elapsed time is 2.221729 seconds. %# calling Excel COM directly
I think that xlswrite will overwrite an existing file, so you're better off gathering all the data, then writing it in one go. Also, writing it all in one go will be faster since it involves opening and closing Excel only once.
However, if you really want to write it in a loop, the following should work (assuming you mean going down):
range = sprintf('A%i:G%i', (k-1)*6+[1 6]);
xlswrite('Filename.xls', A, range);
Note that this won't adjust automatically if A changes size.