Gradient markup with Gspread Formatting - python

I am using Gspread Formatting to set background color to cells in Google Sheets.
Now I want to use the GradientRule to accomplish this:
Conditional formatting with GradientRule
I know I have to set a "minpoint" and a "maxpoint", but I am not sure how to do this.
This is what I got so far:
def color():
spr = client.open("Kleurtjes")
sheet = spr.worksheet("Tab3")
rule = ConditionalFormatRule(
ranges=[GridRange.from_a1_range('A1:A10', sheet)],
GradientRule=GradientRule(
minpoint(format=CellFormat(backgroundColor=Color(255,255,255)), type='number'),
maxpoint(format=CellFormat(backgroundColor=Color(0,128,0)), type='number')
)
)
rules = get_conditional_format_rules(sheet)
rules.append(rule)
rules.save()
Can you help me out?
Many thanks in advance!

I believe your goal as follows.
You want to achieve the following situation. (The image is from your question.)
Modification points:
You can see the script of GradientRule() and InterpolationPoint() at here and here, respectively.
At ConditionalFormatRule(), it seems that the AddConditionalFormatRuleRequest of the batchUpdate method in Sheets API is used. In this case, the color is required to be set from 0 to 1. Please be careful this.
When above points are reflected to your script, it becomes as follows.
Modified script:
Please modify your script as follows.
From:
rule = ConditionalFormatRule(
ranges=[GridRange.from_a1_range('A1:A10', sheet)],
GradientRule=GradientRule(
minpoint(format=CellFormat(backgroundColor=Color(255,255,255)), type='number'),
maxpoint(format=CellFormat(backgroundColor=Color(0,128,0)), type='number')
)
)
To:
rule = ConditionalFormatRule(
ranges=[GridRange.from_a1_range('A1:A10', sheet)],
gradientRule=GradientRule(
maxpoint=InterpolationPoint(color=Color(1, 1, 1), type='MAX'),
minpoint=InterpolationPoint(color=Color(0, 128 / 255, 0), type='MIN')
)
)
Note:
In this modification, it supposes that you have already been able to get and put values for Google Spreadsheet by using Sheets API with gspread and gspread_formatting. Please be careful this.
When you want to achieve the colors of above your image, for example, how about minpoint=InterpolationPoint(color=Color(0.34117648, 0.73333335, 0.5411765), type='MIN')?
References:
AddConditionalFormatRuleRequest
Color
gspread-formatting

Related

How to update Span (Bokeh) using ColumnDataSource?

I am trying to update Span using ColumnDataSource, but the information is not being passed onto the source. Span unfortunately does not have a paremeter "source", so is there a better way?
I have defined my sources, figure and line like so:
m1_source = ColumnDataSource(data=dict(x1=[], y1=[]))
m1_spans = ColumnDataSource(data=dict(x1=[]))
p = figure(x_axis_type="datetime", title="", sizing_mode="fixed", height = 500, width = 1400)
p.line(x ="x1", y="y1", color = 'blue', source=m1_source)
Then I have a for loop that should ideally plot multiple spans, each 'i' will be a separate timestamp:
for i in m1_spans.data['x1']:
p.add_layout(Span(location=i, dimension='height', line_color='red', line_dash='solid', line_width=1))
This is taken from my update() function:
m1_source.data = dict(
x1=machine_1_vals['mpTimestamp'],
y1=machine_1_vals['Value'])
m1_spans.data = dict( x1=ToolsDF.loc[ToolsDF['Value'] == float(vals['Tool_val'])]['Timestamp'])
I have checked this, and m1_spans does successfully return multiple timestamps, so the error shouldn't be here.
The reason I am confused, is because my p.line will successfully update with no issues, but it does have a source parameter, while span does not.
I would be really appreciative for any advice about how to solve this issue.
If I should have supplied more information, I apologize and can update as needed, I just tried to keep it brief for you.
Thanks.
Span objects do not currently have an ability to be "powered" by a ColumnDataSource. Each Span only draws one span, specified by its own location property.
You will need to update the location property individually on each Span object in order to update it. Alternatively, if you absolutely want to be able to drive updates through a CDS, you could look at using a multi_line, segment, or ray glyph instead. Those all have different ways to configure their coordinates, so you'd have to see which is most convenient to your use-case. But they all come with one trade-off, which is that none of them have the full "infinite extent" that a Span supports.

How to clear a range in google sheet via gspread

Hi I would like to clear a range of A3:J10000 in google sheet by using gspread.
Doing a loop like this takes too much time:
for cell in range_to_clear:
cell.value=''
sh.worksheet('WorksheetX').update_cells(range_to_clear,value_input_option='USER_ENTERED')
I found the values_clear() method but wasn't able to make it working:
range_2_delete = sh.worksheet("WorksheetX").range("A3:J10000")
sh.values_clear(range_2_delete)
The above code giving this error: AttributeError: 'list' object has no attribute 'encode'
You want to clear the values of range on Google Spreadsheet.
You want to achieve this using gspread with python.
You have already been able to put and get values for Spreadsheet using Sheets API.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
I think that the method of values_clear() can be used for your situation.
Modified script:
Please modify your script as follows.
From:
range_2_delete = sh.worksheet("WorksheetX").range("A3:J10000")
sh.values_clear(range_2_delete)
To:
sh.values_clear("WorksheetX!A3:J10000")
or
sh.values_clear("'WorksheetX'!A3:J10000")
Note:
This answer supposes as follows.
The latest version (v3.1.0) of gspread is used.
sh is declared. If sh is not declared, please use sh = gc.open('My poor gym results') and sh = client.open_by_key(spreadsheetId). Ref
Reference:
values_clear(range)
If this was not the result you want, I apologize.
You should try re-writing the code as follows:
range_2_delete = sh.worksheet("WorksheetX").range("A3:J10000")
values_clear(range_2_delete)

Chart objects in xlwings

The code snippet came from the official documentation of xlwings here and it is the setup for my question.
import xlwings as xw
sht = xw.Book().sheets[0]
sht.range('A1').value = [['Foo1', 'Foo2'], [1, 2]]
chart = sht.charts.add()
chart.set_source_data(sht.range('A1').expand())
chart.chart_type = 'line'
chart.name
Running print(chart.api) outputs the tuple below.
(<xlwings._xlwindows.COMRetryObjectWrapper at 0x1fcd60c9a90>, <xlwings._xlwindows.COMRetryObjectWrapper at 0x1fcd60c9f28>)
If I want to use the api attribute to do some basic chart manipulation like remove the legend and add a title, it only works if I do it to chart.api[1]. For instance the code below works fine. It removes the chart legend and adds a title.
chart.api[1].HasLegend = 0
chart.api[1].SetElement(2)
chart.api[1].ChartTitle.Text = 'A title'
However, anything I do to chart.api[0] yields an error, (for instance print(chart.api[0].HasLegend) yields an error). I can't understand what kind of object this is or how it is useful. I can't find anything regarding this in the official documentation.
Finally my question is: what is the object at the index 0 above? Please, help me grok what it is.
There is another post that addresses your question about the object at the index 0.
set chart name in Xlwings
The expression chart.api returns a tuple with two COM wrappers. I'm
not really sure why there are two COM wrappers, but it seems that you
need the second one to access the chart. Hence the use of chart.api[1]
here.

Style Normal exists already - Python - OpenPyxl

I have looked into many stackoverflow questions but none of them seemed to solve my problem. I am using Python and Openpyxl to fill a whole row with red given a certain condition. I did all the importations necessary :
from openpyxl.styles import PatternFill, NamedStyle, Color
from openpyxl.styles.colors import RED
And my code is the following :
for cell in sheet[i]:
cell.style = NamedStyle(fill=PatternFill(patternType='solid',
fill_type='solid',
fgColor=Color(RED)))
When I ask to print the first occurence of cell it gives me
<Cell 'Divers'.A4>
which is what I am looking for.
However, the following error comes every time : "Style Normal exists already". There is absolutely no cell formatting or style whatsoever in the rest of the code but the Excel file cells are indeed filled with yellow already.
Any idea on how to solve this ? Thanks in advance for any help.
If using a NamedStyle, you're required to pass a name.
red_foreground = NamedStyle(
name="RedForeground",
fill=PatternFill(
patternType='solid',
fill_type='solid',
fgColor=Color(RED)
)
)
Since you're assigning this NamedStyle to more than one cell, it makes sense to register it to your workbook.
wb.add_named_style(red_foreground)
Then you can update it's application to cells, like so:
for cell in sheet[i]:
cell.style = "RedForeground"
Reference:
Creating NamedStyle
NamedStyle Constructor
I also have this problem, and finally found that it was because there were 2 styles, of which had the same name. This is usually caused when you use copy.copy(style). Then after change one of the style.name = 'newname', it will work.
This code would solve already existing named styles.
for index,cur_style in enumerate(excel_workbook._named_styles):
if cur_style.name == 'my_new_style':
excel_workbook._named_styles[index] = my_new_style
my_new_style.bind(excel_workbook)
break
else:
excel_workbook.add_named_style(my_new_style)
However, in your case, you should use some other name than "Normal", because "Normal" is the default named style, just find another name and you can use the code I pasted
There is another way to solve traceback by adding existing styles:
if not 'Style_A' in wb.named_styles:
wb.add_named_style(Style_A)

Python help: Paths in gmplot

I can’t find any documentation on using paths in gmplot. I came up with this code which gets close, but it connects all of the lines and fills it in with a color - I don't want that.
I simply want a path like this:
http://imgur.com/3iaC2NQ
But, what I’m getting is this:
http://imgur.com/ypXEqof
Heres’s my code:
pathlon = -117.2974695,-117.2980671,-117.2984607,-117.2979182,-117.2974082,-117.2966604,-117.2977518,-117.2987498,-117.2981491,-117.297708,-117.2972804,-117.2965301,-117.2979485,-117.2975028,-117.2980506,-117.2982983,-117.2976609,-117.2970861,-117.2969908,-117.2981731,-117.2987695,-117.2981146,-117.2976909,-117.2969674,-117.2969299,-117.298394
pathlat = 33.27172039,33.27197757,33.27217535,33.27225324,33.27218351,33.27233921,33.27242614,33.27248971,33.27268346,33.27265944,33.27263664,33.27279608,33.27281652,33.27194103,33.27176546,33.27224514,33.27222714,33.27208829,33.27237357,33.27243373,33.27262189,33.27268296,33.27265933,33.27262125,33.27282274,33.27283925
gmap = gmplot.GoogleMapPlotter(pathlat[0],pathlon[0],18)
gmap.polygon(pathlat,pathlon,edge_color="cyan", edge_width=5, face_color=None, face_alpha=None, clickable = False)
gmap.draw('map.html')
Hoping someone can point me in the right direction.
Thanks in advance!
Since you are using polygon, this is the expected consequence. You should use plot method.
Please see following part;
pathlon = -117.2974695,-117.2980671,-117.2984607,-117.2979182,-117.2974082,-117.2966604,-117.2977518,-117.2987498,-117.2981491,-117.297708,-117.2972804,-117.2965301,-117.2979485,-117.2975028,-117.2980506,-117.2982983,-117.2976609,-117.2970861,-117.2969908,-117.2981731,-117.2987695,-117.2981146,-117.2976909,-117.2969674,-117.2969299,-117.298394
pathlat = 33.27172039,33.27197757,33.27217535,33.27225324,33.27218351,33.27233921,33.27242614,33.27248971,33.27268346,33.27265944,33.27263664,33.27279608,33.27281652,33.27194103,33.27176546,33.27224514,33.27222714,33.27208829,33.27237357,33.27243373,33.27262189,33.27268296,33.27265933,33.27262125,33.27282274,33.27283925
gmap = gmplot.GoogleMapPlotter(pathlat[0],pathlon[0],18)
gmap.plot(pathlat,pathlon,'cornflowerblue', edge_width=10)
gmap.draw('map.html')

Categories