Skip to content

Commit 9d7af1b

Browse files
committed
table: cell: added<w:tcPr>
Can now set column spans and cell shading properties.
1 parent c429673 commit 9d7af1b

5 files changed

Lines changed: 148 additions & 13 deletions

File tree

docx/oxml/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# custom element class mappings
1313
# ===========================================================================
1414

15-
from docx.oxml.shared import CT_DecimalNumber, CT_OnOff, CT_String
15+
from docx.oxml.shared import CT_DecimalNumber, CT_OnOff, CT_String, CT_Shading
1616

1717
from docx.oxml.shape import (
1818
CT_Blip, CT_BlipFillProperties, CT_GraphicalObject,
@@ -53,6 +53,8 @@
5353
register_custom_element_class('w:tc', CT_Tc)
5454
register_custom_element_class('w:tr', CT_Row)
5555
register_custom_element_class('w:tcPr', CT_TcPr)
56+
register_custom_element_class('w:gridSpan', CT_DecimalNumber)
57+
register_custom_element_class('w:shd', CT_Shading)
5658

5759
from docx.oxml.text import CT_Br, CT_P, CT_PPr, CT_R, CT_RPr, CT_Text
5860
register_custom_element_class('w:b', CT_OnOff)

docx/oxml/shared.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,3 +340,92 @@ def val(self):
340340
@val.setter
341341
def val(self, val):
342342
return self.set(qn('w:val'), val)
343+
344+
345+
class CT_Shading(OxmlBaseElement):
346+
@classmethod
347+
def new(cls, nsptagname, valDict):
348+
"""
349+
Return a new ``CT_Shading`` element with tagname *nsptagname* and
350+
attributes set by key, value pairs in *valDict*.
351+
"""
352+
attrsDict = {}
353+
for k, v in valDict.iteritems():
354+
attrsDict[qn('w:'+str(k))] = v
355+
return OxmlElement(nsptagname, attrs=attrsDict)
356+
357+
@property
358+
def valDict(self):
359+
valDict={}
360+
for val in ['val','color', 'themeColor','themeTint', 'themeShade',
361+
'fill', 'themeFill', 'themeFillTint', 'themeFillSHade']:
362+
valDict[val] = self.get(qn('w:'+val))
363+
return valDict
364+
@valDict.setter
365+
def valDict(self, valDict):
366+
for k, v in valDict:
367+
self.set(qn('w:'+str(k)), v)
368+
return
369+
370+
@property
371+
def val(self):
372+
return self.get(qn('w:val'))
373+
@val.setter
374+
def val(self, val):
375+
return self.set(qn('w:val'), val)
376+
377+
@property
378+
def color(self):
379+
return self.get(qn('w:color'))
380+
@color.setter
381+
def color(self, color):
382+
return self.set(qn('w:color'), color)
383+
384+
@property
385+
def themeColor(self):
386+
return self.get(qn('w:themeColor'))
387+
@themeColor.setter
388+
def themeColor(self, themeColor):
389+
return self.set(qn('w:themeColor'), themeColor)
390+
391+
@property
392+
def themeTint(self):
393+
return self.get(qn('w:themeTint'))
394+
@themeTint.setter
395+
def themeTint(self, themeTint):
396+
return self.set(qn('w:themeTint'), themeTint)
397+
398+
@property
399+
def themeShade(self):
400+
return self.get(qn('w:themeShade'))
401+
@themeShade.setter
402+
def themeShade(self, themeShade):
403+
return self.set(qn('w:themeShade'), themeShade)
404+
405+
@property
406+
def fill(self):
407+
return self.get(qn('w:fill'))
408+
@fill.setter
409+
def fill(self, fill):
410+
return self.set(qn('w:fill'), fill)
411+
412+
@property
413+
def themeFill(self):
414+
return self.get(qn('w:themFill'))
415+
@themeFill.setter
416+
def themeFill(self, themeFill):
417+
return self.set(qn('w:themeFill'), themeFill)
418+
419+
@property
420+
def themeFillTint(self):
421+
return self.get(qn('w:themeFillTint'))
422+
@themeFillTint.setter
423+
def themeFillTint(self, themeFillTint):
424+
return self.set(qn('w:themeFillTint'), themeFillTint)
425+
426+
@property
427+
def themeFillShade(self):
428+
return self.get(qn('w:themeFillShade'))
429+
@themeFillShade.setter
430+
def themeFillShade(self, themeFillShade):
431+
return self.set(qn('w:themeFillShade'), themeFillShade)

docx/oxml/table.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from docx.oxml.shared import OxmlBaseElement, OxmlElement, qn
1010

1111
from .exceptions import ValidationError
12-
from .shared import CT_String
12+
from .shared import CT_String, CT_DecimalNumber, CT_Shading
1313
from .text import CT_P
1414

1515

@@ -286,7 +286,7 @@ def add_gridSpan(self, span):
286286
Return a new <w:gridSpan> element newly inserted in sequence among
287287
the existing child elements.gridSpan
288288
"""
289-
gridSpan = CT_String.new('w:gridSpan', str(span))
289+
gridSpan = CT_DecimalNumber.new('w:gridSpan', span)
290290
self.append(gridSpan) # append or insert?
291291
return gridSpan
292292

@@ -297,21 +297,21 @@ def gridSpan(self):
297297
"""
298298
return self.find(qn('w:gridSpan'))
299299

300-
def add_gridSpan(self, span):
300+
def add_shading(self, argDict):
301301
"""
302-
Return a new <w:gridSpan> element newly inserted in sequence among
302+
Return a new <w:shd> element newly inserted in sequence among
303303
the existing child elements.gridSpan
304304
"""
305-
gridSpan = CT_String.new('w:gridSpan', str(span))
306-
self.append(gridSpan) # append or insert?
307-
return gridSpan
305+
shading = CT_Shading.new('w:shd', argDict)
306+
self.append(shading) # append or insert?
307+
return shading
308308

309309
@property
310-
def gridSpan(self):
310+
def shading(self):
311311
"""
312-
Optional <w:gridSpan> child element, or |None| if not present.
312+
Optional <w:shd> child element, or |None| if not present.
313313
"""
314-
return self.find(qn('w:gridSpan'))
314+
return self.find(qn('w:shd'))
315315

316316

317317

docx/table.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,51 @@ def colSpan(self, val):
130130
if span is None:
131131
self._tc.get_or_add_tcPr().add_gridSpan(val)
132132
else:
133-
span.val = val
133+
span.val = val
134+
135+
@property
136+
def shading(self):
137+
"""
138+
Set the cell shading.
139+
"""
140+
shading = self._tc.get_or_add_tcPr().shading
141+
if shading is None:
142+
return None
143+
return shading.valDict
144+
145+
@shading.setter
146+
def shading(self, valDict):
147+
shading = self._tc.get_or_add_tcPr().shading
148+
if shading is None:
149+
self._tc.get_or_add_tcPr().add_shading(valDict)
150+
else:
151+
shading.valDict = valDict
152+
153+
def set_shading(self, val = None, color = None, themeColor = None,
154+
themeTint = None, themeShade = None, fill = None,
155+
themeFill = None, themeFillTint = None,
156+
themeFillShade = None, argDict = None):
157+
"""
158+
Convienence method for setting individual values of the shading dict.
159+
It only replaces values that are not `None`.
160+
"""
161+
if self.shading is None:
162+
valDict = {}
163+
164+
argDict = {'val':val,'color':color, 'themeColor':themeColor,
165+
'themeTint':themeTint, 'themeShade':themeShade,
166+
'fill':fill, 'themeFill':themeFill,
167+
'themeFillTint':themeFillTint,
168+
'themeFillShade':themeFillShade,
169+
}
170+
171+
for k, v in argDict.iteritems():
172+
if v is not None:
173+
valDict[k]=v
174+
175+
self.shading = valDict
176+
177+
134178

135179
class _Column(object):
136180
"""

tests/test_text.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def bool_prop_get_fixture(self, request):
269269
('snap_to_grid', True), ('snap_to_grid', False),
270270
('snap_to_grid', None),
271271
('spec_vanish', True), ('spec_vanish', False), ('spec_vanish', None),
272-
('strike', True), ('strike', False), ('strike', None),
272+
('strike', True), ('strikregister_custom_element_class('w:tcPr', CT_TcPr)e', False), ('strike', None),
273273
('web_hidden', True), ('web_hidden', False), ('web_hidden', None),
274274
])
275275
def bool_prop_set_fixture(self, request):

0 commit comments

Comments
 (0)