707 lines
19 KiB
Python
707 lines
19 KiB
Python
|
###############################################################################
|
||
|
#
|
||
|
# Vml - A class for writing the Excel XLSX Vml file.
|
||
|
#
|
||
|
# Copyright 2013-2019, John McNamara, jmcnamara@cpan.org
|
||
|
#
|
||
|
|
||
|
# Package imports.
|
||
|
from . import xmlwriter
|
||
|
|
||
|
|
||
|
class Vml(xmlwriter.XMLwriter):
|
||
|
"""
|
||
|
A class for writing the Excel XLSX Vml file.
|
||
|
|
||
|
|
||
|
"""
|
||
|
|
||
|
###########################################################################
|
||
|
#
|
||
|
# Public API.
|
||
|
#
|
||
|
###########################################################################
|
||
|
|
||
|
def __init__(self):
|
||
|
"""
|
||
|
Constructor.
|
||
|
|
||
|
"""
|
||
|
|
||
|
super(Vml, self).__init__()
|
||
|
|
||
|
###########################################################################
|
||
|
#
|
||
|
# Private API.
|
||
|
#
|
||
|
###########################################################################
|
||
|
def _assemble_xml_file(self, data_id, vml_shape_id, comments_data=None,
|
||
|
buttons_data=None, header_images_data=None):
|
||
|
# Assemble and write the XML file.
|
||
|
z_index = 1
|
||
|
|
||
|
self._write_xml_namespace()
|
||
|
|
||
|
# Write the o:shapelayout element.
|
||
|
self._write_shapelayout(data_id)
|
||
|
|
||
|
if buttons_data:
|
||
|
# Write the v:shapetype element.
|
||
|
self._write_button_shapetype()
|
||
|
|
||
|
for button in buttons_data:
|
||
|
# Write the v:shape element.
|
||
|
vml_shape_id += 1
|
||
|
self._write_button_shape(vml_shape_id, z_index, button)
|
||
|
z_index += 1
|
||
|
|
||
|
if comments_data:
|
||
|
# Write the v:shapetype element.
|
||
|
self._write_comment_shapetype()
|
||
|
|
||
|
for comment in comments_data:
|
||
|
# Write the v:shape element.
|
||
|
vml_shape_id += 1
|
||
|
self._write_comment_shape(vml_shape_id, z_index, comment)
|
||
|
z_index += 1
|
||
|
|
||
|
if header_images_data:
|
||
|
|
||
|
# Write the v:shapetype element.
|
||
|
self._write_image_shapetype()
|
||
|
|
||
|
index = 1
|
||
|
for image in header_images_data:
|
||
|
# Write the v:shape element.
|
||
|
vml_shape_id += 1
|
||
|
self._write_image_shape(vml_shape_id, index, image)
|
||
|
index += 1
|
||
|
|
||
|
self._xml_end_tag('xml')
|
||
|
|
||
|
# Close the XML writer filehandle.
|
||
|
self._xml_close()
|
||
|
|
||
|
def _pixels_to_points(self, vertices):
|
||
|
# Convert comment vertices from pixels to points.
|
||
|
|
||
|
left, top, width, height = vertices[8:12]
|
||
|
|
||
|
# Scale to pixels.
|
||
|
left *= 0.75
|
||
|
top *= 0.75
|
||
|
width *= 0.75
|
||
|
height *= 0.75
|
||
|
|
||
|
return left, top, width, height
|
||
|
|
||
|
###########################################################################
|
||
|
#
|
||
|
# XML methods.
|
||
|
#
|
||
|
###########################################################################
|
||
|
def _write_xml_namespace(self):
|
||
|
# Write the <xml> element. This is the root element of VML.
|
||
|
schema = 'urn:schemas-microsoft-com:'
|
||
|
xmlns = schema + 'vml'
|
||
|
xmlns_o = schema + 'office:office'
|
||
|
xmlns_x = schema + 'office:excel'
|
||
|
|
||
|
attributes = [
|
||
|
('xmlns:v', xmlns),
|
||
|
('xmlns:o', xmlns_o),
|
||
|
('xmlns:x', xmlns_x),
|
||
|
]
|
||
|
|
||
|
self._xml_start_tag('xml', attributes)
|
||
|
|
||
|
def _write_shapelayout(self, data_id):
|
||
|
# Write the <o:shapelayout> element.
|
||
|
attributes = [('v:ext', 'edit')]
|
||
|
|
||
|
self._xml_start_tag('o:shapelayout', attributes)
|
||
|
|
||
|
# Write the o:idmap element.
|
||
|
self._write_idmap(data_id)
|
||
|
|
||
|
self._xml_end_tag('o:shapelayout')
|
||
|
|
||
|
def _write_idmap(self, data_id):
|
||
|
# Write the <o:idmap> element.
|
||
|
attributes = [
|
||
|
('v:ext', 'edit'),
|
||
|
('data', data_id),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('o:idmap', attributes)
|
||
|
|
||
|
def _write_comment_shapetype(self):
|
||
|
# Write the <v:shapetype> element.
|
||
|
shape_id = '_x0000_t202'
|
||
|
coordsize = '21600,21600'
|
||
|
spt = 202
|
||
|
path = 'm,l,21600r21600,l21600,xe'
|
||
|
|
||
|
attributes = [
|
||
|
('id', shape_id),
|
||
|
('coordsize', coordsize),
|
||
|
('o:spt', spt),
|
||
|
('path', path),
|
||
|
]
|
||
|
|
||
|
self._xml_start_tag('v:shapetype', attributes)
|
||
|
|
||
|
# Write the v:stroke element.
|
||
|
self._write_stroke()
|
||
|
|
||
|
# Write the v:path element.
|
||
|
self._write_comment_path('t', 'rect')
|
||
|
|
||
|
self._xml_end_tag('v:shapetype')
|
||
|
|
||
|
def _write_button_shapetype(self):
|
||
|
# Write the <v:shapetype> element.
|
||
|
shape_id = '_x0000_t201'
|
||
|
coordsize = '21600,21600'
|
||
|
spt = 201
|
||
|
path = 'm,l,21600r21600,l21600,xe'
|
||
|
|
||
|
attributes = [
|
||
|
('id', shape_id),
|
||
|
('coordsize', coordsize),
|
||
|
('o:spt', spt),
|
||
|
('path', path),
|
||
|
]
|
||
|
|
||
|
self._xml_start_tag('v:shapetype', attributes)
|
||
|
|
||
|
# Write the v:stroke element.
|
||
|
self._write_stroke()
|
||
|
|
||
|
# Write the v:path element.
|
||
|
self._write_button_path()
|
||
|
|
||
|
# Write the o:lock element.
|
||
|
self._write_shapetype_lock()
|
||
|
|
||
|
self._xml_end_tag('v:shapetype')
|
||
|
|
||
|
def _write_image_shapetype(self):
|
||
|
# Write the <v:shapetype> element.
|
||
|
shape_id = '_x0000_t75'
|
||
|
coordsize = '21600,21600'
|
||
|
spt = 75
|
||
|
o_preferrelative = 't'
|
||
|
path = 'm@4@5l@4@11@9@11@9@5xe'
|
||
|
filled = 'f'
|
||
|
stroked = 'f'
|
||
|
|
||
|
attributes = [
|
||
|
('id', shape_id),
|
||
|
('coordsize', coordsize),
|
||
|
('o:spt', spt),
|
||
|
('o:preferrelative', o_preferrelative),
|
||
|
('path', path),
|
||
|
('filled', filled),
|
||
|
('stroked', stroked),
|
||
|
]
|
||
|
|
||
|
self._xml_start_tag('v:shapetype', attributes)
|
||
|
|
||
|
# Write the v:stroke element.
|
||
|
self._write_stroke()
|
||
|
|
||
|
# Write the v:formulas element.
|
||
|
self._write_formulas()
|
||
|
|
||
|
# Write the v:path element.
|
||
|
self._write_image_path()
|
||
|
|
||
|
# Write the o:lock element.
|
||
|
self._write_aspect_ratio_lock()
|
||
|
|
||
|
self._xml_end_tag('v:shapetype')
|
||
|
|
||
|
def _write_stroke(self):
|
||
|
# Write the <v:stroke> element.
|
||
|
joinstyle = 'miter'
|
||
|
|
||
|
attributes = [('joinstyle', joinstyle)]
|
||
|
|
||
|
self._xml_empty_tag('v:stroke', attributes)
|
||
|
|
||
|
def _write_comment_path(self, gradientshapeok, connecttype):
|
||
|
# Write the <v:path> element.
|
||
|
attributes = []
|
||
|
|
||
|
if gradientshapeok:
|
||
|
attributes.append(('gradientshapeok', 't'))
|
||
|
|
||
|
attributes.append(('o:connecttype', connecttype))
|
||
|
|
||
|
self._xml_empty_tag('v:path', attributes)
|
||
|
|
||
|
def _write_button_path(self):
|
||
|
# Write the <v:path> element.
|
||
|
shadowok = 'f'
|
||
|
extrusionok = 'f'
|
||
|
strokeok = 'f'
|
||
|
fillok = 'f'
|
||
|
connecttype = 'rect'
|
||
|
|
||
|
attributes = [
|
||
|
('shadowok', shadowok),
|
||
|
('o:extrusionok', extrusionok),
|
||
|
('strokeok', strokeok),
|
||
|
('fillok', fillok),
|
||
|
('o:connecttype', connecttype),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('v:path', attributes)
|
||
|
|
||
|
def _write_image_path(self):
|
||
|
# Write the <v:path> element.
|
||
|
extrusionok = 'f'
|
||
|
gradientshapeok = 't'
|
||
|
connecttype = 'rect'
|
||
|
|
||
|
attributes = [
|
||
|
('o:extrusionok', extrusionok),
|
||
|
('gradientshapeok', gradientshapeok),
|
||
|
('o:connecttype', connecttype),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('v:path', attributes)
|
||
|
|
||
|
def _write_shapetype_lock(self):
|
||
|
# Write the <o:lock> element.
|
||
|
ext = 'edit'
|
||
|
shapetype = 't'
|
||
|
|
||
|
attributes = [
|
||
|
('v:ext', ext),
|
||
|
('shapetype', shapetype),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('o:lock', attributes)
|
||
|
|
||
|
def _write_rotation_lock(self):
|
||
|
# Write the <o:lock> element.
|
||
|
ext = 'edit'
|
||
|
rotation = 't'
|
||
|
|
||
|
attributes = [
|
||
|
('v:ext', ext),
|
||
|
('rotation', rotation),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('o:lock', attributes)
|
||
|
|
||
|
def _write_aspect_ratio_lock(self):
|
||
|
# Write the <o:lock> element.
|
||
|
ext = 'edit'
|
||
|
aspectratio = 't'
|
||
|
|
||
|
attributes = [
|
||
|
('v:ext', ext),
|
||
|
('aspectratio', aspectratio),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('o:lock', attributes)
|
||
|
|
||
|
def _write_comment_shape(self, shape_id, z_index, comment):
|
||
|
# Write the <v:shape> element.
|
||
|
shape_type = '#_x0000_t202'
|
||
|
insetmode = 'auto'
|
||
|
visibility = 'hidden'
|
||
|
|
||
|
# Set the shape index.
|
||
|
shape_id = '_x0000_s' + str(shape_id)
|
||
|
|
||
|
# Get the comment parameters
|
||
|
row = comment[0]
|
||
|
col = comment[1]
|
||
|
visible = comment[4]
|
||
|
fillcolor = comment[5]
|
||
|
vertices = comment[9]
|
||
|
|
||
|
(left, top, width, height) = self._pixels_to_points(vertices)
|
||
|
|
||
|
# Set the visibility.
|
||
|
if visible:
|
||
|
visibility = 'visible'
|
||
|
|
||
|
style = (
|
||
|
'position:absolute;'
|
||
|
'margin-left:%.15gpt;'
|
||
|
'margin-top:%.15gpt;'
|
||
|
'width:%.15gpt;'
|
||
|
'height:%.15gpt;'
|
||
|
'z-index:%d;'
|
||
|
'visibility:%s' % (left, top, width, height, z_index, visibility))
|
||
|
|
||
|
attributes = [
|
||
|
('id', shape_id),
|
||
|
('type', shape_type),
|
||
|
('style', style),
|
||
|
('fillcolor', fillcolor),
|
||
|
('o:insetmode', insetmode),
|
||
|
]
|
||
|
|
||
|
self._xml_start_tag('v:shape', attributes)
|
||
|
|
||
|
# Write the v:fill element.
|
||
|
self._write_comment_fill()
|
||
|
|
||
|
# Write the v:shadow element.
|
||
|
self._write_shadow()
|
||
|
|
||
|
# Write the v:path element.
|
||
|
self._write_comment_path(None, 'none')
|
||
|
|
||
|
# Write the v:textbox element.
|
||
|
self._write_comment_textbox()
|
||
|
|
||
|
# Write the x:ClientData element.
|
||
|
self._write_comment_client_data(row, col, visible, vertices)
|
||
|
|
||
|
self._xml_end_tag('v:shape')
|
||
|
|
||
|
def _write_button_shape(self, shape_id, z_index, button):
|
||
|
# Write the <v:shape> element.
|
||
|
shape_type = '#_x0000_t201'
|
||
|
|
||
|
# Set the shape index.
|
||
|
shape_id = '_x0000_s' + str(shape_id)
|
||
|
|
||
|
# Get the button parameters.
|
||
|
# row = button["_row"]
|
||
|
# col = button["_col"]
|
||
|
vertices = button["vertices"]
|
||
|
|
||
|
(left, top, width, height) = self._pixels_to_points(vertices)
|
||
|
|
||
|
style = (
|
||
|
'position:absolute;'
|
||
|
'margin-left:%.15gpt;'
|
||
|
'margin-top:%.15gpt;'
|
||
|
'width:%.15gpt;'
|
||
|
'height:%.15gpt;'
|
||
|
'z-index:%d;'
|
||
|
'mso-wrap-style:tight' % (left, top, width, height, z_index))
|
||
|
|
||
|
attributes = [
|
||
|
('id', shape_id),
|
||
|
('type', shape_type),
|
||
|
('style', style),
|
||
|
('o:button', 't'),
|
||
|
('fillcolor', 'buttonFace [67]'),
|
||
|
('strokecolor', 'windowText [64]'),
|
||
|
('o:insetmode', 'auto'),
|
||
|
]
|
||
|
|
||
|
self._xml_start_tag('v:shape', attributes)
|
||
|
|
||
|
# Write the v:fill element.
|
||
|
self._write_button_fill()
|
||
|
|
||
|
# Write the o:lock element.
|
||
|
self._write_rotation_lock()
|
||
|
|
||
|
# Write the v:textbox element.
|
||
|
self._write_button_textbox(button["font"])
|
||
|
|
||
|
# Write the x:ClientData element.
|
||
|
self._write_button_client_data(button)
|
||
|
|
||
|
self._xml_end_tag('v:shape')
|
||
|
|
||
|
def _write_image_shape(self, shape_id, z_index, image_data):
|
||
|
# Write the <v:shape> element.
|
||
|
shape_type = '#_x0000_t75'
|
||
|
|
||
|
# Set the shape index.
|
||
|
shape_id = '_x0000_s' + str(shape_id)
|
||
|
|
||
|
# Get the image parameters
|
||
|
width = image_data[0]
|
||
|
height = image_data[1]
|
||
|
name = image_data[2]
|
||
|
position = image_data[3]
|
||
|
x_dpi = image_data[4]
|
||
|
y_dpi = image_data[5]
|
||
|
|
||
|
# Scale the height/width by the resolution, relative to 72dpi.
|
||
|
width = width * 72.0 / x_dpi
|
||
|
height = height * 72.0 / y_dpi
|
||
|
|
||
|
# Excel uses a rounding based around 72 and 96 dpi.
|
||
|
width = 72.0 / 96 * int(width * 96.0 / 72 + 0.25)
|
||
|
height = 72.0 / 96 * int(height * 96.0 / 72 + 0.25)
|
||
|
|
||
|
style = (
|
||
|
'position:absolute;'
|
||
|
'margin-left:0;'
|
||
|
'margin-top:0;'
|
||
|
'width:%.15gpt;'
|
||
|
'height:%.15gpt;'
|
||
|
'z-index:%d' % (width, height, z_index))
|
||
|
|
||
|
attributes = [
|
||
|
('id', position),
|
||
|
('o:spid', shape_id),
|
||
|
('type', shape_type),
|
||
|
('style', style),
|
||
|
]
|
||
|
|
||
|
self._xml_start_tag('v:shape', attributes)
|
||
|
|
||
|
# Write the v:imagedata element.
|
||
|
self._write_imagedata(z_index, name)
|
||
|
|
||
|
# Write the o:lock element.
|
||
|
self._write_rotation_lock()
|
||
|
|
||
|
self._xml_end_tag('v:shape')
|
||
|
|
||
|
def _write_comment_fill(self):
|
||
|
# Write the <v:fill> element.
|
||
|
color_2 = '#ffffe1'
|
||
|
|
||
|
attributes = [('color2', color_2)]
|
||
|
|
||
|
self._xml_empty_tag('v:fill', attributes)
|
||
|
|
||
|
def _write_button_fill(self):
|
||
|
# Write the <v:fill> element.
|
||
|
color_2 = 'buttonFace [67]'
|
||
|
detectmouseclick = 't'
|
||
|
|
||
|
attributes = [
|
||
|
('color2', color_2),
|
||
|
('o:detectmouseclick', detectmouseclick),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('v:fill', attributes)
|
||
|
|
||
|
def _write_shadow(self):
|
||
|
# Write the <v:shadow> element.
|
||
|
on = 't'
|
||
|
color = 'black'
|
||
|
obscured = 't'
|
||
|
|
||
|
attributes = [
|
||
|
('on', on),
|
||
|
('color', color),
|
||
|
('obscured', obscured),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('v:shadow', attributes)
|
||
|
|
||
|
def _write_comment_textbox(self):
|
||
|
# Write the <v:textbox> element.
|
||
|
style = 'mso-direction-alt:auto'
|
||
|
|
||
|
attributes = [('style', style)]
|
||
|
|
||
|
self._xml_start_tag('v:textbox', attributes)
|
||
|
|
||
|
# Write the div element.
|
||
|
self._write_div('left')
|
||
|
|
||
|
self._xml_end_tag('v:textbox')
|
||
|
|
||
|
def _write_button_textbox(self, font):
|
||
|
# Write the <v:textbox> element.
|
||
|
style = 'mso-direction-alt:auto'
|
||
|
|
||
|
attributes = [('style', style), ('o:singleclick', 'f')]
|
||
|
|
||
|
self._xml_start_tag('v:textbox', attributes)
|
||
|
|
||
|
# Write the div element.
|
||
|
self._write_div('center', font)
|
||
|
|
||
|
self._xml_end_tag('v:textbox')
|
||
|
|
||
|
def _write_div(self, align, font=None):
|
||
|
# Write the <div> element.
|
||
|
|
||
|
style = 'text-align:' + align
|
||
|
|
||
|
attributes = [('style', style)]
|
||
|
|
||
|
self._xml_start_tag('div', attributes)
|
||
|
|
||
|
if font:
|
||
|
# Write the font element.
|
||
|
self._write_font(font)
|
||
|
|
||
|
self._xml_end_tag('div')
|
||
|
|
||
|
def _write_font(self, font):
|
||
|
# Write the <font> element.
|
||
|
caption = font["caption"]
|
||
|
face = 'Calibri'
|
||
|
size = 220
|
||
|
color = '#000000'
|
||
|
|
||
|
attributes = [
|
||
|
('face', face),
|
||
|
('size', size),
|
||
|
('color', color),
|
||
|
]
|
||
|
|
||
|
self._xml_data_element('font', caption, attributes)
|
||
|
|
||
|
def _write_comment_client_data(self, row, col, visible, vertices):
|
||
|
# Write the <x:ClientData> element.
|
||
|
object_type = 'Note'
|
||
|
|
||
|
attributes = [('ObjectType', object_type)]
|
||
|
|
||
|
self._xml_start_tag('x:ClientData', attributes)
|
||
|
|
||
|
# Write the x:MoveWithCells element.
|
||
|
self._write_move_with_cells()
|
||
|
|
||
|
# Write the x:SizeWithCells element.
|
||
|
self._write_size_with_cells()
|
||
|
|
||
|
# Write the x:Anchor element.
|
||
|
self._write_anchor(vertices)
|
||
|
|
||
|
# Write the x:AutoFill element.
|
||
|
self._write_auto_fill()
|
||
|
|
||
|
# Write the x:Row element.
|
||
|
self._write_row(row)
|
||
|
|
||
|
# Write the x:Column element.
|
||
|
self._write_column(col)
|
||
|
|
||
|
# Write the x:Visible element.
|
||
|
if visible:
|
||
|
self._write_visible()
|
||
|
|
||
|
self._xml_end_tag('x:ClientData')
|
||
|
|
||
|
def _write_button_client_data(self, button):
|
||
|
# Write the <x:ClientData> element.
|
||
|
macro = button["macro"]
|
||
|
vertices = button["vertices"]
|
||
|
|
||
|
object_type = 'Button'
|
||
|
|
||
|
attributes = [('ObjectType', object_type)]
|
||
|
|
||
|
self._xml_start_tag('x:ClientData', attributes)
|
||
|
|
||
|
# Write the x:Anchor element.
|
||
|
self._write_anchor(vertices)
|
||
|
|
||
|
# Write the x:PrintObject element.
|
||
|
self._write_print_object()
|
||
|
|
||
|
# Write the x:AutoFill element.
|
||
|
self._write_auto_fill()
|
||
|
|
||
|
# Write the x:FmlaMacro element.
|
||
|
self._write_fmla_macro(macro)
|
||
|
|
||
|
# Write the x:TextHAlign element.
|
||
|
self._write_text_halign()
|
||
|
|
||
|
# Write the x:TextVAlign element.
|
||
|
self._write_text_valign()
|
||
|
|
||
|
self._xml_end_tag('x:ClientData')
|
||
|
|
||
|
def _write_move_with_cells(self):
|
||
|
# Write the <x:MoveWithCells> element.
|
||
|
self._xml_empty_tag('x:MoveWithCells')
|
||
|
|
||
|
def _write_size_with_cells(self):
|
||
|
# Write the <x:SizeWithCells> element.
|
||
|
self._xml_empty_tag('x:SizeWithCells')
|
||
|
|
||
|
def _write_visible(self):
|
||
|
# Write the <x:Visible> element.
|
||
|
self._xml_empty_tag('x:Visible')
|
||
|
|
||
|
def _write_anchor(self, vertices):
|
||
|
# Write the <x:Anchor> element.
|
||
|
(col_start, row_start, x1, y1, col_end, row_end, x2, y2) = vertices[:8]
|
||
|
|
||
|
strings = [col_start, x1, row_start, y1, col_end, x2, row_end, y2]
|
||
|
strings = [str(i) for i in strings]
|
||
|
|
||
|
data = ", ".join(strings)
|
||
|
|
||
|
self._xml_data_element('x:Anchor', data)
|
||
|
|
||
|
def _write_auto_fill(self):
|
||
|
# Write the <x:AutoFill> element.
|
||
|
data = 'False'
|
||
|
|
||
|
self._xml_data_element('x:AutoFill', data)
|
||
|
|
||
|
def _write_row(self, data):
|
||
|
# Write the <x:Row> element.
|
||
|
self._xml_data_element('x:Row', data)
|
||
|
|
||
|
def _write_column(self, data):
|
||
|
# Write the <x:Column> element.
|
||
|
self._xml_data_element('x:Column', data)
|
||
|
|
||
|
def _write_print_object(self):
|
||
|
# Write the <x:PrintObject> element.
|
||
|
self._xml_data_element('x:PrintObject', 'False')
|
||
|
|
||
|
def _write_text_halign(self):
|
||
|
# Write the <x:TextHAlign> element.
|
||
|
self._xml_data_element('x:TextHAlign', 'Center')
|
||
|
|
||
|
def _write_text_valign(self):
|
||
|
# Write the <x:TextVAlign> element.
|
||
|
self._xml_data_element('x:TextVAlign', 'Center')
|
||
|
|
||
|
def _write_fmla_macro(self, data):
|
||
|
# Write the <x:FmlaMacro> element.
|
||
|
self._xml_data_element('x:FmlaMacro', data)
|
||
|
|
||
|
def _write_imagedata(self, image_index, o_title):
|
||
|
# Write the <v:imagedata> element.
|
||
|
attributes = [
|
||
|
('o:relid', 'rId' + str(image_index)),
|
||
|
('o:title', o_title),
|
||
|
]
|
||
|
|
||
|
self._xml_empty_tag('v:imagedata', attributes)
|
||
|
|
||
|
def _write_formulas(self):
|
||
|
# Write the <v:formulas> element.
|
||
|
self._xml_start_tag('v:formulas')
|
||
|
|
||
|
# Write the v:f elements.
|
||
|
self._write_formula('if lineDrawn pixelLineWidth 0')
|
||
|
self._write_formula('sum @0 1 0')
|
||
|
self._write_formula('sum 0 0 @1')
|
||
|
self._write_formula('prod @2 1 2')
|
||
|
self._write_formula('prod @3 21600 pixelWidth')
|
||
|
self._write_formula('prod @3 21600 pixelHeight')
|
||
|
self._write_formula('sum @0 0 1')
|
||
|
self._write_formula('prod @6 1 2')
|
||
|
self._write_formula('prod @7 21600 pixelWidth')
|
||
|
self._write_formula('sum @8 21600 0')
|
||
|
self._write_formula('prod @7 21600 pixelHeight')
|
||
|
self._write_formula('sum @10 21600 0')
|
||
|
|
||
|
self._xml_end_tag('v:formulas')
|
||
|
|
||
|
def _write_formula(self, eqn):
|
||
|
# Write the <v:f> element.
|
||
|
attributes = [('eqn', eqn)]
|
||
|
|
||
|
self._xml_empty_tag('v:f', attributes)
|