Ruby WIN32OLE excel chart seriescollection values - ruby

I am trying to change the values of an Excel (actually PowerPoint) chart.
I tried doing this by passing an array but it doesn't seem to work.
Although as mentioned on this page it should work...: http://msdn.microsoft.com/en-us/library/office/ff746833.aspx
So how does my code looks like at the moment:
require 'win32ole'
mspp_app = WIN32OLE.new("Powerpoint.Application")
mspp = mspp_app.Presentations.Open(pathToFile)
slide = mspp.Slides(1)
shapes = slide.shapes
chartshape = shapes(3) #the chart happens to be shape n°3
chart = chartshape.chart
# now get the seriescollection
sc = chart.SeriesCollection
sc3 = sc.Item(3)
values = sc3.values #returns the current values as an array example: [1.0, 1.0, 5.0, 2.0]
# now set the values
sc3.values = [2.0, 2.0, 5.0, 1.0] # returns no error
# see if the values are set
values = sc3.values # returns an empty Array []
Anyone tried this before?

For manipulating the diagram data you have to change the underlying worksheet:
ws = myChart.Chart.ChartData.Workbook.Worksheets(1)
ws.Range("A2").Value = "Coffee"
ws.Range("A3").Value = "Soda"
ws.Range("A4").Value = "Tea"
ws.Range("A5").Value = "Water"
ws.Range("B1").Value = "Amount" # used as label for legend
ws.Range("B2").Value = "1000"
ws.Range("B3").Value = "2500"
ws.Range("B4").Value = "4000"
ws.Range("B5").Value = "3000"
It is important to change the SourceData-Range if dimension has changed. Take care of the different notion known from Excel: "=Tabelle1!A1:B5" instead of "A1:B5".
For english office version change "Tabelle1" to "Sheet1"
myChart.Chart.SetSourceData("=Tabelle1!A1:B5")
myChart.Chart.ChartData.Workbook.Close
Don't forget to close the worksheet afterwards.

Related

Ruby axlsx pie chart title font size

I'm using the axslx ruby gem to create a spreadsheet with a pie chart. For the most part it is very straightforward and I've had no problems with one exception: I can't figure out how to set the font size for the title in the pie chart. I've read through the documentation and examples and found no mention of it. I'm sure I have overlooked it but if anyone knows how to do that, I would appreciate any help.
thanks!
adding code ... sorry, should have provided this initially
issue_sheet.add_chart(Axlsx::Pie3DChart, start_at: 'I3', end_at: 'S32') do |chart|
chart.add_series data: issue_sheet['G3:G7'], labels: issue_sheet['F3:F7'], colors: ['9467BD','D62828','EF7E12','82BBDD','3AA02B']
chart.title = "Distribution by Severity"
chart.d_lbls.show_val = false
chart.d_lbls.show_percent = true
chart.d_lbls.d_lbl_pos = :outEnd
chart.d_lbls.show_leader_lines = true
end
I did notice something interesting but I'm not sure what it means. If I use a cell reference rather than a string for the chart.title, the font size changes.
chart.title = "Distribution by Severity" # this sets the font size to 16
chart.title = issue_chart['F2'] # this sets the font size to 10
You can make use of sz property provided in this link
item_style = s.add_style :b => false, :sz => 9, :font_name => 'courier'
row = sheet.add_row [item.name, item.price], :style => item_style

How to set fixed width/height in Enaml grid container

I have just come across Enaml for python GUI programming. I only used PySide2 once before for a simple calculator GUI mockup, so I'm new to both Qt and Enaml. Forgive my ignorance ;)
Essentially, I want to have a regular grid of Field or other elements, with fixed, square sizes. After going over some of the examples, I came up with:
from enaml.layout.api import grid
from enaml.widgets.api import Window, Container, Field
enamldef DigitField(Field):
# The fields will contain a single digit for testing.
mask = 'D'
max_length = 1
# These don't have any effect?
hug_width = 'required'
hug_height = 'required'
enamldef Main(Window):
Container:
constraints = [
grid(
[f11, f12],
[f21, f22],
),
]
DigitField: f11:
text = '1'
DigitField: f12:
text = '1'
DigitField: f21:
text = '1'
DigitField: f22:
text = '1'
But the hug_width and hug_height don't seem to work. I then tried manually setting f11.width == 50, for example, inside the constraints, but the kiwisolver shouts at me about unresolvable constraints. I tried everything I could find from the examples about setting width values, but stuff that works for vbox doesn't seem to play with grid.
Any ideas? Also, if someone has a full app made with Enaml, that is open source, I would love to take a look. The docs are OK but some more advanced examples would be awesome.
Well, I think I have found a way to make it work. hug_width restricts width to the field content plus some default padding (from the Qt toolkit). Instead, using resist_width = 'ignore' I was able to completely remove the padding. The grid can be generated using a manual or an automatic method.
The manual method:
from enaml.layout.api import grid
from enaml.widgets.api import Window, Container, Field
enamldef DigitField(Field):
# The fields will contain a single digit for testing.
mask = 'D'
max_length = 1
resist_width = 'ignore'
resist_height = 'ignore'
enamldef Main(Window):
Container:
constraints = [
grid(
[f11, f12],
[f21, f22],
),
f11.width == f11.height,
f12.width == f12.height,
]
DigitField: f11:
text = '1'
DigitField: f12:
text = '1'
DigitField: f21:
text = '1'
DigitField: f22:
text = '1'
This is too WET and scales horribly, so instead we have...
The factory method:
from itertools import zip_longest
from enaml.core.api import Include
from enaml.layout.api import align, grid, factory
from enaml.widgets.api import Window, Container, Field
enamldef DigitField(Field):
mask = 'D'
max_length = 1
resist_width = 'ignore'
resist_height = 'ignore'
def generate_grid(container, num_cols):
rows = []
widgets = container.visible_widgets()
row_iters = (iter(widgets),) * num_cols
rows = list(zip_longest(*row_iters))
return [grid(*rows), align('width', *widgets)]
enamldef Main(Window):
Container:
Container:
constraints << [factory(generate_grid, 3)]
Include:
objects << [DigitField(text=str(1)) for i in range(9)]
I have nested the Container because there will probably be other things in the main window as well, and Enaml windows require a single master Container.

callback via taptool presents datatable

From what I can tell in my limited review of bokeh documentation the ability to click on a glyph on a plot then present a Dialog box or Datatable is a feature not yet available. I do not want the Datatable to be presented until a glyph has been selected. Would ideally like the ability to hide the Dialog or Datatable as well.
It seems that bokeh.models.widgets.dialog were deprecated sometime after 0.10.0. I could use that but its not available in python 3.7 at this point. Suggestions?
Some features are not officially supported but sometimes one can come up with a work-arounds like this one (tested on Bokeh v1.0.4):
from bokeh.plotting import figure, show
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider, DataTable, TableColumn, CustomJS
plot = figure(tools = 'tap')
source = ColumnDataSource(dict(x = list(range(6)), y = [x ** 2 for x in range(6)]))
circles = plot.circle('x', 'y', source = source, size = 20)
slider = Slider(start = -1, end = 5, value = 6, step = 1, title = "i", width = 300)
columns = [TableColumn(field = "x", title = "x"), TableColumn(field = "y", title = "x**2")]
table = DataTable(source = source, columns = columns, width = 320)
plot.js_on_event('tap', CustomJS(args = {'table': table, 'source': source, 'slider': slider}, code = '''
const selected_index = source.selected.indices[0]
if (selected_index != null)
table.height = 0;
else
table.height = slider.value * 25 + 25;'''))
callback_code = """ i = slider.value;
new_data = {"x": [0,1,2,3,4,5], "y": [0,1,4,9,16,25]}
table.source.data = new_data
table.height = i * 25 + 25; """
callback = CustomJS(args = dict(slider = slider, table = table), code = callback_code)
slider.js_on_change('value', callback)
show(column(slider, plot, table))
Result:

Different color for sorting in SSRS

I have a customer who would like some color formatting in an SSRS report. I cannot utilize grouping due to the customer requirements. I have the report sorting by Main Tank and would like the sorts to alternate in color. So it would have several rows of Tank A all be grey then several rows of Tank B all be white. I'm using this currently but it only works on the first row of each sort
=iif(
Fields!Tank.Value=previous(Fields!Tank.Value),
"Transparent",
"Red"
)
Any help would be great.
You can use custom code to get the required logic. Using a custom function in your code that returns the color based on the the Tank value.
Go to Report menu, Report Properties / Code tab and in the text area put this code:
Dim prevColor As String = "Transparent"
Public Function GetColor(ByVal flag As Integer) As String
If flag = 1 Then
If prevColor = "Transparent" Then
prevColor = "Gray"
Else
prevColor = "Transparent"
End If
End If
Return prevColor
End Function
Now in the cell background-color property use this expression:
=Code.GetColor(iif(Fields!Tank.Value=previous(Fields!Tank.Value),0,1))
It will color the background as below:
UPDATE: The above logic colors correctly only the first, third, fifth columns and so on. It is caused by multiple calls to the GetColor function and overwritting of the global variable prevColor.
I managed to solve that issue by passing the row number to the function. This is the updated function:
Dim prevColor As String = "Transparent"
Dim rowNum As Integer = 0
Public Function GetColor(ByVal flag As Integer, ByVal nRow As Integer) As String
If flag = 1 And rowNum <> nRow Then
If prevColor = "Transparent" Then
prevColor = "Gray"
Else
prevColor = "Transparent"
End If
End If
rowNum = nRow
Return prevColor
End Function
Note the function receives a new argument so the expression for calling has changed:
=Code.GetColor(iif(Fields!Tank.Value=previous(Fields!Tank.Value),0,1),
RowNumber("DataSet3"))
Replace "DataSet3" by the actual name of your dataset.
It should generate the following tablix:
Let me know if this helps.
I would handle this in your query by adding a column that returns a 0 or 1 to define the color - idea sketch: use rank to get numbers that correlate to the sort order and then use MOD 2 to get a 0 or 1. If you post a sample query, we can help figure out the specifics.

Figure window showing up matlab

I have written this code to help me compare different image histograms however when i run it i get a figure window popping up. I can't see anywhere in the code where i have written imshow and am really confused. Can anyone see why? thanks
%ensure we start with an empty workspace
clear
myPath= 'C:\coursework\'; %#'
number_of_desired_results = 5; %top n results to return
images_path = strcat(myPath, 'fruitnveg');
images_file_names = dir(fullfile(images_path, '*.png'));
images = cell(length(images_file_names), 3);
number_of_images = length(images);
%textures contruction
%loop through all textures and store them
disp('Starting construction of search domain...');
for i = 1:length(images)
image = strcat(images_path, '\', images_file_names(i).name); %#'
%store image object of image
images{i, 1} = imread(image);
%store histogram of image
images{i, 2} = imhist(rgb2ind(images{i, 1}, colormap(colorcube(256))));
%store name of image
images{i, 3} = images_file_names(i).name;
disp(strcat({'Loaded image '}, num2str(i)));
end
disp('Construction of search domain done');
%load the three example images
RGB1 = imread('C:\coursework\examples\salmon.jpg');
X1 = rgb2ind(RGB1,colormap(colorcube(256)));
example1 = imhist(X1);
RGB2 = imread('C:\coursework\examples\eggs.jpg');
X2 = rgb2ind(RGB2,colormap(colorcube(256)));
example2 = imhist(X2);
RGB3 = imread('C:\coursework\examples\steak.jpg');
X3 = rgb2ind(RGB3,colormap(colorcube(256)));
example3 = imhist(X3);
disp('three examples loaded');
disp('compare examples to loaded fruit images');
results = cell(length(images), 2);
results2 = cell(length(images), 2);
results3 = cell(length(images), 2);
for i = 1:length(images)
results{i,1} = images{i,3};
results{i,2} = hi(example1,images{i, 2});
end
results = flipdim(sortrows(results,2),1);
for i = 1:length(images)
results2{i,1} = images{i,3};
results2{i,2} = hi(example2,images{i, 2});
end
results2 = flipdim(sortrows(results2,2),1);
for i = 1:length(images)
results3{i,1} = images{i,3};
results3{i,2} = hi(example3,images{i, 2});
end
results3 = flipdim(sortrows(results3,2),1);
The colormap function sets the current figure's colormap, if there is no figure one is created.
The second parameter of imhist should be the number of bins used in the histogram, not the colormap.
Run your code in the Matlab debugger, step through it line by line, and see when the figure window pops up. That'll tell you what's creating it.
Etienne's answer is right for why you're getting a figure, but I'd just like to add that colormap is unnecessary in this code:
images{i, 2} = imhist(rgb2ind(images{i, 1}, colormap(colorcube(256))));
All you need is:
images{i, 2} = imhist(rgb2ind(images{i, 1}, colorcube(256)));
The second input of rgb2ind should be a colormap, yes. But the output of colorcube is a colormap already. Unless you've got an existing figure and you either want to set the colormap of it or retrieve the colormap it is currently using, the actual function colormap is not necessary.
Other than opening an unnecessary figure, the output of your existing code won't be wrong, as I think in this situation colormap will just pass as an output argument the colormap it was given as an input argument. For example, if you want to set the current figure colormap to one of the inbuilts and return the actual colormap:
cmap = colormap('bone');

Resources