I googled for some code to create Visio documents via Python. I want to add shapes, and have hyperlinks. So that you can click on the shape, or preferably on the text inside the shape, and get to a URL.
import os
import win32com.client
from win32com.client import constants
appVisio = win32com.client.Dispatch("Visio.Application")
appVisio.Visible =1
doc = appVisio.Documents.Add("Basic Diagram.vst")
pagObj = doc.Pages.Item(1)
stnObj = appVisio.Documents("Basic Shapes.vss")
mastObj = stnObj.Masters("Rectangle")
shpObj1 = pagObj.Drop(mastObj, 4.25, 5.5)
shpObj1.Text = "This is some text."
shpObj2 = pagObj.Drop(mastObj, 2, 2)
shpObj2.Text = """This is some more text. {\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}"""
connectorMaster = appVisio.Application.ConnectorToolDataObject
connector = pagObj.Drop(connectorMaster, 0, 0)
connector.Cells("BeginX").GlueTo(shpObj1.Cells("PinX"))
connector.Cells("EndX").GlueTo(shpObj2.Cells("PinX"))
doc.SaveAs(r'C:\utils\MyDrawing.vsd')
doc.Close()
appVisio.Visible =0
appVisio.Quit()
The RTF link is ignored - I tried that. Visio can add hyperlinks in the UI. So... does anyone know how I can add a link via Python here?
Visio only supports links on a shape (rather than within the text itself). A shape has Hyperlinks collection of Hyperlink objects and so you can add as follows:
# shpObj2.Text = """This is some more text. {\field{\*\fldinst HYPERLINK "http://www.google.com/"}{\fldrslt http://www.google.com}}"""
shpObj2.Text = "This is a shape with multiple links."
shp2Hyperlink1 = shpObj2.Hyperlinks.Add()
shp2Hyperlink1.Name = "Google"
shp2Hyperlink1.Address = "http://www.google.com"
shp2Hyperlink2 = shpObj2.Hyperlinks.Add()
shp2Hyperlink2.Name = "BBC"
shp2Hyperlink2.Address = "http://www.bbc.co.uk"
Under the covers this is just writing cells into the ShapeSheet:
Related
I’m using this code to draw myself a server in visio:
import win32com.client as w32
visio = w32.Dispatch("visio.Application")
visio.Visible = 1
doc = visio.Documents.Add("Detailed Network Diagram.vst")
page = doc.Pages.Item(1)
page.name = "My drawing"
stn2 = visio.Documents("Servers.vss")
server = stn2.Masters("Server")
serv = page.Drop(server, 0, 0)
for ssh in serv.shapes:
ssh.Cells( 'Fillforegnd' ).FormulaForceU = 'RGB(255,0,0)'
And my problem is when I’m trying to fill the object with a color (instead of the regular server color) it doesn’t work.
Nothing really worked. I’m using python 3.8.
Try this code please
import win32com.client as w32
visio = w32.Dispatch("visio.Application")
visio.Visible = 1
doc = visio.activedocument
page = doc.pages(1)
page.name = "Mydrawing"
stn2 = visio.Documents(2)
server = stn2.Masters(2)
serv = page.Drop(server, 0, 0)
#iterate all sub-shapes into Serv-shape
for ssh in serv.shapes:
ssh.Cells( 'Fillforegnd' ).FormulaForceU = 'RGB(255,255,0)'
If you dont need iterate all sub-shapes, you can change only same of them
#iterate 2nd, 3rd and 4rd sub-shapes into Serv-shape #
for i in range (2,5):
ssh = serv.shapes(i)
# if you need get solid color for sub-shapes uncomment next line
# ssh.Cells('FillPattern').FormulaForceU = '1'
ssh.Cells('Fillforegnd').FormulaU = 'RGB(255,255,0)'
Code in my Jupyterlab notebook change only 3 sub-shapes, which i select and delete for demonstrate difference…
PS The user's problem was not in the code, but in the Visio sub-shapes, which did not want to inherit the color of the main shape. Because these sub-shapes had formulas that used functions like THEMEGUARD and similar to it in their cells.
I modified the shape from the built-in set of elements and the problem was solved…
PPS Solved! To remove the dependency on those sub-shapes, you need to change their Fillstyle to Normal. Just add new line of code ssh.FillStyle = 'Normal'.
Look at code ↓
import win32com.client as w32
visio = w32.Dispatch("visio.Application")
visio.Visible = 1
# create document based on Detailed Network Diagram template (use full path)
doc = visio.Documents.Add ("C:\Program Files\Microsoft Office\root\Office16\visio content\1033\dtlnet_m.vstx")
# use one of docked stencils
stn2 = visio.Documents("PERIPH_M.vssx")
# define 'Server' master-shape
server = stn2.Masters("Server")
# define page
page = doc.Pages.Item(1)
# rename page
page.name = "My drawing"
# drop master-shape on page, define 'Server' instance
serv = page.Drop(server, 0, 0)
# iterate sub-shapes (side edges)
for i in range (2,6):
# define one od side edges from 'Server'
ssh = serv.shapes(i)
# Change Fill Style to 'Normal'
ssh.FillStyle = 'Normal'
# fix FillForegnd cell for side edge
ssh.Cells( 'Fillforegnd' ).FormulaForceU = 'Guard(Sheet.' + str(serv.id) + '!FillForegnd)'
# fix FillBkgnd cell for side edge
ssh.Cells( 'FillBkgnd' ).FormulaForceU = 'Guard(Sheet.' + str(serv.id) + '!FillBkgnd)'
# instead formula 'Guard(x)' rewrite formula 'Guard(1)'
ssh.Cells( 'FillPattern' ).FormulaForceU = 'Guard(1)'
# fill main shape in 'Server' master-shape
serv.Cells("FillForegnd").FormulaForceU = '5'
I read the documentation of VBA and couldn't convert this to Python code.
I simply created shape and tried to make its align right.
If I delete alignment line of code, rest code works perfectly.
I don't know, I might be using wrong VBA objects and methods. I'm open to your advices. If you provide me your solution code, I would be very appreciated.
import win32com.client
app = win32com.client.Dispatch("Visio.Application")
app.Visible = True
my_shape = page.DrawRectangle(3, 3, 5, 5)) # Draw rectangle
my_shape.Text = "Hello world!" # Add text to rectangle
my_shape.LineStyle = "None" # Add some styling
my_shape.Characters.ParaProps['visHorzAlign'] = 'visAlignRight' #Tried alignment here
my_shape.SetCenter(4.4281, 3) # Change position of rectangle
Here is the error
Related documentations and forums that I found:
http://www.44342.com/visio-f963-t1206-p1.htm
https://learn.microsoft.com/en-us/office/vba/api/visio.selection.align
Try this code:
import win32com.client as win32
app = win32.Dispatch("Visio.Application")
app.Visible = True
page = app.Documents.AddEx("", 1, 0).Pages(1) # create new document and get 1 page
my_shape = page.DrawRectangle(3, 3, 5, 5) # Draw rectangle
my_shape.Text = "Hello world!" # Add text to rectangle
my_shape.LineStyle = "None" # Add some styling
my_shape.Cells("Para.HorzAlign").FormulaU = "2" # 2 - right alignment
# or use my_shape.CellsSRC(4, 0, 6).FormulaU = "2" #visSectionParagraph=4, visHorzAlign=6
my_shape.SetCenter(4.4281, 3) # Change position of rectangle
I'm using django and generating reports following this example, I need to generate a last page but without headers or footers and different content.
I'm trying to do this:
def print_example(self):
buffer = self.buffer
doc = SimpleDocTemplate(buffer,
rightMargin=72,
leftMargin=72,
topMargin=72,
bottomMargin=72,
pagesize=self.pagesize)
elements = []
elements.append(Paragraph('Content for all pages'), my_custom_style)
# ...
doc.build(elements, onFirstPage=self._header_footer, onLaterPages=self._header_footer,
canvasmaker=NumberedCanvas)
doc2 = SimpleDocTemplate(buffer,
rightMargin=72,
leftMargin=72,
topMargin=72,
bottomMargin=72,
pagesize=self.pagesize)
elements2 = []
elements2.append(Paragraph('Content for the last page only'), my_custom_style)
doc2.build(elements2, canvasmaker=NumberedCanvas)
# Get the value of the BytesIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
return pdf
Then only the last content appears and previous content dissapears.
How can I generate the last page with different content?
I don't think it's possible using SimpleDocTemplate but you can achieve this by using BaseDocTemplate and defining your own templates.
Basic example
from reportlab.platypus import PageTemplate, BaseDocTemplate, NextPageTemplate, PageBreak
def headerFooterLayout(canvas, doc):
canvas.saveState()
canvas.setPageSize(self.pagesize)
# add header/footer
canvas.restoreState()
def emptyLayout(canvas, doc):
canvas.saveState()
canvas.setPageSize(self.pagesize)
canvas.restoreState()
pHeight, pWidth = self.pagesize
myFrame = Frame(0, 0, pHeight, pWidth, id='myFrame')
headerFooterTemplate = PageTemplate(id='headerFooterTemplate',
frames=[myFrame],
onPage=headerFooterLayout)
emptyTemplate = PageTemplate(id='emptyTemplate',
frames=[myFrame],
onPage=emptyLayout)
elements = []
elements.append(Paragraph('blah', style))
elements.append(NextPageTemplate('emptyTemplate'))
elements.append(PageBreak())
elements.append(Paragraph('last page', style))
doc = BaseDocTemplate(buffer,
rightMargin=72,
leftMargin=72,
topMargin=72,
bottomMargin=72)
doc.addPageTemplates([headerFooterTemplate, emptyTemplate])
doc.build(elements)
It's been quite a while since I used this so there may well be some issues but comment if something doesn't work.
This is all in the user guide but can be hard to find what you're looking for.
I am trying to set the pageorientation in an OpenOffice document with python. The following code i use to try this:
import json
from win32com.client import Dispatch as Dispatch
svm = Dispatch("com.sun.star.ServiceManager")
svm._FlagAsMethod("Bridge_GetStruct")
coreflect = svm.createInstance("com.sun.star.reflection.CoreReflection")
desktop = svm.createInstance("com.sun.star.frame.Desktop")
doc = desktop.loadComponentFromURL("private:factory/swriter", "_blank",0, [])
txt = doc.getText()
cur = txt.createTextCursor()
Then i tried two different approaches:
p = doc.getPagePrintSettings()
p[8].Value = True
doc.setPagePrintSettings(p)
and
oStyleFamilies = doc.getStyleFamilies()
oObj1 = oStyleFamilies.getByName("PageStyles")
oObj2 = oObj1.getByName("Default")
oObj2.IsLandscape = True
Both give no error, but the page is still in Portrait.. Anybody has an idea?
Thanks in advance!!
try : oObj2.setPropertyValue("IsLandscape",True)
see http://codesnippets.services.openoffice.org/Calc/Calc.SwitchOrientation.snip
I build PDF using ReportLab. My program has a MyDocTemplate(SimpleDocTemplate) class with two methods: beforePage(self) and afterPage(self) which add header and footer (as PNG image) on every page. There is also a MyDocStyle class which describe ParagraphStyle.
Main method looks like this:
TITLE = Paragraph(Title, MyDocStyle.h1)
TO = Paragraph(To, MyDocStyle.h2)
FROM = Paragraph(From, MyDocStyle.h2)
SUBJECT = Paragraph(Subject, MyDocStyle.h2)
LONG_PARAGRAPH = Paragraph(Text, MyDocStyle.h3)
...
Elements = [TITLE, TO, FROM, SUBJECT, LONG_PARAGRAPH, ...]
doc = MyDocTemplete('output.pdf', pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=4*cm, bottomMargin=4*cm)
doc.build(Elements)
Data comes from CSV files and GUI. From time to time (depends on data length) I receive an error:
Flowable <Spacer at 0x2631120 frame=normal>...(1 x 5.66929133858) too large
on page 1 in frame 'normal'(469.88976378 x 603.118110236) of template 'First'
This exception stop my program. For short Paragraphs I set in MyDocStyle class h2.keepWithNext = 1 however it's not perfect solution. ReportLab split correctly long paragraph if end of paragraph does not "coincide" with end of page (text area).
How can I deal with it?
This error occurs when ReportLab try to split a Spacer over two pages. It seems that the only way to workaround this issue is wrap your Spacer into a KeepTogether element:
elements.append(KeepTogether(Spacer(width, height)))
Solved. Don't use Spacer (e.g. Spacer(1, 0.2*cm)) as a separator for Paragraph. Instead, define spaceBefore and spaceAfter in ParagraphStyle, for example:
ParagraphStyle(name = 'Normal',
fontName = "Verdana",
fontSize = 11,
leading = 15,
alignment = TA_JUSTIFY,
allowOrphans = 0,
spaceBefore = 20,
spaceAfter = 20,
wordWrap = 1)