Importing a list from excel, but having trouble splitting it into 4 columns - excel

I know this is very basic, but I have been using Python for 2 weeks now and banging my head against the wall trying to fix this. I have checked almost every single thread in here and tried to make sense of the Python 2.7 documentation and also researched whatever excerpts from Programming with Win32 by Hammod I could find.
Below is a section of my code. I am pulling in a named range from excel into a Python Gui. The data comes into row=4, column=1 as I coded it. The problem is I need to parse this named range so that the range (which is four float points) is split amongst row=4 clomuns 1,2,3,4. I know this is basic. I wouldnt have posted if I could find the answer anywhere else. If someone could just point me in the right direction i would really appreciate it.
xl = win32com.client.Dispatch('excel.application')
wbs = xl.Workbooks
wb = wbs.Open('C:\Users\Owner\Desktop\AutoPrime.xls')
xl.visible = 1
xlSheet = xl.Sheets(1)
xlSheet.Range('Fronts').Value
#Frame
Ftreas = Frame(F, relief="groove", border=2)
Ftreas.pack(side="left")
lp2a = Label(Ftreas, text=xl.ActiveSheet.Range('Fronts').Value, justify='center')
lp2a.grid(row=4,column=1, sticky='EW')

While I have not worked with Phyton before, I know that your line xlSheet.Range('Fronts') will return a Range object. You can access individual cells of a Range object with the default property, e.g.:
rng = xlSheet.Range('Fronts')
val1 = rng(1, 1).Value
val2 = rng(2, 1).Value //this returns the cell in row 2/column 1 of the range
arr = rng.Cells //this will return a 4x1 array of values

Related

Excel VBA graph based on Series not working properly

I'm using the following VBA code in Excel in order to produce 2 graphs with a data picked up from the sheet and slightly elaborated. As I'm not using ranges directly for the graphs and need to use arrays for X and Y axes, I decided to go for Series. X has Date type and Y has Integer type. First it worked, but then the graphs started giving me wrong data, something random coming directly off the sheet. I suppose there could be something wrong in the way how the charts are declared. Here's the code, what could go wrong with it?
Dim crt1, crt2 As Chart
Dim sr1, sr2 As Series
ActiveSheet.Shapes.AddChart2(201, xlColumnClustered, 60, 50).Select
Set crt1 = ActiveChart
Set s1 = crt1.SeriesCollection.NewSeries()
sr1.Values = dataArray1
sr1.XValues = datesArray1
ActiveSheet.Shapes.AddChart2(332, xlLineMarkers).Select
Set crt2 = ActiveChart
Set s2 = crt2.SeriesCollection.NewSeries()
sr2.Values = dataArray2
sr2.XValues = datesArray2
This problem also persists when I comment the code for the second graph.
P.S. Excel says "Runtime error 424. Object required" underlining "sr1.Values = dataArray1" and then "sr1.XValues = datesArray1"

Creating an Excel Table with MATLAB

Since writing varying sized data ranges to a sheet seems to remove an Excel Table if the data range is larger than the existing Excel tables range, I want to create a Table in Excel every time I run the code. I'm currently having a fair bit of difficulty creating the tables. The code I have right now to try and create the ListObject:
eSheets = e.ActiveWorkbook.Sheets;
eSheet = eSheets.get('Item', j);
eSheet.Activate;
eSheet.Range(horzcat('A1:R',mat2str(size(obj,1)+1))).Select;
eSheet.Listobjects.Add;
eSheet.Listobjects.Item(1).TableStyle = 'TableStyleMedium2';
eSheet.ListObjects.Item(1).Name = tablename;
Any commentary or suggestions would be appreciated
I dont know about using eSheet in matlab but with the function
xlswrite(filename,A,sheet,xlRange)
you can also write your data from a matrix to an excel table http://de.mathworks.com/help/matlab/ref/xlswrite.html and with
[A,B] = xlsfinfo('foofoo.xlsx');
sheetValid = any(strcmp(B, 'foo2'));
you can also check if a table sheet already exist so that you wont override the old one and create a new one, as seen in https://de.mathworks.com/matlabcentral/answers/25848-how-to-check-existence-of-worksheet-in-excel-file
I am not sure if this is what you are looking for thougth
Alright, since the post got downvoted (not sure why...) I found my own answer with the help of some VBA forums and MATLAB Newsgroup. Here's what the final code looks like for anyone else that has issues:
e = actxserver('Excel.Application');
ewb = e.Workbooks.Open('Path/to/file');
eSheets = e.ActiveWorkbook.Sheets;
eSheet = eSheets.get('Item', j);
eSheet.Activate;
range = horzcat('A1:R',mat2str(size(obj,1)+1));
range_todelete = horzcat('A1:R',mat2str(size(obj,1)+300));
Range1 = eSheet.get('Range',range_todelete);
Range1.Value=[];
eSheet.Range(range).Select;
name = 'Table_Name';
try eSheet.ListObjects(name).Item(1).Delete
catch
end
eSheet.Listobjects.Add;
eSheet.ListObjects.Item(1).Name = name;
eSheet.ListObjects.Item(1).TableStyle = 'TableStyleMedium2';
Range = eSheet.get('Range',range);
Range.Value = cellarray;

LibreOffice Basic Ignoring “some” of my Type...End Type Definition

I'm using LibreOffice Version: 4.4.3.2 Build ID: 40m0(Build:2) Locale: en_AU
I have a Basic Module
At the top of this module before any sub or functions I have
Type InitHeadings
MySort_By As Integer
MyCharacter As Integer
MyInitiative As Integer
MyRolled As Integer
MyTotal As Integer
End Type
...
Global InitiativeColumn As New InitHeadings
But when I run a sub, set a breakpoint and 'watch' the InitiativeColumn Object only the first two fields are shown.
The rest of my code relevant to this struct as the documentation calls them is below. I don't reference it anywhere else. Can anyone tell me why the first two would work but not the rest? I have two other structs in this code and both also ignore the last three fields. Is this a Bug?
Sub Main
'Initialise Doc and Sheet Objects
Dim Doc As Object
Doc = ThisComponent
StatsSheet = Doc.Sheets.getByName("Stats")
InitiativeSheet = Doc.Sheets.getByName("Initiative")
CombatSheet = Doc.Sheets.getByName("Combat")
'LOAD HEADING NAMES
'Initiative Sheet
For Column = 0 to 25 'Columns A to Z
MyHeadingName = InitiativeSheet.getCellByPosition(Column,0).String
Select Case MyHeadingName
Case "Sort By"
InitiativeColumn.MySort_By = Column
Case "Character"
InitiativeColumn.MyCharacter = Column
Case "Initiative"
InitiativeColumn.MyInitiative = Column
Case "Rolled"
InitiativeColumn.MyRolled = Column
Case "Total"
InitiativeColumn.MyTotal = Column
End Select
Next Column
End Sub
Sub MyInitiativeButton
'Iterate over a range of cells:
For Row = 1 To 25 'Rows 2 to 26
'Column 3 is column D the "Rolled" column
InitiativeSheet.getCellByPosition(InitiativeColumn.MyRolled,Row).VALUE = Roledice(1,20,0)
Next Row
End Sub
It looks like a bug, and seems to have been reported here. The problem did not occur when I tested it in a newer version (LO 5.1.0.3).
This is only an issue for the debugger window. The values are still there:
Sub TestStructs
InitiativeColumn.MySort_By = 5
InitiativeColumn.MyCharacter = 5
InitiativeColumn.MyTotal = 5
InitiativeColumn.DoesntExist = 5
End Sub
This code works fine until the line InitiativeColumn.DoesntExist = 5, whereupon it crashes.
Now the Global problem that you mentioned in the comments is really a problem. Considering the standard programming advice that global variables are bad, I think it's wise to consider alternatives.
Instead of a subroutine, could you perhaps use a Function that returns InitiativeColumn? If not, then assigning the variable as you suggested seems a viable workaround. Personally for LO macros I prefer Python or Java since they have classes.

Working with Excel sheets in MATLAB

I need to import some Excel files in MATLAB and work on them. My problem is that each Excel file has 15 sheets and I don't know how to "number" each sheet so that I can make a loop or something similar (because I need to find the average on a certain column on each sheet).
I have already tried importing the data and building a loop but MATLAB registers the sheets as chars.
Use xlsinfo to get the sheet names, then use xlsread in a loop.
[status,sheets,xlFormat] = xlsfinfo(filename);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(filename,sheets{sheetindex});
data{sheetindex}=num; %keep for example the numeric data to process it later outside the loop.
end
I 've just remembered that i posted this question almost 2 years ago, and since I figured it out, I thought that posting the answer could prove useful to someone in the future.
So to recap; I needed to import a single column from 4 excel files, with each file containing 15 worksheets. The columns were of variable lengths. I figured out two ways to do this. The first one is by using the xlsread function with the following syntax.
for count_p = 1:2
a = sprintf('control_group_%d.xls',count_p);
[status,sheets,xlFormat] = xlsfinfo(a);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(a,sheets{sheetindex},'','basic');
data{sheetindex}=num;
FifthCol{count_p,sheetindex} = (data{sheetindex}(:,5));
end
end
for count_p = 3:4
a = sprintf('exercise_group_%d.xls',(count_p-2));
[status,sheets,xlFormat] = xlsfinfo(a);
for sheetindex=1:numel(sheets)
[num,txt,raw]=xlsread(a,sheets{sheetindex},'','basic');
data{sheetindex}=num;
FifthCol{count_p,sheetindex} = (data{sheetindex}(:,5));
end
end
The files where obviously named control_group_1, control_group_2 etc. I used the 'basic' input in xlsread, because I only needed the raw data from the files, and it proved to be much faster than using the full functionality of the function.
The second way to import the data, and the one that i ended up using, is building your own activeX server and running a single excelapplication on it. Xlsread "opens" and "closes" an activeX server each time it's called so it's rather time consuming (using the 'basic' input does not though). The code i used is the following.
Folder=cd(pwd); %getting the working directory
d = dir('*.xls'); %finding the xls files
N_File=numel(d); % Number of files
hexcel = actxserver ('Excel.Application'); %starting the activeX server
%and running an Excel
%Application on it
hexcel.DisplayAlerts = true;
for index = 1:N_File %Looping through the workbooks(xls files)
Wrkbk = hexcel.Workbooks.Open(fullfile(pwd, d(index).name)); %VBA
%functions
WorkName = Wrkbk.Name; %getting the workbook name %&commands
display(WorkName)
Sheets=Wrkbk.Sheets; %sheets handle
ShCo(index)=Wrkbk.Sheets.Count; %counting them for use in the next loop
for j = 1:ShCo(index) %looping through each sheet
itemm = hexcel.Sheets.Item(sprintf('sheet%d',j)); %VBA commands
itemm.Activate;
robj = itemm.Columns.End(4); %getting the column i needed
numrows = robj.row; %counting to the end of the column
dat_range = ['E1:E' num2str(numrows)]; %data range
rngObj = hexcel.Range(dat_range);
xldat{index, j} = cell2mat(rngObj.Value); %getting the data in a cell
end;
end
%invoke(hexcel);
Quit(hexcel);
delete(hexcel);

Excel VBA - Get chart data range

I want to add data to a bunch of existing charts. Assume that each chart has a different number of data series and that the location of the raw data is somewhere in the same workbook. Here's what I'm starting with:
For iChart = 1 To iCount
ActiveSheet.ChartObjects("Chart " & iChart).Activate
intSeries = 1
Do Until ActiveChart.SeriesCollection(intSeries).Name = ""
Set rXVal = ActiveChart.SeriesCollection(intSeries).XValues '<- Object Required error
Set rXVal = Range(rXVal, rXVal.End(xlDown))
Set rYVal = ActiveChart.SeriesCollection(intSeries).Values
Set rYVal = Range(rYVal, rYVal.End(xlDown))
ActiveChart.SeriesCollection(intSeries).XValues = rXVal
ActiveChart.SeriesCollection(intSeries).Values = rYVal
intSeries = intSeries + 1
Loop
Next iChart
I know that ActiveChart...XValues = rXVal works, but I'm getting an "Object Required" error on the Set rXVal = ActiveChart....XValues line. I'm assuming that since a range went in to define the data series, I can get that range back out again and then add to it.
UPDATE
To clarify things a little, I have accelerometers in 8 places and FFT software setup to record peak vibration response in 4 separate frequency bands. This yields 32 data points per sample. When exporting, the software spits out an Excel workbook with 4 sheets; one for each frequency band. Each sheet has the accelerometer names going across and sample numbers going down.
I have succeeded using this syntax:
Dim rXVal() As Variant
rXVal = ActiveChart.SeriesCollection(intSeries).XValues
UPDATE
In this case you get an array, because your given statement (ActiveChart.SeriesCollection(intSeries).XValues) is an array and not a range. This is what you see in Locals window if you dig into Series object of ActiveChart.SeriesCollection(intSeries):
(in my dummy data I have rows named r1, r2, r3, r4.)
What I want to say, XValues does not have any property which would indicate its occupied range.
If you actually need a range, I would suggest getting it from the formula property. And the way I would suggest is replacing your error causing line with this one:
Set rXVal = Range(Split(ActiveChart.SeriesCollection(intSeries).Formula, ",")(1))
Next, I see you trying to get the range for Values. Similarly, use this:
Set rYVal = Range(Split(ActiveChart.SeriesCollection(intSeries).Formula, ",")(2))
Another thing.
The following lines will cause you an error finally:
intSeries = 1
Do Until ActiveChart.SeriesCollection(intSeries).Name = ""
...some code...
intSeries = intSeries + 1
Loop
Do change them with:
For intSeries = 1 To ActiveChart.SeriesCollection.Count
...some code...
Next
Yet another thing.
Consider using With and End With, as you repeat a lot ActiveChart.SeriesCollection(intSeries). Then your code will be much more readable, as you would just skip this long line! Wouldn't that be awesome???
This works fine for me:
Dim rXVal() As Variant
Dim rXValMin, rXValMax As Double
rXVal = ActiveChart.SeriesCollection(intSeries).XValues
rXValMin = WorksheetFunction.Min(rXVal)
rXValMax = WorksheetFunction.Max(rXVal)

Resources