xlwings: set cell formatting from python on a Mac specifically - python

I'm trying to format font size, font color, horizontal alignment, border style/weight etc on a worksheet using python xlwings on a Mac. I know you'd have to use the missing features to do this type of editing on python but i don't know what API member functions to use in order to do these formatting on Mac. The ones for windows I can find everywhere; for example:
import xlwings
wb = xlwings.Book('checker_output.xlsx')
wb.sheets.add('sheet1')
sht = wb.sheets['sheet1']
sht.range('A3:A26').api.Font.Size = 15
would work on the windows API, but not on a mac. Any work around for this?

I found you can use .api to center / left / right align but this is on a PC, perhaps it can work on Mac as well.
Set the value of the HorizontalAlignment property of the cell to:
Center-aligned, we’d set HorizontalValue to -4108;
Right-aligned, we’d set HorizontalValue to -4152;
Left-aligned, we’d set HorizontalValue to -4131;
What it would look like:
import xlwings as xw
sht = xw.sheets.active
sht.range(f'$A1:$C5').api.HorizontalAlignment = -4131

Related

python appscript for macOS

I am trying to use python package appscript to control applications in my MacBook. Unfortunately I am really confused.
For example, I am trying to control one of my excel files. I want to get the position and scroll to certain roll. Here is my code
# -*- coding:utf-8 -*-
from appscript import *
file = app('Microsoft Excel').documents[u'test.csv']
position = file.window.left_position()
print position
The code is only trying to get the position but it is not working. I download the ASDictionary to check the command but I still can not fix it. Here is the screenshot of the command:
Thank you so much for your help.
Excel’s Apple event (“AppleScript”) support is atypical and quirky.
Avoid using documents; it doesn’t work correctly. Use workbooks instead.
Workbooks don’t have a window property. They do, however, have windows elements (since you can view a workbook in more than one window).
Corrected Python code:
wb = app('Microsoft Excel').workbooks[u'test.csv']
position = wb.windows[1].left_position()
print(position)
Or, in AppleScript:
tell application "Microsoft Excel"
tell workbook "test.csv"
get left position of window 1
end tell
end tell

PIL Custom Font Alternate Glyphs Not Utilized

I made a custom handwriting font and exported it to a .ttf file. The service I used, Caligriphr, allows for alternate glyphs for each character. When I type with the font in notepad, alternate glyphs display correctly. However, when I write text onto an image using PIL with the custom font, only one glyph is used
for each character. Below is my code to write on the image:
body = ""
with open('body.txt') as fin:
ls = fin.readlines()
for l in ls:
words = l.split(' ')
for word in words:
double = random.randint(1,2) == 2
if(double):
body += ' ' + word
else:
body += ' ' + word
image = Image.open('graph.jpg').convert("RGBA")
text = Image.new('RGBA', image.size, (255,255,255,0))
font = ImageFont.FreeTypeFont('Graphite.ttf', 100)
d = ImageDraw.Draw(text)
d.text(xy=offset, text=body, fill = (26,29,32, 230), font=font)
tilt = random.random() * 2
slt = text.rotate(tilt, expand=1)
sx, sy = slt.size
image.paste(slt, (0,0, sx, sy), slt)
image.save('sample.png')
Edit: showing code for how body string is constructed
Any help would be appreciated.
Alternate Glyphs Displayed in Notepad
PIL output not utilizing alternate glyphs
This may depend on whether you're using the original PIL library, or Pillow.
Getting contextual alternate glyphs in the drawn output requires that the rendering engine draw the string as an entire string (not character by character) and, while doing so, process certain data in the font that performs glyph substitutions from the default glyphs.
This data could be OpenType Layout tables in OpenType fonts, AAT tables in Apple TrueType fonts, or Graphite tables in Graphite fonts, depending on what the platform/library supports. Since you mention you got alternates in Notepad, that indicates that the font has OpenType Layout data.
Reading the Pillow ImageFont documentation, it doesn't give any indication as to whether it supports any of these font formats. However, looking at the Pillow project in Github, I see that [winbuild\config.py] pulls in Harfbuzz, and that would provide support for OpenType Layout data. So, it seems that Pillow ought to draw using the contextual alternate glyphs, though I don't know if anything is needed to trigger it. (In Notepad, it happens by default, but that's not true everywhere.)
If using Pillow, you might need to explicitly enable the Raqm layout engine when loading the font: "Raqm - A library for complex text layout" http://host-oman.github.io/libraqm/raqm-Raqm.html
This engine can be specified using the ImageFont.truetype() function:
font = ImageFont.truetype('Graphite.ttf', 100, layout_engine=ImageFont.LAYOUT_RAQM)
Docs: https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.truetype
Testing if Raqm is availble on your system:
>>> from PIL import features
>>> features.check('raqm')
True
If not available, on my Ubuntu 20 it installs via
$ sudo apt install libraqm0
Edit: It looks like you don't even have to specify the layout_engine parameter at all. On my system alternate glyphs are used as soon as I install the Raqm library, even without changing the code.

Customize font when using style sheet

I am using the 'ggplot' style sheet. Now, the style is great, except that I would like to specifically change the font style. Is that possible?
If found the documentation about customizing styles. However, I just want to change the font while keeping the rest of the style.
Also, does anyone know where to see the setting-details of each style (like font, figsize, etc.)?
plt.imshow(ori, vmin = 0, vmax = 300)
plt.style.use('ggplot')
plt.show()
Combining styles
I think that the most elegant is to combine styles.
For example, you could define your own font settings in mystyle.mplstyle (see below where to save it, and what it could look like). To get the ggplot style with your own font settings you would then only have to specify:
plt.style.use(['ggplot', 'mystyle'])
This solution is elegant, because it allows consistent application in all your plots and allows you to mix-and-match.
Where to save your custom style?
Taken from one of my own styles mystyle.mplstyle could have the following entries (you should customise to your need obviously):
font.family : serif
font.serif : CMU Serif
font.weight : bold
font.size : 18
text.usetex : true
Which you should save it matplotlib's configuration directory. For me this is ~/.matplotlib/stylelib/, but use
import matplotlib
matplotlib.get_configdir()
to find out what to use on your operating system. See documentation. You could also write a Python function to install in the right location.
Where to find existing styles?
Then the final part of your question. First, it is usefull to know that you can obtain a list with available styles using
import matplotlib.pyplot as plt
plt.style.available
See the documentation for a graphical representation.
How to inspect for example ggplot.mplstyle? I think that the best reference in matplotlib's source. You can also find the *.mplstyle files on your system. Where, however, depends on your operating system and installation. For me
find / -iname 'ggplot.mplstyle' 2>/dev/null
gives
/usr/local/lib/python3.7/site-packages/matplotlib/mpl-data/stylelib/ggplot.mplstyle
Or more generally you could search for all styles:
find / -iname '*.mplstyle' 2>/dev/null
For Windows I am not really an expert, but maybe the file-paths that were listed above give you a clue where to look.
Python script to install style in the right location
To install your custom styles in the right location, you could build a script that looks something like:
def copy_style():
import os
import matplotlib
# style definition(s)
styles = {}
styles['mystyle.mplstyle'] = '''
font.family : serif
'''
# write style definitions
# directory name where the styles are stored
dirname = os.path.abspath(os.path.join(matplotlib.get_configdir(), 'stylelib'))
# make directory if it does not yet exist
if not os.path.isdir(dirname): os.makedirs(dirname)
# write all styles
for fname, style in styles.items():
open(os.path.join(dirname, fname),'w').write(style)
Yes, it is possible. And you can do it either locally by passing the font to individual labels
font = {'fontname':'your font'}
plt.xlabel('xlabel', **hfont)
plt.ylabel('xlabel', **hfont)
or globally
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'your font'
Try rcParams
matplotlib.rcParams.update({'font.size': 12})
Read more matplotlib

How can I manipulate shapes (colors) in PowerPoint using Python and win32com.client?

As I've made slight progress with the problem at hand since i posted this question, I've found it necessary to split it in two parts to maintain clarity.
How can I manipulate shape colors in PowerPoint using Python and win32com.client?
How can I inspect com objects in Python using dir()?
1. Manipulate shape colors in PowerPoint using Python
There are some examples on how to edit PowerPoint slides using the pptx library here. However, I find it much easier to manipulate an active PowerPoint presentation using win32com.client as described here. Using an example from Microsoft Developer Network I've found that I can easily replicate parts of the functionality of this VBA snippet...
With ActivePresentation.Slides(1).Shapes(1)
With .TextFrame.TextRange.Font
.Size = 48
.Name = "Palatino"
.Bold = True
.Color.RGB = RGB(255, 127, 255)
End With
End With
...with this Python snippet:
import win32com.client
Application = win32com.client.Dispatch("PowerPoint.Application")
Presentation = Application.Activepresentation
slidenr = Presentation.Slides.Count
slide = Presentation.slides(slidenr)
shape1 = slide.Shapes.AddTextbox(Orientation=0x1,Left=100,Top=100,Width=100,Height=100)
shape1.TextFrame.TextRange.Text='Hello, world'
#Manipulate font size, name and boldness
shape1.TextFrame.TextRange.Font.Size=20
shape1.TextFrame.TextRange.Characters(1, 4).Font.Name = "Times New Roman"
shape1.TextFrame.TextRange.Font.Bold=True
Here I'm able to manipulate font size and name. I can also change the orientation of the textbox by changing
Orientation=0x1 to Orientation=0x5 in shape1 = slide.Shapes.AddTextbox(Orientation=0x1,Left=100,Top=100,Width=100,Height=100).
What seems impossible though, is editing the box or font color.
This does not work:
shape1.TextFrame.TextRange.Font.Color.RGB = RGB(255, 127, 255)
Error message:
I had high hopes to fix this by importing some RGB functionality following the information on pypi.python.org
But I'm having trouble here as well with pip install colour:
By now I'm a bit lost on all accounts, so any hints to ANY way of manipulating colors would be great!
2. Inspect objects in Python using dir()
In my attempts to manage those pesky colors, I started inspecting the output from dir(shape1.TextFrame), dir(shape1.TextFrame.Textrange) and so on.
To my disappointment, I could not find anything about colors, and not even Font, although Font is clearly accessible for manipulation.
So my second question is this: Is this not the way to inspect and manipulate these shapes at all? And how could I find the right object (or method?) to manipulate shape1 further? I have had a look at the PowerPoint objectmodel, but with little success.
Thank you for any suggestions!
You can recreate the Global VBA function easily in your python script
def RGB(red, green, blue):
assert 0 <= red <=255
assert 0 <= green <=255
assert 0 <= blue <=255
return red + (green << 8) + (blue << 16)
About your 2nd Question. The best place to learn about these objects is the Excel Macro Object Browser. When in Macro Editor, Press F2 and then filter for Powerpoint library. Then you can search and explore the object model just related to powerpoint

Openpyxl - Apply Borders to Cells

I am hoping someone can help me as I have been unable to figure this one out for myself unfortunately.
I am trying to put a thin border around a cell using openpyxl 2.3.3 and python 3.4. I have the following code:
from openpyxl.styles import Border
ws.cell('A1').border = Border(top = Side(border_style='thin', color='FF000000'),
right = Side(border_style='thin', color='FF000000'),
bottom = Side(border_style='thin', color='FF000000'),
left = Side(border_style='thin', color='FF000000'))
Oddly this is throwing the following error:
NameError: name 'Side' is not defined
I have looked at the official documentation here:
http://openpyxl.readthedocs.org/en/2.4/styles.html
http://openpyxl.readthedocs.org/en/2.4/_modules/openpyxl/styles/borders.html
I have also looked at the following articles with no luck:
https://bitbucket.org/openpyxl/openpyxl/issues/365/styling-merged-cells-isnt-working
Applying borders to a cell in OpenPyxl
Apply borders to all cells in a range with openpyxl
Apply Border To Range Of Cells Using Openpyxl
Is anyone able to help me out?
Thanks in advance,
Eamon
You haven't imported the Side object.
from openpyxl.styles import Border, Side

Categories